@@ -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
@@ -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))
{
@@ -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;
@@ -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
new file mode 100644
@@ -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;
@@ -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);
@@ -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() {
@@ -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 }