diff options
author | Jason Merrill <jason@redhat.com> | 2022-05-22 15:04:33 -0400 |
---|---|---|
committer | Jason Merrill <jason@redhat.com> | 2022-05-25 11:06:36 -0400 |
commit | 6209009df65ff68482ef66951856f50cf362d990 (patch) | |
tree | 400d50b2f5a8debf3c6eecd1f3c9dbd063076a5e /gcc | |
parent | 1b661f3f5e712c951e774b3b91fffe4dac734cc7 (diff) | |
download | gcc-6209009df65ff68482ef66951856f50cf362d990.zip gcc-6209009df65ff68482ef66951856f50cf362d990.tar.gz gcc-6209009df65ff68482ef66951856f50cf362d990.tar.bz2 |
c++: strict constexpr and local vars
A change I was working on made constexpr_searcher.cc start to fail, and when
I looked at it I wondered why it had been accepted before. This turned out
to be because we try to be more flexible about constant-evaluation of static
initializers, as allowed, but we were wrongly doing the same for non-static
initializers as well.
gcc/cp/ChangeLog:
* constexpr.cc (maybe_constant_init_1): Only pass false for
strict when initializing a variable of static duration.
libstdc++-v3/ChangeLog:
* testsuite/20_util/function_objects/constexpr_searcher.cc: Add
constexpr.
gcc/testsuite/ChangeLog:
* g++.dg/cpp1y/constexpr-local4.C: New test.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/constexpr.cc | 12 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp1y/constexpr-local4.C | 17 |
2 files changed, 26 insertions, 3 deletions
diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc index 388239e..1a70fda 100644 --- a/gcc/cp/constexpr.cc +++ b/gcc/cp/constexpr.cc @@ -8301,9 +8301,15 @@ maybe_constant_init_1 (tree t, tree decl, bool allow_non_constant, else if (CONSTANT_CLASS_P (t) && allow_non_constant) /* No evaluation needed. */; else - t = cxx_eval_outermost_constant_expr (t, allow_non_constant, - /*strict*/false, - manifestly_const_eval, false, decl); + { + /* [basic.start.static] allows constant-initialization of variables with + static or thread storage duration even if it isn't required, but we + shouldn't bend the rules the same way for automatic variables. */ + bool is_static = (decl && DECL_P (decl) + && (TREE_STATIC (decl) || DECL_EXTERNAL (decl))); + t = cxx_eval_outermost_constant_expr (t, allow_non_constant, !is_static, + manifestly_const_eval, false, decl); + } if (TREE_CODE (t) == TARGET_EXPR) { tree init = TARGET_EXPR_INITIAL (t); diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-local4.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-local4.C new file mode 100644 index 0000000..bef6248 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-local4.C @@ -0,0 +1,17 @@ +// { dg-do compile { target c++14 } } + +struct A +{ + int i; + constexpr A(int i): i(i) {}; +}; + +const A a = 42; + +constexpr int f() +{ + const int j = a.i; // { dg-message "'a'" } + return j; +} + +static_assert (f() == 42,""); // { dg-error "non-constant" } |