diff options
author | Jason Merrill <jason@redhat.com> | 2011-09-05 00:33:08 -0400 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2011-09-05 00:33:08 -0400 |
commit | aee8801251cc3fd10dc12e4fc48a0d0bc5f37019 (patch) | |
tree | d41708befc760369af40f5ad47e802f104006409 /gcc/cp | |
parent | e818d3ff6869ccfe551e999cbe270266ff1c33ec (diff) | |
download | gcc-aee8801251cc3fd10dc12e4fc48a0d0bc5f37019.zip gcc-aee8801251cc3fd10dc12e4fc48a0d0bc5f37019.tar.gz gcc-aee8801251cc3fd10dc12e4fc48a0d0bc5f37019.tar.bz2 |
re PR c++/50248 ([C++0x] unnecessary instantiation of constexpr constructor)
PR c++/50248
Core 1358
* init.c (perform_member_init): Don't diagnose missing inits here.
(emit_mem_initializers): Or here.
* method.c (process_subob_fn): Don't instantiate constexpr ctors.
* semantics.c (cx_check_missing_mem_inits): New.
(explain_invalid_constexpr_fn): Call it.
(register_constexpr_fundef): Likewise. Leave
DECL_DECLARED_CONSTEXPR_P set when the body is unsuitable.
(cxx_eval_call_expression): Adjust diagnostics.
(cxx_eval_constant_expression): Catch use of 'this' in a constructor.
From-SVN: r178518
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/ChangeLog | 14 | ||||
-rw-r--r-- | gcc/cp/init.c | 19 | ||||
-rw-r--r-- | gcc/cp/method.c | 21 | ||||
-rw-r--r-- | gcc/cp/semantics.c | 80 |
4 files changed, 95 insertions, 39 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 96ac237..a83d19b 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,17 @@ +2011-09-04 Jason Merrill <jason@redhat.com> + + PR c++/50248 + Core 1358 + * init.c (perform_member_init): Don't diagnose missing inits here. + (emit_mem_initializers): Or here. + * method.c (process_subob_fn): Don't instantiate constexpr ctors. + * semantics.c (cx_check_missing_mem_inits): New. + (explain_invalid_constexpr_fn): Call it. + (register_constexpr_fundef): Likewise. Leave + DECL_DECLARED_CONSTEXPR_P set when the body is unsuitable. + (cxx_eval_call_expression): Adjust diagnostics. + (cxx_eval_constant_expression): Catch use of 'this' in a constructor. + 2011-08-30 Jason Merrill <jason@redhat.com> PR c++/50084 diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 847f519..ff1884b 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -606,15 +606,6 @@ perform_member_init (tree member, tree init) core_type = strip_array_types (type); - if (DECL_DECLARED_CONSTEXPR_P (current_function_decl) - && !type_has_constexpr_default_constructor (core_type)) - { - if (!DECL_TEMPLATE_INSTANTIATION (current_function_decl)) - error ("uninitialized member %qD in %<constexpr%> constructor", - member); - DECL_DECLARED_CONSTEXPR_P (current_function_decl) = false; - } - if (CLASS_TYPE_P (core_type) && (CLASSTYPE_READONLY_FIELDS_NEED_INIT (core_type) || CLASSTYPE_REF_FIELDS_NEED_INIT (core_type))) @@ -962,16 +953,6 @@ emit_mem_initializers (tree mem_inits) OPT_Wextra, "base class %q#T should be explicitly " "initialized in the copy constructor", BINFO_TYPE (subobject)); - - if (DECL_DECLARED_CONSTEXPR_P (current_function_decl) - && !(type_has_constexpr_default_constructor - (BINFO_TYPE (subobject)))) - { - if (!DECL_TEMPLATE_INSTANTIATION (current_function_decl)) - error ("uninitialized base %qT in %<constexpr%> constructor", - BINFO_TYPE (subobject)); - DECL_DECLARED_CONSTEXPR_P (current_function_decl) = false; - } } /* Initialize the base. */ diff --git a/gcc/cp/method.c b/gcc/cp/method.c index 3d272a3..74a3bdb 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -952,23 +952,14 @@ process_subob_fn (tree fn, bool move_p, tree *spec_p, bool *trivial_p, goto bad; } - if (constexpr_p) + if (constexpr_p && !DECL_DECLARED_CONSTEXPR_P (fn)) { - /* If this is a specialization of a constexpr template, we need to - force the instantiation now so that we know whether or not it's - really constexpr. */ - if (DECL_DECLARED_CONSTEXPR_P (fn) && DECL_TEMPLATE_INSTANTIATION (fn) - && !DECL_TEMPLATE_INSTANTIATED (fn)) - instantiate_decl (fn, /*defer_ok*/false, /*expl_class*/false); - if (!DECL_DECLARED_CONSTEXPR_P (fn)) + *constexpr_p = false; + if (msg) { - *constexpr_p = false; - if (msg) - { - inform (0, "defaulted constructor calls non-constexpr " - "%q+D", fn); - explain_invalid_constexpr_fn (fn); - } + inform (0, "defaulted constructor calls non-constexpr " + "%q+D", fn); + explain_invalid_constexpr_fn (fn); } } diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index ce84062..fd96d70 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -5775,6 +5775,53 @@ massage_constexpr_body (tree fun, tree body) return body; } +/* FUN is a constexpr constructor with massaged body BODY. Return true + if some bases/fields are uninitialized, and complain if COMPLAIN. */ + +static bool +cx_check_missing_mem_inits (tree fun, tree body, bool complain) +{ + bool bad; + tree field; + unsigned i, nelts; + + if (TREE_CODE (body) != CONSTRUCTOR) + return false; + + bad = false; + nelts = CONSTRUCTOR_NELTS (body); + field = TYPE_FIELDS (DECL_CONTEXT (fun)); + for (i = 0; i <= nelts; ++i) + { + tree index; + if (i == nelts) + index = NULL_TREE; + else + { + index = CONSTRUCTOR_ELT (body, i)->index; + /* Skip base vtable inits. */ + if (TREE_CODE (index) == COMPONENT_REF) + continue; + } + for (; field != index; field = DECL_CHAIN (field)) + { + if (TREE_CODE (field) != FIELD_DECL + || (DECL_C_BIT_FIELD (field) && !DECL_NAME (field))) + continue; + if (!complain) + return true; + error ("uninitialized member %qD in %<constexpr%> constructor", + field); + bad = true; + } + if (field == NULL_TREE) + break; + field = DECL_CHAIN (field); + } + + return bad; +} + /* We are processing the definition of the constexpr function FUN. Check that its BODY fulfills the propriate requirements and enter it in the constexpr function definition table. @@ -5797,12 +5844,15 @@ register_constexpr_fundef (tree fun, tree body) if (!potential_rvalue_constant_expression (body)) { - DECL_DECLARED_CONSTEXPR_P (fun) = false; if (!DECL_TEMPLATE_INFO (fun)) require_potential_rvalue_constant_expression (body); return NULL; } + if (DECL_CONSTRUCTOR_P (fun) + && cx_check_missing_mem_inits (fun, body, !DECL_TEMPLATE_INFO (fun))) + return NULL; + /* Create the constexpr function table if necessary. */ if (constexpr_fundef_table == NULL) constexpr_fundef_table = htab_create_ggc (101, @@ -5842,8 +5892,7 @@ explain_invalid_constexpr_fn (tree fun) save_loc = input_location; input_location = DECL_SOURCE_LOCATION (fun); - inform (0, "%q+D is not constexpr because it does not satisfy the " - "requirements:", fun); + inform (0, "%q+D is not usable as a constexpr function because:", fun); /* First check the declaration. */ if (is_valid_constexpr_fn (fun, true)) { @@ -5854,6 +5903,8 @@ explain_invalid_constexpr_fn (tree fun) { body = massage_constexpr_body (fun, DECL_SAVED_TREE (fun)); require_potential_rvalue_constant_expression (body); + if (DECL_CONSTRUCTOR_P (fun)) + cx_check_missing_mem_inits (fun, body, true); } } input_location = save_loc; @@ -6203,7 +6254,16 @@ cxx_eval_call_expression (const constexpr_call *old_call, tree t, if (new_call.fundef == NULL || new_call.fundef->body == NULL) { if (!allow_non_constant) - error_at (loc, "%qD used before its definition", fun); + { + if (DECL_SAVED_TREE (fun)) + { + /* The definition of fun was somehow unsuitable. */ + error_at (loc, "%qD called in a constant expression", fun); + explain_invalid_constexpr_fn (fun); + } + else + error_at (loc, "%qD used before its definition", fun); + } *non_constant_p = true; return t; } @@ -7176,7 +7236,17 @@ cxx_eval_constant_expression (const constexpr_call *call, tree t, case PARM_DECL: if (call && DECL_CONTEXT (t) == call->fundef->decl) - r = lookup_parameter_binding (call, t); + { + if (DECL_ARTIFICIAL (t) && DECL_CONSTRUCTOR_P (DECL_CONTEXT (t))) + { + if (!allow_non_constant) + sorry ("use of the value of the object being constructed " + "in a constant expression"); + *non_constant_p = true; + } + else + r = lookup_parameter_binding (call, t); + } else if (addr) /* Defer in case this is only used for its type. */; else |