From: Jason Merrill Date: Mon, 3 Feb 2020 21:03:45 +0000 (-0500) Subject: c++: Fix constexpr vs. reference parameter. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=87fbd5347b33883006dc77e779b9edc590fcd2f0;p=gcc.git 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 --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index a8af79c77a7..8b352134aa7 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +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 diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index a39ba413d68..3962763fb21 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 3a483989c1f..1c065120314 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 00000000000..7c3ce66b4c9 --- /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 e0080b3d4f6..2f48dae4746 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); [&]() {