Hi,
On 03/11/2014 02:10 PM, Jason Merrill wrote:
On 03/11/2014 08:03 AM, Paolo Carlini wrote:
+ if (DECL_INHERITED_CTOR_BASE (fun)
+ && TREE_CODE (fun) == TEMPLATE_DECL)
+ {
+ ret = false;
+ if (complain)
+ error ("inherited constructors inherit %<constexpr%> from "
+ "the designated base");
+ }
To correct my wording, the B constructor is the inheriting
constructor, the inherited constructor is in A.
Let's look up the inherited constructor here and print it to be
helpful. Probably the easiest way to find it will be to add a new
entry point to locate_fn_flags so we call it with
(DECL_INHERITED_CTOR_BASE (fun), DECL_NAME (fun),
FUNCTION_FIRST_USER_PARMTYPE (fun), LOOKUP_NORMAL|LOOKUP_SPECULATIVE,
complain)
Then we can say "inherited constructor %qD is not constexpr".
I see. The below tries to implement the above (note:
complete_ctor_identifier; push_deferring_access_checks, otherwise for a
similar testcase inheriting from class A we produce duplicate diagnostic
about accessibility). Tested x86_64-linux.
Thanks,
Paolo.
PS: I think we should also be more careful about inform vs error, but
probably not at this Stage...
Index: cp/cp-tree.h
===================================================================
--- cp/cp-tree.h (revision 208474)
+++ cp/cp-tree.h (working copy)
@@ -5476,6 +5476,7 @@ extern tree get_copy_ctor (tree,
tsubst_flags_t)
extern tree get_copy_assign (tree);
extern tree get_default_ctor (tree);
extern tree get_dtor (tree, tsubst_flags_t);
+extern tree get_inherited_ctor (tree);
extern tree locate_ctor (tree);
extern tree implicitly_declare_fn (special_function_kind, tree,
bool, tree, tree);
Index: cp/method.c
===================================================================
--- cp/method.c (revision 208474)
+++ cp/method.c (working copy)
@@ -971,6 +971,25 @@ get_copy_assign (tree type)
return fn;
}
+/* Locate the inherited constructor of constructor CTOR. */
+
+tree
+get_inherited_ctor (tree ctor)
+{
+ gcc_assert (DECL_INHERITED_CTOR_BASE (ctor));
+
+ push_deferring_access_checks (dk_no_check);
+ tree fn = locate_fn_flags (DECL_INHERITED_CTOR_BASE (ctor),
+ complete_ctor_identifier,
+ FUNCTION_FIRST_USER_PARMTYPE (ctor),
+ LOOKUP_NORMAL|LOOKUP_SPECULATIVE,
+ tf_none);
+ pop_deferring_access_checks ();
+ if (fn == error_mark_node)
+ return NULL_TREE;
+ return fn;
+}
+
/* Subroutine of synthesized_method_walk. Update SPEC_P, TRIVIAL_P and
DELETED_P or give an error message MSG with argument ARG. */
Index: cp/semantics.c
===================================================================
--- cp/semantics.c (revision 208474)
+++ cp/semantics.c (working copy)
@@ -7438,19 +7438,31 @@ retrieve_constexpr_fundef (tree fun)
static bool
is_valid_constexpr_fn (tree fun, bool complain)
{
- tree parm = FUNCTION_FIRST_USER_PARM (fun);
bool ret = true;
- for (; parm != NULL; parm = TREE_CHAIN (parm))
- if (!literal_type_p (TREE_TYPE (parm)))
- {
- ret = false;
- if (complain)
+
+ if (DECL_INHERITED_CTOR_BASE (fun)
+ && TREE_CODE (fun) == TEMPLATE_DECL)
+ {
+ ret = false;
+ if (complain)
+ error ("inherited constructor %qD is not constexpr",
+ get_inherited_ctor (fun));
+ }
+ else
+ {
+ for (tree parm = FUNCTION_FIRST_USER_PARM (fun);
+ parm != NULL_TREE; parm = TREE_CHAIN (parm))
+ if (!literal_type_p (TREE_TYPE (parm)))
{
- error ("invalid type for parameter %d of constexpr "
- "function %q+#D", DECL_PARM_INDEX (parm), fun);
- explain_non_literal_class (TREE_TYPE (parm));
+ ret = false;
+ if (complain)
+ {
+ error ("invalid type for parameter %d of constexpr "
+ "function %q+#D", DECL_PARM_INDEX (parm), fun);
+ explain_non_literal_class (TREE_TYPE (parm));
+ }
}
- }
+ }
if (!DECL_CONSTRUCTOR_P (fun))
{
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 "inherited" }
+};
+
+constexpr B b; // { dg-error "literal" }