From 8fda2c274ac66d60c1dfc1349e9efb4e8c2a3580 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Mon, 3 Feb 2020 11:11:55 -0500 Subject: [PATCH] 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. --- gcc/cp/ChangeLog | 8 ++++++++ gcc/cp/constexpr.c | 19 +++++++++++++++---- gcc/testsuite/g++.dg/cpp0x/constexpr-empty14.C | 10 ++++++++++ gcc/testsuite/g++.dg/cpp1z/constexpr-if12.C | 3 ++- 4 files changed, 35 insertions(+), 5 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/constexpr-empty14.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 2429b1f..a8af79c 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,11 @@ +2020-02-03 Jason Merrill + + 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 PR c++/93458 diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index 577022e..a39ba41 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -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: diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-empty14.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-empty14.C new file mode 100644 index 0000000..ca4f9a5 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-empty14.C @@ -0,0 +1,10 @@ +// PR c++/91953 +// { dg-do compile { target c++11 } } + +struct S {}; + +template void +foo (S s) +{ + constexpr S x = s; +} diff --git a/gcc/testsuite/g++.dg/cpp1z/constexpr-if12.C b/gcc/testsuite/g++.dg/cpp1z/constexpr-if12.C index f21a989..005aa80 100644 --- a/gcc/testsuite/g++.dg/cpp1z/constexpr-if12.C +++ b/gcc/testsuite/g++.dg/cpp1z/constexpr-if12.C @@ -2,12 +2,13 @@ // { dg-do compile { target c++17 } } struct T { + int i; constexpr auto foo() { return false; } }; template constexpr auto bf(T t) { - if constexpr(t.foo()) { // { dg-error "constant expression" } + if constexpr(t.foo()) { return false; } return true; -- 2.7.4