diff mbox

C++ PATCH for c++/48003 (allow integer overflow in template args with -fpermissive)

Message ID 4D75BCF3.4050705@redhat.com
State New
Headers show

Commit Message

Jason Merrill March 8, 2011, 5:21 a.m. UTC
This patch changes convert_nontype_argument to defer to 
cxx_constant_value on whether or not to go ahead with a semi-constant 
template argument, and whether or not to give a diagnostic.  Making this 
change revealed a bug in potential_constant_expression_1, which was 
failing to check for overflow.

Tested x86_64-pc-linux-gnu, applying to trunk.
commit 0e5ec26f6aeca92278e290181b3bd66f9344953f
Author: Jason Merrill <jason@redhat.com>
Date:   Mon Mar 7 16:17:21 2011 -0500

    	PR c++/48003
    	* pt.c (convert_nontype_argument): Fix -fpermissive allowing
    	integer overflow.
    	* semantics.c (potential_constant_expression_1): Check TREE_OVERFLOW.
diff mbox

Patch

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index dfc9728..076224c 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -5402,11 +5402,19 @@  convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
 	{
 	  if (complain & tf_error)
 	    {
-	      error ("%qE is not a valid template argument for type %qT "
-		     "because it is a non-constant expression", expr, type);
-	      cxx_constant_value (expr);
+	      int errs = errorcount, warns = warningcount;
+	      expr = cxx_constant_value (expr);
+	      if (errorcount > errs || warningcount > warns)
+		inform (EXPR_LOC_OR_HERE (expr),
+			"in template argument for type %qT ", type);
+	      if (expr == error_mark_node)
+		return NULL_TREE;
+	      /* else cxx_constant_value complained but gave us
+		 a real constant, so go ahead.  */
+	      gcc_assert (TREE_CODE (expr) == INTEGER_CST);
 	    }
-	  return NULL_TREE;
+	  else
+	    return NULL_TREE;
 	}
     }
   /* [temp.arg.nontype]/5, bullet 2
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 52a962d..a0f48c0e 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -7275,7 +7275,20 @@  potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
       return false;
     }
   if (CONSTANT_CLASS_P (t))
-    return true;
+    {
+      if (TREE_OVERFLOW (t))
+	{
+	  if (flags & tf_error)
+	    {
+	      permerror (EXPR_LOC_OR_HERE (t),
+			 "overflow in constant expression");
+	      if (flag_permissive)
+		return true;
+	    }
+	  return false;
+	}
+      return true;
+    }
 
   switch (TREE_CODE (t))
     {
diff --git a/gcc/testsuite/g++.dg/init/member1.C b/gcc/testsuite/g++.dg/init/member1.C
index aededf2..88f9b31 100644
--- a/gcc/testsuite/g++.dg/init/member1.C
+++ b/gcc/testsuite/g++.dg/init/member1.C
@@ -12,7 +12,7 @@  template<typename T> struct C
 {
   static const int i = A<T>::i;  // { dg-error "incomplete" }
   static const int j = i;
-  B<j> b;  // { dg-error "not a valid template arg" }
+  B<j> b;
 };
 
 C<int> c;
diff --git a/gcc/testsuite/g++.dg/parse/constant4.C b/gcc/testsuite/g++.dg/parse/constant4.C
index 4d9814f..a1be5dd 100644
--- a/gcc/testsuite/g++.dg/parse/constant4.C
+++ b/gcc/testsuite/g++.dg/parse/constant4.C
@@ -18,7 +18,7 @@  void Foo ()
   
   static const unsigned J = X<T>::J; // { dg-message "not initialized with a constant expression" }
   
-  Y<J> j; // { dg-error "constant" "" }
+  Y<J> j; // { dg-error "constant|template argument" "" }
 }
 
 struct A 
diff --git a/gcc/testsuite/g++.dg/template/nontype20.C b/gcc/testsuite/g++.dg/template/nontype20.C
new file mode 100644
index 0000000..e4aba32
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/nontype20.C
@@ -0,0 +1,11 @@ 
+// PR c++/48003
+// { dg-options "-fpermissive -w" }
+// Test that we allow integer overflow in constant exprs with -fpermissive
+
+template<int N>
+struct test
+{
+  typedef test<N - 1> prior;
+};
+
+test<-2147483647-1> f;
diff --git a/gcc/testsuite/g++.dg/template/qualified-id3.C b/gcc/testsuite/g++.dg/template/qualified-id3.C
index bbfb51e..c769a52 100644
--- a/gcc/testsuite/g++.dg/template/qualified-id3.C
+++ b/gcc/testsuite/g++.dg/template/qualified-id3.C
@@ -3,7 +3,7 @@ 
 template <const int N> struct A { };
 template <class T> struct B {
   static const int c; // { dg-message "not initialized with a constant expression" }
-  typedef A<B<T>::c> C;		// { dg-error "constant expression" }
+  typedef A<B<T>::c> C;	// { dg-error "constant expression|template argument" }
 };
 template <class T> const int B<T>::c = sizeof (T);
 
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/crash10.C b/gcc/testsuite/g++.old-deja/g++.pt/crash10.C
index af0e919..86f3861 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/crash10.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/crash10.C
@@ -5,6 +5,7 @@  class GCD {
 public:
   enum { val = (N == 0) ? M : GCD<N, M % N>::val }; // { dg-warning "division" "division" }
 // { dg-error "constant expression" "valid" { target *-*-* } 6 }
+// { dg-message "template argument" "valid" { target *-*-* } 6 }
 };
 
 int main() {
diff --git a/libstdc++-v3/testsuite/20_util/ratio/cons/cons_overflow_neg.cc b/libstdc++-v3/testsuite/20_util/ratio/cons/cons_overflow_neg.cc
index 51dcdac..ca91e46 100644
--- a/libstdc++-v3/testsuite/20_util/ratio/cons/cons_overflow_neg.cc
+++ b/libstdc++-v3/testsuite/20_util/ratio/cons/cons_overflow_neg.cc
@@ -51,7 +51,4 @@  test04()
 // { dg-error "instantiated from here" "" { target *-*-* } 46 }
 // { dg-error "denominator cannot be zero" "" { target *-*-* } 155 }
 // { dg-error "out of range" "" { target *-*-* } 156 }
-// { dg-error "non-constant expression" "" { target *-*-* } 61 }
-// { dg-error "overflow in constant expression" "" { target *-*-* } 61 }
-// { dg-error "not a member" "" { target *-*-* } 164 }
-// { dg-error "not a valid template argument" "" { target *-*-* } 166 }
+// { dg-error "overflow in constant expression" "" { target *-*-* } 74 }