From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 45950 invoked by alias); 4 Feb 2020 20:56:24 -0000 Mailing-List: contact gcc-cvs-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-cvs-owner@gcc.gnu.org Received: (qmail 45932 invoked by uid 9846); 4 Feb 2020 20:56:24 -0000 Date: Tue, 04 Feb 2020 20:56:00 -0000 Message-ID: <20200204205624.45931.qmail@sourceware.org> Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: Iain D Sandoe To: gcc-cvs@gcc.gnu.org Subject: [gcc/devel/c++-coroutines] c++: Fix constexpr vs. reference parameter. X-Act-Checkin: gcc X-Git-Author: Jason Merrill X-Git-Refname: refs/heads/devel/c++-coroutines X-Git-Oldrev: 8fda2c274ac66d60c1dfc1349e9efb4e8c2a3580 X-Git-Newrev: 87fbd5347b33883006dc77e779b9edc590fcd2f0 X-SW-Source: 2020-02/txt/msg00263.txt.bz2 https://gcc.gnu.org/g:87fbd5347b33883006dc77e779b9edc590fcd2f0 commit 87fbd5347b33883006dc77e779b9edc590fcd2f0 Author: Jason Merrill Date: Mon Feb 3 16:03:45 2020 -0500 c++: Fix constexpr vs. reference parameter. [expr.const] specifically rules out mentioning a reference even if its address is never used, because it implies indirection that is similarly non-constant for a pointer variable. PR c++/66477 * constexpr.c (cxx_eval_constant_expression) [PARM_DECL]: Don't defer loading the value of a reference. Diff: --- gcc/cp/ChangeLog | 6 +++ gcc/cp/constexpr.c | 2 - gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr6.C | 2 +- gcc/testsuite/g++.dg/cpp0x/constexpr-ref12.C | 46 ++++++++++++++++++++++ .../g++.dg/cpp1y/lambda-generic-const10.C | 2 +- 5 files changed, 54 insertions(+), 4 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index a8af79c..8b35213 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,11 @@ 2020-02-03 Jason Merrill + PR c++/66477 + * constexpr.c (cxx_eval_constant_expression) [PARM_DECL]: Don't + defer loading the value of a reference. + +2020-02-03 Jason Merrill + PR c++/91953 * constexpr.c (potential_constant_expression_1) [PARM_DECL]: Allow empty class type. diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index a39ba41..3962763 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -5322,8 +5322,6 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, r = *p; else if (lval) /* Defer in case this is only used for its type. */; - else if (TYPE_REF_P (TREE_TYPE (t))) - /* Defer, there's no lvalue->rvalue conversion. */; else if (COMPLETE_TYPE_P (TREE_TYPE (t)) && is_really_empty_class (TREE_TYPE (t), /*ignore_vptr*/false)) { diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr6.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr6.C index 3a48398..1c06512 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr6.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr6.C @@ -12,7 +12,7 @@ constexpr auto sz_d = size(array_double); static_assert(sz_d == 3, "Array size failure"); void f(bool (¶m)[2]) { - static_assert(size(param) == 2, "Array size failure"); // Line 13 + static_assert(size(param) == 2, "Array size failure"); // { dg-error "" } short data[] = {-1, 2, -45, 6, 88, 99, -345}; static_assert(size(data) == 7, "Array size failure"); } diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ref12.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ref12.C new file mode 100644 index 0000000..7c3ce66 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ref12.C @@ -0,0 +1,46 @@ +// PR c++/66477 +// { dg-do compile { target c++11 } } + +struct a { constexpr bool g() const { return true; } }; +constexpr bool g(a&) { return true;} +constexpr bool h(a) { return true;} + +a a1; +a& ar = a1; + +void f(a ap, a& arp) +{ + a a2; + a& ar2 = a2; + + // Most of these are OK because no data is actually loaded. + static_assert (a1.g(),""); + static_assert (g(a1),""); + static_assert (h(a1),""); + + static_assert (a2.g(),""); + static_assert (g(a2),""); + static_assert (h(a2),""); + + static_assert (ap.g(),""); + static_assert (g(ap),""); + static_assert (h(ap),""); + + static_assert (ar.g(),""); + static_assert (g(ar),""); + static_assert (h(ar),""); + + // But these are specifically prohibited in [expr.const]/4.12: + // * an id-expression that refers to a variable or data member of reference + // type unless the reference has a preceding initialization and either + // ** it is usable in constant expressions or + // ** its lifetime began within the evaluation of e; + + static_assert (ar2.g(),""); // { dg-error "constant" } + static_assert (g(ar2),""); // { dg-error "constant" } + static_assert (h(ar2),""); // { dg-error "constant" } + + static_assert (arp.g(),""); // { dg-error "constant" } + static_assert (g(arp),""); // { dg-error "constant" } + static_assert (h(arp),""); // { dg-error "constant" } +} diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-generic-const10.C b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-const10.C index e0080b3..2f48dae4 100644 --- a/gcc/testsuite/g++.dg/cpp1y/lambda-generic-const10.C +++ b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-const10.C @@ -11,7 +11,7 @@ int main() constexpr auto x = f(); //ok, call constexpr const non-static method [](auto const &f) { - constexpr auto x = f(); /*ok*/ + constexpr auto x = f(); // { dg-error "" } }(f); [&]() {