Hi,
this regression is just an ICE on invalid, but I'm finding it somewhat
tricky. Let's see if I can explain clearly enough what I figured out so far.
The problem manifests itself when is_valid_constexpr_fn is called by
explain_invalid_constexpr_fn with a TEMPLATE_DECL (the inherited
template constructor) as the fun argument and FUNCTION_FIRST_USER_PARM
cannot be used on it. This happens because explain_invalid_constexpr_fn
(called from the second half of explain_non_literal_class) doesn't early
return via:
/* Only diagnose defaulted functions or instantiations. */
if (!DECL_DEFAULTED_FN (fun)
&& !is_instantiation_of_constexpr (fun))
return;
because we internally represent inherited *template* constructors too as
defaulted. Thus, the idea of handling those specially per the first
draft I'm attaching. In fact, note that if we try to fix up
is_valid_constexpr_fn (like in the second draft I'm attaching below), we
get a final error message of the form
60389.C:13:12: note: ‘template<class ... T> B::B(T ...)’ is not usable
as a constexpr function because:
using A::A;
^
60389.C:13:12: error: invalid type for parameter 1 of constexpr function
‘template<class ... T> B::B(T ...)’
which I find quite confusing, because that parameter is a
TYPE_PACK_EXPANSION (for which the literal_type_p check in
is_valid_constexpr_fn returns false) but in fact a B::B() is needed...
Note, moreover, that if the user tries to "force" the compilation by
simply declaring the A::A(T...) constructor explicitly constexpr, the
compilation in fact succeeds (at least, with GCC ;) and that doesn't
appear to make much sense vs the latter error message. So, what shall we
do? Just patch 1 (with a comment explaining the early return)? Or Patch
2 and reconsider these issues later? Or something else?
Thanks!
Paolo.
/////////////////////////
Index: cp/semantics.c
===================================================================
--- cp/semantics.c (revision 208317)
+++ cp/semantics.c (working copy)
@@ -8002,7 +8002,9 @@ explain_invalid_constexpr_fn (tree fun)
tree body;
location_t save_loc;
/* Only diagnose defaulted functions or instantiations. */
- if (!DECL_DEFAULTED_FN (fun)
+ if ((!DECL_DEFAULTED_FN (fun)
+ || (DECL_INHERITED_CTOR_BASE (fun)
+ && TREE_CODE (fun) == TEMPLATE_DECL))
&& !is_instantiation_of_constexpr (fun))
return;
if (diagnosed == NULL)
Index: testsuite/g++.dg/cpp0x/inh-ctor19.C
===================================================================
--- testsuite/g++.dg/cpp0x/inh-ctor19.C (revision 0)
+++ testsuite/g++.dg/cpp0x/inh-ctor19.C (working copy)
@@ -0,0 +1,14 @@
+// PR c++/60389
+// { dg-do compile { target c++11 } }
+
+struct A
+{
+ template<typename...T> A(T...) {}
+};
+
+struct B : A
+{
+ using A::A;
+};
+
+constexpr B b; // { dg-error "literal" }
Index: cp/semantics.c
===================================================================
--- cp/semantics.c (revision 208317)
+++ cp/semantics.c (working copy)
@@ -7430,7 +7430,7 @@ retrieve_constexpr_fundef (tree fun)
static bool
is_valid_constexpr_fn (tree fun, bool complain)
{
- tree parm = FUNCTION_FIRST_USER_PARM (fun);
+ tree parm = FUNCTION_FIRST_USER_PARM (STRIP_TEMPLATE (fun));
bool ret = true;
for (; parm != NULL; parm = TREE_CHAIN (parm))
if (!literal_type_p (TREE_TYPE (parm)))
Index: testsuite/g++.dg/cpp0x/inh-ctor19.C
===================================================================
--- testsuite/g++.dg/cpp0x/inh-ctor19.C (revision 0)
+++ testsuite/g++.dg/cpp0x/inh-ctor19.C (working copy)
@@ -0,0 +1,14 @@
+// PR c++/60389
+// { dg-do compile { target c++11 } }
+
+struct A
+{
+ template<typename...T> A(T...) {}
+};
+
+struct B : A
+{
+ using A::A; // { dg-error "invalid type" }
+};
+
+constexpr B b; // { dg-error "literal" }