diff options
author | Jakub Jelinek <jakub@redhat.com> | 2022-03-24 10:12:25 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@redhat.com> | 2022-03-24 10:12:25 +0100 |
commit | 72124f487ccb5c8065dd5f7b8fba254600b7e611 (patch) | |
tree | 8de82fe3cbd553d06bbcba957c4685e2a51f5a3e | |
parent | 497bde3ab92b2c292f78672db341bbb7cc1bcf1f (diff) | |
download | gcc-72124f487ccb5c8065dd5f7b8fba254600b7e611.zip gcc-72124f487ccb5c8065dd5f7b8fba254600b7e611.tar.gz gcc-72124f487ccb5c8065dd5f7b8fba254600b7e611.tar.bz2 |
c++: extern thread_local declarations in constexpr [PR104994]
C++14 to C++20 apparently should allow extern thread_local declarations in
constexpr functions, however useless they are there (because accessing
such vars is not valid in a constant expression, perhaps sizeof/decltype).
P2242 changed that for C++23 to passing through declaration but
https://cplusplus.github.io/CWG/issues/2552.html
has been filed for it yesterday.
The following patch implements the proposed wording of CWG 2552 in addition
to fixing the C++14 - C++20 handling bug.
If you'd like instead to keep the current pedantic C++23 wording for now,
that would mean taking out the first hunk (cxx_eval_constant_expression) and
g++.dg/cpp23/constexpr-nonlit2.C hunk.
2022-03-24 Jakub Jelinek <jakub@redhat.com>
PR c++/104994
* constexpr.cc (cxx_eval_constant_expression): Don't diagnose passing
through extern thread_local declarations. Change wording from
declaration to definition.
(potential_constant_expression_1): Don't diagnose extern thread_local
declarations. Change wording from declared to defined.
* decl.cc (start_decl): Likewise.
* g++.dg/diagnostic/constexpr1.C: Change expected diagnostic wording
from declared to defined.
* g++.dg/cpp23/constexpr-nonlit1.C: Likewise.
(garply): Change dg-error into dg-bogus.
* g++.dg/cpp23/constexpr-nonlit2.C: Change expected diagnostic wording
from declaration to definition.
* g++.dg/cpp23/constexpr-nonlit6.C: Change expected diagnostic wording
from declared to defined.
* g++.dg/cpp23/constexpr-nonlit7.C: New test.
* g++.dg/cpp2a/constexpr-try5.C: Change expected diagnostic wording
from declared to defined.
* g++.dg/cpp2a/consteval3.C: Likewise.
-rw-r--r-- | gcc/cp/constexpr.cc | 13 | ||||
-rw-r--r-- | gcc/cp/decl.cc | 6 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp23/constexpr-nonlit1.C | 6 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp23/constexpr-nonlit2.C | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp23/constexpr-nonlit6.C | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp23/constexpr-nonlit7.C | 6 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp2a/consteval3.C | 6 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp2a/constexpr-try5.C | 14 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/diagnostic/constexpr1.C | 8 |
9 files changed, 37 insertions, 30 deletions
diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc index a3136ce..ce4ef8e 100644 --- a/gcc/cp/constexpr.cc +++ b/gcc/cp/constexpr.cc @@ -6723,17 +6723,18 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, } if (VAR_P (r) - && (TREE_STATIC (r) || CP_DECL_THREAD_LOCAL_P (r)) + && (TREE_STATIC (r) + || (CP_DECL_THREAD_LOCAL_P (r) && !DECL_REALLY_EXTERN (r))) /* Allow __FUNCTION__ etc. */ && !DECL_ARTIFICIAL (r)) { if (!ctx->quiet) { if (CP_DECL_THREAD_LOCAL_P (r)) - error_at (loc, "control passes through declaration of %qD " + error_at (loc, "control passes through definition of %qD " "with thread storage duration", r); else - error_at (loc, "control passes through declaration of %qD " + error_at (loc, "control passes through definition of %qD " "with static storage duration", r); } *non_constant_p = true; @@ -9188,17 +9189,17 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now, tmp = DECL_EXPR_DECL (t); if (VAR_P (tmp) && !DECL_ARTIFICIAL (tmp)) { - if (CP_DECL_THREAD_LOCAL_P (tmp)) + if (CP_DECL_THREAD_LOCAL_P (tmp) && !DECL_REALLY_EXTERN (tmp)) { if (flags & tf_error) - error_at (DECL_SOURCE_LOCATION (tmp), "%qD declared " + error_at (DECL_SOURCE_LOCATION (tmp), "%qD defined " "%<thread_local%> in %<constexpr%> context", tmp); return false; } else if (TREE_STATIC (tmp)) { if (flags & tf_error) - error_at (DECL_SOURCE_LOCATION (tmp), "%qD declared " + error_at (DECL_SOURCE_LOCATION (tmp), "%qD defined " "%<static%> in %<constexpr%> context", tmp); return false; } diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc index efef1b7..68741bbf 100644 --- a/gcc/cp/decl.cc +++ b/gcc/cp/decl.cc @@ -5774,15 +5774,15 @@ start_decl (const cp_declarator *declarator, && cxx_dialect < cxx23) { bool ok = false; - if (CP_DECL_THREAD_LOCAL_P (decl)) + if (CP_DECL_THREAD_LOCAL_P (decl) && !DECL_REALLY_EXTERN (decl)) error_at (DECL_SOURCE_LOCATION (decl), - "%qD declared %<thread_local%> in %qs function only " + "%qD defined %<thread_local%> in %qs function only " "available with %<-std=c++2b%> or %<-std=gnu++2b%>", decl, DECL_IMMEDIATE_FUNCTION_P (current_function_decl) ? "consteval" : "constexpr"); else if (TREE_STATIC (decl)) error_at (DECL_SOURCE_LOCATION (decl), - "%qD declared %<static%> in %qs function only available " + "%qD defined %<static%> in %qs function only available " "with %<-std=c++2b%> or %<-std=gnu++2b%>", decl, DECL_IMMEDIATE_FUNCTION_P (current_function_decl) ? "consteval" : "constexpr"); diff --git a/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit1.C b/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit1.C index c80ea38..c60fb8c 100644 --- a/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit1.C +++ b/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit1.C @@ -23,7 +23,7 @@ baz (int x) { if (!x) return 1; - static int a; // { dg-error "'a' declared 'static' in 'constexpr' function only available with" "" { target c++20_down } } + static int a; // { dg-error "'a' defined 'static' in 'constexpr' function only available with" "" { target c++20_down } } return ++a; // { dg-error "uninitialized variable 'a' in 'constexpr' function" "" { target c++17_down } .-1 } } @@ -32,7 +32,7 @@ qux (int x) { if (!x) return 1; - thread_local int a; // { dg-error "'a' declared 'thread_local' in 'constexpr' function only available with" "" { target c++20_down } } + thread_local int a; // { dg-error "'a' defined 'thread_local' in 'constexpr' function only available with" "" { target c++20_down } } return ++a; // { dg-error "uninitialized variable 'a' in 'constexpr' function" "" { target c++17_down } .-1 } } @@ -41,7 +41,7 @@ garply (int x) { if (!x) return 1; - extern thread_local int a; // { dg-error "'a' declared 'thread_local' in 'constexpr' function only available with" "" { target c++20_down } } + extern thread_local int a; // { dg-bogus "'thread_local' in 'constexpr' function only available with" "" { target c++20_down } } return ++a; } diff --git a/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit2.C b/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit2.C index 0f7b229..b01f728 100644 --- a/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit2.C +++ b/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit2.C @@ -24,7 +24,7 @@ baz (int x) { if (!x) return 1; - static int a; // { dg-error "control passes through declaration of 'a' with static storage duration" } + static int a; // { dg-error "control passes through definition of 'a' with static storage duration" } return ++a; } @@ -33,7 +33,7 @@ qux (int x) { if (!x) return 1; - thread_local int a; // { dg-error "control passes through declaration of 'a' with thread storage duration" } + thread_local int a; // { dg-error "control passes through definition of 'a' with thread storage duration" } return ++a; } diff --git a/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit6.C b/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit6.C index 11cb518..fbeb830 100644 --- a/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit6.C +++ b/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit6.C @@ -13,13 +13,13 @@ lab: constexpr int bar () { - static int a; // { dg-error "'a' declared 'static' in 'constexpr' context" } + static int a; // { dg-error "'a' defined 'static' in 'constexpr' context" } return ++a; } constexpr int baz (int x) { - thread_local int a; // { dg-error "'a' declared 'thread_local' in 'constexpr' context" } + thread_local int a; // { dg-error "'a' defined 'thread_local' in 'constexpr' context" } return ++a; } diff --git a/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit7.C b/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit7.C new file mode 100644 index 0000000..0612575 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit7.C @@ -0,0 +1,6 @@ +// PR c++/104994 +// CWG2552 +// { dg-do compile { target c++14 } } + +constexpr bool foo () { extern thread_local int t; return true; } +static constexpr bool a = foo (); diff --git a/gcc/testsuite/g++.dg/cpp2a/consteval3.C b/gcc/testsuite/g++.dg/cpp2a/consteval3.C index 8f93164..8346386 100644 --- a/gcc/testsuite/g++.dg/cpp2a/consteval3.C +++ b/gcc/testsuite/g++.dg/cpp2a/consteval3.C @@ -56,8 +56,8 @@ template consteval float f12 (float x); // { dg-error "explicit instantiation sh consteval int f13 (int x) { - static int a = 5; // { dg-error "'a' declared 'static' in 'consteval' function only available with" "" { target c++20_only } } - // { dg-error "'a' declared 'static' in 'constexpr' context" "" { target c++23 } .-1 } - thread_local int b = 6; // { dg-error "'b' declared 'thread_local' in 'consteval' function only available with" "" { target c++20_only } } + static int a = 5; // { dg-error "'a' defined 'static' in 'consteval' function only available with" "" { target c++20_only } } + // { dg-error "'a' defined 'static' in 'constexpr' context" "" { target c++23 } .-1 } + thread_local int b = 6; // { dg-error "'b' defined 'thread_local' in 'consteval' function only available with" "" { target c++20_only } } return x; } diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-try5.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-try5.C index ed5e40d..216634d 100644 --- a/gcc/testsuite/g++.dg/cpp2a/constexpr-try5.C +++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-try5.C @@ -5,14 +5,14 @@ constexpr int foo () try { // { dg-warning "function-try-block body of 'constexpr' function only available with" "" { target c++17_down } } int a; // { dg-error "uninitialized variable 'a' in 'constexpr' function" "" { target c++17_down } } - static double b = 1.0;// { dg-error "'b' declared 'static' in 'constexpr' function only available with" "" { target c++20_down } } - // { dg-error "'b' declared 'static' in 'constexpr' context" "" { target c++23 } .-1 } + static double b = 1.0;// { dg-error "'b' defined 'static' in 'constexpr' function only available with" "" { target c++20_down } } + // { dg-error "'b' defined 'static' in 'constexpr' context" "" { target c++23 } .-1 } goto l; // { dg-error "'goto' in 'constexpr' function only available with" "" { target c++20_down } } l:; return 0; } catch (...) { long int c; // { dg-error "uninitialized variable 'c' in 'constexpr' function" "" { target c++17_down } } - static float d = 2.0f;// { dg-error "'d' declared 'static' in 'constexpr' function only available with" "" { target c++20_down } } + static float d = 2.0f;// { dg-error "'d' defined 'static' in 'constexpr' function only available with" "" { target c++20_down } } goto l2; // { dg-error "'goto' in 'constexpr' function only available with" "" { target c++20_down } } l2:; return -1; @@ -21,20 +21,20 @@ try { // { dg-warning "function-try-block body of 'constexpr' function only av constexpr int bar () { int a; // { dg-error "uninitialized variable 'a' in 'constexpr' function" "" { target c++17_down } } - static long double b = 3.0;// { dg-error "'b' declared 'static' in 'constexpr' function only available with" "" { target c++20_down } } - // { dg-error "'b' declared 'static' in 'constexpr' context" "" { target c++23 } .-1 } + static long double b = 3.0;// { dg-error "'b' defined 'static' in 'constexpr' function only available with" "" { target c++20_down } } + // { dg-error "'b' defined 'static' in 'constexpr' context" "" { target c++23 } .-1 } goto l; // { dg-error "'goto' in 'constexpr' function only available with" "" { target c++20_down } } l:; try { // { dg-warning "'try' in 'constexpr' function only available with" "" { target c++17_down } } short c; // { dg-error "uninitialized variable 'c' in 'constexpr' function" "" { target c++17_down } } - static float d; // { dg-error "'d' declared 'static' in 'constexpr' function only available with" "" { target c++20_down } } + static float d; // { dg-error "'d' defined 'static' in 'constexpr' function only available with" "" { target c++20_down } } // { dg-error "uninitialized variable 'd' in 'constexpr' function" "" { target c++17_down } .-1 } goto l2; // { dg-error "'goto' in 'constexpr' function only available with" "" { target c++20_down } } l2:; return 0; } catch (int) { char e; // { dg-error "uninitialized variable 'e' in 'constexpr' function" "" { target c++17_down } } - static int f = 5; // { dg-error "'f' declared 'static' in 'constexpr' function only available with" "" { target c++20_down } } + static int f = 5; // { dg-error "'f' defined 'static' in 'constexpr' function only available with" "" { target c++20_down } } goto l3; // { dg-error "'goto' in 'constexpr' function only available with" "" { target c++20_down } } l3:; return 1; diff --git a/gcc/testsuite/g++.dg/diagnostic/constexpr1.C b/gcc/testsuite/g++.dg/diagnostic/constexpr1.C index f2bcec6..c962a60 100644 --- a/gcc/testsuite/g++.dg/diagnostic/constexpr1.C +++ b/gcc/testsuite/g++.dg/diagnostic/constexpr1.C @@ -1,7 +1,7 @@ // { dg-do compile { target c++11 } } -constexpr int foo() { thread_local int i __attribute__((unused)) {}; return 1; } // { dg-error "40:.i. declared .thread_local." "" { target c++20_down } } -// { dg-error "40:.i. declared .thread_local. in .constexpr. context" "" { target c++23 } .-1 } +constexpr int foo() { thread_local int i __attribute__((unused)) {}; return 1; } // { dg-error "40:.i. defined .thread_local." "" { target c++20_down } } +// { dg-error "40:.i. defined .thread_local. in .constexpr. context" "" { target c++23 } .-1 } -constexpr int bar() { static int i __attribute__((unused)) {}; return 1; } // { dg-error "34:.i. declared .static." "" { target c++20_down } } -// { dg-error "34:.i. declared .static. in .constexpr. context" "" { target c++23 } .-1 } +constexpr int bar() { static int i __attribute__((unused)) {}; return 1; } // { dg-error "34:.i. defined .static." "" { target c++20_down } } +// { dg-error "34:.i. defined .static. in .constexpr. context" "" { target c++23 } .-1 } |