[gcc(refs/users/marxin/heads/marxin-gcc-benchmark-branch)] c++: Fix constexpr vs. reference parameter.

Martin Liska marxin@gcc.gnu.org
Mon Mar 30 10:44:51 GMT 2020


https://gcc.gnu.org/g:87fbd5347b33883006dc77e779b9edc590fcd2f0

commit 87fbd5347b33883006dc77e779b9edc590fcd2f0
Author: Jason Merrill <jason@redhat.com>
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 a8af79c77a7..8b352134aa7 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,9 @@
+2020-02-03  Jason Merrill  <jason@redhat.com>
+
+	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  <jason@redhat.com>
 
 	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 (&param)[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);
 
   [&]() {


More information about the Gcc-cvs mailing list