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
This commit is contained in:
Nathan Sidwell 2017-01-24 19:25:32 +00:00 committed by Nathan Sidwell
parent b20ba138ef
commit 3e4b91f275
4 changed files with 102 additions and 26 deletions

View File

@ -1,3 +1,12 @@
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>
PR c++/71710 - template using directive of field

View File

@ -696,23 +696,21 @@ 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. */
/* CTYPE is a type constructed from 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)
cx_check_missing_mem_inits (tree ctype, tree body, bool complain)
{
bool bad;
tree field;
unsigned i, nelts;
tree ctype;
if (TREE_CODE (body) != CONSTRUCTOR)
return false;
nelts = CONSTRUCTOR_NELTS (body);
ctype = DECL_CONTEXT (fun);
field = TYPE_FIELDS (ctype);
unsigned nelts = 0;
if (body)
{
if (TREE_CODE (body) != CONSTRUCTOR)
return false;
nelts = CONSTRUCTOR_NELTS (body);
}
tree field = TYPE_FIELDS (ctype);
if (TREE_CODE (ctype) == UNION_TYPE)
{
@ -726,13 +724,13 @@ cx_check_missing_mem_inits (tree fun, tree body, bool complain)
return false;
}
bad = false;
for (i = 0; i <= nelts; ++i)
/* Iterate over the CONSTRUCTOR, checking any missing fields don't
need an explicit initialization. */
bool bad = false;
for (unsigned i = 0; i <= nelts; ++i)
{
tree index;
if (i == nelts)
index = NULL_TREE;
else
tree index = NULL_TREE;
if (i < nelts)
{
index = CONSTRUCTOR_ELT (body, i)->index;
/* Skip base and vtable inits. */
@ -740,13 +738,25 @@ cx_check_missing_mem_inits (tree fun, tree body, bool complain)
|| DECL_ARTIFICIAL (index))
continue;
}
for (; field != index; field = DECL_CHAIN (field))
{
tree ftype;
if (TREE_CODE (field) != FIELD_DECL
|| (DECL_C_BIT_FIELD (field) && !DECL_NAME (field))
|| DECL_ARTIFICIAL (field))
if (TREE_CODE (field) != FIELD_DECL)
continue;
if (DECL_C_BIT_FIELD (field) && !DECL_NAME (field))
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));
if (type_has_constexpr_default_constructor (ftype))
{
@ -766,6 +776,15 @@ cx_check_missing_mem_inits (tree fun, tree body, bool complain)
}
if (field == NULL_TREE)
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);
}
@ -803,7 +822,8 @@ register_constexpr_fundef (tree fun, tree body)
}
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;
/* Create the constexpr function table if necessary. */
@ -864,7 +884,7 @@ 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);
cx_check_missing_mem_inits (DECL_CONTEXT (fun), body, true);
}
}
input_location = save_loc;

View File

@ -1,3 +1,8 @@
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>
* gcc.target/arm/vfp-longcall-apcs.c: New test.
@ -305,7 +310,7 @@
2017-01-20 Nathan Sidwell <nathan@acm.org>
PR c++/79495
PR c++/78495
* g++.dg/cpp1z/inh-ctor38.C: New.
2017-01-20 Marek Polacek <polacek@redhat.com>

View File

@ -0,0 +1,42 @@
// { 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);