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 <ja...@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 --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 }