From caee690e915e13a48a16dabbb61110ae88d1821a Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Tue, 13 Jan 2015 16:04:43 -0500 Subject: [PATCH] re PR c++/64356 (Some constexpr expressions not recognized as constexpr) 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 | 6 +++++ gcc/cp/constexpr.c | 21 +++++++++++++----- gcc/testsuite/g++.dg/cpp1y/constexpr-local2.C | 22 +++++++++++++++++++ gcc/testsuite/g++.dg/cpp1y/pr63996.C | 2 +- .../optional/constexpr/make_optional.cc | 3 --- .../optional/constexpr/observers/2.cc | 3 --- .../optional/constexpr/observers/3.cc | 3 --- 7 files changed, 45 insertions(+), 15 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-local2.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 668b13bc1be..013c432a661 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,11 @@ 2015-01-13 Jason Merrill + 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. diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index 650250b015a..14325069531 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 00000000000..fd6143b091e --- /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 +constexpr size_t f(const char (&x)[N]) { + size_t s = 0; + for(size_t c : x) + s += c; + return s; +} + +template +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 d0bf9b51332..8f66cdc3893 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 f3b43880da0..d57cf5cf6eb 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 20c307da03d..803927bec05 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 59b1bdd9973..be170f57246 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. //