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 <ja...@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;
+};