diff options
author | Reid Kleckner <rnk@google.com> | 2018-08-17 20:59:27 +0000 |
---|---|---|
committer | Reid Kleckner <rnk@google.com> | 2018-08-17 20:59:27 +0000 |
commit | df8dd61f2309124689b07844e47abddf46203d4e (patch) | |
tree | 32354278182035ccba0880108097a8da559b3473 /clang/lib/AST/MicrosoftMangle.cpp | |
parent | f6e36ee83e1cd5c881b450561a021e834acc9810 (diff) | |
download | bcm5719-llvm-df8dd61f2309124689b07844e47abddf46203d4e.tar.gz bcm5719-llvm-df8dd61f2309124689b07844e47abddf46203d4e.zip |
[MS] Mangle a hash of the main file path into anonymous namespaces
Summary:
This is needed to avoid conflicts in mangled names for codeview types in
anonymous namespaces. In CodeView, types refer to each other typically
through forward declarations, which contain mangled names. These names
have to be unique, otherwise the debugger will look up the mangled name
and find the wrong definition.
Furthermore, ThinLTO will deduplicate the types, and debug info
verification can fail when the types have the wrong sizes. This is
PR38608.
Fixes PR38609.
Reviewers: majnemer, inglorion, hans
Subscribers: mehdi_amini, aprantl, JDevlieghere, dexonsmith, cfe-commits
Differential Revision: https://reviews.llvm.org/D50877
llvm-svn: 340079
Diffstat (limited to 'clang/lib/AST/MicrosoftMangle.cpp')
-rw-r--r-- | clang/lib/AST/MicrosoftMangle.cpp | 41 |
1 files changed, 38 insertions, 3 deletions
diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp index 8067c42dff5..d5332ba7db5 100644 --- a/clang/lib/AST/MicrosoftMangle.cpp +++ b/clang/lib/AST/MicrosoftMangle.cpp @@ -29,6 +29,7 @@ #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" @@ -127,10 +128,10 @@ class MicrosoftMangleContextImpl : public MicrosoftMangleContext { 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; @@ -238,6 +239,12 @@ public: 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); }; @@ -371,6 +378,34 @@ private: }; } +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(); @@ -785,7 +820,7 @@ void MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, if (const NamespaceDecl *NS = dyn_cast<NamespaceDecl>(ND)) { if (NS->isAnonymousNamespace()) { - Out << "?A@"; + Out << "?A0x" << Context.getAnonymousNamespaceHash() << '@'; break; } } |