c++: Allow parm of empty class type in constexpr.

Since copying a class object is defined in terms of the copy constructor,
copying an empty class is OK even if it would otherwise not be usable in a
constant expression.  Relatedly, using a parameter as an lvalue is no more
problematic than a local variable, and calling a member function uses the
object as an lvalue.

	PR c++/91953
	* constexpr.c (potential_constant_expression_1) [PARM_DECL]: Allow
	empty class type.
	[COMPONENT_REF]: A member function reference doesn't use the object
	as an rvalue.
This commit is contained in:
Jason Merrill 2020-02-03 11:11:55 -05:00
parent 19e43cbce3
commit 8fda2c274a
4 changed files with 35 additions and 5 deletions

View File

@ -1,3 +1,11 @@
2020-02-03 Jason Merrill <jason@redhat.com>
PR c++/91953
* constexpr.c (potential_constant_expression_1) [PARM_DECL]: Allow
empty class type.
[COMPONENT_REF]: A member function reference doesn't use the object
as an rvalue.
2020-02-03 Iain Sandoe <iain@sandoe.co.uk>
PR c++/93458

View File

@ -7013,8 +7013,13 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
return true;
case PARM_DECL:
if (now)
if (now && want_rval)
{
tree type = TREE_TYPE (t);
if (dependent_type_p (type)
|| is_really_empty_class (type, /*ignore_vptr*/false))
/* An empty class has no data to read. */
return true;
if (flags & tf_error)
error ("%qE is not a constant expression", t);
return false;
@ -7270,10 +7275,7 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
#endif
return RECUR (t, any);
case REALPART_EXPR:
case IMAGPART_EXPR:
case COMPONENT_REF:
case BIT_FIELD_REF:
case ARROW_EXPR:
case OFFSET_REF:
/* -- a class member access unless its postfix-expression is
@ -7282,6 +7284,15 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
postfix-expression being a potential constant expression. */
if (type_unknown_p (t))
return true;
if (is_overloaded_fn (t))
/* In a template, a COMPONENT_REF of a function expresses ob.fn(),
which uses ob as an lvalue. */
want_rval = false;
gcc_fallthrough ();
case REALPART_EXPR:
case IMAGPART_EXPR:
case BIT_FIELD_REF:
return RECUR (TREE_OPERAND (t, 0), want_rval);
case EXPR_PACK_EXPANSION:

View File

@ -0,0 +1,10 @@
// PR c++/91953
// { dg-do compile { target c++11 } }
struct S {};
template <class T> void
foo (S s)
{
constexpr S x = s;
}

View File

@ -2,12 +2,13 @@
// { dg-do compile { target c++17 } }
struct T {
int i;
constexpr auto foo() { return false; }
};
template <class MustBeTemplate>
constexpr auto bf(T t) {
if constexpr(t.foo()) { // { dg-error "constant expression" }
if constexpr(t.foo()) {
return false;
}
return true;