Skip to content

Commit 5d086cc

Browse files
author
Yuanfang Chen
committed
[Clang] perform "maximum TLS alignment" check for template instantiation
follow up llvm@d30e2ee Reviewed By: mizvekov Differential Revision: https://reviews.llvm.org/D136744
1 parent d1115c2 commit 5d086cc

File tree

5 files changed

+49
-31
lines changed

5 files changed

+49
-31
lines changed

clang/include/clang/Sema/Sema.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3013,6 +3013,7 @@ class Sema final {
30133013
void SetDeclDeleted(Decl *dcl, SourceLocation DelLoc);
30143014
void SetDeclDefaulted(Decl *dcl, SourceLocation DefaultLoc);
30153015
void CheckStaticLocalForDllExport(VarDecl *VD);
3016+
void CheckThreadLocalForLargeAlignment(VarDecl *VD);
30163017
void FinalizeDeclaration(Decl *D);
30173018
DeclGroupPtrTy FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS,
30183019
ArrayRef<Decl *> Group);

clang/lib/Sema/SemaDecl.cpp

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -14032,6 +14032,26 @@ void Sema::CheckStaticLocalForDllExport(VarDecl *VD) {
1403214032
}
1403314033
}
1403414034

14035+
void Sema::CheckThreadLocalForLargeAlignment(VarDecl *VD) {
14036+
assert(VD->getTLSKind());
14037+
14038+
// Perform TLS alignment check here after attributes attached to the variable
14039+
// which may affect the alignment have been processed. Only perform the check
14040+
// if the target has a maximum TLS alignment (zero means no constraints).
14041+
if (unsigned MaxAlign = Context.getTargetInfo().getMaxTLSAlign()) {
14042+
// Protect the check so that it's not performed on dependent types and
14043+
// dependent alignments (we can't determine the alignment in that case).
14044+
if (!VD->hasDependentAlignment()) {
14045+
CharUnits MaxAlignChars = Context.toCharUnitsFromBits(MaxAlign);
14046+
if (Context.getDeclAlign(VD) > MaxAlignChars) {
14047+
Diag(VD->getLocation(), diag::err_tls_var_aligned_over_maximum)
14048+
<< (unsigned)Context.getDeclAlign(VD).getQuantity() << VD
14049+
<< (unsigned)MaxAlignChars.getQuantity();
14050+
}
14051+
}
14052+
}
14053+
}
14054+
1403514055
/// FinalizeDeclaration - called by ParseDeclarationAfterDeclarator to perform
1403614056
/// any semantic actions necessary after any initializer has been attached.
1403714057
void Sema::FinalizeDeclaration(Decl *ThisDecl) {
@@ -14075,25 +14095,12 @@ void Sema::FinalizeDeclaration(Decl *ThisDecl) {
1407514095

1407614096
checkAttributesAfterMerging(*this, *VD);
1407714097

14078-
// Perform TLS alignment check here after attributes attached to the variable
14079-
// which may affect the alignment have been processed. Only perform the check
14080-
// if the target has a maximum TLS alignment (zero means no constraints).
14081-
if (unsigned MaxAlign = Context.getTargetInfo().getMaxTLSAlign()) {
14082-
// Protect the check so that it's not performed on dependent types and
14083-
// dependent alignments (we can't determine the alignment in that case).
14084-
if (VD->getTLSKind() && !VD->hasDependentAlignment()) {
14085-
CharUnits MaxAlignChars = Context.toCharUnitsFromBits(MaxAlign);
14086-
if (Context.getDeclAlign(VD) > MaxAlignChars) {
14087-
Diag(VD->getLocation(), diag::err_tls_var_aligned_over_maximum)
14088-
<< (unsigned)Context.getDeclAlign(VD).getQuantity() << VD
14089-
<< (unsigned)MaxAlignChars.getQuantity();
14090-
}
14091-
}
14092-
}
14093-
1409414098
if (VD->isStaticLocal())
1409514099
CheckStaticLocalForDllExport(VD);
1409614100

14101+
if (VD->getTLSKind())
14102+
CheckThreadLocalForLargeAlignment(VD);
14103+
1409714104
// Perform check for initializers of device-side global variables.
1409814105
// CUDA allows empty constructors as initializers (see E.2.3.1, CUDA
1409914106
// 7.5). We must also apply the same checks to all __shared__

clang/lib/Sema/SemaDeclAttr.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4341,7 +4341,7 @@ void Sema::AddAlignedAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E,
43414341
}
43424342

43434343
const auto *VD = dyn_cast<VarDecl>(D);
4344-
if (VD && Context.getTargetInfo().isTLSSupported()) {
4344+
if (VD) {
43454345
unsigned MaxTLSAlign =
43464346
Context.toCharUnitsFromBits(Context.getTargetInfo().getMaxTLSAlign())
43474347
.getQuantity();

clang/lib/Sema/SemaTemplateInstantiateDecl.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1179,6 +1179,9 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D,
11791179
if (Var->isStaticLocal())
11801180
SemaRef.CheckStaticLocalForDllExport(Var);
11811181

1182+
if (Var->getTLSKind())
1183+
SemaRef.CheckThreadLocalForLargeAlignment(Var);
1184+
11821185
return Var;
11831186
}
11841187

clang/test/Sema/tls_alignment.cpp

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -58,27 +58,34 @@ int baz ()
5858
bar5.some_data[5];
5959
}
6060

61-
62-
// Verify alignment check where a dependent type is involved.
63-
// The check is (correctly) not performed on "t", but the check still is
64-
// performed on the structure as a whole once it has been instantiated.
65-
6661
template<class T> struct templated_tls {
6762
static __thread T t;
6863
T other_t __attribute__(( aligned(64) ));
6964
};
70-
__thread templated_tls<int> blah; // expected-error{{alignment (64) of thread-local variable}}
71-
72-
int blag() {
73-
return blah.other_t * 2;
74-
}
65+
__thread templated_tls<int> blah; // expected-error{{alignment (64) of thread-local variable}}
7566

76-
77-
// Verify alignment check where the alignment is a template parameter.
78-
// The check is only performed during instantiation.
7967
template <int N>
8068
struct S {
69+
struct alignas(64) B {};
70+
struct alignas(N) C {};
71+
static inline void f() {
72+
thread_local B b; // expected-error{{alignment (64) of thread-local variable}}
73+
thread_local C c; // expected-error{{alignment (64) of thread-local variable}}
74+
}
75+
template<int J> static inline thread_local int b alignas(J) = J; // expected-error{{alignment (64) of thread-local variable}}
8176
static int __thread __attribute__((aligned(N))) x; // expected-error{{alignment (64) of thread-local variable}}
8277
};
8378

84-
S<64> s_instance; // expected-note{{in instantiation of template class 'S<64>' requested here}}
79+
int blag() {
80+
// Verify alignment check where the alignment is a template parameter.
81+
// The check is only performed during instantiation.
82+
S<64> s_instance; // expected-note{{in instantiation of template class 'S<64>' requested here}}
83+
84+
// Verify alignment for dependent local variables.
85+
S<64>::f(); // expected-note{{in instantiation of member function 'S<64>::f' requested here}}
86+
87+
// Verify alignment check where a dependent type is involved.
88+
// The check is (correctly) not performed on "t", but the check still is
89+
// performed on the structure as a whole once it has been instantiated.
90+
return blah.other_t * 2 + S<64>::b<64>; // expected-note{{in instantiation of static data member 'S<64>::b' requested here}}
91+
}

0 commit comments

Comments
 (0)