Set a tentative TLS model in grokdeclarator and update DECL_TLS_MODEL
with the default TLS access model after a TLS variable has been fully
processed if the default TLS access model is stronger.
gcc/c/
PR c/107419
* c-decl.cc (grokdeclarator): Add a pointer to bool argument to
indicate if DECL_TLS_MODEL should be updated later. Set a
tentative TLS model if DECL_TLS_MODEL will be updated later.
(start_decl): Pass a pointer to bool argument to grokdeclarator.
Call set_decl_tls_model to update DECL_TLS_MODEL with the default
TLS access model after calling grokdeclarator if the default TLS
access model is stronger.
gcc/testsuite/
PR c/107419
* c-c++-common/tls-attr-common.c: New test.
* c-c++-common/tls-attr-le-pic.c: Likewise.
* c-c++-common/tls-attr-le-pie.c: Likewise.
Signed-off-by: H.J. Lu <[email protected]>
---
gcc/c/c-decl.cc | 33 +++++++++++++++++---
gcc/testsuite/c-c++-common/tls-attr-common.c | 17 ++++++++++
gcc/testsuite/c-c++-common/tls-attr-le-pic.c | 15 +++++++++
gcc/testsuite/c-c++-common/tls-attr-le-pie.c | 15 +++++++++
4 files changed, 76 insertions(+), 4 deletions(-)
create mode 100644 gcc/testsuite/c-c++-common/tls-attr-common.c
create mode 100644 gcc/testsuite/c-c++-common/tls-attr-le-pic.c
create mode 100644 gcc/testsuite/c-c++-common/tls-attr-le-pie.c
diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
index 4bef43864a1..c07ba82689c 100644
--- a/gcc/c/c-decl.cc
+++ b/gcc/c/c-decl.cc
@@ -685,7 +685,8 @@ static tree c_make_fname_decl (location_t, tree, int);
static tree grokdeclarator (const struct c_declarator *,
struct c_declspecs *,
enum decl_context, bool, tree *, tree *, tree *,
- bool *, enum deprecated_states);
+ bool *, enum deprecated_states,
+ bool * = nullptr);
static tree grokparms (struct c_arg_info *, bool);
static void layout_array_type (tree);
static const char *header_for_builtin_fn (tree);
@@ -5603,9 +5604,10 @@ start_decl (struct c_declarator *declarator, struct
c_declspecs *declspecs,
else if (lookup_attribute ("deprecated", attributes))
deprecated_state = DEPRECATED_SUPPRESS;
+ bool tls_model_p = false;
decl = grokdeclarator (declarator, declspecs,
NORMAL, initialized, NULL, &attributes, &expr, NULL,
- deprecated_state);
+ deprecated_state, &tls_model_p);
if (!decl || decl == error_mark_node)
return NULL_TREE;
@@ -5722,6 +5724,15 @@ start_decl (struct c_declarator *declarator, struct
c_declspecs *declspecs,
DECL_EXTERNAL (decl) = !DECL_EXTERNAL (decl);
}
+ if (tls_model_p)
+ {
+ // tls_model attribute can set a stronger TLS access model.
+ tls_model model = DECL_TLS_MODEL (decl);
+ tls_model default_model = decl_default_tls_model (decl);
+ if (default_model > model)
+ set_decl_tls_model (decl, default_model);
+ }
+
if (TREE_CODE (decl) == FUNCTION_DECL
&& DECL_DECLARED_INLINE_P (decl)
&& DECL_UNINLINABLE (decl)
@@ -6819,7 +6830,8 @@ grokdeclarator (const struct c_declarator *declarator,
struct c_declspecs *declspecs,
enum decl_context decl_context, bool initialized, tree *width,
tree *decl_attrs, tree *expr, bool *expr_const_operands,
- enum deprecated_states deprecated_state)
+ enum deprecated_states deprecated_state,
+ bool *tls_model_p)
{
tree type = declspecs->type;
bool threadp = declspecs->thread_p;
@@ -8312,7 +8324,20 @@ grokdeclarator (const struct c_declarator *declarator,
}
if (threadp)
- set_decl_tls_model (decl, decl_default_tls_model (decl));
+ {
+ tls_model model;
+ if (tls_model_p)
+ {
+ // NB: Set a tentative TLS model to avoid tls_model
+ // attribute warnings due to lack of thread storage
+ // duration. It will be updated later.
+ model = TLS_MODEL_REAL;
+ *tls_model_p = true;
+ }
+ else
+ model = decl_default_tls_model (decl);
+ set_decl_tls_model (decl, model);
+ }
}
if ((storage_class == csc_extern
diff --git a/gcc/testsuite/c-c++-common/tls-attr-common.c
b/gcc/testsuite/c-c++-common/tls-attr-common.c
new file mode 100644
index 00000000000..07c3fd2d440
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/tls-attr-common.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target fpic } */
+/* { dg-require-effective-target tls } */
+/* { dg-options "-O2 -fno-pic -fdump-ipa-whole-program" } */
+/* { dg-additional-options "-mno-direct-extern-access" } */
+
+__attribute__((common))
+__thread int i;
+
+int *
+foo (void)
+{
+ return &i;
+}
+
+/* tls_model should be tls-initial-exec due to common attribute. */
+/* { dg-final { scan-ipa-dump "Varpool flags: tls-initial-exec"
"whole-program" } } */
diff --git a/gcc/testsuite/c-c++-common/tls-attr-le-pic.c
b/gcc/testsuite/c-c++-common/tls-attr-le-pic.c
new file mode 100644
index 00000000000..c02df6919f1
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/tls-attr-le-pic.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target fpic } */
+/* { dg-require-effective-target tls } */
+/* { dg-options "-O2 -fpic -fdump-ipa-whole-program" } */
+
+__attribute__ ((tls_model ("local-exec"))) __thread int i;
+
+int *
+foo (void)
+{
+ return &i;
+}
+
+/* tls_model should be local-exec due to tls_model attribute. */
+/* { dg-final { scan-ipa-dump "Varpool flags: tls-local-exec" "whole-program"
} } */
diff --git a/gcc/testsuite/c-c++-common/tls-attr-le-pie.c
b/gcc/testsuite/c-c++-common/tls-attr-le-pie.c
new file mode 100644
index 00000000000..b8ef7840d79
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/tls-attr-le-pie.c
@@ -0,0 +1,15 @@
+/* { dg-do compile { target { tls && pie } } } */
+/* { dg-options "-O2 -fPIE -fdump-ipa-whole-program" } */
+
+extern const int afoo[3];
+
+__thread const int *pfoo __attribute__ ((tls_model ("initial-exec"))) = afoo;
+
+const int **
+ppfoo (void)
+{
+ return &pfoo;
+}
+
+/* tls_model should be local-exec due to -fPIE. */
+/* { dg-final { scan-ipa-dump "Varpool flags: initialized tls-local-exec"
"whole-program" } } */
--
2.50.1