This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

C++ PATCH for c++/64356 and libstdc++/58777 (constexpr pointer arithmetic)


In this testcase we are iterating through an array which is a local variable in a constexpr function. So its address is not constant, but we can still do arithmetic on it to get to the address of an element and then pull out the value of the element; we shouldn't reject the evaluation as non-constant unless the non-constant address is part of the value of the complete expression.

This patch also fixes libstdc++/58777, another issue with giving up on an intermediate non-constant address even though the final value is constant.

Tested x86_64-pc-linux-gnu, applying to trunk.
commit 10760eb60bfd8f5de38ff1194718851a3d0f9073
Author: Jason Merrill <jason@redhat.com>
Date:   Tue Jan 13 07:45:03 2015 -0500

    	PR c++/64356
    	PR libstdc++/58777
    	* constexpr.c (cxx_eval_binary_expression): Don't VERIFY_CONSTANT
    	pointer expressions.
    	(cxx_eval_increment_expression): Likewise.

diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index 650250b..1432506 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -1616,10 +1616,15 @@ cxx_eval_binary_expression (const constexpr_ctx *ctx, tree t,
   tree lhs, rhs;
   lhs = cxx_eval_constant_expression (ctx, orig_lhs, /*lval*/false,
 				      non_constant_p, overflow_p);
-  VERIFY_CONSTANT (lhs);
+  /* Don't VERIFY_CONSTANT if this might be dealing with a pointer to
+     a local array in a constexpr function.  */
+  bool ptr = POINTER_TYPE_P (TREE_TYPE (lhs));
+  if (!ptr)
+    VERIFY_CONSTANT (lhs);
   rhs = cxx_eval_constant_expression (ctx, orig_rhs, /*lval*/false,
 				      non_constant_p, overflow_p);
-  VERIFY_CONSTANT (rhs);
+  if (!ptr)
+    VERIFY_CONSTANT (lhs);
 
   location_t loc = EXPR_LOCATION (t);
   enum tree_code code = TREE_CODE (t);
@@ -1634,7 +1639,8 @@ cxx_eval_binary_expression (const constexpr_ctx *ctx, tree t,
     }
   else if (cxx_eval_check_shift_p (loc, ctx, code, type, lhs, rhs))
     *non_constant_p = true;
-  VERIFY_CONSTANT (r);
+  if (!ptr)
+    VERIFY_CONSTANT (lhs);
   return r;
 }
 
@@ -2704,7 +2710,11 @@ cxx_eval_increment_expression (const constexpr_ctx *ctx, tree t,
   tree val = rvalue (op);
   val = cxx_eval_constant_expression (ctx, val, false,
 				      non_constant_p, overflow_p);
-  VERIFY_CONSTANT (val);
+  /* Don't VERIFY_CONSTANT if this might be dealing with a pointer to
+     a local array in a constexpr function.  */
+  bool ptr = POINTER_TYPE_P (TREE_TYPE (val));
+  if (!ptr)
+    VERIFY_CONSTANT (val);
 
   /* The modified value.  */
   bool inc = (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR);
@@ -2719,7 +2729,8 @@ cxx_eval_increment_expression (const constexpr_ctx *ctx, tree t,
     }
   else
     mod = fold_build2 (inc ? PLUS_EXPR : MINUS_EXPR, type, val, offset);
-  VERIFY_CONSTANT (mod);
+  if (!ptr)
+    VERIFY_CONSTANT (mod);
 
   /* Storing the modified value.  */
   tree store = build2 (MODIFY_EXPR, type, op, mod);
diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-local2.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-local2.C
new file mode 100644
index 0000000..fd6143b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-local2.C
@@ -0,0 +1,22 @@
+// PR c++/64356
+// { dg-do compile { target c++14 } }
+
+typedef unsigned long size_t;
+
+template<size_t N>
+constexpr size_t f(const char (&x)[N]) {
+  size_t s = 0;
+  for(size_t c : x)
+    s += c;
+  return s;
+}
+
+template<size_t N>
+constexpr size_t g(const char (&x)[N]) {
+  char y[N] = {0};
+  for(size_t i = 0; i < N; ++i)
+    y[i] = x[i];
+  return f(y);
+}
+
+constexpr auto x = g(__DATE__);
diff --git a/gcc/testsuite/g++.dg/cpp1y/pr63996.C b/gcc/testsuite/g++.dg/cpp1y/pr63996.C
index d0bf9b5..8f66cdc 100644
--- a/gcc/testsuite/g++.dg/cpp1y/pr63996.C
+++ b/gcc/testsuite/g++.dg/cpp1y/pr63996.C
@@ -6,5 +6,5 @@ foo (int i)
   int a[i] = { }; // { dg-error "forbids variable length" }
 }
 
-constexpr int j = foo (1); // { dg-error "is not a constant expression" }
+constexpr int j = foo (1); // { dg-error "flows off the end" }
 
diff --git a/libstdc++-v3/testsuite/experimental/optional/constexpr/make_optional.cc b/libstdc++-v3/testsuite/experimental/optional/constexpr/make_optional.cc
index f3b4388..d57cf5c 100644
--- a/libstdc++-v3/testsuite/experimental/optional/constexpr/make_optional.cc
+++ b/libstdc++-v3/testsuite/experimental/optional/constexpr/make_optional.cc
@@ -1,7 +1,4 @@
 // { dg-options "-std=gnu++14" }
-// XFAIL pending resolution of PR libstdc++/58777
-// { dg-do compile { xfail *-*-* } }
-// { dg-excess-errors "" }
 
 // Copyright (C) 2013-2015 Free Software Foundation, Inc.
 //
diff --git a/libstdc++-v3/testsuite/experimental/optional/constexpr/observers/2.cc b/libstdc++-v3/testsuite/experimental/optional/constexpr/observers/2.cc
index 20c307d..803927b 100644
--- a/libstdc++-v3/testsuite/experimental/optional/constexpr/observers/2.cc
+++ b/libstdc++-v3/testsuite/experimental/optional/constexpr/observers/2.cc
@@ -1,7 +1,4 @@
 // { dg-options "-std=gnu++14" }
-// XFAIL pending resolution of PR libstdc++/58777
-// { dg-do compile { xfail *-*-* } }
-// { dg-excess-errors "" }
 
 // Copyright (C) 2013-2015 Free Software Foundation, Inc.
 //
diff --git a/libstdc++-v3/testsuite/experimental/optional/constexpr/observers/3.cc b/libstdc++-v3/testsuite/experimental/optional/constexpr/observers/3.cc
index 59b1bdd..be170f5 100644
--- a/libstdc++-v3/testsuite/experimental/optional/constexpr/observers/3.cc
+++ b/libstdc++-v3/testsuite/experimental/optional/constexpr/observers/3.cc
@@ -1,7 +1,4 @@
 // { dg-options "-std=gnu++14" }
-// XFAIL pending resolution of PR libstdc++/58777
-// { dg-do compile { xfail *-*-* } }
-// { dg-excess-errors "" }
 
 // Copyright (C) 2013-2015 Free Software Foundation, Inc.
 //

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]