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>
|
2011-08-30 Jason Merrill <jason@redhat.com>
|
||||||
|
|
||||||
PR c++/50084
|
PR c++/50084
|
||||||
|
@ -606,15 +606,6 @@ perform_member_init (tree member, tree init)
|
|||||||
|
|
||||||
core_type = strip_array_types (type);
|
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)
|
if (CLASS_TYPE_P (core_type)
|
||||||
&& (CLASSTYPE_READONLY_FIELDS_NEED_INIT (core_type)
|
&& (CLASSTYPE_READONLY_FIELDS_NEED_INIT (core_type)
|
||||||
|| CLASSTYPE_REF_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 "
|
OPT_Wextra, "base class %q#T should be explicitly "
|
||||||
"initialized in the copy constructor",
|
"initialized in the copy constructor",
|
||||||
BINFO_TYPE (subobject));
|
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. */
|
/* Initialize the base. */
|
||||||
|
@ -952,23 +952,14 @@ process_subob_fn (tree fn, bool move_p, tree *spec_p, bool *trivial_p,
|
|||||||
goto bad;
|
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
|
*constexpr_p = false;
|
||||||
force the instantiation now so that we know whether or not it's
|
if (msg)
|
||||||
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;
|
inform (0, "defaulted constructor calls non-constexpr "
|
||||||
if (msg)
|
"%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;
|
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.
|
/* We are processing the definition of the constexpr function FUN.
|
||||||
Check that its BODY fulfills the propriate requirements and
|
Check that its BODY fulfills the propriate requirements and
|
||||||
enter it in the constexpr function definition table.
|
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))
|
if (!potential_rvalue_constant_expression (body))
|
||||||
{
|
{
|
||||||
DECL_DECLARED_CONSTEXPR_P (fun) = false;
|
|
||||||
if (!DECL_TEMPLATE_INFO (fun))
|
if (!DECL_TEMPLATE_INFO (fun))
|
||||||
require_potential_rvalue_constant_expression (body);
|
require_potential_rvalue_constant_expression (body);
|
||||||
return NULL;
|
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. */
|
/* Create the constexpr function table if necessary. */
|
||||||
if (constexpr_fundef_table == NULL)
|
if (constexpr_fundef_table == NULL)
|
||||||
constexpr_fundef_table = htab_create_ggc (101,
|
constexpr_fundef_table = htab_create_ggc (101,
|
||||||
@ -5842,8 +5892,7 @@ explain_invalid_constexpr_fn (tree fun)
|
|||||||
|
|
||||||
save_loc = input_location;
|
save_loc = input_location;
|
||||||
input_location = DECL_SOURCE_LOCATION (fun);
|
input_location = DECL_SOURCE_LOCATION (fun);
|
||||||
inform (0, "%q+D is not constexpr because it does not satisfy the "
|
inform (0, "%q+D is not usable as a constexpr function because:", fun);
|
||||||
"requirements:", fun);
|
|
||||||
/* First check the declaration. */
|
/* First check the declaration. */
|
||||||
if (is_valid_constexpr_fn (fun, true))
|
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));
|
body = massage_constexpr_body (fun, DECL_SAVED_TREE (fun));
|
||||||
require_potential_rvalue_constant_expression (body);
|
require_potential_rvalue_constant_expression (body);
|
||||||
|
if (DECL_CONSTRUCTOR_P (fun))
|
||||||
|
cx_check_missing_mem_inits (fun, body, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
input_location = save_loc;
|
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 (new_call.fundef == NULL || new_call.fundef->body == NULL)
|
||||||
{
|
{
|
||||||
if (!allow_non_constant)
|
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;
|
*non_constant_p = true;
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
@ -7176,7 +7236,17 @@ cxx_eval_constant_expression (const constexpr_call *call, tree t,
|
|||||||
|
|
||||||
case PARM_DECL:
|
case PARM_DECL:
|
||||||
if (call && DECL_CONTEXT (t) == call->fundef->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)
|
else if (addr)
|
||||||
/* Defer in case this is only used for its type. */;
|
/* Defer in case this is only used for its type. */;
|
||||||
else
|
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>
|
2011-09-04 Eric Botcazou <ebotcazou@adacore.com>
|
||||||
|
|
||||||
* gnat.dg/specs/debug1.ads: Tweak pattern.
|
* gnat.dg/specs/debug1.ads: Tweak pattern.
|
||||||
|
@ -14,7 +14,7 @@ struct s {
|
|||||||
int v;
|
int v;
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr s bang; // { dg-error "" }
|
constexpr s bang; // { dg-message "" }
|
||||||
|
|
||||||
struct R {
|
struct R {
|
||||||
int i,j;
|
int i,j;
|
||||||
@ -33,7 +33,7 @@ struct T {
|
|||||||
|
|
||||||
constexpr T t1;
|
constexpr T t1;
|
||||||
// Ill-formed (diagnostic required)
|
// Ill-formed (diagnostic required)
|
||||||
constexpr T t2(t1); // { dg-error "" }
|
constexpr T t2(t1); // { dg-message "" }
|
||||||
|
|
||||||
// Well-formed
|
// Well-formed
|
||||||
struct U {
|
struct U {
|
||||||
|
@ -89,6 +89,6 @@ struct resource {
|
|||||||
};
|
};
|
||||||
constexpr resource f(resource d)
|
constexpr resource f(resource d)
|
||||||
{ return d; } // { dg-error "non-constexpr" }
|
{ 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
|
// 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