[llvm-branch-commits] [clang] 2a41d97 - [C23] Use thread_local semantics (#70107)

Tobias Hieta via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Fri Oct 27 05:51:06 PDT 2023


Author: Aaron Ballman
Date: 2023-10-27T14:47:29+02:00
New Revision: 2a41d978b4fa6dee568e247dd8bd9cabf34660b4

URL: https://github.com/llvm/llvm-project/commit/2a41d978b4fa6dee568e247dd8bd9cabf34660b4
DIFF: https://github.com/llvm/llvm-project/commit/2a41d978b4fa6dee568e247dd8bd9cabf34660b4.diff

LOG: [C23] Use thread_local semantics (#70107)

When implementing thread_local as a keyword in C23, we accidentally
started using C++11 thread_local semantics when using that keyword
instead of using C11 _Thread_local semantics.

This oversight is fixed by pretending the user wrote _Thread_local
instead. This doesn't have the best behavior in terms of diagnostics,
but it does correct the semantic behavior.

Fixes https://github.com/llvm/llvm-project/issues/70068
Fixes https://github.com/llvm/llvm-project/issues/69167

Added: 
    clang/test/CodeGen/thread_local.c
    clang/test/Sema/thread_local.c

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/lib/Parse/ParseDecl.cpp

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 3323c6ceb2bcffb..88844ad9b4c5566 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -719,6 +719,10 @@ Bug Fixes in This Version
   points (i.e., uses function descriptor objects instead).
 - Fixes a ``clang-17`` regression where ``LLVM_UNREACHABLE_OPTIMIZE=OFF``
   cannot be used with ``Release`` mode builds. (`#68237 <https://github.com/llvm/llvm-project/issues/68237>`_).
+- No longer use C++ ``thread_local`` semantics in C23 when using
+  ``thread_local`` instead of ``_Thread_local``.
+  Fixes (`#70068 <https://github.com/llvm/llvm-project/issues/70068>`_) and
+  (`#69167 <https://github.com/llvm/llvm-project/issues/69167>`_)
 
 Bug Fixes to Compiler Builtins
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

diff  --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index 43b2a32cce71ca3..46315cc4e4115e3 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -3997,9 +3997,16 @@ void Parser::ParseDeclarationSpecifiers(
       break;
     case tok::kw_thread_local:
       if (getLangOpts().C2x)
-        Diag(Tok, diag::warn_c2x_compat_keyword) << Tok.getName();
-      isInvalid = DS.SetStorageClassSpecThread(DeclSpec::TSCS_thread_local, Loc,
-                                               PrevSpec, DiagID);
+        Diag(Tok, diag::warn_c23_compat_keyword) << Tok.getName();
+      // We map thread_local to _Thread_local in C23 mode so it retains the C
+      // semantics rather than getting the C++ semantics.
+      // FIXME: diagnostics will show _Thread_local when the user wrote
+      // thread_local in source in C23 mode; we need some general way to
+      // identify which way the user spelled the keyword in source.
+      isInvalid = DS.SetStorageClassSpecThread(
+          getLangOpts().C2x ? DeclSpec::TSCS__Thread_local
+                            : DeclSpec::TSCS_thread_local,
+          Loc, PrevSpec, DiagID);
       isStorageClass = true;
       break;
     case tok::kw__Thread_local:

diff  --git a/clang/test/CodeGen/thread_local.c b/clang/test/CodeGen/thread_local.c
new file mode 100644
index 000000000000000..b97f31c2fff2f6c
--- /dev/null
+++ b/clang/test/CodeGen/thread_local.c
@@ -0,0 +1,27 @@
+// RUN: %clang_cc1 -triple i686-pc-linux-gnu -std=c23 -emit-llvm -o - %s | FileCheck %s
+
+// Ensure that thread_local and _Thread_local emit the same codegen. See
+// https://github.com/llvm/llvm-project/issues/70068 for details.
+
+void func(void) {
+  static thread_local int i = 12;
+  static _Thread_local int j = 13;
+
+  extern thread_local int k;
+  extern thread_local int l;
+
+  (void)k;
+  (void)l;
+}
+
+// CHECK:      @func.i = internal thread_local global i32 12, align 4
+// CHECK-NEXT: @func.j = internal thread_local global i32 13, align 4
+// CHECK-NEXT: @k = external thread_local global i32, align 4
+// CHECK-NEXT: @l = external thread_local global i32, align 4
+
+// CHECK:      define dso_local void @func()
+// CHECK-NEXT: entry:
+// CHECK-NEXT: %[[K:.+]] = call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @k)
+// CHECK-NEXT: load i32, ptr %[[K]], align 4
+// CHECK-NEXT: %[[L:.+]] = call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @l)
+// CHECK-NEXT: load i32, ptr %[[L]], align 4

diff  --git a/clang/test/Sema/thread_local.c b/clang/test/Sema/thread_local.c
new file mode 100644
index 000000000000000..a0de0aa4e39a6e1
--- /dev/null
+++ b/clang/test/Sema/thread_local.c
@@ -0,0 +1,19 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c23 %s -verify
+
+// Ensure that thread_local and _Thread_local are synonyms in C23 and both
+// restrict local variables to be explicitly static or extern.
+void func(void) {
+  // FIXME: it would be nice if the diagnostic said 'thread_local' in this case.
+  thread_local int i = 12;  // expected-error {{'_Thread_local' variables must have global storage}}
+  _Thread_local int j = 13; // expected-error {{'_Thread_local' variables must have global storage}}
+
+  static thread_local int k = 14;
+  static _Thread_local int l = 15;
+
+  extern thread_local int m;
+  extern thread_local int n;
+}
+
+// This would previously fail because the tls models were 
diff erent.
+extern thread_local unsigned a;
+_Thread_local unsigned a = 0;


        


More information about the llvm-branch-commits mailing list