aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2011-09-05 00:33:08 -0400
committerJason Merrill <jason@gcc.gnu.org>2011-09-05 00:33:08 -0400
commitaee8801251cc3fd10dc12e4fc48a0d0bc5f37019 (patch)
treed41708befc760369af40f5ad47e802f104006409 /gcc/cp
parente818d3ff6869ccfe551e999cbe270266ff1c33ec (diff)
downloadgcc-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/ChangeLog14
-rw-r--r--gcc/cp/init.c19
-rw-r--r--gcc/cp/method.c21
-rw-r--r--gcc/cp/semantics.c80
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