diff options
author | Joseph Myers <joseph@codesourcery.com> | 2013-11-12 17:38:47 +0000 |
---|---|---|
committer | Joseph Myers <jsm28@gcc.gnu.org> | 2013-11-12 17:38:47 +0000 |
commit | 582d9b50ed4166d1e561b76db84e73298a1429a9 (patch) | |
tree | dc4dfcb336fe8a6bf6fab451a6d9be16fbe15ec3 /gcc/c/c-decl.c | |
parent | e9dc054758a019d3687d1b7e4e188bd5d2468444 (diff) | |
download | gcc-582d9b50ed4166d1e561b76db84e73298a1429a9.zip gcc-582d9b50ed4166d1e561b76db84e73298a1429a9.tar.gz gcc-582d9b50ed4166d1e561b76db84e73298a1429a9.tar.bz2 |
c-common.c (c_common_reswords): Add _Thread_local.
c-family:
* c-common.c (c_common_reswords): Add _Thread_local.
c:
* c-tree.h (struct c_declspecs): Add thread_gnu_p field.
* c-parser.c (c_parser_declspecs): Mention _Thread_local in
comment.
* c-decl.c (shadow_tag_warned, grokdeclarator): Mention __thread
or _Thread_local as appropriate in diagnostics.
(build_null_declspecs): Initialize ret->thread_gnu_p.
(declspecs_add_scspec): Handle either __thread or _Thread_local
for RID_THREAD. Diagnose _Thread_local for pre-C11 standards if
pedantic. Do not disallow _Thread_local extern and _Thread_local
static.
testsuite:
* gcc.dg/c90-thread-local-1.c, gcc.dg/c99-thread-local-1.c,
gcc.dg/c11-thread-local-1.c, gcc.dg/c11-thread-local-2.c: New
tests.
* gcc.dg/tls/diag-2.c, objc.dg/tls/diag-2.m: Update expected
diagnostics.
From-SVN: r204711
Diffstat (limited to 'gcc/c/c-decl.c')
-rw-r--r-- | gcc/c/c-decl.c | 47 |
1 files changed, 36 insertions, 11 deletions
diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c index 9520e4d..6fe418e 100644 --- a/gcc/c/c-decl.c +++ b/gcc/c/c-decl.c @@ -3805,7 +3805,8 @@ shadow_tag_warned (const struct c_declspecs *declspecs, int warned) if (!warned && !in_system_header && declspecs->thread_p) { - warning (0, "useless %<__thread%> in empty declaration"); + warning (0, "useless %qs in empty declaration", + declspecs->thread_gnu_p ? "__thread" : "_Thread_local"); warned = 2; } @@ -5164,7 +5165,8 @@ grokdeclarator (const struct c_declarator *declarator, if (storage_class == csc_typedef) error_at (loc, "function definition declared %<typedef%>"); if (threadp) - error_at (loc, "function definition declared %<__thread%>"); + error_at (loc, "function definition declared %qs", + declspecs->thread_gnu_p ? "__thread" : "_Thread_local"); threadp = false; if (storage_class == csc_auto || storage_class == csc_register @@ -5233,8 +5235,8 @@ grokdeclarator (const struct c_declarator *declarator, else if (threadp && storage_class == csc_none) { error_at (loc, "function-scope %qE implicitly auto and declared " - "%<__thread%>", - name); + "%qs", name, + declspecs->thread_gnu_p ? "__thread" : "_Thread_local"); threadp = false; } } @@ -8980,6 +8982,7 @@ build_null_declspecs (void) ret->inline_p = false; ret->noreturn_p = false; ret->thread_p = false; + ret->thread_gnu_p = false; ret->const_p = false; ret->volatile_p = false; ret->atomic_p = false; @@ -9773,14 +9776,29 @@ declspecs_add_scspec (source_location loc, case RID_THREAD: dupe = specs->thread_p; if (specs->storage_class == csc_auto) - error ("%<__thread%> used with %<auto%>"); + error ("%qE used with %<auto%>", scspec); else if (specs->storage_class == csc_register) - error ("%<__thread%> used with %<register%>"); + error ("%qE used with %<register%>", scspec); else if (specs->storage_class == csc_typedef) - error ("%<__thread%> used with %<typedef%>"); + error ("%qE used with %<typedef%>", scspec); else { specs->thread_p = true; + specs->thread_gnu_p = (strcmp (IDENTIFIER_POINTER (scspec), + "__thread") == 0); + /* A diagnostic is not required for the use of this + identifier in the implementation namespace; only diagnose + it for the C11 spelling because of existing code using + the other spelling. */ + if (!flag_isoc11 && !specs->thread_gnu_p) + { + if (flag_isoc99) + pedwarn (loc, OPT_Wpedantic, + "ISO C99 does not support %qE", scspec); + else + pedwarn (loc, OPT_Wpedantic, + "ISO C90 does not support %qE", scspec); + } specs->locations[cdw_thread] = loc; } break; @@ -9790,7 +9808,7 @@ declspecs_add_scspec (source_location loc, case RID_EXTERN: n = csc_extern; /* Diagnose "__thread extern". */ - if (specs->thread_p) + if (specs->thread_p && specs->thread_gnu_p) error ("%<__thread%> before %<extern%>"); break; case RID_REGISTER: @@ -9799,7 +9817,7 @@ declspecs_add_scspec (source_location loc, case RID_STATIC: n = csc_static; /* Diagnose "__thread static". */ - if (specs->thread_p) + if (specs->thread_p && specs->thread_gnu_p) error ("%<__thread%> before %<static%>"); break; case RID_TYPEDEF: @@ -9811,7 +9829,12 @@ declspecs_add_scspec (source_location loc, if (n != csc_none && n == specs->storage_class) dupe = true; if (dupe) - error ("duplicate %qE", scspec); + { + if (i == RID_THREAD) + error ("duplicate %<_Thread_local%> or %<__thread%>"); + else + error ("duplicate %qE", scspec); + } if (n != csc_none) { if (specs->storage_class != csc_none && n != specs->storage_class) @@ -9824,7 +9847,9 @@ declspecs_add_scspec (source_location loc, specs->locations[cdw_storage_class] = loc; if (n != csc_extern && n != csc_static && specs->thread_p) { - error ("%<__thread%> used with %qE", scspec); + error ("%qs used with %qE", + specs->thread_gnu_p ? "__thread" : "_Thread_local", + scspec); specs->thread_p = false; } } |