Patchwork C++ PATCH for c++/47897 (failure with dependent static const)

login
register
mail settings
Submitter Jason Merrill
Date Feb. 27, 2011, 8:10 a.m.
Message ID <4D6A06FE.5060905@redhat.com>
Download mbox | patch
Permalink /patch/84679/
State New
Headers show

Comments

Jason Merrill - Feb. 27, 2011, 8:10 a.m.
potential_constant_expression needs to allow dependent variables that 
might have integral type when instantiated.  While I was touching that, 
I factored out the better diagnostics from cxx_eval_constant_expression 
so that we can have them in potential_constant_expression as well.

Tested x86_64-pc-linux-gnu, applied to trunk.
commit 1718f6f84c9d3795f9bd29cd2f51c50482f1fd8a
Author: Jason Merrill <jason@redhat.com>
Date:   Sat Feb 26 19:49:55 2011 -0500

    	PR c++/47897
    	* semantics.c (non_const_var_error): Split out from...
    	(cxx_eval_constant_expression): ...here.
    	(potential_constant_expression_1) [VAR_DECL]: Use it.
    	Allow dependent variables.

Patch

diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 199084a..a33a7ed 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -6704,6 +6704,46 @@  cxx_eval_indirect_ref (const constexpr_call *call, tree t,
   return r;
 }
 
+/* Complain about R, a VAR_DECL, not being usable in a constant expression.
+   Shared between potential_constant_expression and
+   cxx_eval_constant_expression.  */
+
+static void
+non_const_var_error (tree r)
+{
+  tree type = TREE_TYPE (r);
+  error ("the value of %qD is not usable in a constant "
+	 "expression", r);
+  if (DECL_DECLARED_CONSTEXPR_P (r))
+    inform (DECL_SOURCE_LOCATION (r),
+	    "%qD used in its own initializer", r);
+  else if (INTEGRAL_OR_ENUMERATION_TYPE_P (type))
+    {
+      if (!CP_TYPE_CONST_P (type))
+	inform (DECL_SOURCE_LOCATION (r),
+		"%q#D is not const", r);
+      else if (CP_TYPE_VOLATILE_P (type))
+	inform (DECL_SOURCE_LOCATION (r),
+		"%q#D is volatile", r);
+      else if (!DECL_INITIAL (r))
+	inform (DECL_SOURCE_LOCATION (r),
+		"%qD was not initialized with a constant "
+		"expression", r);
+      else
+	gcc_unreachable ();
+    }
+  else
+    {
+      if (cxx_dialect >= cxx0x && !DECL_DECLARED_CONSTEXPR_P (r))
+	inform (DECL_SOURCE_LOCATION (r),
+		"%qD was not declared %<constexpr%>", r);
+      else
+	inform (DECL_SOURCE_LOCATION (r),
+		"%qD does not have integral or enumeration type",
+		r);
+    }
+}
+
 /* Attempt to reduce the expression T to a constant value.
    On failure, issue diagnostic and return error_mark_node.  */
 /* FIXME unify with c_fully_fold */
