From 3e4b91f275a6fb8f6466f1ab8c9f24e3d2abf13f Mon Sep 17 00:00:00 2001 From: Nathan Sidwell Date: Tue, 24 Jan 2017 19:25:32 +0000 Subject: [PATCH] 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 --- gcc/cp/ChangeLog | 9 ++++ gcc/cp/constexpr.c | 70 ++++++++++++++++++---------- gcc/testsuite/ChangeLog | 7 ++- gcc/testsuite/g++.dg/cpp0x/pr79118.C | 42 +++++++++++++++++ 4 files changed, 102 insertions(+), 26 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/pr79118.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 66151e9b0a4..5b863446b89 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,12 @@ +2017-01-24 Nathan Sidwell + + 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 PR c++/71710 - template using directive of field diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index a3dec6884ab..67d2428e9b6 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -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; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index e70200bac57..cdd4e1b8a04 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2017-01-24 Nathan Sidwell + + PR c++/79118 + * g++.dg/cpp0x/pr79118.C: New. + 2017-01-24 Eric Botcazou * gcc.target/arm/vfp-longcall-apcs.c: New test. @@ -305,7 +310,7 @@ 2017-01-20 Nathan Sidwell - PR c++/79495 + PR c++/78495 * g++.dg/cpp1z/inh-ctor38.C: New. 2017-01-20 Marek Polacek diff --git a/gcc/testsuite/g++.dg/cpp0x/pr79118.C b/gcc/testsuite/g++.dg/cpp0x/pr79118.C new file mode 100644 index 00000000000..e7dfeb37957 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/pr79118.C @@ -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); -- 2.30.2