Skip to content

Commit f128607

Browse files
authored
[clang][MSVC] Correct mangling of thread-safe static initialization variables. (#85300)
Static local variables with dynamic initializers depend on implicitly defined guard variables to synchronize thread-safe initialization. These guard variables may have external linkage and therefore require a stable name for linkage purposes. The Microsoft ABI assigns these variables a local name of '$TSS' followed by a discriminator and mangles them as a static local variable of type 'int'. Previously, the '$TSS<discriminator>' portion of the name was not registered as a back reference candidate and this resulted in incorrect back references for enclosing class and/or namespace scopes that might be referenced in the signature of the enclosing function. This change adds the previously missing back reference registration. This matches the mangling performed by MSVC and resolves incompatibilities when inline functions with static local variables are inlined across DLL boundaries. This is an ABI change and has the potential to cause backward compatibility issues with previous Clang releases. Fixes #83616
1 parent 8d7ee46 commit f128607

File tree

3 files changed

+26
-2
lines changed

3 files changed

+26
-2
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,12 @@ C++ Specific Potentially Breaking Changes
4747

4848
ABI Changes in This Version
4949
---------------------------
50+
- Fixed Microsoft name mangling of implicitly defined variables used for thread
51+
safe static initialization of static local variables. This change resolves
52+
incompatibilities with code compiled by MSVC but might introduce
53+
incompatibilities with code compiled by earlier versions of Clang when an
54+
inline member function that contains a static local variable with a dynamic
55+
initializer is declared with ``__declspec(dllimport)``. (#GH83616).
5056

5157
AST Dumping Potentially Breaking Changes
5258
----------------------------------------

clang/lib/AST/MicrosoftMangle.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,7 @@ class MicrosoftCXXNameMangler {
390390
const FunctionDecl *D = nullptr,
391391
bool ForceThisQuals = false,
392392
bool MangleExceptionSpec = true);
393+
void mangleSourceName(StringRef Name);
393394
void mangleNestedName(GlobalDecl GD);
394395

395396
private:
@@ -408,7 +409,6 @@ class MicrosoftCXXNameMangler {
408409
mangleUnqualifiedName(GD, cast<NamedDecl>(GD.getDecl())->getDeclName());
409410
}
410411
void mangleUnqualifiedName(GlobalDecl GD, DeclarationName Name);
411-
void mangleSourceName(StringRef Name);
412412
void mangleOperatorName(OverloadedOperatorKind OO, SourceLocation Loc);
413413
void mangleCXXDtorType(CXXDtorType T);
414414
void mangleQualifiers(Qualifiers Quals, bool IsMember);
@@ -3920,7 +3920,8 @@ void MicrosoftMangleContextImpl::mangleThreadSafeStaticGuardVariable(
39203920
msvc_hashing_ostream MHO(Out);
39213921
MicrosoftCXXNameMangler Mangler(*this, MHO);
39223922

3923-
Mangler.getStream() << "?$TSS" << GuardNum << '@';
3923+
Mangler.getStream() << "?";
3924+
Mangler.mangleSourceName("$TSS" + llvm::utostr(GuardNum));
39243925
Mangler.mangleNestedName(VD);
39253926
Mangler.getStream() << "@4HA";
39263927
}

clang/test/CodeGenCXX/mangle-ms-back-references.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,3 +83,20 @@ class H;
8383

8484
void ManyParams(T01 &, T02 &, T03 &, T04 &, T05 &, T06 &, T07 &, T08 &, T09 &, T10 &, H<T11> &, H<T11> &) {}
8585
// CHECK: "?ManyParams@@YAXAAVT01@@AAVT02@@AAVT03@@AAVT04@@AAVT05@@AAVT06@@AAVT07@@AAVT08@@AAVT09@@AAVT10@@AAV?$H@VT11@@@@AAV?$H@VT11@@@@@Z"
86+
87+
namespace NS {
88+
// The name "TSS0" for the name of the class below has been specifically
89+
// chosen to ensure that back reference lookup does not match against the
90+
// implicitly generated "$TSS0" name of the thread safe static initialization
91+
// variable.
92+
struct __declspec(dllexport) TSS0 {
93+
static TSS0& get();
94+
__forceinline static TSS0& singleton() {
95+
static TSS0& lsv = get();
96+
return lsv;
97+
}
98+
};
99+
}
100+
// CHECK: "?singleton@TSS0@NS@@SAAAU12@XZ"
101+
// CHECK: "?lsv@?1??singleton@TSS0@NS@@SAAAU23@XZ@4AAU23@A"
102+
// CHECK: "?$TSS0@?1??singleton@TSS0@NS@@SAAAU23@XZ@4HA"

0 commit comments

Comments
 (0)