aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2016-08-09 00:33:42 -0400
committerJason Merrill <jason@gcc.gnu.org>2016-08-09 00:33:42 -0400
commit7dc2b4a235481acda5ae9e51f4cc0401b1fb192f (patch)
treeaf1d5b910d980f8803fa3cb95c390dfbf608337e /gcc
parentb08e71f9e8afbdf264d159627760aa2bf8a8ca1a (diff)
downloadgcc-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/ChangeLog8
-rw-r--r--gcc/cp/class.c2
-rw-r--r--gcc/cp/constexpr.c19
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-empty12.C5
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-empty13.C7
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/var-templ42.C2
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>),"");