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
This commit is contained in:
parent
e818d3ff68
commit
aee8801251
@ -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
|
||||
|
@ -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. */
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -1,3 +1,12 @@
|
||||
2011-09-04 Jason Merrill <jason@redhat.com>
|
||||
|
||||
PR c++/50248
|
||||
Core 1358
|
||||
* g++.dg/cpp0x/constexpr-template1.C: New.
|
||||
* g++.dg/cpp0x/constexpr-template2.C: New.
|
||||
* g++.dg/cpp0x/constexpr-48089.C: Adjust error markup.
|
||||
* g++.dg/cpp0x/constexpr-ex1.C: Adjust error markup.
|
||||
|
||||
2011-09-04 Eric Botcazou <ebotcazou@adacore.com>
|
||||
|
||||
* gnat.dg/specs/debug1.ads: Tweak pattern.
|
||||
|
@ -14,7 +14,7 @@ struct s {
|
||||
int v;
|
||||
};
|
||||
|
||||
constexpr s bang; // { dg-error "" }
|
||||
constexpr s bang; // { dg-message "" }
|
||||
|
||||
struct R {
|
||||
int i,j;
|
||||
@ -33,7 +33,7 @@ struct T {
|
||||
|
||||
constexpr T t1;
|
||||
// Ill-formed (diagnostic required)
|
||||
constexpr T t2(t1); // { dg-error "" }
|
||||
constexpr T t2(t1); // { dg-message "" }
|
||||
|
||||
// Well-formed
|
||||
struct U {
|
||||
|
@ -89,6 +89,6 @@ struct resource {
|
||||
};
|
||||
constexpr resource f(resource d)
|
||||
{ return d; } // { dg-error "non-constexpr" }
|
||||
constexpr resource d = f(9); // { dg-error "resource" }
|
||||
constexpr resource d = f(9); // { dg-message "constexpr" }
|
||||
|
||||
// 4.4 floating-point constant expressions
|
||||
|
27
gcc/testsuite/g++.dg/cpp0x/constexpr-template1.C
Normal file
27
gcc/testsuite/g++.dg/cpp0x/constexpr-template1.C
Normal file
@ -0,0 +1,27 @@
|
||||
// PR c++/50248, DR 1358
|
||||
// { dg-options -std=c++0x }
|
||||
|
||||
template<class Elt, unsigned max>
|
||||
struct earray
|
||||
{
|
||||
Elt elts[max];
|
||||
earray() = default;
|
||||
template<typename... Elt2>
|
||||
constexpr earray(Elt2&& ... e): elts(0) { }
|
||||
};
|
||||
|
||||
struct SessionData
|
||||
{
|
||||
SessionData(SessionData&) = delete;
|
||||
SessionData() = default;
|
||||
};
|
||||
|
||||
struct MapSessionData : SessionData
|
||||
{
|
||||
earray<short, 11> equip_index;
|
||||
};
|
||||
|
||||
void test()
|
||||
{
|
||||
MapSessionData *sd = new MapSessionData;
|
||||
}
|
12
gcc/testsuite/g++.dg/cpp0x/constexpr-template2.C
Normal file
12
gcc/testsuite/g++.dg/cpp0x/constexpr-template2.C
Normal file
@ -0,0 +1,12 @@
|
||||
// { dg-options -std=c++0x }
|
||||
|
||||
template <class T> struct A
|
||||
{
|
||||
T t;
|
||||
constexpr A() { } // { dg-error "uninitialized" }
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
constexpr A<int> a; // { dg-error "A()" }
|
||||
}
|
Loading…
Reference in New Issue
Block a user