This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

C++ PATCH for c++/62255 (error with recursive instantiation of static data member constant)


In this testcase, asking for the value of the static data member involves instantiating Derived in order to look up X::Type, which instantiation depends on the value of the static data member. But the recursion ends there, since the second time through we just try to look it up in the partially-complete Derived, so we should be able to accept this like we did in 4.7 and before.

Tested x86_64-pc-linux-gnu, applying to trunk.
commit d3725c29769d3d96e40940d2636fd6d0a6be31fc
Author: Jason Merrill <jason@redhat.com>
Date:   Mon Sep 8 14:14:04 2014 -0400

    	PR c++/62255
    	* pt.c (instantiate_decl): Handle recursive instantiation of
    	static data member.

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 5ea5a58..38093ec 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -19996,13 +19996,18 @@ instantiate_decl (tree d, int defer_ok,
 			      args,
 			      tf_warning_or_error, NULL_TREE,
 			      /*integral_constant_expression_p=*/false);
-	  /* Make sure the initializer is still constant, in case of
-	     circular dependency (template/instantiate6.C). */
-	  const_init
-	    = DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (code_pattern);
-	  cp_finish_decl (d, init, /*init_const_expr_p=*/const_init,
-			  /*asmspec_tree=*/NULL_TREE,
-			  LOOKUP_ONLYCONVERTING);
+	  /* If instantiating the initializer involved instantiating this
+	     again, don't call cp_finish_decl twice.  */
+	  if (!DECL_INITIAL (d))
+	    {
+	      /* Make sure the initializer is still constant, in case of
+		 circular dependency (template/instantiate6.C). */
+	      const_init
+		= DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (code_pattern);
+	      cp_finish_decl (d, init, /*init_const_expr_p=*/const_init,
+			      /*asmspec_tree=*/NULL_TREE,
+			      LOOKUP_ONLYCONVERTING);
+	    }
 	  if (enter_context)
 	    pop_nested_class ();
 	  pop_nested_namespace (ns);
diff --git a/gcc/testsuite/g++.dg/template/recurse4.C b/gcc/testsuite/g++.dg/template/recurse4.C
new file mode 100644
index 0000000..ee8d1b7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/recurse4.C
@@ -0,0 +1,18 @@
+// PR c++/62255
+
+// It's not clear whether this is well-formed; instantiating the
+// initializer of 'value' causes the instantiation of Derived, which in
+// turn requires the value of 'value', but the recursion ends there, so it
+// seems reasonable to allow it.
+
+template <typename T> struct Test {
+  template<typename X> static int check(typename X::Type*);
+  template<typename> static char check(...);
+  static const bool value = (sizeof(check<T>(0)) == sizeof(int));
+};
+template <int> struct Sink { };
+template <typename T> struct Derived : Sink<Test<Derived<T> >::value> {
+  typedef int Type;
+};
+
+Sink<Test<Derived<int> >::value> s;

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]