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
This commit is contained in:
Jason Merrill 2016-08-09 00:33:42 -04:00 committed by Jason Merrill
parent b08e71f9e8
commit 7dc2b4a235
6 changed files with 37 additions and 6 deletions

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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>),"");