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