@@ -6744,39 +6784,7 @@  cxx_eval_constant_expression (const constexpr_call *call, tree t,
       if (DECL_P (r))
 	{
 	  if (!allow_non_constant)
-	    {
-	      tree type = TREE_TYPE (r);
-	      error ("the value of %qD is not usable in a constant "
-		     "expression", r);
-	      if (DECL_DECLARED_CONSTEXPR_P (r))
-		inform (DECL_SOURCE_LOCATION (r),
-			"%qD used in its own initializer", r);
-	      else if (INTEGRAL_OR_ENUMERATION_TYPE_P (type))
-		{
-		  if (!CP_TYPE_CONST_P (type))
-		    inform (DECL_SOURCE_LOCATION (r),
-			    "%q#D is not const", r);
-		  else if (CP_TYPE_VOLATILE_P (type))
-		    inform (DECL_SOURCE_LOCATION (r),
-			    "%q#D is volatile", r);
-		  else if (!DECL_INITIAL (r))
-		    inform (DECL_SOURCE_LOCATION (r),
-			    "%qD was not initialized with a constant "
-			    "expression", r);
-		  else
-		    gcc_unreachable ();
-		}
-	      else
-		{
-		  if (cxx_dialect >= cxx0x && !DECL_DECLARED_CONSTEXPR_P (r))
-		    inform (DECL_SOURCE_LOCATION (r),
-			    "%qD was not declared %<constexpr%>", r);
-		  else
-		    inform (DECL_SOURCE_LOCATION (r),
-			    "%qD does not have integral or enumeration type",
-			    r);
-		}
-	    }
+	    non_const_var_error (r);
 	  *non_constant_p = true;
 	}
       break;
@@ -7371,10 +7379,11 @@  potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
       return potential_constant_expression_1 (TREE_OPERAND (t, 0), rval, flags);
 
     case VAR_DECL:
-      if (want_rval && !decl_constant_var_p (t))
+      if (want_rval && !decl_constant_var_p (t)
+	  && !dependent_type_p (TREE_TYPE (t)))
         {
           if (flags & tf_error)
-            error ("variable %qD is not declared constexpr", t);
+            non_const_var_error (t);
           return false;
         }
       return true;
diff --git a/gcc/testsuite/g++.dg/cpp0x/regress/debug-debug7.C b/gcc/testsuite/g++.dg/cpp0x/regress/debug-debug7.C
index 8ee8824..ea8f1eb 100644
--- a/gcc/testsuite/g++.dg/cpp0x/regress/debug-debug7.C
+++ b/gcc/testsuite/g++.dg/cpp0x/regress/debug-debug7.C
@@ -7,8 +7,8 @@  int
 main() {
 
   int a = 4;
-  int b = 5;
-  int (*x)[b] = new int[a][b]; // { dg-error "" }
+  int b = 5;			// { dg-message "not const" }
+  int (*x)[b] = new int[a][b];	// { dg-error "not usable" }
 
   x[2][1] = 7;
 
diff --git a/gcc/testsuite/g++.dg/cpp0x/regress/template-const1.C b/gcc/testsuite/g++.dg/cpp0x/regress/template-const1.C
new file mode 100644
index 0000000..32db1f8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/regress/template-const1.C
@@ -0,0 +1,9 @@ 
+// PR c++/47897
+// { dg-options -std=c++0x }
+
+template < typename T, T N >
+struct S
+{
+    static const T value = N;
+    typedef S< T, value + 1 > next;
+};
diff --git a/gcc/testsuite/g++.dg/cpp0x/regress/template-function1.C b/gcc/testsuite/g++.dg/cpp0x/regress/template-function1.C
index 028669e..66cbd4b 100644
--- a/gcc/testsuite/g++.dg/cpp0x/regress/template-function1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/regress/template-function1.C
@@ -1,28 +1,29 @@ 
 // PR c++/38647
 // { dg-do compile }
 // { dg-options "-std=c++0x" }
+// { dg-prune-output "note" }
 
 template<const char *, int> struct A {};
 const char func[] = "abc";
-template<int N> struct A<func, N> {};	// { dg-error "cannot appear|is invalid|not a valid|not declared constexpr" }
+template<int N> struct A<func, N> {};	// { dg-error "cannot appear|is invalid|not a valid|constant expression" }
 
 char a1[1];
 A<a1, 0> a;
 
 template<const char *, int> struct B {};
-template<int N> struct B<__FUNCTION__, N> {};	// { dg-error "cannot appear|is invalid|is not a valid|not declared constexpr" }
+template<int N> struct B<__FUNCTION__, N> {};	// { dg-error "cannot appear|is invalid|is not a valid|constant expression" }
 
 char b1[1];
 B<b1, 0> b;
 
 template<const char *, int> struct C {};
-template<int N> struct C<__PRETTY_FUNCTION__, N> {};	// { dg-error "cannot appear|is invalid|is not a valid|not declared constexpr" }
+template<int N> struct C<__PRETTY_FUNCTION__, N> {};	// { dg-error "cannot appear|is invalid|is not a valid|constant expression" }
 
 char c1[1];
 C<c1, 0> c;
 
 template<const char *, int> struct D {};
-template<int N> struct D<__func__, N> {};	// { dg-error "cannot appear|is invalid|is not a valid|function scope|not declared constexpr" }
+template<int N> struct D<__func__, N> {};	// { dg-error "cannot appear|is invalid|is not a valid|function scope|constant expression" }
 
 char d1[1];
 D<d1, 0> d;
diff --git a/gcc/testsuite/g++.dg/debug/debug7.C b/gcc/testsuite/g++.dg/debug/debug7.C
index 31d47ed..8731cf8 100644
--- a/gcc/testsuite/g++.dg/debug/debug7.C
+++ b/gcc/testsuite/g++.dg/debug/debug7.C
@@ -1,4 +1,5 @@ 
 // { dg-do compile }
+// { dg-prune-output "note" }
 
 void f (int);
 
diff --git a/gcc/testsuite/g++.dg/template/function1.C b/gcc/testsuite/g++.dg/template/function1.C
index 8a112c1..bceed9d 100644
--- a/gcc/testsuite/g++.dg/template/function1.C
+++ b/gcc/testsuite/g++.dg/template/function1.C
@@ -1,27 +1,28 @@ 
 // PR c++/38647
 // { dg-do compile }
+// { dg-prune-output "note" }
 
 template<const char *, int> struct A {};
 const char func[] = "abc";
-template<int N> struct A<func, N> {};	// { dg-error "cannot appear|is invalid|not a valid|not declared constexpr" }
+template<int N> struct A<func, N> {};	// { dg-error "cannot appear|is invalid|not a valid|constant expression" }
 
 char a1[1];
 A<a1, 0> a;
 
 template<const char *, int> struct B {};
-template<int N> struct B<__FUNCTION__, N> {};	// { dg-error "cannot appear|is invalid|is not a valid|not declared constexpr" }
+template<int N> struct B<__FUNCTION__, N> {};	// { dg-error "cannot appear|is invalid|is not a valid|constant expression" }
 
 char b1[1];
 B<b1, 0> b;
 
 template<const char *, int> struct C {};
-template<int N> struct C<__PRETTY_FUNCTION__, N> {};	// { dg-error "cannot appear|is invalid|is not a valid|not declared constexpr" }
+template<int N> struct C<__PRETTY_FUNCTION__, N> {};	// { dg-error "cannot appear|is invalid|is not a valid|constant expression" }
 
 char c1[1];
 C<c1, 0> c;
 
 template<const char *, int> struct D {};
-template<int N> struct D<__func__, N> {};	// { dg-error "cannot appear|is invalid|is not a valid|function scope|not declared constexpr" }
+template<int N> struct D<__func__, N> {};	// { dg-error "cannot appear|is invalid|is not a valid|function scope|constant expression" }
 
 char d1[1];
 D<d1, 0> d;