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 <hjl.to...@gmail.com>
---
 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

Reply via email to