diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 08c25189649..4db438b8eab 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,8 @@ 2016-03-04 Jason Merrill + PR c++/67364 + * constexpr.c (cxx_eval_component_reference): Further tweak. + * constexpr.c (struct constexpr_ctx): Add save_exprs field. (cxx_eval_loop_expr): Discard SAVE_EXPR values before looping. (cxx_eval_constant_expression) [SAVE_EXPR]: Add it to the set. diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index 4fadc0fd507..d308175cb5f 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -1990,13 +1990,16 @@ cxx_eval_component_reference (const constexpr_ctx *ctx, tree t, return t; } - if (CONSTRUCTOR_NO_IMPLICIT_ZERO (whole) - && !is_really_empty_class (TREE_TYPE (t))) + /* We only create a CONSTRUCTOR for a subobject when we modify it, so empty + classes never get represented; throw together a value now. */ + if (is_really_empty_class (TREE_TYPE (t))) + return build_constructor (TREE_TYPE (t), NULL); + + if (CONSTRUCTOR_NO_IMPLICIT_ZERO (whole)) { /* 'whole' is part of the aggregate initializer we're currently building; if there's no initializer for this member yet, that's an - error. But expand_aggr_init_1 doesn't bother to initialize really - empty classes, so ignore them here, too. */ + error. */ if (!ctx->quiet) error ("accessing uninitialized member %qD", part); *non_constant_p = true; diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-empty2.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-empty2.C new file mode 100644 index 00000000000..2acfa98364b --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-empty2.C @@ -0,0 +1,27 @@ +// { dg-do compile { target c++14 } } + +struct A +{ + constexpr A(int) { } +}; + +struct B: A { + constexpr B(int i): A(i) { } + constexpr B(const B& b): A(b) { } +}; + +struct C { + B b; + constexpr C(int i): b(i) { } + constexpr C(const C&c): b(c.b) {} +}; + +constexpr int f() +{ + C b1{42}; + C b2{b1}; + b2.b; + return 42; +} + +constexpr int i = f();