re PR c++/64356 (Some constexpr expressions not recognized as constexpr)
authorJason Merrill <jason@redhat.com>
Tue, 13 Jan 2015 21:04:43 +0000 (16:04 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Tue, 13 Jan 2015 21:04:43 +0000 (16:04 -0500)
PR c++/64356
PR libstdc++/58777
* constexpr.c (cxx_eval_binary_expression): Don't VERIFY_CONSTANT
pointer expressions.
(cxx_eval_increment_expression): Likewise.

From-SVN: r219559

gcc/cp/ChangeLog
gcc/cp/constexpr.c
gcc/testsuite/g++.dg/cpp1y/constexpr-local2.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1y/pr63996.C
libstdc++-v3/testsuite/experimental/optional/constexpr/make_optional.cc
libstdc++-v3/testsuite/experimental/optional/constexpr/observers/2.cc
libstdc++-v3/testsuite/experimental/optional/constexpr/observers/3.cc

index 668b13bc1be2ea10ce0fc52620efcca1b224051d..013c432a6618f64b269f61e392e80f526bd7377f 100644 (file)
@@ -1,5 +1,11 @@
 2015-01-13  Jason Merrill  <jason@redhat.com>
 
+       PR c++/64356
+       PR libstdc++/58777
+       * constexpr.c (cxx_eval_binary_expression): Don't VERIFY_CONSTANT
+       pointer expressions.
+       (cxx_eval_increment_expression): Likewise.
+
        PR c++/64514
        * pt.c (coerce_template_parameter_pack): Return NULL for a
        zero-length fixed parameter pack with a pack expansion arg.
index 650250b015acfc4e0486f7c518870d43a2f2fc57..14325069531e280024d8256f6315d6dc9cef1aed 100644 (file)
@@ -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 (file)
index 0000000..fd6143b
--- /dev/null
@@ -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__);
index d0bf9b5133289751639e7117e592d85492e265b8..8f66cdc389362eae22dde72c2dbd51dc9414c53c 100644 (file)
@@ -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" }
 
index f3b43880da04373e0c88ce2d880cdabd5452f458..d57cf5cf6ebe7b419b3bf1542a1011bfc28293f8 100644 (file)
@@ -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 20c307da03d5e428803b4d365e40ae33f186af88..803927bec05243a7f8b88f6e4e7c8cfc2655076d 100644 (file)
@@ -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 59b1bdd99733ba79fbe448df9ea04e58f02c06b9..be170f572462fb6c0f08c91d741db7c6a0e69948 100644 (file)
@@ -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.
 //