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" }

Reply via email to