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++/70528 (mutual dependence error)


The problem with this testcase was that in order to determine whether J is a literal type, we needed to implicitly declare its default constructor, which calls the H default constructor, and instantiating the template arguments for H() requires the K default constructor, which needs the First default mem-initializer, which we haven't parsed yet.

We can break this chain by just treating the implicitly-declared default constructor as constexpr. This doesn't break anything in the regression testsuite: tests for non-literal type diagnostics still pass, just because of a member/base type being non-literal rather than because of the default constructor, which actually produces better diagnostics.

This is also a direction that Core has been discussing; the notion of literal type is only a convenience for diagnostics, it's not important to get it right at the cost of excessive instantiation.

Tested x86_64-pc-linux-gnu, applying to trunk.
commit 743489d435da4976c6ecdd66468b85b3ef9a1968
Author: Jason Merrill <jason@redhat.com>
Date:   Thu Apr 7 07:45:03 2016 -0400

    	PR c++/70528
    
    	* class.c (type_has_constexpr_default_constructor): Return true
    	for an implicitly declared constructor.

diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 02a992f..e6d5bb0 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -3346,7 +3346,6 @@ add_implicitly_declared_members (tree t, tree* access_decls,
       CLASSTYPE_LAZY_DEFAULT_CTOR (t) = 1;
       if (cxx_dialect >= cxx11)
 	TYPE_HAS_CONSTEXPR_CTOR (t)
-	  /* This might force the declaration.  */
 	  = type_has_constexpr_default_constructor (t);
     }
 
@@ -5349,8 +5348,11 @@ type_has_constexpr_default_constructor (tree t)
     {
       if (!TYPE_HAS_COMPLEX_DFLT (t))
 	return trivial_default_constructor_is_constexpr (t);
-      /* Non-trivial, we need to check subobject constructors.  */
-      lazily_declare_fn (sfk_constructor, t);
+      /* Assume it's constexpr to avoid unnecessary instantiation; if the
+	 definition would have made the class non-literal, it will still be
+	 non-literal because of the base or member in question, and that
+	 gives a better diagnostic.  */
+      return true;
     }
   fns = locate_ctor (t);
   return (fns && DECL_DECLARED_CONSTEXPR_P (fns));
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor12.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor12.C
index 45e1ed2..42ca30a 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor12.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor12.C
@@ -3,6 +3,7 @@
 
 template <typename Tp>
 struct C {
+  C() = default;
   constexpr C(const Tp& r) { }
 };
 
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-default-ctor.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-default-ctor.C
index a67505d..8d352d0 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-default-ctor.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-default-ctor.C
@@ -7,6 +7,6 @@ struct A {
 struct B: A { };
 constexpr int f(B b) { return b.i; }
 
-struct C { C(); };	       // { dg-message "calls non-constexpr" }
-struct D: C { };	       // { dg-message "no constexpr constructor" }
+struct C { C(); };	       // { dg-message "" }
+struct D: C { };	       // { dg-message "" }
 constexpr int g(D d) { return 42; } // { dg-error "invalid type" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ice6.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ice6.C
index 30e0a64..bf95b24 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-ice6.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ice6.C
@@ -6,6 +6,6 @@ struct A
   A(int);
 };
 
-struct B : A {};                   // { dg-error "no matching" }
+struct B : A {};                   // { dg-message "" }
 
 constexpr int foo(B) { return 0; } // { dg-error "invalid type" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/inh-ctor19.C b/gcc/testsuite/g++.dg/cpp0x/inh-ctor19.C
index 7a22f88..7e2d58b 100644
--- a/gcc/testsuite/g++.dg/cpp0x/inh-ctor19.C
+++ b/gcc/testsuite/g++.dg/cpp0x/inh-ctor19.C
@@ -8,7 +8,7 @@ struct A
 
 struct B : A
 {
-  using A::A;   // { dg-error "inherited" }
+  using A::A;
 };
 
 constexpr B b;  // { dg-error "literal" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr70528.C b/gcc/testsuite/g++.dg/cpp0x/pr70528.C
new file mode 100644
index 0000000..af1c84e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/pr70528.C
@@ -0,0 +1,16 @@
+// PR c++/70258
+// { dg-do compile { target c++11 } }
+
+template <class T>
+struct H
+{
+  template <typename A = T, typename = decltype (A())>
+  H ();
+};
+
+struct J {
+  struct K {
+    int First = 0;
+  };
+  H<K> FunctionMDInfo;
+};

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