diff options
author | Jason Merrill <jason@redhat.com> | 2016-08-09 00:33:42 -0400 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2016-08-09 00:33:42 -0400 |
commit | 7dc2b4a235481acda5ae9e51f4cc0401b1fb192f (patch) | |
tree | af1d5b910d980f8803fa3cb95c390dfbf608337e /gcc | |
parent | b08e71f9e8afbdf264d159627760aa2bf8a8ca1a (diff) | |
download | gcc-7dc2b4a235481acda5ae9e51f4cc0401b1fb192f.zip gcc-7dc2b4a235481acda5ae9e51f4cc0401b1fb192f.tar.gz gcc-7dc2b4a235481acda5ae9e51f4cc0401b1fb192f.tar.bz2 |
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/cp/class.c | 2 | ||||
-rw-r--r-- | gcc/cp/constexpr.c | 19 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/constexpr-empty12.C | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/constexpr-empty13.C | 7 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp1y/var-templ42.C | 2 |
6 files changed, 37 insertions, 6 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index bd036a8..1ff70d4 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,11 @@ +2016-08-08 Jason Merrill <jason@redhat.com> + + 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 <jakub@redhat.com> PR c++/58706 diff --git a/gcc/cp/class.c b/gcc/cp/class.c index f834965..d898c38 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 e7b08c8..2ced9c6 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 0000000..7463442 --- /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 0000000..1896ead --- /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 a43149d..de11b26 100644 --- a/gcc/testsuite/g++.dg/cpp1y/var-templ42.C +++ b/gcc/testsuite/g++.dg/cpp1y/var-templ42.C @@ -14,4 +14,4 @@ template <template <typename...> class F> struct A { template <typename F> auto valid_call(F f) -> decltype(f()); constexpr auto valid_call(...) { return 0; } template <typename> struct no_type; -static_assert(!valid_call(metafunction<no_type>),""); // { dg-error "" } +static_assert(!valid_call(metafunction<no_type>),""); |