Patchwork C++ PATCH for c++/47207 (ICE on constexpr var in own init)

login
register
mail settings
Submitter Jason Merrill
Date Feb. 21, 2011, 3:34 p.m.
Message ID <4D628601.1090207@redhat.com>
Download mbox | patch
Permalink /patch/83851/
State New
Headers show

Comments

Jason Merrill - Feb. 21, 2011, 3:34 p.m.
Here decl_constant_var_p was asserting that a constexpr variable is 
always usable as a constant, which is not the case if it's used in its 
own initializer.

Tested x86_64-pc-linux-gnu, applied to trunk.
commit 54c825f1ac61ada5551de1610ac15198f920b885
Author: Jason Merrill <jason@redhat.com>
Date:   Mon Feb 21 09:56:11 2011 -0500

    	PR c++/47207
    	* decl2.c (decl_constant_var_p): A constexpr var needs an
    	initializer to be constant.
    	* semantics.c (cxx_eval_constant_expression): Complain about
    	constexpr var used in its own initializer.
    	* call.c (set_up_extended_ref_temp): Set
    	DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P too.

Patch

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 078542a..8dccbbe 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -8149,6 +8149,7 @@  set_up_extended_ref_temp (tree decl, tree expr, tree *cleanup, tree *initp)
 	     Currently this is only useful for initializer_list temporaries,
 	     since reference vars can't appear in constant expressions.  */
 	  DECL_DECLARED_CONSTEXPR_P (var) = true;
+	  DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (var) = true;
 	  TREE_CONSTANT (var) = true;
 	}
       DECL_INITIAL (var) = init;
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index a4b7dfa..93d44a4 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -3550,20 +3550,21 @@  decl_constant_var_p (tree decl)
   tree type = TREE_TYPE (decl);
   if (TREE_CODE (decl) != VAR_DECL)
     return false;
-  if (DECL_DECLARED_CONSTEXPR_P (decl))
-    ret = true;
-  else if (CP_TYPE_CONST_NON_VOLATILE_P (type)
-	   && INTEGRAL_OR_ENUMERATION_TYPE_P (type))
+  if (DECL_DECLARED_CONSTEXPR_P (decl)
+      || (CP_TYPE_CONST_NON_VOLATILE_P (type)
+	  && INTEGRAL_OR_ENUMERATION_TYPE_P (type)))
     {
       /* We don't know if a template static data member is initialized with
-	 a constant expression until we instantiate its initializer.  */
+	 a constant expression until we instantiate its initializer.  Even
+	 in the case of a constexpr variable, we can't treat it as a
+	 constant until its initializer is complete in case it's used in
+	 its own initializer.  */
       mark_used (decl);
       ret = DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl);
     }
   else
     ret = false;
 
-  gcc_assert (!ret || DECL_INITIAL (decl));
   return ret;
 }
 
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index b7ed525..6a9c6a0 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -6768,7 +6768,10 @@  cxx_eval_constant_expression (const constexpr_call *call, tree t,
 	      tree type = TREE_TYPE (r);
 	      error ("the value of %qD is not usable in a constant "
 		     "expression", r);
-	      if (INTEGRAL_OR_ENUMERATION_TYPE_P (type))
+	      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),
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-diag2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-diag2.C
new file mode 100644
index 0000000..c78416e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-diag2.C
@@ -0,0 +1,5 @@ 
+// PR c++/47207
+// { dg-options -std=c++0x }
+
+constexpr int X (X);		// { dg-error "not usable" }
+// { dg-message "own initializer" "" { target *-*-* } 4 }