+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
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)))
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. */
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);
}
}
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.
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,
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))
{
{
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;
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;
}
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
+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.
int v;
};
-constexpr s bang; // { dg-error "" }
+constexpr s bang; // { dg-message "" }
struct R {
int i,j;
constexpr T t1;
// Ill-formed (diagnostic required)
-constexpr T t2(t1); // { dg-error "" }
+constexpr T t2(t1); // { dg-message "" }
// Well-formed
struct U {
};
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
--- /dev/null
+// 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;
+}
--- /dev/null
+// { 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()" }
+}