Author: Aaron Ballman Date: 2023-10-25T07:51:28-04:00 New Revision: 66f4a1399d7de3d38312a5b251d4f8acd75237ca
URL: https://github.com/llvm/llvm-project/commit/66f4a1399d7de3d38312a5b251d4f8acd75237ca DIFF: https://github.com/llvm/llvm-project/commit/66f4a1399d7de3d38312a5b251d4f8acd75237ca.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 4cc148905d4e130..c0514e5b70783b6 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -496,6 +496,10 @@ Bug Fixes in This Version Fixes (`#65143 <https://github.com/llvm/llvm-project/issues/65143>`_) - Fix crash in formatting the real/imaginary part of a complex lvalue. Fixes (`#69218 <https://github.com/llvm/llvm-project/issues/69218>`_) +- 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 14a28e5a31c57db..78c3ab72979a007 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -4076,8 +4076,15 @@ void Parser::ParseDeclarationSpecifiers( case tok::kw_thread_local: if (getLangOpts().C23) Diag(Tok, diag::warn_c23_compat_keyword) << Tok.getName(); - isInvalid = DS.SetStorageClassSpecThread(DeclSpec::TSCS_thread_local, Loc, - PrevSpec, DiagID); + // 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().C23 ? 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; _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits