diff options
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; } } |