[clang] 5d086cc - [Clang] perform "maximum TLS alignment" check for template instantiation
Yuanfang Chen via cfe-commits
cfe-commits at lists.llvm.org
Sun Oct 30 22:40:24 PDT 2022
Author: Yuanfang Chen
Date: 2022-10-30T22:39:47-07:00
New Revision: 5d086cce8b92680a2cdadf1f07d4267cd374122e
URL: https://github.com/llvm/llvm-project/commit/5d086cce8b92680a2cdadf1f07d4267cd374122e
DIFF: https://github.com/llvm/llvm-project/commit/5d086cce8b92680a2cdadf1f07d4267cd374122e.diff
LOG: [Clang] perform "maximum TLS alignment" check for template instantiation
follow up https://github.com/llvm/llvm-project/commit/d30e2eefc3cf8dfd2210aefd62f13a6e7c011b43
Reviewed By: mizvekov
Differential Revision: https://reviews.llvm.org/D136744
Added:
Modified:
clang/include/clang/Sema/Sema.h
clang/lib/Sema/SemaDecl.cpp
clang/lib/Sema/SemaDeclAttr.cpp
clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
clang/test/Sema/tls_alignment.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index b32dfe158c8f3..23b4e3f60cef1 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -3013,6 +3013,7 @@ class Sema final {
void SetDeclDeleted(Decl *dcl, SourceLocation DelLoc);
void SetDeclDefaulted(Decl *dcl, SourceLocation DefaultLoc);
void CheckStaticLocalForDllExport(VarDecl *VD);
+ void CheckThreadLocalForLargeAlignment(VarDecl *VD);
void FinalizeDeclaration(Decl *D);
DeclGroupPtrTy FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS,
ArrayRef<Decl *> Group);
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 19bd670e791bc..686a126968e8a 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -14032,6 +14032,26 @@ void Sema::CheckStaticLocalForDllExport(VarDecl *VD) {
}
}
+void Sema::CheckThreadLocalForLargeAlignment(VarDecl *VD) {
+ assert(VD->getTLSKind());
+
+ // Perform TLS alignment check here after attributes attached to the variable
+ // which may affect the alignment have been processed. Only perform the check
+ // if the target has a maximum TLS alignment (zero means no constraints).
+ if (unsigned MaxAlign = Context.getTargetInfo().getMaxTLSAlign()) {
+ // Protect the check so that it's not performed on dependent types and
+ // dependent alignments (we can't determine the alignment in that case).
+ if (!VD->hasDependentAlignment()) {
+ CharUnits MaxAlignChars = Context.toCharUnitsFromBits(MaxAlign);
+ if (Context.getDeclAlign(VD) > MaxAlignChars) {
+ Diag(VD->getLocation(), diag::err_tls_var_aligned_over_maximum)
+ << (unsigned)Context.getDeclAlign(VD).getQuantity() << VD
+ << (unsigned)MaxAlignChars.getQuantity();
+ }
+ }
+ }
+}
+
/// FinalizeDeclaration - called by ParseDeclarationAfterDeclarator to perform
/// any semantic actions necessary after any initializer has been attached.
void Sema::FinalizeDeclaration(Decl *ThisDecl) {
@@ -14075,25 +14095,12 @@ void Sema::FinalizeDeclaration(Decl *ThisDecl) {
checkAttributesAfterMerging(*this, *VD);
- // Perform TLS alignment check here after attributes attached to the variable
- // which may affect the alignment have been processed. Only perform the check
- // if the target has a maximum TLS alignment (zero means no constraints).
- if (unsigned MaxAlign = Context.getTargetInfo().getMaxTLSAlign()) {
- // Protect the check so that it's not performed on dependent types and
- // dependent alignments (we can't determine the alignment in that case).
- if (VD->getTLSKind() && !VD->hasDependentAlignment()) {
- CharUnits MaxAlignChars = Context.toCharUnitsFromBits(MaxAlign);
- if (Context.getDeclAlign(VD) > MaxAlignChars) {
- Diag(VD->getLocation(), diag::err_tls_var_aligned_over_maximum)
- << (unsigned)Context.getDeclAlign(VD).getQuantity() << VD
- << (unsigned)MaxAlignChars.getQuantity();
- }
- }
- }
-
if (VD->isStaticLocal())
CheckStaticLocalForDllExport(VD);
+ if (VD->getTLSKind())
+ CheckThreadLocalForLargeAlignment(VD);
+
// Perform check for initializers of device-side global variables.
// CUDA allows empty constructors as initializers (see E.2.3.1, CUDA
// 7.5). We must also apply the same checks to all __shared__
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index d8dd1ab8e1d17..da9aa611793f9 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -4341,7 +4341,7 @@ void Sema::AddAlignedAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E,
}
const auto *VD = dyn_cast<VarDecl>(D);
- if (VD && Context.getTargetInfo().isTLSSupported()) {
+ if (VD) {
unsigned MaxTLSAlign =
Context.toCharUnitsFromBits(Context.getTargetInfo().getMaxTLSAlign())
.getQuantity();
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index e034094431bb7..49be412df64c0 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -1179,6 +1179,9 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D,
if (Var->isStaticLocal())
SemaRef.CheckStaticLocalForDllExport(Var);
+ if (Var->getTLSKind())
+ SemaRef.CheckThreadLocalForLargeAlignment(Var);
+
return Var;
}
diff --git a/clang/test/Sema/tls_alignment.cpp b/clang/test/Sema/tls_alignment.cpp
index 18db565055d0e..c5c79aafa9ead 100644
--- a/clang/test/Sema/tls_alignment.cpp
+++ b/clang/test/Sema/tls_alignment.cpp
@@ -58,27 +58,34 @@ int baz ()
bar5.some_data[5];
}
-
-// Verify alignment check where a dependent type is involved.
-// The check is (correctly) not performed on "t", but the check still is
-// performed on the structure as a whole once it has been instantiated.
-
template<class T> struct templated_tls {
static __thread T t;
T other_t __attribute__(( aligned(64) ));
};
-__thread templated_tls<int> blah; // expected-error{{alignment (64) of thread-local variable}}
-
-int blag() {
- return blah.other_t * 2;
-}
+ __thread templated_tls<int> blah; // expected-error{{alignment (64) of thread-local variable}}
-
-// Verify alignment check where the alignment is a template parameter.
-// The check is only performed during instantiation.
template <int N>
struct S {
+ struct alignas(64) B {};
+ struct alignas(N) C {};
+ static inline void f() {
+ thread_local B b; // expected-error{{alignment (64) of thread-local variable}}
+ thread_local C c; // expected-error{{alignment (64) of thread-local variable}}
+ }
+ template<int J> static inline thread_local int b alignas(J) = J; // expected-error{{alignment (64) of thread-local variable}}
static int __thread __attribute__((aligned(N))) x; // expected-error{{alignment (64) of thread-local variable}}
};
-S<64> s_instance; // expected-note{{in instantiation of template class 'S<64>' requested here}}
+int blag() {
+ // Verify alignment check where the alignment is a template parameter.
+ // The check is only performed during instantiation.
+ S<64> s_instance; // expected-note{{in instantiation of template class 'S<64>' requested here}}
+
+ // Verify alignment for dependent local variables.
+ S<64>::f(); // expected-note{{in instantiation of member function 'S<64>::f' requested here}}
+
+ // Verify alignment check where a dependent type is involved.
+ // The check is (correctly) not performed on "t", but the check still is
+ // performed on the structure as a whole once it has been instantiated.
+ return blah.other_t * 2 + S<64>::b<64>; // expected-note{{in instantiation of static data member 'S<64>::b' requested here}}
+}
More information about the cfe-commits
mailing list