From 7dc2b4a235481acda5ae9e51f4cc0401b1fb192f Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Tue, 9 Aug 2016 00:33:42 -0400 Subject: [PATCH] Fix empty class parameters with constexpr. PR c++/67131 * class.c (is_really_empty_class): Call complete_type. * constexpr.c (cxx_eval_constant_expression): Check is_really_empty_class. (potential_constant_expression_1): Likewise. Check for error type. From-SVN: r239267 --- gcc/cp/ChangeLog | 8 ++++++++ gcc/cp/class.c | 2 +- gcc/cp/constexpr.c | 19 +++++++++++++++---- .../g++.dg/cpp0x/constexpr-empty12.C | 5 +++++ .../g++.dg/cpp0x/constexpr-empty13.C | 7 +++++++ gcc/testsuite/g++.dg/cpp1y/var-templ42.C | 2 +- 6 files changed, 37 insertions(+), 6 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/constexpr-empty12.C create mode 100644 gcc/testsuite/g++.dg/cpp0x/constexpr-empty13.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index bd036a8a628..1ff70d4a8e7 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,11 @@ +2016-08-08 Jason Merrill + + PR c++/67131 + * class.c (is_really_empty_class): Call complete_type. + * constexpr.c (cxx_eval_constant_expression): Check + is_really_empty_class. + (potential_constant_expression_1): Likewise. Check for error type. + 2016-08-08 Jakub Jelinek PR c++/58706 diff --git a/gcc/cp/class.c b/gcc/cp/class.c index f8349650fe6..d898c380057 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -8419,7 +8419,7 @@ is_really_empty_class (tree type) /* CLASSTYPE_EMPTY_P isn't set properly until the class is actually laid out, but we'd like to be able to check this before then. */ - if (COMPLETE_TYPE_P (type) && is_empty_class (type)) + if (COMPLETE_TYPE_P (complete_type (type)) && is_empty_class (type)) return true; for (binfo = TYPE_BINFO (type), i = 0; diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index e7b08c8a9be..2ced9c64e44 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -3670,7 +3670,13 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, CONST_DECL for aggregate constants. */ if (lval) return t; - if (ctx->strict) + if (is_really_empty_class (TREE_TYPE (t))) + { + /* If the class is empty, we aren't actually loading anything. */ + r = build_constructor (TREE_TYPE (t), NULL); + TREE_CONSTANT (r) = true; + } + else if (ctx->strict) r = decl_really_constant_value (t); else r = decl_constant_value (t); @@ -3705,7 +3711,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, /* Defer in case this is only used for its type. */; else if (TREE_CODE (TREE_TYPE (t)) == REFERENCE_TYPE) /* Defer, there's no lvalue->rvalue conversion. */; - else if (is_empty_class (TREE_TYPE (t))) + else if (is_really_empty_class (TREE_TYPE (t))) { /* If the class is empty, we aren't actually loading anything. */ r = build_constructor (TREE_TYPE (t), NULL); @@ -4736,6 +4742,9 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, } if (CONSTANT_CLASS_P (t)) return true; + if (CODE_CONTAINS_STRUCT (TREE_CODE (t), TS_TYPED) + && TREE_TYPE (t) == error_mark_node) + return false; switch (TREE_CODE (t)) { @@ -4891,12 +4900,14 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, case VAR_DECL: if (want_rval + && !var_in_constexpr_fn (t) + && !type_dependent_expression_p (t) && !decl_constant_var_p (t) && (strict || !CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (t)) || !DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (t)) - && !var_in_constexpr_fn (t) - && !type_dependent_expression_p (t)) + && COMPLETE_TYPE_P (TREE_TYPE (t)) + && !is_really_empty_class (TREE_TYPE (t))) { if (flags & tf_error) non_const_var_error (t); diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-empty12.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-empty12.C new file mode 100644 index 00000000000..74634424f44 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-empty12.C @@ -0,0 +1,5 @@ +// { dg-do compile { target c++11 } } + +struct A { } a; +constexpr int f (A a) { return 42; } +constexpr int i = f(a); diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-empty13.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-empty13.C new file mode 100644 index 00000000000..1896ead6dca --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-empty13.C @@ -0,0 +1,7 @@ +// { dg-do compile { target c++11 } } + +struct A { + struct B { } b; +} a; +constexpr int f (A a) { return 42; } +constexpr int i = f(a); diff --git a/gcc/testsuite/g++.dg/cpp1y/var-templ42.C b/gcc/testsuite/g++.dg/cpp1y/var-templ42.C index a43149d9b55..de11b26a99f 100644 --- a/gcc/testsuite/g++.dg/cpp1y/var-templ42.C +++ b/gcc/testsuite/g++.dg/cpp1y/var-templ42.C @@ -14,4 +14,4 @@ template