#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Basic/TargetInfo.h"
#include "llvm/ADT/StringExtras.h"
-#include "llvm/Support/MathExtras.h"
#include "llvm/Support/JamCRC.h"
+#include "llvm/Support/MD5.h"
+#include "llvm/Support/MathExtras.h"
using namespace clang;
namespace {
+struct msvc_hashing_ostream : public llvm::raw_svector_ostream {
+ raw_ostream &OS;
+ llvm::SmallString<64> Buffer;
+
+ msvc_hashing_ostream(raw_ostream &OS)
+ : llvm::raw_svector_ostream(Buffer), OS(OS) {}
+ ~msvc_hashing_ostream() override {
+ StringRef MangledName = str();
+ bool StartsWithEscape = MangledName.startswith("\01");
+ if (StartsWithEscape)
+ MangledName = MangledName.drop_front(1);
+ if (MangledName.size() <= 4096) {
+ OS << str();
+ return;
+ }
+
+ llvm::MD5 Hasher;
+ llvm::MD5::MD5Result Hash;
+ Hasher.update(MangledName);
+ Hasher.final(Hash);
+
+ SmallString<32> HexString;
+ llvm::MD5::stringifyResult(Hash, HexString);
+
+ if (StartsWithEscape)
+ OS << '\01';
+ OS << "??@" << HexString << '@';
+ }
+};
+
/// \brief Retrieve the declaration context that should be used when mangling
/// the given declaration.
static const DeclContext *getEffectiveDeclContext(const Decl *D) {
}
private:
- void mangleInitFiniStub(const VarDecl *D, raw_ostream &Out, char CharCode);
+ void mangleInitFiniStub(const VarDecl *D, char CharCode, raw_ostream &Out);
};
/// MicrosoftCXXNameMangler - Manage the mangling of a single name for the
getASTContext().getSourceManager(),
"Mangling declaration");
- MicrosoftCXXNameMangler Mangler(*this, Out);
+ msvc_hashing_ostream MHO(Out);
+ MicrosoftCXXNameMangler Mangler(*this, MHO);
return Mangler.mangle(D);
}
const MicrosoftVTableContext::MethodVFTableLocation &ML =
VTContext->getMethodVFTableLocation(GlobalDecl(MD));
- MicrosoftCXXNameMangler Mangler(*this, Out);
+ msvc_hashing_ostream MHO(Out);
+ MicrosoftCXXNameMangler Mangler(*this, MHO);
Mangler.getStream() << "\01?";
Mangler.mangleVirtualMemPtrThunk(MD, ML);
}
void MicrosoftMangleContextImpl::mangleThunk(const CXXMethodDecl *MD,
const ThunkInfo &Thunk,
raw_ostream &Out) {
- MicrosoftCXXNameMangler Mangler(*this, Out);
- Out << "\01?";
+ msvc_hashing_ostream MHO(Out);
+ MicrosoftCXXNameMangler Mangler(*this, MHO);
+ Mangler.getStream() << "\01?";
Mangler.mangleName(MD);
- mangleThunkThisAdjustment(MD, Thunk.This, Mangler, Out);
+ mangleThunkThisAdjustment(MD, Thunk.This, Mangler, MHO);
if (!Thunk.Return.isEmpty())
assert(Thunk.Method != nullptr &&
"Thunk info should hold the overridee decl");
// dtors rather than scalar deleting dtors. Just use the vector deleting dtor
// mangling manually until we support both deleting dtor types.
assert(Type == Dtor_Deleting);
- MicrosoftCXXNameMangler Mangler(*this, Out, DD, Type);
- Out << "\01??_E";
+ msvc_hashing_ostream MHO(Out);
+ MicrosoftCXXNameMangler Mangler(*this, MHO, DD, Type);
+ Mangler.getStream() << "\01??_E";
Mangler.mangleName(DD->getParent());
- mangleThunkThisAdjustment(DD, Adjustment, Mangler, Out);
+ mangleThunkThisAdjustment(DD, Adjustment, Mangler, MHO);
Mangler.mangleFunctionType(DD->getType()->castAs<FunctionProtoType>(), DD);
}
// <cvr-qualifiers> [<name>] @
// NOTE: <cvr-qualifiers> here is always 'B' (const). <storage-class>
// is always '6' for vftables.
- MicrosoftCXXNameMangler Mangler(*this, Out);
+ msvc_hashing_ostream MHO(Out);
+ MicrosoftCXXNameMangler Mangler(*this, MHO);
if (Derived->hasAttr<DLLImportAttr>())
Mangler.getStream() << "\01??_S";
else
// <cvr-qualifiers> [<name>] @
// NOTE: <cvr-qualifiers> here is always 'B' (const). <storage-class>
// is always '7' for vbtables.
- MicrosoftCXXNameMangler Mangler(*this, Out);
+ msvc_hashing_ostream MHO(Out);
+ MicrosoftCXXNameMangler Mangler(*this, MHO);
Mangler.getStream() << "\01??_8";
Mangler.mangleName(Derived);
Mangler.getStream() << "7B"; // '7' for vbtable, 'B' for const.
}
void MicrosoftMangleContextImpl::mangleCXXRTTI(QualType T, raw_ostream &Out) {
- MicrosoftCXXNameMangler Mangler(*this, Out);
+ msvc_hashing_ostream MHO(Out);
+ MicrosoftCXXNameMangler Mangler(*this, MHO);
Mangler.getStream() << "\01??_R0";
Mangler.mangleType(T, SourceRange(), MicrosoftCXXNameMangler::QMM_Result);
Mangler.getStream() << "@8";
void MicrosoftMangleContextImpl::mangleCXXVirtualDisplacementMap(
const CXXRecordDecl *SrcRD, const CXXRecordDecl *DstRD, raw_ostream &Out) {
- MicrosoftCXXNameMangler Mangler(*this, Out);
+ msvc_hashing_ostream MHO(Out);
+ MicrosoftCXXNameMangler Mangler(*this, MHO);
Mangler.getStream() << "\01??_K";
Mangler.mangleName(SrcRD);
Mangler.getStream() << "$C";
bool IsVolatile,
uint32_t NumEntries,
raw_ostream &Out) {
- MicrosoftCXXNameMangler Mangler(*this, Out);
+ msvc_hashing_ostream MHO(Out);
+ MicrosoftCXXNameMangler Mangler(*this, MHO);
Mangler.getStream() << "_TI";
if (IsConst)
Mangler.getStream() << 'C';
void MicrosoftMangleContextImpl::mangleCXXCatchableTypeArray(
QualType T, uint32_t NumEntries, raw_ostream &Out) {
- MicrosoftCXXNameMangler Mangler(*this, Out);
+ msvc_hashing_ostream MHO(Out);
+ MicrosoftCXXNameMangler Mangler(*this, MHO);
Mangler.getStream() << "_CTA";
Mangler.getStream() << NumEntries;
Mangler.mangleType(T, SourceRange(), MicrosoftCXXNameMangler::QMM_Result);
llvm::SmallString<64> RTTIMangling;
{
llvm::raw_svector_ostream Stream(RTTIMangling);
- mangleCXXRTTI(T, Stream);
+ msvc_hashing_ostream MHO(Stream);
+ mangleCXXRTTI(T, MHO);
}
Mangler.getStream() << RTTIMangling.substr(1);
// VS2015 CTP6 omits the copy-constructor in the mangled name. This name is,
// in fact, superfluous but I'm not sure the change was made consciously.
- // TODO: Revisit this when VS2015 gets released.
llvm::SmallString<64> CopyCtorMangling;
- if (CD) {
+ if (!getASTContext().getLangOpts().isCompatibleWithMSVC(
+ LangOptions::MSVC2015) &&
+ CD) {
llvm::raw_svector_ostream Stream(CopyCtorMangling);
- mangleCXXCtor(CD, CT, Stream);
+ msvc_hashing_ostream MHO(Stream);
+ mangleCXXCtor(CD, CT, MHO);
}
Mangler.getStream() << CopyCtorMangling.substr(1);
void MicrosoftMangleContextImpl::mangleCXXRTTIBaseClassDescriptor(
const CXXRecordDecl *Derived, uint32_t NVOffset, int32_t VBPtrOffset,
uint32_t VBTableOffset, uint32_t Flags, raw_ostream &Out) {
- MicrosoftCXXNameMangler Mangler(*this, Out);
+ msvc_hashing_ostream MHO(Out);
+ MicrosoftCXXNameMangler Mangler(*this, MHO);
Mangler.getStream() << "\01??_R1";
Mangler.mangleNumber(NVOffset);
Mangler.mangleNumber(VBPtrOffset);
void MicrosoftMangleContextImpl::mangleCXXRTTIBaseClassArray(
const CXXRecordDecl *Derived, raw_ostream &Out) {
- MicrosoftCXXNameMangler Mangler(*this, Out);
+ msvc_hashing_ostream MHO(Out);
+ MicrosoftCXXNameMangler Mangler(*this, MHO);
Mangler.getStream() << "\01??_R2";
Mangler.mangleName(Derived);
Mangler.getStream() << "8";
void MicrosoftMangleContextImpl::mangleCXXRTTIClassHierarchyDescriptor(
const CXXRecordDecl *Derived, raw_ostream &Out) {
- MicrosoftCXXNameMangler Mangler(*this, Out);
+ msvc_hashing_ostream MHO(Out);
+ MicrosoftCXXNameMangler Mangler(*this, MHO);
Mangler.getStream() << "\01??_R3";
Mangler.mangleName(Derived);
Mangler.getStream() << "8";
// <cvr-qualifiers> [<name>] @
// NOTE: <cvr-qualifiers> here is always 'B' (const). <storage-class>
// is always '6' for vftables.
- MicrosoftCXXNameMangler Mangler(*this, Out);
- Mangler.getStream() << "\01??_R4";
- Mangler.mangleName(Derived);
- Mangler.getStream() << "6B"; // '6' for vftable, 'B' for const.
- for (const CXXRecordDecl *RD : BasePath)
- Mangler.mangleName(RD);
- Mangler.getStream() << '@';
+ llvm::SmallString<64> VFTableMangling;
+ llvm::raw_svector_ostream Stream(VFTableMangling);
+ mangleCXXVFTable(Derived, BasePath, Stream);
+
+ if (VFTableMangling.startswith("\01??@")) {
+ assert(VFTableMangling.endswith("@"));
+ Out << VFTableMangling << "??_R4@";
+ return;
+ }
+
+ assert(VFTableMangling.startswith("\01??_7") ||
+ VFTableMangling.startswith("\01??_S"));
+
+ Out << "\01??_R4" << StringRef(VFTableMangling).drop_front(5);
}
void MicrosoftMangleContextImpl::mangleSEHFilterExpression(
const NamedDecl *EnclosingDecl, raw_ostream &Out) {
- MicrosoftCXXNameMangler Mangler(*this, Out);
+ msvc_hashing_ostream MHO(Out);
+ MicrosoftCXXNameMangler Mangler(*this, MHO);
// The function body is in the same comdat as the function with the handler,
// so the numbering here doesn't have to be the same across TUs.
//
void MicrosoftMangleContextImpl::mangleSEHFinallyBlock(
const NamedDecl *EnclosingDecl, raw_ostream &Out) {
- MicrosoftCXXNameMangler Mangler(*this, Out);
+ msvc_hashing_ostream MHO(Out);
+ MicrosoftCXXNameMangler Mangler(*this, MHO);
// The function body is in the same comdat as the function with the handler,
// so the numbering here doesn't have to be the same across TUs.
//
void MicrosoftMangleContextImpl::mangleCXXCtor(const CXXConstructorDecl *D,
CXXCtorType Type,
raw_ostream &Out) {
- MicrosoftCXXNameMangler mangler(*this, Out, D, Type);
+ msvc_hashing_ostream MHO(Out);
+ MicrosoftCXXNameMangler mangler(*this, MHO, D, Type);
mangler.mangle(D);
}
void MicrosoftMangleContextImpl::mangleCXXDtor(const CXXDestructorDecl *D,
CXXDtorType Type,
raw_ostream &Out) {
- MicrosoftCXXNameMangler mangler(*this, Out, D, Type);
+ msvc_hashing_ostream MHO(Out);
+ MicrosoftCXXNameMangler mangler(*this, MHO, D, Type);
mangler.mangle(D);
}
void MicrosoftMangleContextImpl::mangleReferenceTemporary(
const VarDecl *VD, unsigned ManglingNumber, raw_ostream &Out) {
- MicrosoftCXXNameMangler Mangler(*this, Out);
+ msvc_hashing_ostream MHO(Out);
+ MicrosoftCXXNameMangler Mangler(*this, MHO);
Mangler.getStream() << "\01?$RT" << ManglingNumber << '@';
Mangler.mangle(VD, "");
void MicrosoftMangleContextImpl::mangleThreadSafeStaticGuardVariable(
const VarDecl *VD, unsigned GuardNum, raw_ostream &Out) {
- MicrosoftCXXNameMangler Mangler(*this, Out);
+ msvc_hashing_ostream MHO(Out);
+ MicrosoftCXXNameMangler Mangler(*this, MHO);
Mangler.getStream() << "\01?$TSS" << GuardNum << '@';
Mangler.mangleNestedName(VD);
// than 32 static locals. We don't fully implement the second mangling
// because those guards are not externally visible, and instead use LLVM's
// default renaming when creating a new guard variable.
- MicrosoftCXXNameMangler Mangler(*this, Out);
+ msvc_hashing_ostream MHO(Out);
+ MicrosoftCXXNameMangler Mangler(*this, MHO);
bool Visible = VD->isExternallyVisible();
if (Visible) {
}
void MicrosoftMangleContextImpl::mangleInitFiniStub(const VarDecl *D,
- raw_ostream &Out,
- char CharCode) {
- MicrosoftCXXNameMangler Mangler(*this, Out);
+ char CharCode,
+ raw_ostream &Out) {
+ msvc_hashing_ostream MHO(Out);
+ MicrosoftCXXNameMangler Mangler(*this, MHO);
Mangler.getStream() << "\01??__" << CharCode;
Mangler.mangleName(D);
if (D->isStaticDataMember()) {
void MicrosoftMangleContextImpl::mangleDynamicInitializer(const VarDecl *D,
raw_ostream &Out) {
// <initializer-name> ::= ?__E <name> YAXXZ
- mangleInitFiniStub(D, Out, 'E');
+ mangleInitFiniStub(D, 'E', Out);
}
void
MicrosoftMangleContextImpl::mangleDynamicAtExitDestructor(const VarDecl *D,
raw_ostream &Out) {
// <destructor-name> ::= ?__F <name> YAXXZ
- mangleInitFiniStub(D, Out, 'F');
+ mangleInitFiniStub(D, 'F', Out);
}
void MicrosoftMangleContextImpl::mangleStringLiteral(const StringLiteral *SL,