#include "clang/Basic/TargetInfo.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/JamCRC.h"
+#include "llvm/Support/xxhash.h"
#include "llvm/Support/MD5.h"
#include "llvm/Support/MathExtras.h"
llvm::DenseMap<const CXXRecordDecl *, unsigned> LambdaIds;
llvm::DenseMap<const NamedDecl *, unsigned> SEHFilterIds;
llvm::DenseMap<const NamedDecl *, unsigned> SEHFinallyIds;
+ SmallString<16> AnonymousNamespaceHash;
public:
- MicrosoftMangleContextImpl(ASTContext &Context, DiagnosticsEngine &Diags)
- : MicrosoftMangleContext(Context, Diags) {}
+ MicrosoftMangleContextImpl(ASTContext &Context, DiagnosticsEngine &Diags);
bool shouldMangleCXXName(const NamedDecl *D) override;
bool shouldMangleStringLiteral(const StringLiteral *SL) override;
void mangleCXXName(const NamedDecl *D, raw_ostream &Out) override;
return Result.first->second;
}
+ /// Return a character sequence that is (somewhat) unique to the TU suitable
+ /// for mangling anonymous namespaces.
+ StringRef getAnonymousNamespaceHash() const {
+ return AnonymousNamespaceHash;
+ }
+
private:
void mangleInitFiniStub(const VarDecl *D, char CharCode, raw_ostream &Out);
};
};
}
+MicrosoftMangleContextImpl::MicrosoftMangleContextImpl(ASTContext &Context,
+ DiagnosticsEngine &Diags)
+ : MicrosoftMangleContext(Context, Diags) {
+ // To mangle anonymous namespaces, hash the path to the main source file. The
+ // path should be whatever (probably relative) path was passed on the command
+ // line. The goal is for the compiler to produce the same output regardless of
+ // working directory, so use the uncanonicalized relative path.
+ //
+ // It's important to make the mangled names unique because, when CodeView
+ // debug info is in use, the debugger uses mangled type names to distinguish
+ // between otherwise identically named types in anonymous namespaces.
+ //
+ // These symbols are always internal, so there is no need for the hash to
+ // match what MSVC produces. For the same reason, clang is free to change the
+ // hash at any time without breaking compatibility with old versions of clang.
+ // The generated names are intended to look similar to what MSVC generates,
+ // which are something like "?A0x01234567@".
+ SourceManager &SM = Context.getSourceManager();
+ if (const FileEntry *FE = SM.getFileEntryForID(SM.getMainFileID())) {
+ // Truncate the hash so we get 8 characters of hexadecimal.
+ uint32_t TruncatedHash = uint32_t(xxHash64(FE->getName()));
+ AnonymousNamespaceHash = llvm::utohexstr(TruncatedHash);
+ } else {
+ // If we don't have a path to the main file, we'll just use 0.
+ AnonymousNamespaceHash = "0";
+ }
+}
+
bool MicrosoftMangleContextImpl::shouldMangleCXXName(const NamedDecl *D) {
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
LanguageLinkage L = FD->getLanguageLinkage();
if (const NamespaceDecl *NS = dyn_cast<NamespaceDecl>(ND)) {
if (NS->isAnonymousNamespace()) {
- Out << "?A@";
+ Out << "?A0x" << Context.getAnonymousNamespaceHash() << '@';
break;
}
}
b.f();
}
-// MS: @[[B_VTABLE:.*]] = private unnamed_addr constant { [2 x i8*] } {{.*}}@"??_R4B@?A@@6B@"{{.*}}@"?f@B@?A@@UEAAXXZ"
+// MS: @[[B_VTABLE:.*]] = private unnamed_addr constant { [2 x i8*] } {{.*}}@"??_R4B@?A0x{{[^@]*}}@@6B@"{{.*}}@"?f@B@?A0x{{[^@]*}}@@UEAAXXZ"
// CHECK: %[[VT:.*]] = load void (%struct.A*)**, void (%struct.A*)***
// CHECK: %[[VT2:.*]] = bitcast {{.*}}%[[VT]] to i8*, !nosanitize
}
// ITANIUM: define internal void @_ZN12_GLOBAL__N_11fENS_1SE({{.*}} !type [[TS1:![0-9]+]] !type [[TS2:![0-9]+]]
-// MS: define internal void @"?f@?A@@YAXUS@?A@@@Z"({{.*}} !type [[TS1:![0-9]+]] !type [[TS2:![0-9]+]]
+// MS: define internal void @"?f@?A0x{{[^@]*}}@@YAXUS@?A0x{{[^@]*}}@@@Z"({{.*}} !type [[TS1:![0-9]+]] !type [[TS2:![0-9]+]]
// CHECK: [[VOIDS1]] = distinct !{}
// CHECK: [[TS1]] = !{i64 0, [[VOIDS1]]}
};
}
void C::c() {}
-// CHECK-DAG: DISubprogram{{.*}}linkageName: "?f@C@?A@Test4@@W7EAAXXZ"{{.*}} flags: {{.*}}DIFlagThunk
+// CHECK-DAG: DISubprogram{{.*}}linkageName: "?f@C@?A0x{{[^@]*}}@Test4@@W7EAAXXZ"{{.*}} flags: {{.*}}DIFlagThunk
void C::f() {}
// Force C::f to be used.
};
void PR23308::f(InternalLinkageType*) {}
long use(PR23308* p) { p->f(nullptr); }
-// M32-DAG: define internal x86_thiscallcc void @"?f@PR23308@@QAEXPAUInternalLinkageType@?A@@@Z"
+// M32-DAG: define internal x86_thiscallcc void @"?f@PR23308@@QAEXPAUInternalLinkageType@?A0x{{[^@]*}}@@@Z"
template <typename T> struct PR23770BaseTemplate { void f() {} };
template <typename T> struct PR23770DerivedTemplate : PR23770BaseTemplate<int> {};
namespace {
int anonymous;
-// CHECK-DAG: @"?anonymous@?A@N@@3HA"
+// CHECK-DAG: @"?anonymous@?A0x{{[^@]*}}@N@@3HA"
}
}
void *getA() {
return (void*)new A();
}
-// CHECK: define internal x86_thiscallcc i8* @"??_GA@?A@@UAEPAXI@Z"
+// CHECK: define internal x86_thiscallcc i8* @"??_GA@?A0x{{[^@]*}}@@UAEPAXI@Z"
// CHECK: (%"struct.(anonymous namespace)::A"* %this, i32 %should_call_delete)
-// CHECK: define internal x86_thiscallcc void @"??1A@?A@@UAE@XZ"
+// CHECK: define internal x86_thiscallcc void @"??1A@?A0x{{[^@]*}}@@UAE@XZ"
// CHECK: (%"struct.(anonymous namespace)::A"* %this)
// Check that we correctly transform __stdcall to __thiscall for ctors and
// CHECK-DAG: @_TI1P6AXXZ = linkonce_odr unnamed_addr constant %eh.ThrowInfo { i32 0, i8* null, i8* null, i8* bitcast (%eh.CatchableTypeArray.1* @_CTA1P6AXXZ to i8*) }, section ".xdata", comdat
// CHECK-DAG: @_TIU2PAPFAH = linkonce_odr unnamed_addr constant %eh.ThrowInfo { i32 4, i8* null, i8* null, i8* bitcast (%eh.CatchableTypeArray.2* @_CTA2PAPFAH to i8*) }, section ".xdata", comdat
// CHECK-DAG: @_CTA2PAPFAH = linkonce_odr unnamed_addr constant %eh.CatchableTypeArray.2 { i32 2, [2 x %eh.CatchableType*] [%eh.CatchableType* @"_CT??_R0PAPFAH@84", %eh.CatchableType* @"_CT??_R0PAX@84"] }, section ".xdata", comdat
-// CHECK-DAG: @"_TI1?AUFoo@?A@@" = internal unnamed_addr constant %eh.ThrowInfo { i32 0, i8* null, i8* null, i8* bitcast (%eh.CatchableTypeArray.1* @"_CTA1?AUFoo@?A@@" to i8*) }, section ".xdata"
+// CHECK-DAG: @"_TI1?AUFoo@?A0x{{[^@]*}}@@" = internal unnamed_addr constant %eh.ThrowInfo { i32 0, i8* null, i8* null, i8* bitcast (%eh.CatchableTypeArray.1* @"_CTA1?AUFoo@?A0x{{[^@]*}}@@" to i8*) }, section ".xdata"
struct N { ~N(); };
void *GetExceptionInfo_test2() {
// CHECK-LABEL: @"?GetExceptionInfo_test2@@YAPAXXZ"
-// CHECK: ret i8* bitcast (%eh.ThrowInfo* @"_TI1?AUFoo@?A@@" to i8*)
+// CHECK: ret i8* bitcast (%eh.ThrowInfo* @"_TI1?AUFoo@?A0x{{[^@]*}}@@" to i8*)
return __GetExceptionInfo(foo_exc);
}
E::E() {}
E e;
// Class with internal linkage has internal linkage thunks.
-// CODEGEN: define internal x86_thiscallcc %struct.C* @"?goo@E@?A@@QAEPAUB@@XZ"
+// CODEGEN: define internal x86_thiscallcc %struct.C* @"?goo@E@?A0x{{[^@]*}}@@QAEPAUB@@XZ"
}
virtual ~W() {}
} w;
}
-// RTTI-DAG: [[VTABLE_W:@.*]] = private unnamed_addr constant { [2 x i8*] } { [2 x i8*] [i8* bitcast ({{.*}} @"??_R4W@?A@@6B@" to i8*), i8* bitcast ({{.*}} @"??_GW@?A@@UAEPAXI@Z" to i8*)] }
-// RTTI-DAG: @"??_7W@?A@@6B@" = internal unnamed_addr alias i8*, getelementptr inbounds ({ [2 x i8*] }, { [2 x i8*] }* [[VTABLE_W]], i32 0, i32 0, i32 1)
+// RTTI-DAG: [[VTABLE_W:@.*]] = private unnamed_addr constant { [2 x i8*] } { [2 x i8*] [i8* bitcast ({{.*}} @"??_R4W@?A0x{{[^@]*}}@@6B@" to i8*), i8* bitcast ({{.*}} @"??_GW@?A0x{{[^@]*}}@@UAEPAXI@Z" to i8*)] }
+// RTTI-DAG: @"??_7W@?A0x{{[^@]*}}@@6B@" = internal unnamed_addr alias i8*, getelementptr inbounds ({ [2 x i8*] }, { [2 x i8*] }* [[VTABLE_W]], i32 0, i32 0, i32 1)
-// NO-RTTI-DAG: @"??_7W@?A@@6B@" = internal unnamed_addr constant { [1 x i8*] } { [1 x i8*] [i8* bitcast ({{.*}} @"??_GW@?A@@UAEPAXI@Z" to i8*)] }
+// NO-RTTI-DAG: @"??_7W@?A0x{{[^@]*}}@@6B@" = internal unnamed_addr constant { [1 x i8*] } { [1 x i8*] [i8* bitcast ({{.*}} @"??_GW@?A0x{{[^@]*}}@@UAEPAXI@Z" to i8*)] }
struct X {};
template <class> struct Y : virtual X {
// CHECK32: store i8* bitcast (void (%struct.C*, ...)* @"??_9C@@$BA@AE" to i8*), i8** %ptr
// CHECK32: store i8* bitcast (void (%struct.C*, ...)* @"??_9C@@$B3AE" to i8*), i8** %ptr2
// CHECK32: store i8* bitcast (void (%struct.C*, ...)* @"??_9C@@$B7AE" to i8*), i8** %ptr3
-// CHECK32: store i8* bitcast (void (%"struct.(anonymous namespace)::D"*, ...)* @"??_9D@?A@@$BA@AE" to i8*), i8** %ptr4
+// CHECK32: store i8* bitcast (void (%"struct.(anonymous namespace)::D"*, ...)* @"??_9D@?A0x{{[^@]*}}@@$BA@AE" to i8*), i8** %ptr4
// CHECK32: }
//
// CHECK64-LABEL: define dso_local void @"?f@@YAXXZ"()
// CHECK64: store i8* bitcast (void (%struct.C*, ...)* @"??_9C@@$BA@AA" to i8*), i8** %ptr
// CHECK64: store i8* bitcast (void (%struct.C*, ...)* @"??_9C@@$B7AA" to i8*), i8** %ptr2
// CHECK64: store i8* bitcast (void (%struct.C*, ...)* @"??_9C@@$BBA@AA" to i8*), i8** %ptr3
-// CHECK64: store i8* bitcast (void (%"struct.(anonymous namespace)::D"*, ...)* @"??_9D@?A@@$BA@AA" to i8*), i8** %ptr
+// CHECK64: store i8* bitcast (void (%"struct.(anonymous namespace)::D"*, ...)* @"??_9D@?A0x{{[^@]*}}@@$BA@AA" to i8*), i8** %ptr
// CHECK64: }
}
// CHECK64: }
// Thunk for calling the virtual function in internal class D.
-// CHECK32-LABEL: define internal x86_thiscallcc void @"??_9D@?A@@$BA@AE"(%"struct.(anonymous namespace)::D"* %this, ...)
+// CHECK32-LABEL: define internal x86_thiscallcc void @"??_9D@?A0x{{[^@]*}}@@$BA@AE"(%"struct.(anonymous namespace)::D"* %this, ...)
// CHECK32: #[[ATTR]]
// CHECK32: [[VPTR:%.*]] = getelementptr inbounds void (%"struct.(anonymous namespace)::D"*, ...)*, void (%"struct.(anonymous namespace)::D"*, ...)** %{{.*}}, i64 0
// CHECK32: [[CALLEE:%.*]] = load void (%"struct.(anonymous namespace)::D"*, ...)*, void (%"struct.(anonymous namespace)::D"*, ...)** [[VPTR]]
// CHECK32-NEXT: ret void
// CHECK32: }
//
-// CHECK64-LABEL: define internal void @"??_9D@?A@@$BA@AA"(%"struct.(anonymous namespace)::D"* %this, ...)
+// CHECK64-LABEL: define internal void @"??_9D@?A0x{{[^@]*}}@@$BA@AA"(%"struct.(anonymous namespace)::D"* %this, ...)
// CHECK64: #[[ATTR]]
// CHECK64: [[VPTR:%.*]] = getelementptr inbounds void (%"struct.(anonymous namespace)::D"*, ...)*, void (%"struct.(anonymous namespace)::D"*, ...)** %{{.*}}, i64 0
// CHECK64: [[CALLEE:%.*]] = load void (%"struct.(anonymous namespace)::D"*, ...)*, void (%"struct.(anonymous namespace)::D"*, ...)** [[VPTR]]
namespace {
void __attribute__((__swiftcall__)) __attribute__((__used__)) f() { }
}
-// CHECK-DAG: @"?f@?A@@YSXXZ"
-// CHECK-64-DAG: @"?f@?A@@YSXXZ"
+// CHECK-DAG: @"?f@?A0x{{[^@]*}}@@YSXXZ"
+// CHECK-64-DAG: @"?f@?A0x{{[^@]*}}@@YSXXZ"
namespace n {
void __attribute__((__swiftcall__)) f() {}
namespace {
void __attribute__((__preserve_most__)) __attribute__((__used__)) g() {}
}
-// CHECK-DAG: @"?g@?A@@YUXXZ"
-// CHECK-64-DAG: @"?g@?A@@YUXXZ"
+// CHECK-DAG: @"?g@?A0x{{[^@]*}}@@YUXXZ"
+// CHECK-64-DAG: @"?g@?A0x{{[^@]*}}@@YUXXZ"
namespace n {
void __attribute__((__preserve_most__)) g() {}
namespace internal_init {
namespace {
int x = f();
-// CHECK: @"?x@?A@internal_init@@3HA" = internal global i32 0, align 4
-// CHECK: @__cxx_init_fn_ptr.2 = private constant void ()* @"??__Ex@?A@internal_init@@YAXXZ", section ".asdf"
+// CHECK: @"?x@?A0x{{[^@]*}}@internal_init@@3HA" = internal global i32 0, align 4
+// CHECK: @__cxx_init_fn_ptr.2 = private constant void ()* @"??__Ex@?A0x{{[^@]*}}@internal_init@@YAXXZ", section ".asdf"
}
}
// MS: comdat($"??_7B@@6B0@@"), !type [[B8:![0-9]+]]
// MS: comdat($"??_7B@@6BA@@@"), !type [[A8]]
// MS: comdat($"??_7C@@6B@"), !type [[A8]]
-// MS: comdat($"??_7D@?A@@6BB@@@"), !type [[B8]], !type [[D8:![0-9]+]]
-// MS: comdat($"??_7D@?A@@6BA@@@"), !type [[A8]]
+// MS: comdat($"??_7D@?A0x{{[^@]*}}@@6BB@@@"), !type [[B8]], !type [[D8:![0-9]+]]
+// MS: comdat($"??_7D@?A0x{{[^@]*}}@@6BA@@@"), !type [[A8]]
// MS: comdat($"??_7FA@?1??foo@@YAXXZ@6B@"), !type [[A8]], !type [[FA8:![0-9]+]]
struct A {
}
// ITANIUM: define internal void @_Z3df1PN12_GLOBAL__N_11DE
-// MS: define internal void @"?df1@@YAXPEAUD@?A@@@Z"
+// MS: define internal void @"?df1@@YAXPEAUD@?A0x{{[^@]*}}@@@Z"
void df1(D *d) {
// TT-ITANIUM: {{%[^ ]*}} = call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata ![[DTYPE:[0-9]+]])
// TT-MS: {{%[^ ]*}} = call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata !"?AUA@@")
}
// ITANIUM: define internal void @_Z3dg1PN12_GLOBAL__N_11DE
-// MS: define internal void @"?dg1@@YAXPEAUD@?A@@@Z"
+// MS: define internal void @"?dg1@@YAXPEAUD@?A0x{{[^@]*}}@@@Z"
void dg1(D *d) {
// TT-ITANIUM: {{%[^ ]*}} = call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B")
// TT-MS: {{%[^ ]*}} = call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata !"?AUB@@")
}
// ITANIUM: define internal void @_Z3dh1PN12_GLOBAL__N_11DE
-// MS: define internal void @"?dh1@@YAXPEAUD@?A@@@Z"
+// MS: define internal void @"?dh1@@YAXPEAUD@?A0x{{[^@]*}}@@@Z"
void dh1(D *d) {
// TT-ITANIUM: {{%[^ ]*}} = call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata ![[DTYPE]])
// TT-MS: {{%[^ ]*}} = call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata ![[DTYPE:[0-9]+]])
}
// ITANIUM: define internal void @_Z3df2PN12_GLOBAL__N_11DE
-// MS: define internal void @"?df2@@YAXPEAUD@?A@@@Z"
+// MS: define internal void @"?df2@@YAXPEAUD@?A0x{{[^@]*}}@@@Z"
__attribute__((no_sanitize("cfi")))
void df2(D *d) {
// CFI-NVT-NOT: call i1 @llvm.type.test
}
// ITANIUM: define internal void @_Z3df3PN12_GLOBAL__N_11DE
-// MS: define internal void @"?df3@@YAXPEAUD@?A@@@Z"
+// MS: define internal void @"?df3@@YAXPEAUD@?A0x{{[^@]*}}@@@Z"
__attribute__((no_sanitize("address"))) __attribute__((no_sanitize("cfi-vcall")))
void df3(D *d) {
// CFI-NVT-NOT: call i1 @llvm.type.test