Commit 3e4b91f2 by Nathan Sidwell Committed by Nathan Sidwell

PR c++/79118 - anon-members and constexpr

	PR c++/79118 - anon-members and constexpr
	* constexpr.c (cx_check_missing_mem_inits): Caller passes type not
	ctor decl.  Recursively check anonymous members.
	(register_constexpr_fundef): Adjust cx_check_missing_mem_inits
	call.
	(explain_invalid_constexpr_fn): Likewise.


	PR c++/79118
	* g++.dg/cpp0x/pr79118.C: New.

From-SVN: r244881
parent b20ba138
2017-01-24 Nathan Sidwell <nathan@acm.org>
PR c++/79118 - anon-members and constexpr
* constexpr.c (cx_check_missing_mem_inits): Caller passes type not
ctor decl. Recursively check anonymous members.
(register_constexpr_fundef): Adjust cx_check_missing_mem_inits
call.
(explain_invalid_constexpr_fn): Likewise.
2017-01-23 Nathan Sidwell <nathan@acm.org> 2017-01-23 Nathan Sidwell <nathan@acm.org>
PR c++/71710 - template using directive of field PR c++/71710 - template using directive of field
......
...@@ -696,23 +696,21 @@ massage_constexpr_body (tree fun, tree body) ...@@ -696,23 +696,21 @@ massage_constexpr_body (tree fun, tree body)
return body; return body;
} }
/* FUN is a constexpr constructor with massaged body BODY. Return true /* CTYPE is a type constructed from BODY. Return true if some
if some bases/fields are uninitialized, and complain if COMPLAIN. */ bases/fields are uninitialized, and complain if COMPLAIN. */
static bool static bool
cx_check_missing_mem_inits (tree fun, tree body, bool complain) cx_check_missing_mem_inits (tree ctype, tree body, bool complain)
{ {
bool bad; unsigned nelts = 0;
tree field;
unsigned i, nelts; if (body)
tree ctype; {
if (TREE_CODE (body) != CONSTRUCTOR)
if (TREE_CODE (body) != CONSTRUCTOR) return false;
return false; nelts = CONSTRUCTOR_NELTS (body);
}
nelts = CONSTRUCTOR_NELTS (body); tree field = TYPE_FIELDS (ctype);
ctype = DECL_CONTEXT (fun);
field = TYPE_FIELDS (ctype);
if (TREE_CODE (ctype) == UNION_TYPE) if (TREE_CODE (ctype) == UNION_TYPE)
{ {
...@@ -726,13 +724,13 @@ cx_check_missing_mem_inits (tree fun, tree body, bool complain) ...@@ -726,13 +724,13 @@ cx_check_missing_mem_inits (tree fun, tree body, bool complain)
return false; return false;
} }
bad = false; /* Iterate over the CONSTRUCTOR, checking any missing fields don't
for (i = 0; i <= nelts; ++i) need an explicit initialization. */
bool bad = false;
for (unsigned i = 0; i <= nelts; ++i)
{ {
tree index; tree index = NULL_TREE;
if (i == nelts) if (i < nelts)
index = NULL_TREE;
else
{ {
index = CONSTRUCTOR_ELT (body, i)->index; index = CONSTRUCTOR_ELT (body, i)->index;
/* Skip base and vtable inits. */ /* Skip base and vtable inits. */
...@@ -740,13 +738,25 @@ cx_check_missing_mem_inits (tree fun, tree body, bool complain) ...@@ -740,13 +738,25 @@ cx_check_missing_mem_inits (tree fun, tree body, bool complain)
|| DECL_ARTIFICIAL (index)) || DECL_ARTIFICIAL (index))
continue; continue;
} }
for (; field != index; field = DECL_CHAIN (field)) for (; field != index; field = DECL_CHAIN (field))
{ {
tree ftype; tree ftype;
if (TREE_CODE (field) != FIELD_DECL if (TREE_CODE (field) != FIELD_DECL)
|| (DECL_C_BIT_FIELD (field) && !DECL_NAME (field)) continue;
|| DECL_ARTIFICIAL (field)) if (DECL_C_BIT_FIELD (field) && !DECL_NAME (field))
continue; continue;
if (DECL_ARTIFICIAL (field))
continue;
if (ANON_AGGR_TYPE_P (TREE_TYPE (field)))
{
/* Recurse to check the anonummous aggregate member. */
bad |= cx_check_missing_mem_inits
(TREE_TYPE (field), NULL_TREE, complain);
if (bad && !complain)
return true;
continue;
}
ftype = strip_array_types (TREE_TYPE (field)); ftype = strip_array_types (TREE_TYPE (field));
if (type_has_constexpr_default_constructor (ftype)) if (type_has_constexpr_default_constructor (ftype))
{ {
...@@ -766,6 +776,15 @@ cx_check_missing_mem_inits (tree fun, tree body, bool complain) ...@@ -766,6 +776,15 @@ cx_check_missing_mem_inits (tree fun, tree body, bool complain)
} }
if (field == NULL_TREE) if (field == NULL_TREE)
break; break;
if (ANON_AGGR_TYPE_P (TREE_TYPE (index)))
{
/* Check the anonymous aggregate initializer is valid. */
bad |= cx_check_missing_mem_inits
(TREE_TYPE (index), CONSTRUCTOR_ELT (body, i)->value, complain);
if (bad && !complain)
return true;
}
field = DECL_CHAIN (field); field = DECL_CHAIN (field);
} }
...@@ -803,7 +822,8 @@ register_constexpr_fundef (tree fun, tree body) ...@@ -803,7 +822,8 @@ register_constexpr_fundef (tree fun, tree body)
} }
if (DECL_CONSTRUCTOR_P (fun) if (DECL_CONSTRUCTOR_P (fun)
&& cx_check_missing_mem_inits (fun, massaged, !DECL_GENERATED_P (fun))) && cx_check_missing_mem_inits (DECL_CONTEXT (fun),
massaged, !DECL_GENERATED_P (fun)))
return NULL; return NULL;
/* Create the constexpr function table if necessary. */ /* Create the constexpr function table if necessary. */
...@@ -864,7 +884,7 @@ explain_invalid_constexpr_fn (tree fun) ...@@ -864,7 +884,7 @@ 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)) if (DECL_CONSTRUCTOR_P (fun))
cx_check_missing_mem_inits (fun, body, true); cx_check_missing_mem_inits (DECL_CONTEXT (fun), body, true);
} }
} }
input_location = save_loc; input_location = save_loc;
......
2017-01-24 Nathan Sidwell <nathan@acm.org>
PR c++/79118
* g++.dg/cpp0x/pr79118.C: New.
2017-01-24 Eric Botcazou <ebotcazou@adacore.com> 2017-01-24 Eric Botcazou <ebotcazou@adacore.com>
* gcc.target/arm/vfp-longcall-apcs.c: New test. * gcc.target/arm/vfp-longcall-apcs.c: New test.
...@@ -305,7 +310,7 @@ ...@@ -305,7 +310,7 @@
2017-01-20 Nathan Sidwell <nathan@acm.org> 2017-01-20 Nathan Sidwell <nathan@acm.org>
PR c++/79495 PR c++/78495
* g++.dg/cpp1z/inh-ctor38.C: New. * g++.dg/cpp1z/inh-ctor38.C: New.
2017-01-20 Marek Polacek <polacek@redhat.com> 2017-01-20 Marek Polacek <polacek@redhat.com>
......
// { dg-do compile { target c++11 } }
// { dg-additional-options { -Wno-pedantic } }
// PR c++/79118 failure to check initialization of anonymous members.
struct One
{
union
{
int a;
int b;
};
constexpr One () : a(), b() {} // { dg-error "multiple" }
constexpr One (int) : a() {}
constexpr One (unsigned) : b () {}
constexpr One (void *) {} // { dg-error "exactly one" }
};
One a ();
One b (0);
One c (0u);
One d ((void *)0);
struct Two
{
struct
{
int a;
int b;
};
constexpr Two () : a(), b() {}
constexpr Two (int) : a() {} // { dg-error "b' must be initialized" }
constexpr Two (unsigned) : b () {} // { dg-error "a' must be initialized" }
constexpr Two (void *) {} // { dg-error "a' must be initialized" }
// { dg-error "b' must be initialized" "" { target *-*-* } 35 }
};
Two e ();
Two f (0);
Two g (0u);
Two h ((void *)0);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment