#include "clang/AST/ASTContext.h"
#include "clang/AST/Attr.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/CharUnits.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclOpenMP.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/GlobalDecl.h"
#include "clang/AST/Mangle.h"
#include "clang/AST/VTableBuilder.h"
#include "clang/Basic/ABI.h"
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/CRC.h"
#include "llvm/Support/MD5.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/StringSaver.h"
#include "llvm/Support/xxhash.h"
using namespace clang;
namespace {
static GlobalDecl getGlobalDeclAsDeclContext(const DeclContext *DC) {
GlobalDecl GD;
if (auto *CD = dyn_cast<CXXConstructorDecl>(DC))
GD = GlobalDecl(CD, Ctor_Complete);
else if (auto *DD = dyn_cast<CXXDestructorDecl>(DC))
GD = GlobalDecl(DD, Dtor_Complete);
else
GD = GlobalDecl(cast<FunctionDecl>(DC));
return GD;
}
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 << '@';
}
};
static const DeclContext *
getLambdaDefaultArgumentDeclContext(const Decl *D) {
if (const auto *RD = dyn_cast<CXXRecordDecl>(D))
if (RD->isLambda())
if (const auto *Parm =
dyn_cast_or_null<ParmVarDecl>(RD->getLambdaContextDecl()))
return Parm->getDeclContext();
return nullptr;
}
static const DeclContext *getEffectiveDeclContext(const Decl *D) {
if (const auto *LDADC = getLambdaDefaultArgumentDeclContext(D))
return LDADC;
if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) {
if (ParmVarDecl *ContextParam =
dyn_cast_or_null<ParmVarDecl>(BD->getBlockManglingContextDecl()))
return ContextParam->getDeclContext();
}
const DeclContext *DC = D->getDeclContext();
if (isa<CapturedDecl>(DC) || isa<OMPDeclareReductionDecl>(DC) ||
isa<OMPDeclareMapperDecl>(DC)) {
return getEffectiveDeclContext(cast<Decl>(DC));
}
return DC->getRedeclContext();
}
static const DeclContext *getEffectiveParentContext(const DeclContext *DC) {
return getEffectiveDeclContext(cast<Decl>(DC));
}
static const FunctionDecl *getStructor(const NamedDecl *ND) {
if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(ND))
return FTD->getTemplatedDecl()->getCanonicalDecl();
const auto *FD = cast<FunctionDecl>(ND);
if (const auto *FTD = FD->getPrimaryTemplate())
return FTD->getTemplatedDecl()->getCanonicalDecl();
return FD->getCanonicalDecl();
}
class MicrosoftMangleContextImpl : public MicrosoftMangleContext {
typedef std::pair<const DeclContext *, IdentifierInfo *> DiscriminatorKeyTy;
llvm::DenseMap<DiscriminatorKeyTy, unsigned> Discriminator;
llvm::DenseMap<const NamedDecl *, unsigned> Uniquifier;
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,
bool IsAux = false);
bool shouldMangleCXXName(const NamedDecl *D) override;
bool shouldMangleStringLiteral(const StringLiteral *SL) override;
void mangleCXXName(GlobalDecl GD, raw_ostream &Out) override;
void mangleVirtualMemPtrThunk(const CXXMethodDecl *MD,
const MethodVFTableLocation &ML,
raw_ostream &Out) override;
void mangleThunk(const CXXMethodDecl *MD, const ThunkInfo &Thunk,
raw_ostream &) override;
void mangleCXXDtorThunk(const CXXDestructorDecl *DD, CXXDtorType Type,
const ThisAdjustment &ThisAdjustment,
raw_ostream &) override;
void mangleCXXVFTable(const CXXRecordDecl *Derived,
ArrayRef<const CXXRecordDecl *> BasePath,
raw_ostream &Out) override;
void mangleCXXVBTable(const CXXRecordDecl *Derived,
ArrayRef<const CXXRecordDecl *> BasePath,
raw_ostream &Out) override;
void mangleCXXVirtualDisplacementMap(const CXXRecordDecl *SrcRD,
const CXXRecordDecl *DstRD,
raw_ostream &Out) override;
void mangleCXXThrowInfo(QualType T, bool IsConst, bool IsVolatile,
bool IsUnaligned, uint32_t NumEntries,
raw_ostream &Out) override;
void mangleCXXCatchableTypeArray(QualType T, uint32_t NumEntries,
raw_ostream &Out) override;
void mangleCXXCatchableType(QualType T, const CXXConstructorDecl *CD,
CXXCtorType CT, uint32_t Size, uint32_t NVOffset,
int32_t VBPtrOffset, uint32_t VBIndex,
raw_ostream &Out) override;
void mangleCXXRTTI(QualType T, raw_ostream &Out) override;
void mangleCXXRTTIName(QualType T, raw_ostream &Out) override;
void mangleCXXRTTIBaseClassDescriptor(const CXXRecordDecl *Derived,
uint32_t NVOffset, int32_t VBPtrOffset,
uint32_t VBTableOffset, uint32_t Flags,
raw_ostream &Out) override;
void mangleCXXRTTIBaseClassArray(const CXXRecordDecl *Derived,
raw_ostream &Out) override;
void mangleCXXRTTIClassHierarchyDescriptor(const CXXRecordDecl *Derived,
raw_ostream &Out) override;
void
mangleCXXRTTICompleteObjectLocator(const CXXRecordDecl *Derived,
ArrayRef<const CXXRecordDecl *> BasePath,
raw_ostream &Out) override;
void mangleTypeName(QualType T, raw_ostream &) override;
void mangleReferenceTemporary(const VarDecl *, unsigned ManglingNumber,
raw_ostream &) override;
void mangleStaticGuardVariable(const VarDecl *D, raw_ostream &Out) override;
void mangleThreadSafeStaticGuardVariable(const VarDecl *D, unsigned GuardNum,
raw_ostream &Out) override;
void mangleDynamicInitializer(const VarDecl *D, raw_ostream &Out) override;
void mangleDynamicAtExitDestructor(const VarDecl *D,
raw_ostream &Out) override;
void mangleSEHFilterExpression(const NamedDecl *EnclosingDecl,
raw_ostream &Out) override;
void mangleSEHFinallyBlock(const NamedDecl *EnclosingDecl,
raw_ostream &Out) override;
void mangleStringLiteral(const StringLiteral *SL, raw_ostream &Out) override;
bool getNextDiscriminator(const NamedDecl *ND, unsigned &disc) {
const DeclContext *DC = getEffectiveDeclContext(ND);
if (!DC->isFunctionOrMethod())
return false;
if (const auto *RD = dyn_cast<CXXRecordDecl>(ND)) {
if (RD->isLambda()) {
disc = 1;
return true;
}
}
if (ND->isExternallyVisible()) {
disc = getASTContext().getManglingNumber(ND, isAux());
return true;
}
if (const TagDecl *Tag = dyn_cast<TagDecl>(ND)) {
if (!Tag->hasNameForLinkage() &&
!getASTContext().getDeclaratorForUnnamedTagDecl(Tag) &&
!getASTContext().getTypedefNameForUnnamedTagDecl(Tag))
return false;
}
unsigned &discriminator = Uniquifier[ND];
if (!discriminator)
discriminator = ++Discriminator[std::make_pair(DC, ND->getIdentifier())];
disc = discriminator + 1;
return true;
}
std::string getLambdaString(const CXXRecordDecl *Lambda) override {
assert(Lambda->isLambda() && "RD must be a lambda!");
std::string Name("<lambda_");
Decl *LambdaContextDecl = Lambda->getLambdaContextDecl();
unsigned LambdaManglingNumber = Lambda->getLambdaManglingNumber();
unsigned LambdaId;
const ParmVarDecl *Parm = dyn_cast_or_null<ParmVarDecl>(LambdaContextDecl);
const FunctionDecl *Func =
Parm ? dyn_cast<FunctionDecl>(Parm->getDeclContext()) : nullptr;
if (Func) {
unsigned DefaultArgNo =
Func->getNumParams() - Parm->getFunctionScopeIndex();
Name += llvm::utostr(DefaultArgNo);
Name += "_";
}
if (LambdaManglingNumber)
LambdaId = LambdaManglingNumber;
else
LambdaId = getLambdaIdForDebugInfo(Lambda);
Name += llvm::utostr(LambdaId);
Name += ">";
return Name;
}
unsigned getLambdaId(const CXXRecordDecl *RD) {
assert(RD->isLambda() && "RD must be a lambda!");
assert(!RD->isExternallyVisible() && "RD must not be visible!");
assert(RD->getLambdaManglingNumber() == 0 &&
"RD must not have a mangling number!");
std::pair<llvm::DenseMap<const CXXRecordDecl *, unsigned>::iterator, bool>
Result = LambdaIds.insert(std::make_pair(RD, LambdaIds.size()));
return Result.first->second;
}
unsigned getLambdaIdForDebugInfo(const CXXRecordDecl *RD) {
assert(RD->isLambda() && "RD must be a lambda!");
assert(!RD->isExternallyVisible() && "RD must not be visible!");
assert(RD->getLambdaManglingNumber() == 0 &&
"RD must not have a mangling number!");
llvm::DenseMap<const CXXRecordDecl *, unsigned>::iterator Result =
LambdaIds.find(RD);
if (Result == LambdaIds.end())
return 0;
return Result->second;
}
StringRef getAnonymousNamespaceHash() const {
return AnonymousNamespaceHash;
}
private:
void mangleInitFiniStub(const VarDecl *D, char CharCode, raw_ostream &Out);
};
class MicrosoftCXXNameMangler {
MicrosoftMangleContextImpl &Context;
raw_ostream &Out;
const NamedDecl *Structor;
unsigned StructorType;
typedef llvm::SmallVector<std::string, 10> BackRefVec;
BackRefVec NameBackReferences;
typedef llvm::DenseMap<const void *, unsigned> ArgBackRefMap;
ArgBackRefMap FunArgBackReferences;
ArgBackRefMap TemplateArgBackReferences;
typedef llvm::DenseMap<const void *, StringRef> TemplateArgStringMap;
TemplateArgStringMap TemplateArgStrings;
llvm::StringSaver TemplateArgStringStorage;
llvm::BumpPtrAllocator TemplateArgStringStorageAlloc;
typedef std::set<std::pair<int, bool>> PassObjectSizeArgsSet;
PassObjectSizeArgsSet PassObjectSizeArgs;
ASTContext &getASTContext() const { return Context.getASTContext(); }
const bool PointersAre64Bit;
public:
enum QualifierMangleMode { QMM_Drop, QMM_Mangle, QMM_Escape, QMM_Result };
MicrosoftCXXNameMangler(MicrosoftMangleContextImpl &C, raw_ostream &Out_)
: Context(C), Out(Out_), Structor(nullptr), StructorType(-1),
TemplateArgStringStorage(TemplateArgStringStorageAlloc),
PointersAre64Bit(C.getASTContext().getTargetInfo().getPointerWidth(0) ==
64) {}
MicrosoftCXXNameMangler(MicrosoftMangleContextImpl &C, raw_ostream &Out_,
const CXXConstructorDecl *D, CXXCtorType Type)
: Context(C), Out(Out_), Structor(getStructor(D)), StructorType(Type),
TemplateArgStringStorage(TemplateArgStringStorageAlloc),
PointersAre64Bit(C.getASTContext().getTargetInfo().getPointerWidth(0) ==
64) {}
MicrosoftCXXNameMangler(MicrosoftMangleContextImpl &C, raw_ostream &Out_,
const CXXDestructorDecl *D, CXXDtorType Type)
: Context(C), Out(Out_), Structor(getStructor(D)), StructorType(Type),
TemplateArgStringStorage(TemplateArgStringStorageAlloc),
PointersAre64Bit(C.getASTContext().getTargetInfo().getPointerWidth(0) ==
64) {}
raw_ostream &getStream() const { return Out; }
void mangle(GlobalDecl GD, StringRef Prefix = "?");
void mangleName(GlobalDecl GD);
void mangleFunctionEncoding(GlobalDecl GD, bool ShouldMangle);
void mangleVariableEncoding(const VarDecl *VD);
void mangleMemberDataPointer(const CXXRecordDecl *RD, const ValueDecl *VD,
StringRef Prefix = "$");
void mangleMemberFunctionPointer(const CXXRecordDecl *RD,
const CXXMethodDecl *MD,
StringRef Prefix = "$");
void mangleVirtualMemPtrThunk(const CXXMethodDecl *MD,
const MethodVFTableLocation &ML);
void mangleNumber(int64_t Number);
void mangleNumber(llvm::APSInt Number);
void mangleFloat(llvm::APFloat Number);
void mangleBits(llvm::APInt Number);
void mangleTagTypeKind(TagTypeKind TK);
void mangleArtificialTagType(TagTypeKind TK, StringRef UnqualifiedName,
ArrayRef<StringRef> NestedNames = None);
void mangleAddressSpaceType(QualType T, Qualifiers Quals, SourceRange Range);
void mangleType(QualType T, SourceRange Range,
QualifierMangleMode QMM = QMM_Mangle);
void mangleFunctionType(const FunctionType *T,
const FunctionDecl *D = nullptr,
bool ForceThisQuals = false,
bool MangleExceptionSpec = true);
void mangleNestedName(GlobalDecl GD);
private:
bool isStructorDecl(const NamedDecl *ND) const {
return ND == Structor || getStructor(ND) == Structor;
}
bool is64BitPointer(Qualifiers Quals) const {
LangAS AddrSpace = Quals.getAddressSpace();
return AddrSpace == LangAS::ptr64 ||
(PointersAre64Bit && !(AddrSpace == LangAS::ptr32_sptr ||
AddrSpace == LangAS::ptr32_uptr));
}
void mangleUnqualifiedName(GlobalDecl GD) {
mangleUnqualifiedName(GD, cast<NamedDecl>(GD.getDecl())->getDeclName());
}
void mangleUnqualifiedName(GlobalDecl GD, DeclarationName Name);
void mangleSourceName(StringRef Name);
void mangleOperatorName(OverloadedOperatorKind OO, SourceLocation Loc);
void mangleCXXDtorType(CXXDtorType T);
void mangleQualifiers(Qualifiers Quals, bool IsMember);
void mangleRefQualifier(RefQualifierKind RefQualifier);
void manglePointerCVQualifiers(Qualifiers Quals);
void manglePointerExtQualifiers(Qualifiers Quals, QualType PointeeType);
void mangleUnscopedTemplateName(GlobalDecl GD);
void
mangleTemplateInstantiationName(GlobalDecl GD,
const TemplateArgumentList &TemplateArgs);
void mangleObjCMethodName(const ObjCMethodDecl *MD);
void mangleFunctionArgumentType(QualType T, SourceRange Range);
void manglePassObjectSizeArg(const PassObjectSizeAttr *POSA);
bool isArtificialTagType(QualType T) const;
#define ABSTRACT_TYPE(CLASS, PARENT)
#define NON_CANONICAL_TYPE(CLASS, PARENT)
#define TYPE(CLASS, PARENT) void mangleType(const CLASS##Type *T, \
Qualifiers Quals, \
SourceRange Range);
#include "clang/AST/TypeNodes.inc"
#undef ABSTRACT_TYPE
#undef NON_CANONICAL_TYPE
#undef TYPE
void mangleType(const TagDecl *TD);
void mangleDecayedArrayType(const ArrayType *T);
void mangleArrayType(const ArrayType *T);
void mangleFunctionClass(const FunctionDecl *FD);
void mangleCallingConvention(CallingConv CC);
void mangleCallingConvention(const FunctionType *T);
void mangleIntegerLiteral(const llvm::APSInt &Number,
const NonTypeTemplateParmDecl *PD = nullptr,
QualType TemplateArgType = QualType());
void mangleExpression(const Expr *E, const NonTypeTemplateParmDecl *PD);
void mangleThrowSpecification(const FunctionProtoType *T);
void mangleTemplateArgs(const TemplateDecl *TD,
const TemplateArgumentList &TemplateArgs);
void mangleTemplateArg(const TemplateDecl *TD, const TemplateArgument &TA,
const NamedDecl *Parm);
void mangleTemplateArgValue(QualType T, const APValue &V,
bool WithScalarType = false);
void mangleObjCProtocol(const ObjCProtocolDecl *PD);
void mangleObjCLifetime(const QualType T, Qualifiers Quals,
SourceRange Range);
void mangleObjCKindOfType(const ObjCObjectType *T, Qualifiers Quals,
SourceRange Range);
};
}
MicrosoftMangleContextImpl::MicrosoftMangleContextImpl(ASTContext &Context,
DiagnosticsEngine &Diags,
bool IsAux)
: MicrosoftMangleContext(Context, Diags, IsAux) {
SourceManager &SM = Context.getSourceManager();
if (const FileEntry *FE = SM.getFileEntryForID(SM.getMainFileID())) {
uint32_t TruncatedHash = uint32_t(xxHash64(FE->getName()));
AnonymousNamespaceHash = llvm::utohexstr(TruncatedHash);
} else {
AnonymousNamespaceHash = "0";
}
}
bool MicrosoftMangleContextImpl::shouldMangleCXXName(const NamedDecl *D) {
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
LanguageLinkage L = FD->getLanguageLinkage();
if (FD->hasAttr<OverloadableAttr>())
return true;
if (FD->isMSVCRTEntryPoint())
return false;
if (!FD->getDeclName().isIdentifier() || L == CXXLanguageLinkage)
return true;
if (L == CLanguageLinkage)
return false;
}
if (!getASTContext().getLangOpts().CPlusPlus)
return false;
const VarDecl *VD = dyn_cast<VarDecl>(D);
if (VD && !isa<DecompositionDecl>(D)) {
if (VD->isExternC())
return false;
const DeclContext *DC = getEffectiveDeclContext(D);
if (DC->isFunctionOrMethod() && D->hasLinkage())
while (!DC->isNamespace() && !DC->isTranslationUnit())
DC = getEffectiveParentContext(DC);
if (DC->isTranslationUnit() && D->getFormalLinkage() == InternalLinkage &&
!isa<VarTemplateSpecializationDecl>(D) &&
D->getIdentifier() != nullptr)
return false;
}
return true;
}
bool
MicrosoftMangleContextImpl::shouldMangleStringLiteral(const StringLiteral *SL) {
return true;
}
void MicrosoftCXXNameMangler::mangle(GlobalDecl GD, StringRef Prefix) {
const NamedDecl *D = cast<NamedDecl>(GD.getDecl());
Out << Prefix;
mangleName(GD);
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
mangleFunctionEncoding(GD, Context.shouldMangleDeclName(FD));
else if (const VarDecl *VD = dyn_cast<VarDecl>(D))
mangleVariableEncoding(VD);
else if (isa<MSGuidDecl>(D))
Out << "3U__s_GUID@@B";
else if (isa<TemplateParamObjectDecl>(D)) {
} else
llvm_unreachable("Tried to mangle unexpected NamedDecl!");
}
void MicrosoftCXXNameMangler::mangleFunctionEncoding(GlobalDecl GD,
bool ShouldMangle) {
const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl());
FD = FD->getFirstDecl();
const FunctionProtoType *FT = FD->getType()->castAs<FunctionProtoType>();
if (ShouldMangle) {
if (FD->isExternC() && FD->hasAttr<OverloadableAttr>())
Out << "$$J0";
mangleFunctionClass(FD);
mangleFunctionType(FT, FD, false, false);
} else {
Out << '9';
}
}
void MicrosoftCXXNameMangler::mangleVariableEncoding(const VarDecl *VD) {
if (VD->isStaticDataMember()) {
switch (VD->getAccess()) {
default:
case AS_private: Out << '0'; break;
case AS_protected: Out << '1'; break;
case AS_public: Out << '2'; break;
}
}
else if (!VD->isStaticLocal())
Out << '3';
else
Out << '4';
SourceRange SR = VD->getSourceRange();
QualType Ty = VD->getType();
if (Ty->isPointerType() || Ty->isReferenceType() ||
Ty->isMemberPointerType()) {
mangleType(Ty, SR, QMM_Drop);
manglePointerExtQualifiers(
Ty.getDesugaredType(getASTContext()).getLocalQualifiers(), QualType());
if (const MemberPointerType *MPT = Ty->getAs<MemberPointerType>()) {
mangleQualifiers(MPT->getPointeeType().getQualifiers(), true);
mangleName(MPT->getClass()->getAsCXXRecordDecl());
} else
mangleQualifiers(Ty->getPointeeType().getQualifiers(), false);
} else if (const ArrayType *AT = getASTContext().getAsArrayType(Ty)) {
mangleDecayedArrayType(AT);
if (AT->getElementType()->isArrayType())
Out << 'A';
else
mangleQualifiers(Ty.getQualifiers(), false);
} else {
mangleType(Ty, SR, QMM_Drop);
mangleQualifiers(Ty.getQualifiers(), false);
}
}
void MicrosoftCXXNameMangler::mangleMemberDataPointer(const CXXRecordDecl *RD,
const ValueDecl *VD,
StringRef Prefix) {
int64_t FieldOffset;
int64_t VBTableOffset;
MSInheritanceModel IM = RD->getMSInheritanceModel();
if (VD) {
FieldOffset = getASTContext().getFieldOffset(VD);
assert(FieldOffset % getASTContext().getCharWidth() == 0 &&
"cannot take address of bitfield");
FieldOffset /= getASTContext().getCharWidth();
VBTableOffset = 0;
if (IM == MSInheritanceModel::Virtual)
FieldOffset -= getASTContext().getOffsetOfBaseWithVBPtr(RD).getQuantity();
} else {
FieldOffset = RD->nullFieldOffsetIsZero() ? 0 : -1;
VBTableOffset = -1;
}
char Code = '\0';
switch (IM) {
case MSInheritanceModel::Single: Code = '0'; break;
case MSInheritanceModel::Multiple: Code = '0'; break;
case MSInheritanceModel::Virtual: Code = 'F'; break;
case MSInheritanceModel::Unspecified: Code = 'G'; break;
}
Out << Prefix << Code;
mangleNumber(FieldOffset);
if (inheritanceModelHasVBPtrOffsetField(IM))
mangleNumber(0);
if (inheritanceModelHasVBTableOffsetField(IM))
mangleNumber(VBTableOffset);
}
void
MicrosoftCXXNameMangler::mangleMemberFunctionPointer(const CXXRecordDecl *RD,
const CXXMethodDecl *MD,
StringRef Prefix) {
MSInheritanceModel IM = RD->getMSInheritanceModel();
char Code = '\0';
switch (IM) {
case MSInheritanceModel::Single: Code = '1'; break;
case MSInheritanceModel::Multiple: Code = 'H'; break;
case MSInheritanceModel::Virtual: Code = 'I'; break;
case MSInheritanceModel::Unspecified: Code = 'J'; break;
}
uint64_t NVOffset = 0;
uint64_t VBTableOffset = 0;
uint64_t VBPtrOffset = 0;
if (MD) {
Out << Prefix << Code << '?';
if (MD->isVirtual()) {
MicrosoftVTableContext *VTContext =
cast<MicrosoftVTableContext>(getASTContext().getVTableContext());
MethodVFTableLocation ML =
VTContext->getMethodVFTableLocation(GlobalDecl(MD));
mangleVirtualMemPtrThunk(MD, ML);
NVOffset = ML.VFPtrOffset.getQuantity();
VBTableOffset = ML.VBTableIndex * 4;
if (ML.VBase) {
const ASTRecordLayout &Layout = getASTContext().getASTRecordLayout(RD);
VBPtrOffset = Layout.getVBPtrOffset().getQuantity();
}
} else {
mangleName(MD);
mangleFunctionEncoding(MD, true);
}
if (VBTableOffset == 0 && IM == MSInheritanceModel::Virtual)
NVOffset -= getASTContext().getOffsetOfBaseWithVBPtr(RD).getQuantity();
} else {
if (IM == MSInheritanceModel::Single) {
Out << Prefix << "0A@";
return;
}
if (IM == MSInheritanceModel::Unspecified)
VBTableOffset = -1;
Out << Prefix << Code;
}
if (inheritanceModelHasNVOffsetField(true, IM))
mangleNumber(static_cast<uint32_t>(NVOffset));
if (inheritanceModelHasVBPtrOffsetField(IM))
mangleNumber(VBPtrOffset);
if (inheritanceModelHasVBTableOffsetField(IM))
mangleNumber(VBTableOffset);
}
void MicrosoftCXXNameMangler::mangleVirtualMemPtrThunk(
const CXXMethodDecl *MD, const MethodVFTableLocation &ML) {
CharUnits PointerWidth = getASTContext().toCharUnitsFromBits(
getASTContext().getTargetInfo().getPointerWidth(0));
uint64_t OffsetInVFTable = ML.Index * PointerWidth.getQuantity();
Out << "?_9";
mangleName(MD->getParent());
Out << "$B";
mangleNumber(OffsetInVFTable);
Out << 'A';
mangleCallingConvention(MD->getType()->castAs<FunctionProtoType>());
}
void MicrosoftCXXNameMangler::mangleName(GlobalDecl GD) {
mangleUnqualifiedName(GD);
mangleNestedName(GD);
Out << '@';
}
void MicrosoftCXXNameMangler::mangleNumber(int64_t Number) {
mangleNumber(llvm::APSInt(llvm::APInt(64, Number), false));
}
void MicrosoftCXXNameMangler::mangleNumber(llvm::APSInt Number) {
unsigned Width = std::max(Number.getBitWidth(), 64U);
llvm::APInt Value = Number.extend(Width);
if (Value.isNegative()) {
Value = -Value;
Out << '?';
}
mangleBits(Value);
}
void MicrosoftCXXNameMangler::mangleFloat(llvm::APFloat Number) {
using llvm::APFloat;
switch (APFloat::SemanticsToEnum(Number.getSemantics())) {
case APFloat::S_IEEEsingle: Out << 'A'; break;
case APFloat::S_IEEEdouble: Out << 'B'; break;
case APFloat::S_IEEEhalf: Out << 'V'; break;
case APFloat::S_BFloat: Out << 'W'; break;
case APFloat::S_x87DoubleExtended: Out << 'X'; break;
case APFloat::S_IEEEquad: Out << 'Y'; break;
case APFloat::S_PPCDoubleDouble: Out << 'Z'; break;
}
mangleBits(Number.bitcastToAPInt());
}
void MicrosoftCXXNameMangler::mangleBits(llvm::APInt Value) {
if (Value == 0)
Out << "A@";
else if (Value.uge(1) && Value.ule(10))
Out << (Value - 1);
else {
llvm::SmallString<32> EncodedNumberBuffer;
for (; Value != 0; Value.lshrInPlace(4))
EncodedNumberBuffer.push_back('A' + (Value & 0xf).getZExtValue());
std::reverse(EncodedNumberBuffer.begin(), EncodedNumberBuffer.end());
Out.write(EncodedNumberBuffer.data(), EncodedNumberBuffer.size());
Out << '@';
}
}
static GlobalDecl isTemplate(GlobalDecl GD,
const TemplateArgumentList *&TemplateArgs) {
const NamedDecl *ND = cast<NamedDecl>(GD.getDecl());
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {
if (const TemplateDecl *TD = FD->getPrimaryTemplate()) {
TemplateArgs = FD->getTemplateSpecializationArgs();
return GD.getWithDecl(TD);
}
}
if (const ClassTemplateSpecializationDecl *Spec =
dyn_cast<ClassTemplateSpecializationDecl>(ND)) {
TemplateArgs = &Spec->getTemplateArgs();
return GD.getWithDecl(Spec->getSpecializedTemplate());
}
if (const VarTemplateSpecializationDecl *Spec =
dyn_cast<VarTemplateSpecializationDecl>(ND)) {
TemplateArgs = &Spec->getTemplateArgs();
return GD.getWithDecl(Spec->getSpecializedTemplate());
}
return GlobalDecl();
}
void MicrosoftCXXNameMangler::mangleUnqualifiedName(GlobalDecl GD,
DeclarationName Name) {
const NamedDecl *ND = cast<NamedDecl>(GD.getDecl());
const TemplateArgumentList *TemplateArgs = nullptr;
if (GlobalDecl TD = isTemplate(GD, TemplateArgs)) {
if (isa<FunctionTemplateDecl>(TD.getDecl())) {
mangleTemplateInstantiationName(TD, *TemplateArgs);
Out << '@';
return;
}
ArgBackRefMap::iterator Found = TemplateArgBackReferences.find(ND);
if (Found == TemplateArgBackReferences.end()) {
TemplateArgStringMap::iterator Found = TemplateArgStrings.find(ND);
if (Found == TemplateArgStrings.end()) {
llvm::SmallString<64> TemplateMangling;
llvm::raw_svector_ostream Stream(TemplateMangling);
MicrosoftCXXNameMangler Extra(Context, Stream);
Extra.mangleTemplateInstantiationName(TD, *TemplateArgs);
mangleSourceName(TemplateMangling);
BackRefVec::iterator StringFound =
llvm::find(NameBackReferences, TemplateMangling);
if (StringFound != NameBackReferences.end()) {
TemplateArgBackReferences[ND] =
StringFound - NameBackReferences.begin();
} else {
TemplateArgStrings[ND] =
TemplateArgStringStorage.save(TemplateMangling.str());
}
} else {
Out << Found->second << '@'; }
} else {
Out << Found->second; }
return;
}
switch (Name.getNameKind()) {
case DeclarationName::Identifier: {
if (const IdentifierInfo *II = Name.getAsIdentifierInfo()) {
bool IsDeviceStub =
ND &&
((isa<FunctionDecl>(ND) && ND->hasAttr<CUDAGlobalAttr>()) ||
(isa<FunctionTemplateDecl>(ND) &&
cast<FunctionTemplateDecl>(ND)
->getTemplatedDecl()
->hasAttr<CUDAGlobalAttr>())) &&
GD.getKernelReferenceKind() == KernelReferenceKind::Stub;
if (IsDeviceStub)
mangleSourceName(
(llvm::Twine("__device_stub__") + II->getName()).str());
else
mangleSourceName(II->getName());
break;
}
assert(ND && "mangling empty name without declaration");
if (const NamespaceDecl *NS = dyn_cast<NamespaceDecl>(ND)) {
if (NS->isAnonymousNamespace()) {
Out << "?A0x" << Context.getAnonymousNamespaceHash() << '@';
break;
}
}
if (const DecompositionDecl *DD = dyn_cast<DecompositionDecl>(ND)) {
llvm::SmallString<64> Name("$S");
Name += llvm::utostr(Context.getAnonymousStructId(DD) + 1);
mangleSourceName(Name);
break;
}
if (const VarDecl *VD = dyn_cast<VarDecl>(ND)) {
const CXXRecordDecl *RD = VD->getType()->getAsCXXRecordDecl();
assert(RD && "expected variable decl to have a record type");
llvm::SmallString<64> Name("$S");
Name += llvm::utostr(Context.getAnonymousStructId(RD) + 1);
mangleSourceName(Name.str());
break;
}
if (const MSGuidDecl *GD = dyn_cast<MSGuidDecl>(ND)) {
SmallString<sizeof("_GUID_12345678_1234_1234_1234_1234567890ab")> GUID;
llvm::raw_svector_ostream GUIDOS(GUID);
Context.mangleMSGuidDecl(GD, GUIDOS);
mangleSourceName(GUID);
break;
}
if (const auto *TPO = dyn_cast<TemplateParamObjectDecl>(ND)) {
Out << "?__N";
mangleTemplateArgValue(TPO->getType().getUnqualifiedType(),
TPO->getValue());
break;
}
const TagDecl *TD = cast<TagDecl>(ND);
if (const TypedefNameDecl *D = TD->getTypedefNameForAnonDecl()) {
assert(TD->getDeclContext() == D->getDeclContext() &&
"Typedef should not be in another decl context!");
assert(D->getDeclName().getAsIdentifierInfo() &&
"Typedef was not named!");
mangleSourceName(D->getDeclName().getAsIdentifierInfo()->getName());
break;
}
if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(TD)) {
if (Record->isLambda()) {
llvm::SmallString<10> Name("<lambda_");
Decl *LambdaContextDecl = Record->getLambdaContextDecl();
unsigned LambdaManglingNumber = Record->getLambdaManglingNumber();
unsigned LambdaId;
const ParmVarDecl *Parm =
dyn_cast_or_null<ParmVarDecl>(LambdaContextDecl);
const FunctionDecl *Func =
Parm ? dyn_cast<FunctionDecl>(Parm->getDeclContext()) : nullptr;
if (Func) {
unsigned DefaultArgNo =
Func->getNumParams() - Parm->getFunctionScopeIndex();
Name += llvm::utostr(DefaultArgNo);
Name += "_";
}
if (LambdaManglingNumber)
LambdaId = LambdaManglingNumber;
else
LambdaId = Context.getLambdaId(Record);
Name += llvm::utostr(LambdaId);
Name += ">";
mangleSourceName(Name);
if (LambdaManglingNumber && LambdaContextDecl) {
if ((isa<VarDecl>(LambdaContextDecl) ||
isa<FieldDecl>(LambdaContextDecl)) &&
!isa<ParmVarDecl>(LambdaContextDecl)) {
mangleUnqualifiedName(cast<NamedDecl>(LambdaContextDecl));
}
}
break;
}
}
llvm::SmallString<64> Name;
if (DeclaratorDecl *DD =
Context.getASTContext().getDeclaratorForUnnamedTagDecl(TD)) {
Name += "<unnamed-type-";
Name += DD->getName();
} else if (TypedefNameDecl *TND =
Context.getASTContext().getTypedefNameForUnnamedTagDecl(
TD)) {
Name += "<unnamed-type-";
Name += TND->getName();
} else if (isa<EnumDecl>(TD) &&
cast<EnumDecl>(TD)->enumerator_begin() !=
cast<EnumDecl>(TD)->enumerator_end()) {
auto *ED = cast<EnumDecl>(TD);
Name += "<unnamed-enum-";
Name += ED->enumerator_begin()->getName();
} else {
Name += "<unnamed-type-$S";
Name += llvm::utostr(Context.getAnonymousStructId(TD) + 1);
}
Name += ">";
mangleSourceName(Name.str());
break;
}
case DeclarationName::ObjCZeroArgSelector:
case DeclarationName::ObjCOneArgSelector:
case DeclarationName::ObjCMultiArgSelector: {
llvm::SmallString<64> Name;
mangleSourceName(Name.str());
break;
}
case DeclarationName::CXXConstructorName:
if (isStructorDecl(ND)) {
if (StructorType == Ctor_CopyingClosure) {
Out << "?_O";
return;
}
if (StructorType == Ctor_DefaultClosure) {
Out << "?_F";
return;
}
}
Out << "?0";
return;
case DeclarationName::CXXDestructorName:
if (isStructorDecl(ND))
mangleCXXDtorType(static_cast<CXXDtorType>(StructorType));
else
mangleCXXDtorType(Dtor_Base);
break;
case DeclarationName::CXXConversionFunctionName:
Out << "?B";
break;
case DeclarationName::CXXOperatorName:
mangleOperatorName(Name.getCXXOverloadedOperator(), ND->getLocation());
break;
case DeclarationName::CXXLiteralOperatorName: {
Out << "?__K";
mangleSourceName(Name.getCXXLiteralIdentifier()->getName());
break;
}
case DeclarationName::CXXDeductionGuideName:
llvm_unreachable("Can't mangle a deduction guide name!");
case DeclarationName::CXXUsingDirective:
llvm_unreachable("Can't mangle a using directive name!");
}
}
void MicrosoftCXXNameMangler::mangleNestedName(GlobalDecl GD) {
const NamedDecl *ND = cast<NamedDecl>(GD.getDecl());
const DeclContext *DC = getEffectiveDeclContext(ND);
while (!DC->isTranslationUnit()) {
if (isa<TagDecl>(ND) || isa<VarDecl>(ND)) {
unsigned Disc;
if (Context.getNextDiscriminator(ND, Disc)) {
Out << '?';
mangleNumber(Disc);
Out << '?';
}
}
if (const BlockDecl *BD = dyn_cast<BlockDecl>(DC)) {
auto Discriminate =
[](StringRef Name, const unsigned Discriminator,
const unsigned ParameterDiscriminator) -> std::string {
std::string Buffer;
llvm::raw_string_ostream Stream(Buffer);
Stream << Name;
if (Discriminator)
Stream << '_' << Discriminator;
if (ParameterDiscriminator)
Stream << '_' << ParameterDiscriminator;
return Stream.str();
};
unsigned Discriminator = BD->getBlockManglingNumber();
if (!Discriminator)
Discriminator = Context.getBlockId(BD, false);
unsigned ParameterDiscriminator = 0;
if (const auto *MC = BD->getBlockManglingContextDecl())
if (const auto *P = dyn_cast<ParmVarDecl>(MC))
if (const auto *F = dyn_cast<FunctionDecl>(P->getDeclContext()))
ParameterDiscriminator =
F->getNumParams() - P->getFunctionScopeIndex();
DC = getEffectiveDeclContext(BD);
Out << '?';
mangleSourceName(Discriminate("_block_invoke", Discriminator,
ParameterDiscriminator));
if (const auto *MC = BD->getBlockManglingContextDecl())
if (!isa<ParmVarDecl>(MC))
if (const auto *ND = dyn_cast<NamedDecl>(MC))
mangleUnqualifiedName(ND);
if (const auto *RD = dyn_cast<RecordDecl>(DC))
mangleName(RD);
else
Out << '@';
Out << "YAX";
Out << 'P';
if (PointersAre64Bit)
Out << 'E';
Out << 'A';
mangleArtificialTagType(TTK_Struct,
Discriminate("__block_literal", Discriminator,
ParameterDiscriminator));
Out << "@Z";
if (isa<RecordDecl>(DC))
break;
continue;
} else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(DC)) {
mangleObjCMethodName(Method);
} else if (isa<NamedDecl>(DC)) {
ND = cast<NamedDecl>(DC);
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {
mangle(getGlobalDeclAsDeclContext(FD), "?");
break;
} else {
mangleUnqualifiedName(ND);
if (const auto *LDADC = getLambdaDefaultArgumentDeclContext(ND)) {
DC = LDADC;
continue;
}
}
}
DC = DC->getParent();
}
}
void MicrosoftCXXNameMangler::mangleCXXDtorType(CXXDtorType T) {
switch (T) {
case Dtor_Base: Out << "?1"; return;
case Dtor_Complete: Out << "?_D"; return;
case Dtor_Deleting: Out << "?_G"; return;
case Dtor_Comdat:
llvm_unreachable("not expecting a COMDAT");
}
llvm_unreachable("Unsupported dtor type?");
}
void MicrosoftCXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO,
SourceLocation Loc) {
switch (OO) {
case OO_New: Out << "?2"; break;
case OO_Delete: Out << "?3"; break;
case OO_Equal: Out << "?4"; break;
case OO_GreaterGreater: Out << "?5"; break;
case OO_LessLess: Out << "?6"; break;
case OO_Exclaim: Out << "?7"; break;
case OO_EqualEqual: Out << "?8"; break;
case OO_ExclaimEqual: Out << "?9"; break;
case OO_Subscript: Out << "?A"; break;
case OO_Arrow: Out << "?C"; break;
case OO_Star: Out << "?D"; break;
case OO_PlusPlus: Out << "?E"; break;
case OO_MinusMinus: Out << "?F"; break;
case OO_Minus: Out << "?G"; break;
case OO_Plus: Out << "?H"; break;
case OO_Amp: Out << "?I"; break;
case OO_ArrowStar: Out << "?J"; break;
case OO_Slash: Out << "?K"; break;
case OO_Percent: Out << "?L"; break;
case OO_Less: Out << "?M"; break;
case OO_LessEqual: Out << "?N"; break;
case OO_Greater: Out << "?O"; break;
case OO_GreaterEqual: Out << "?P"; break;
case OO_Comma: Out << "?Q"; break;
case OO_Call: Out << "?R"; break;
case OO_Tilde: Out << "?S"; break;
case OO_Caret: Out << "?T"; break;
case OO_Pipe: Out << "?U"; break;
case OO_AmpAmp: Out << "?V"; break;
case OO_PipePipe: Out << "?W"; break;
case OO_StarEqual: Out << "?X"; break;
case OO_PlusEqual: Out << "?Y"; break;
case OO_MinusEqual: Out << "?Z"; break;
case OO_SlashEqual: Out << "?_0"; break;
case OO_PercentEqual: Out << "?_1"; break;
case OO_GreaterGreaterEqual: Out << "?_2"; break;
case OO_LessLessEqual: Out << "?_3"; break;
case OO_AmpEqual: Out << "?_4"; break;
case OO_PipeEqual: Out << "?_5"; break;
case OO_CaretEqual: Out << "?_6"; break;
case OO_Array_New: Out << "?_U"; break;
case OO_Array_Delete: Out << "?_V"; break;
case OO_Coawait: Out << "?__L"; break;
case OO_Spaceship: Out << "?__M"; break;
case OO_Conditional: {
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
"cannot mangle this conditional operator yet");
Diags.Report(Loc, DiagID);
break;
}
case OO_None:
case NUM_OVERLOADED_OPERATORS:
llvm_unreachable("Not an overloaded operator");
}
}
void MicrosoftCXXNameMangler::mangleSourceName(StringRef Name) {
BackRefVec::iterator Found = llvm::find(NameBackReferences, Name);
if (Found == NameBackReferences.end()) {
if (NameBackReferences.size() < 10)
NameBackReferences.push_back(std::string(Name));
Out << Name << '@';
} else {
Out << (Found - NameBackReferences.begin());
}
}
void MicrosoftCXXNameMangler::mangleObjCMethodName(const ObjCMethodDecl *MD) {
Context.mangleObjCMethodNameAsSourceName(MD, Out);
}
void MicrosoftCXXNameMangler::mangleTemplateInstantiationName(
GlobalDecl GD, const TemplateArgumentList &TemplateArgs) {
ArgBackRefMap OuterFunArgsContext;
ArgBackRefMap OuterTemplateArgsContext;
BackRefVec OuterTemplateContext;
PassObjectSizeArgsSet OuterPassObjectSizeArgs;
NameBackReferences.swap(OuterTemplateContext);
FunArgBackReferences.swap(OuterFunArgsContext);
TemplateArgBackReferences.swap(OuterTemplateArgsContext);
PassObjectSizeArgs.swap(OuterPassObjectSizeArgs);
mangleUnscopedTemplateName(GD);
mangleTemplateArgs(cast<TemplateDecl>(GD.getDecl()), TemplateArgs);
NameBackReferences.swap(OuterTemplateContext);
FunArgBackReferences.swap(OuterFunArgsContext);
TemplateArgBackReferences.swap(OuterTemplateArgsContext);
PassObjectSizeArgs.swap(OuterPassObjectSizeArgs);
}
void MicrosoftCXXNameMangler::mangleUnscopedTemplateName(GlobalDecl GD) {
Out << "?$";
mangleUnqualifiedName(GD);
}
void MicrosoftCXXNameMangler::mangleIntegerLiteral(
const llvm::APSInt &Value, const NonTypeTemplateParmDecl *PD,
QualType TemplateArgType) {
Out << "$";
if (getASTContext().getLangOpts().isCompatibleWithMSVC(
LangOptions::MSVC2019) &&
PD && PD->getType()->getTypeClass() == Type::Auto &&
!TemplateArgType.isNull()) {
Out << "M";
mangleType(TemplateArgType, SourceRange(), QMM_Drop);
}
Out << "0";
mangleNumber(Value);
}
void MicrosoftCXXNameMangler::mangleExpression(
const Expr *E, const NonTypeTemplateParmDecl *PD) {
if (Optional<llvm::APSInt> Value =
E->getIntegerConstantExpr(Context.getASTContext())) {
mangleIntegerLiteral(*Value, PD, E->getType());
return;
}
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(
DiagnosticsEngine::Error, "cannot yet mangle expression type %0");
Diags.Report(E->getExprLoc(), DiagID) << E->getStmtClassName()
<< E->getSourceRange();
}
void MicrosoftCXXNameMangler::mangleTemplateArgs(
const TemplateDecl *TD, const TemplateArgumentList &TemplateArgs) {
const TemplateParameterList *TPL = TD->getTemplateParameters();
assert(TPL->size() == TemplateArgs.size() &&
"size mismatch between args and parms!");
for (size_t i = 0; i < TemplateArgs.size(); ++i) {
const TemplateArgument &TA = TemplateArgs[i];
if (i > 0 && TA.getKind() == TemplateArgument::Pack &&
TemplateArgs[i - 1].getKind() == TemplateArgument::Pack)
Out << "$$Z";
mangleTemplateArg(TD, TA, TPL->getParam(i));
}
}
void MicrosoftCXXNameMangler::mangleTemplateArg(const TemplateDecl *TD,
const TemplateArgument &TA,
const NamedDecl *Parm) {
switch (TA.getKind()) {
case TemplateArgument::Null:
llvm_unreachable("Can't mangle null template arguments!");
case TemplateArgument::TemplateExpansion:
llvm_unreachable("Can't mangle template expansion arguments!");
case TemplateArgument::Type: {
QualType T = TA.getAsType();
mangleType(T, SourceRange(), QMM_Escape);
break;
}
case TemplateArgument::Declaration: {
const NamedDecl *ND = TA.getAsDecl();
if (isa<FieldDecl>(ND) || isa<IndirectFieldDecl>(ND)) {
mangleMemberDataPointer(cast<CXXRecordDecl>(ND->getDeclContext())
->getMostRecentNonInjectedDecl(),
cast<ValueDecl>(ND));
} else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {
const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD);
if (MD && MD->isInstance()) {
mangleMemberFunctionPointer(
MD->getParent()->getMostRecentNonInjectedDecl(), MD);
} else {
Out << "$1?";
mangleName(FD);
mangleFunctionEncoding(FD, true);
}
} else if (TA.getParamTypeForDecl()->isRecordType()) {
Out << "$";
auto *TPO = cast<TemplateParamObjectDecl>(ND);
mangleTemplateArgValue(TPO->getType().getUnqualifiedType(),
TPO->getValue());
} else {
mangle(ND, TA.getParamTypeForDecl()->isReferenceType() ? "$E?" : "$1?");
}
break;
}
case TemplateArgument::Integral: {
QualType T = TA.getIntegralType();
mangleIntegerLiteral(TA.getAsIntegral(),
cast<NonTypeTemplateParmDecl>(Parm), T);
break;
}
case TemplateArgument::NullPtr: {
QualType T = TA.getNullPtrType();
if (const MemberPointerType *MPT = T->getAs<MemberPointerType>()) {
const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl();
if (MPT->isMemberFunctionPointerType() &&
!isa<FunctionTemplateDecl>(TD)) {
mangleMemberFunctionPointer(RD, nullptr);
return;
}
if (MPT->isMemberDataPointer()) {
if (!isa<FunctionTemplateDecl>(TD)) {
mangleMemberDataPointer(RD, nullptr);
return;
}
if (!RD->nullFieldOffsetIsZero()) {
mangleIntegerLiteral(llvm::APSInt::get(-1),
cast<NonTypeTemplateParmDecl>(Parm), T);
return;
}
}
}
mangleIntegerLiteral(llvm::APSInt::getUnsigned(0),
cast<NonTypeTemplateParmDecl>(Parm), T);
break;
}
case TemplateArgument::Expression:
mangleExpression(TA.getAsExpr(), cast<NonTypeTemplateParmDecl>(Parm));
break;
case TemplateArgument::Pack: {
ArrayRef<TemplateArgument> TemplateArgs = TA.getPackAsArray();
if (TemplateArgs.empty()) {
if (isa<TemplateTypeParmDecl>(Parm) ||
isa<TemplateTemplateParmDecl>(Parm))
Out << (Context.getASTContext().getLangOpts().isCompatibleWithMSVC(
LangOptions::MSVC2015)
? "$$V"
: "$$$V");
else if (isa<NonTypeTemplateParmDecl>(Parm))
Out << "$S";
else
llvm_unreachable("unexpected template parameter decl!");
} else {
for (const TemplateArgument &PA : TemplateArgs)
mangleTemplateArg(TD, PA, Parm);
}
break;
}
case TemplateArgument::Template: {
const NamedDecl *ND =
TA.getAsTemplate().getAsTemplateDecl()->getTemplatedDecl();
if (const auto *TD = dyn_cast<TagDecl>(ND)) {
mangleType(TD);
} else if (isa<TypeAliasDecl>(ND)) {
Out << "$$Y";
mangleName(ND);
} else {
llvm_unreachable("unexpected template template NamedDecl!");
}
break;
}
}
}
void MicrosoftCXXNameMangler::mangleTemplateArgValue(QualType T,
const APValue &V,
bool WithScalarType) {
switch (V.getKind()) {
case APValue::None:
case APValue::Indeterminate:
if (WithScalarType)
mangleType(T, SourceRange(), QMM_Escape);
Out << '@';
return;
case APValue::Int:
if (WithScalarType)
mangleType(T, SourceRange(), QMM_Escape);
Out << '0';
mangleNumber(V.getInt());
return;
case APValue::Float:
if (WithScalarType)
mangleType(T, SourceRange(), QMM_Escape);
mangleFloat(V.getFloat());
return;
case APValue::LValue: {
if (WithScalarType)
mangleType(T, SourceRange(), QMM_Escape);
if (V.isLValueOnePastTheEnd())
break;
APValue::LValueBase Base = V.getLValueBase();
if (!V.hasLValuePath() || V.getLValuePath().empty()) {
if (Base.isNull()) {
Out << "0";
mangleNumber(V.getLValueOffset().getQuantity());
} else if (!V.hasLValuePath()) {
break;
} else if (auto *VD = Base.dyn_cast<const ValueDecl*>()) {
Out << (T->isReferenceType() ? "E" : "1");
mangle(VD);
} else {
break;
}
} else {
unsigned NumAts = 0;
if (T->isPointerType()) {
Out << "5";
++NumAts;
}
QualType T = Base.getType();
for (APValue::LValuePathEntry E : V.getLValuePath()) {
if (T->isArrayType())
goto mangling_unknown;
const Decl *D = E.getAsBaseOrMember().getPointer();
auto *FD = dyn_cast<FieldDecl>(D);
if (!FD)
goto mangling_unknown;
Out << "6";
++NumAts;
T = FD->getType();
}
auto *VD = Base.dyn_cast<const ValueDecl*>();
if (!VD)
break;
Out << "E";
mangle(VD);
for (APValue::LValuePathEntry E : V.getLValuePath()) {
const Decl *D = E.getAsBaseOrMember().getPointer();
mangleUnqualifiedName(cast<FieldDecl>(D));
}
for (unsigned I = 0; I != NumAts; ++I)
Out << '@';
}
return;
}
case APValue::MemberPointer: {
if (WithScalarType)
mangleType(T, SourceRange(), QMM_Escape);
if (!V.getMemberPointerPath().empty())
break;
const CXXRecordDecl *RD =
T->castAs<MemberPointerType>()->getMostRecentCXXRecordDecl();
const ValueDecl *D = V.getMemberPointerDecl();
if (T->isMemberDataPointerType())
mangleMemberDataPointer(RD, D, "");
else
mangleMemberFunctionPointer(RD, cast_or_null<CXXMethodDecl>(D), "");
return;
}
case APValue::Struct: {
Out << '2';
mangleType(T, SourceRange(), QMM_Escape);
const CXXRecordDecl *RD = T->getAsCXXRecordDecl();
assert(RD && "unexpected type for record value");
unsigned BaseIndex = 0;
for (const CXXBaseSpecifier &B : RD->bases())
mangleTemplateArgValue(B.getType(), V.getStructBase(BaseIndex++));
for (const FieldDecl *FD : RD->fields())
if (!FD->isUnnamedBitfield())
mangleTemplateArgValue(FD->getType(),
V.getStructField(FD->getFieldIndex()),
true);
Out << '@';
return;
}
case APValue::Union:
Out << '7';
mangleType(T, SourceRange(), QMM_Escape);
if (const FieldDecl *FD = V.getUnionField()) {
mangleUnqualifiedName(FD);
mangleTemplateArgValue(FD->getType(), V.getUnionValue());
}
Out << '@';
return;
case APValue::ComplexInt:
Out << '2';
mangleType(T, SourceRange(), QMM_Escape);
Out << '0';
mangleNumber(V.getComplexIntReal());
Out << '0';
mangleNumber(V.getComplexIntImag());
Out << '@';
return;
case APValue::ComplexFloat:
Out << '2';
mangleType(T, SourceRange(), QMM_Escape);
mangleFloat(V.getComplexFloatReal());
mangleFloat(V.getComplexFloatImag());
Out << '@';
return;
case APValue::Array: {
Out << '3';
QualType ElemT = getASTContext().getAsArrayType(T)->getElementType();
mangleType(ElemT, SourceRange(), QMM_Escape);
for (unsigned I = 0, N = V.getArraySize(); I != N; ++I) {
const APValue &ElemV = I < V.getArrayInitializedElts()
? V.getArrayInitializedElt(I)
: V.getArrayFiller();
mangleTemplateArgValue(ElemT, ElemV);
Out << '@';
}
Out << '@';
return;
}
case APValue::Vector: {
Out << '2';
mangleType(T, SourceRange(), QMM_Escape);
Out << '3';
QualType ElemT = T->castAs<VectorType>()->getElementType();
mangleType(ElemT, SourceRange(), QMM_Escape);
for (unsigned I = 0, N = V.getVectorLength(); I != N; ++I) {
const APValue &ElemV = V.getVectorElt(I);
mangleTemplateArgValue(ElemT, ElemV);
Out << '@';
}
Out << "@@";
return;
}
case APValue::AddrLabelDiff:
case APValue::FixedPoint:
break;
}
mangling_unknown:
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(
DiagnosticsEngine::Error, "cannot mangle this template argument yet");
Diags.Report(DiagID);
}
void MicrosoftCXXNameMangler::mangleObjCProtocol(const ObjCProtocolDecl *PD) {
llvm::SmallString<64> TemplateMangling;
llvm::raw_svector_ostream Stream(TemplateMangling);
MicrosoftCXXNameMangler Extra(Context, Stream);
Stream << "?$";
Extra.mangleSourceName("Protocol");
Extra.mangleArtificialTagType(TTK_Struct, PD->getName());
mangleArtificialTagType(TTK_Struct, TemplateMangling, {"__ObjC"});
}
void MicrosoftCXXNameMangler::mangleObjCLifetime(const QualType Type,
Qualifiers Quals,
SourceRange Range) {
llvm::SmallString<64> TemplateMangling;
llvm::raw_svector_ostream Stream(TemplateMangling);
MicrosoftCXXNameMangler Extra(Context, Stream);
Stream << "?$";
switch (Quals.getObjCLifetime()) {
case Qualifiers::OCL_None:
case Qualifiers::OCL_ExplicitNone:
break;
case Qualifiers::OCL_Autoreleasing:
Extra.mangleSourceName("Autoreleasing");
break;
case Qualifiers::OCL_Strong:
Extra.mangleSourceName("Strong");
break;
case Qualifiers::OCL_Weak:
Extra.mangleSourceName("Weak");
break;
}
Extra.manglePointerCVQualifiers(Quals);
Extra.manglePointerExtQualifiers(Quals, Type);
Extra.mangleType(Type, Range);
mangleArtificialTagType(TTK_Struct, TemplateMangling, {"__ObjC"});
}
void MicrosoftCXXNameMangler::mangleObjCKindOfType(const ObjCObjectType *T,
Qualifiers Quals,
SourceRange Range) {
llvm::SmallString<64> TemplateMangling;
llvm::raw_svector_ostream Stream(TemplateMangling);
MicrosoftCXXNameMangler Extra(Context, Stream);
Stream << "?$";
Extra.mangleSourceName("KindOf");
Extra.mangleType(QualType(T, 0)
.stripObjCKindOfType(getASTContext())
->castAs<ObjCObjectType>(),
Quals, Range);
mangleArtificialTagType(TTK_Struct, TemplateMangling, {"__ObjC"});
}
void MicrosoftCXXNameMangler::mangleQualifiers(Qualifiers Quals,
bool IsMember) {
bool HasConst = Quals.hasConst(),
HasVolatile = Quals.hasVolatile();
if (!IsMember) {
if (HasConst && HasVolatile) {
Out << 'D';
} else if (HasVolatile) {
Out << 'C';
} else if (HasConst) {
Out << 'B';
} else {
Out << 'A';
}
} else {
if (HasConst && HasVolatile) {
Out << 'T';
} else if (HasVolatile) {
Out << 'S';
} else if (HasConst) {
Out << 'R';
} else {
Out << 'Q';
}
}
}
void
MicrosoftCXXNameMangler::mangleRefQualifier(RefQualifierKind RefQualifier) {
switch (RefQualifier) {
case RQ_None:
break;
case RQ_LValue:
Out << 'G';
break;
case RQ_RValue:
Out << 'H';
break;
}
}
void MicrosoftCXXNameMangler::manglePointerExtQualifiers(Qualifiers Quals,
QualType PointeeType) {
bool is64Bit = PointeeType.isNull() ? PointersAre64Bit :
is64BitPointer(PointeeType.getQualifiers());
if (is64Bit && (PointeeType.isNull() || !PointeeType->isFunctionType()))
Out << 'E';
if (Quals.hasRestrict())
Out << 'I';
if (Quals.hasUnaligned() ||
(!PointeeType.isNull() && PointeeType.getLocalQualifiers().hasUnaligned()))
Out << 'F';
}
void MicrosoftCXXNameMangler::manglePointerCVQualifiers(Qualifiers Quals) {
bool HasConst = Quals.hasConst(),
HasVolatile = Quals.hasVolatile();
if (HasConst && HasVolatile) {
Out << 'S';
} else if (HasVolatile) {
Out << 'R';
} else if (HasConst) {
Out << 'Q';
} else {
Out << 'P';
}
}
void MicrosoftCXXNameMangler::mangleFunctionArgumentType(QualType T,
SourceRange Range) {
void *TypePtr;
if (const auto *DT = T->getAs<DecayedType>()) {
QualType OriginalType = DT->getOriginalType();
if (const auto *AT = getASTContext().getAsArrayType(OriginalType))
OriginalType = getASTContext().getIncompleteArrayType(
AT->getElementType(), AT->getSizeModifier(),
AT->getIndexTypeCVRQualifiers());
TypePtr = OriginalType.getCanonicalType().getAsOpaquePtr();
if (OriginalType->isArrayType())
T = T.withConst();
} else {
TypePtr = T.getCanonicalType().getAsOpaquePtr();
}
ArgBackRefMap::iterator Found = FunArgBackReferences.find(TypePtr);
if (Found == FunArgBackReferences.end()) {
size_t OutSizeBefore = Out.tell();
mangleType(T, Range, QMM_Drop);
bool LongerThanOneChar = (Out.tell() - OutSizeBefore > 1);
if (LongerThanOneChar && FunArgBackReferences.size() < 10) {
size_t Size = FunArgBackReferences.size();
FunArgBackReferences[TypePtr] = Size;
}
} else {
Out << Found->second;
}
}
void MicrosoftCXXNameMangler::manglePassObjectSizeArg(
const PassObjectSizeAttr *POSA) {
int Type = POSA->getType();
bool Dynamic = POSA->isDynamic();
auto Iter = PassObjectSizeArgs.insert({Type, Dynamic}).first;
auto *TypePtr = (const void *)&*Iter;
ArgBackRefMap::iterator Found = FunArgBackReferences.find(TypePtr);
if (Found == FunArgBackReferences.end()) {
std::string Name =
Dynamic ? "__pass_dynamic_object_size" : "__pass_object_size";
mangleArtificialTagType(TTK_Enum, Name + llvm::utostr(Type), {"__clang"});
if (FunArgBackReferences.size() < 10) {
size_t Size = FunArgBackReferences.size();
FunArgBackReferences[TypePtr] = Size;
}
} else {
Out << Found->second;
}
}
void MicrosoftCXXNameMangler::mangleAddressSpaceType(QualType T,
Qualifiers Quals,
SourceRange Range) {
assert(Quals.hasAddressSpace() && "Not valid without address space");
llvm::SmallString<32> ASMangling;
llvm::raw_svector_ostream Stream(ASMangling);
MicrosoftCXXNameMangler Extra(Context, Stream);
Stream << "?$";
LangAS AS = Quals.getAddressSpace();
if (Context.getASTContext().addressSpaceMapManglingFor(AS)) {
unsigned TargetAS = Context.getASTContext().getTargetAddressSpace(AS);
Extra.mangleSourceName("_AS");
Extra.mangleIntegerLiteral(llvm::APSInt::getUnsigned(TargetAS));
} else {
switch (AS) {
default:
llvm_unreachable("Not a language specific address space");
case LangAS::opencl_global:
Extra.mangleSourceName("_ASCLglobal");
break;
case LangAS::opencl_global_device:
Extra.mangleSourceName("_ASCLdevice");
break;
case LangAS::opencl_global_host:
Extra.mangleSourceName("_ASCLhost");
break;
case LangAS::opencl_local:
Extra.mangleSourceName("_ASCLlocal");
break;
case LangAS::opencl_constant:
Extra.mangleSourceName("_ASCLconstant");
break;
case LangAS::opencl_private:
Extra.mangleSourceName("_ASCLprivate");
break;
case LangAS::opencl_generic:
Extra.mangleSourceName("_ASCLgeneric");
break;
case LangAS::cuda_device:
Extra.mangleSourceName("_ASCUdevice");
break;
case LangAS::cuda_constant:
Extra.mangleSourceName("_ASCUconstant");
break;
case LangAS::cuda_shared:
Extra.mangleSourceName("_ASCUshared");
break;
case LangAS::ptr32_sptr:
case LangAS::ptr32_uptr:
case LangAS::ptr64:
llvm_unreachable("don't mangle ptr address spaces with _AS");
}
}
Extra.mangleType(T, Range, QMM_Escape);
mangleQualifiers(Qualifiers(), false);
mangleArtificialTagType(TTK_Struct, ASMangling, {"__clang"});
}
void MicrosoftCXXNameMangler::mangleType(QualType T, SourceRange Range,
QualifierMangleMode QMM) {
T = T.getDesugaredType(getASTContext());
Qualifiers Quals = T.getLocalQualifiers();
if (const ArrayType *AT = getASTContext().getAsArrayType(T)) {
if (QMM == QMM_Mangle)
Out << 'A';
else if (QMM == QMM_Escape || QMM == QMM_Result)
Out << "$$B";
mangleArrayType(AT);
return;
}
bool IsPointer = T->isAnyPointerType() || T->isMemberPointerType() ||
T->isReferenceType() || T->isBlockPointerType();
switch (QMM) {
case QMM_Drop:
if (Quals.hasObjCLifetime())
Quals = Quals.withoutObjCLifetime();
break;
case QMM_Mangle:
if (const FunctionType *FT = dyn_cast<FunctionType>(T)) {
Out << '6';
mangleFunctionType(FT);
return;
}
mangleQualifiers(Quals, false);
break;
case QMM_Escape:
if (!IsPointer && Quals) {
Out << "$$C";
mangleQualifiers(Quals, false);
}
break;
case QMM_Result:
Quals.removeUnaligned();
if (Quals.hasObjCLifetime())
Quals = Quals.withoutObjCLifetime();
if ((!IsPointer && Quals) || isa<TagType>(T) || isArtificialTagType(T)) {
Out << '?';
mangleQualifiers(Quals, false);
}
break;
}
const Type *ty = T.getTypePtr();
switch (ty->getTypeClass()) {
#define ABSTRACT_TYPE(CLASS, PARENT)
#define NON_CANONICAL_TYPE(CLASS, PARENT) \
case Type::CLASS: \
llvm_unreachable("can't mangle non-canonical type " #CLASS "Type"); \
return;
#define TYPE(CLASS, PARENT) \
case Type::CLASS: \
mangleType(cast<CLASS##Type>(ty), Quals, Range); \
break;
#include "clang/AST/TypeNodes.inc"
#undef ABSTRACT_TYPE
#undef NON_CANONICAL_TYPE
#undef TYPE
}
}
void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T, Qualifiers,
SourceRange Range) {
switch (T->getKind()) {
case BuiltinType::Void:
Out << 'X';
break;
case BuiltinType::SChar:
Out << 'C';
break;
case BuiltinType::Char_U:
case BuiltinType::Char_S:
Out << 'D';
break;
case BuiltinType::UChar:
Out << 'E';
break;
case BuiltinType::Short:
Out << 'F';
break;
case BuiltinType::UShort:
Out << 'G';
break;
case BuiltinType::Int:
Out << 'H';
break;
case BuiltinType::UInt:
Out << 'I';
break;
case BuiltinType::Long:
Out << 'J';
break;
case BuiltinType::ULong:
Out << 'K';
break;
case BuiltinType::Float:
Out << 'M';
break;
case BuiltinType::Double:
Out << 'N';
break;
case BuiltinType::LongDouble:
Out << 'O';
break;
case BuiltinType::LongLong:
Out << "_J";
break;
case BuiltinType::ULongLong:
Out << "_K";
break;
case BuiltinType::Int128:
Out << "_L";
break;
case BuiltinType::UInt128:
Out << "_M";
break;
case BuiltinType::Bool:
Out << "_N";
break;
case BuiltinType::Char8:
Out << "_Q";
break;
case BuiltinType::Char16:
Out << "_S";
break;
case BuiltinType::Char32:
Out << "_U";
break;
case BuiltinType::WChar_S:
case BuiltinType::WChar_U:
Out << "_W";
break;
#define BUILTIN_TYPE(Id, SingletonId)
#define PLACEHOLDER_TYPE(Id, SingletonId) \
case BuiltinType::Id:
#include "clang/AST/BuiltinTypes.def"
case BuiltinType::Dependent:
llvm_unreachable("placeholder types shouldn't get to name mangling");
case BuiltinType::ObjCId:
mangleArtificialTagType(TTK_Struct, "objc_object");
break;
case BuiltinType::ObjCClass:
mangleArtificialTagType(TTK_Struct, "objc_class");
break;
case BuiltinType::ObjCSel:
mangleArtificialTagType(TTK_Struct, "objc_selector");
break;
#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
case BuiltinType::Id: \
Out << "PAUocl_" #ImgType "_" #Suffix "@@"; \
break;
#include "clang/Basic/OpenCLImageTypes.def"
case BuiltinType::OCLSampler:
Out << "PA";
mangleArtificialTagType(TTK_Struct, "ocl_sampler");
break;
case BuiltinType::OCLEvent:
Out << "PA";
mangleArtificialTagType(TTK_Struct, "ocl_event");
break;
case BuiltinType::OCLClkEvent:
Out << "PA";
mangleArtificialTagType(TTK_Struct, "ocl_clkevent");
break;
case BuiltinType::OCLQueue:
Out << "PA";
mangleArtificialTagType(TTK_Struct, "ocl_queue");
break;
case BuiltinType::OCLReserveID:
Out << "PA";
mangleArtificialTagType(TTK_Struct, "ocl_reserveid");
break;
#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
case BuiltinType::Id: \
mangleArtificialTagType(TTK_Struct, "ocl_" #ExtType); \
break;
#include "clang/Basic/OpenCLExtensionTypes.def"
case BuiltinType::NullPtr:
Out << "$$T";
break;
case BuiltinType::Float16:
mangleArtificialTagType(TTK_Struct, "_Float16", {"__clang"});
break;
case BuiltinType::Half:
if (!getASTContext().getLangOpts().HLSL)
mangleArtificialTagType(TTK_Struct, "_Half", {"__clang"});
else if (getASTContext().getLangOpts().NativeHalfType)
Out << "$f16@";
else
Out << "$halff@";
break;
#define SVE_TYPE(Name, Id, SingletonId) \
case BuiltinType::Id:
#include "clang/Basic/AArch64SVEACLETypes.def"
#define PPC_VECTOR_TYPE(Name, Id, Size) \
case BuiltinType::Id:
#include "clang/Basic/PPCTypes.def"
#define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
#include "clang/Basic/RISCVVTypes.def"
case BuiltinType::ShortAccum:
case BuiltinType::Accum:
case BuiltinType::LongAccum:
case BuiltinType::UShortAccum:
case BuiltinType::UAccum:
case BuiltinType::ULongAccum:
case BuiltinType::ShortFract:
case BuiltinType::Fract:
case BuiltinType::LongFract:
case BuiltinType::UShortFract:
case BuiltinType::UFract:
case BuiltinType::ULongFract:
case BuiltinType::SatShortAccum:
case BuiltinType::SatAccum:
case BuiltinType::SatLongAccum:
case BuiltinType::SatUShortAccum:
case BuiltinType::SatUAccum:
case BuiltinType::SatULongAccum:
case BuiltinType::SatShortFract:
case BuiltinType::SatFract:
case BuiltinType::SatLongFract:
case BuiltinType::SatUShortFract:
case BuiltinType::SatUFract:
case BuiltinType::SatULongFract:
case BuiltinType::BFloat16:
case BuiltinType::Ibm128:
case BuiltinType::Float128: {
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(
DiagnosticsEngine::Error, "cannot mangle this built-in %0 type yet");
Diags.Report(Range.getBegin(), DiagID)
<< T->getName(Context.getASTContext().getPrintingPolicy()) << Range;
break;
}
}
}
void MicrosoftCXXNameMangler::mangleType(const FunctionProtoType *T, Qualifiers,
SourceRange) {
if (T->getMethodQuals() || T->getRefQualifier() != RQ_None) {
Out << "$$A8@@";
mangleFunctionType(T, nullptr, true);
} else {
Out << "$$A6";
mangleFunctionType(T);
}
}
void MicrosoftCXXNameMangler::mangleType(const FunctionNoProtoType *T,
Qualifiers, SourceRange) {
Out << "$$A6";
mangleFunctionType(T);
}
void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T,
const FunctionDecl *D,
bool ForceThisQuals,
bool MangleExceptionSpec) {
const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(T);
SourceRange Range;
if (D) Range = D->getSourceRange();
bool IsInLambda = false;
bool IsStructor = false, HasThisQuals = ForceThisQuals, IsCtorClosure = false;
CallingConv CC = T->getCallConv();
if (const CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(D)) {
if (MD->getParent()->isLambda())
IsInLambda = true;
if (MD->isInstance())
HasThisQuals = true;
if (isa<CXXDestructorDecl>(MD)) {
IsStructor = true;
} else if (isa<CXXConstructorDecl>(MD)) {
IsStructor = true;
IsCtorClosure = (StructorType == Ctor_CopyingClosure ||
StructorType == Ctor_DefaultClosure) &&
isStructorDecl(MD);
if (IsCtorClosure)
CC = getASTContext().getDefaultCallingConvention(
false, true);
}
}
if (HasThisQuals) {
Qualifiers Quals = Proto->getMethodQuals();
manglePointerExtQualifiers(Quals, QualType());
mangleRefQualifier(Proto->getRefQualifier());
mangleQualifiers(Quals, false);
}
mangleCallingConvention(CC);
if (IsStructor) {
if (isa<CXXDestructorDecl>(D) && isStructorDecl(D)) {
if (StructorType == Dtor_Deleting) {
Out << (PointersAre64Bit ? "PEAXI@Z" : "PAXI@Z");
return;
}
if (StructorType == Dtor_Complete) {
Out << "XXZ";
return;
}
}
if (IsCtorClosure) {
Out << 'X';
if (StructorType == Ctor_DefaultClosure) {
Out << 'X';
} else if (StructorType == Ctor_CopyingClosure) {
mangleFunctionArgumentType(getASTContext().getLValueReferenceType(
Proto->getParamType(0)
->getAs<LValueReferenceType>()
->getPointeeType(),
true),
Range);
Out << '@';
} else {
llvm_unreachable("unexpected constructor closure!");
}
Out << 'Z';
return;
}
Out << '@';
} else if (IsInLambda && D && isa<CXXConversionDecl>(D)) {
mangleType(T->getReturnType(), Range, QMM_Result);
} else {
QualType ResultType = T->getReturnType();
if (IsInLambda && isa<CXXConversionDecl>(D)) {
mangleType(ResultType, Range, QMM_Result);
} else if (const auto *AT = dyn_cast_or_null<AutoType>(
ResultType->getContainedAutoType())) {
Out << '?';
mangleQualifiers(ResultType.getLocalQualifiers(), false);
Out << '?';
assert(AT->getKeyword() != AutoTypeKeyword::GNUAutoType &&
"shouldn't need to mangle __auto_type!");
mangleSourceName(AT->isDecltypeAuto() ? "<decltype-auto>" : "<auto>");
Out << '@';
} else if (IsInLambda) {
Out << '@';
} else {
if (ResultType->isVoidType())
ResultType = ResultType.getUnqualifiedType();
mangleType(ResultType, Range, QMM_Result);
}
}
if (!Proto) {
Out << '@';
} else if (Proto->getNumParams() == 0 && !Proto->isVariadic()) {
Out << 'X';
} else {
for (unsigned I = 0, E = Proto->getNumParams(); I != E; ++I) {
mangleFunctionArgumentType(Proto->getParamType(I), Range);
if (D)
if (const auto *P = D->getParamDecl(I)->getAttr<PassObjectSizeAttr>())
manglePassObjectSizeArg(P);
}
if (Proto->isVariadic())
Out << 'Z';
else
Out << '@';
}
if (MangleExceptionSpec && getASTContext().getLangOpts().CPlusPlus17 &&
getASTContext().getLangOpts().isCompatibleWithMSVC(
LangOptions::MSVC2017_5))
mangleThrowSpecification(Proto);
else
Out << 'Z';
}
void MicrosoftCXXNameMangler::mangleFunctionClass(const FunctionDecl *FD) {
if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
bool IsVirtual = MD->isVirtual();
if (isa<CXXDestructorDecl>(MD) && isStructorDecl(MD) &&
StructorType == Dtor_Complete) {
IsVirtual = false;
}
switch (MD->getAccess()) {
case AS_none:
llvm_unreachable("Unsupported access specifier");
case AS_private:
if (MD->isStatic())
Out << 'C';
else if (IsVirtual)
Out << 'E';
else
Out << 'A';
break;
case AS_protected:
if (MD->isStatic())
Out << 'K';
else if (IsVirtual)
Out << 'M';
else
Out << 'I';
break;
case AS_public:
if (MD->isStatic())
Out << 'S';
else if (IsVirtual)
Out << 'U';
else
Out << 'Q';
}
} else {
Out << 'Y';
}
}
void MicrosoftCXXNameMangler::mangleCallingConvention(CallingConv CC) {
switch (CC) {
default:
llvm_unreachable("Unsupported CC for mangling");
case CC_Win64:
case CC_X86_64SysV:
case CC_C: Out << 'A'; break;
case CC_X86Pascal: Out << 'C'; break;
case CC_X86ThisCall: Out << 'E'; break;
case CC_X86StdCall: Out << 'G'; break;
case CC_X86FastCall: Out << 'I'; break;
case CC_X86VectorCall: Out << 'Q'; break;
case CC_Swift: Out << 'S'; break;
case CC_SwiftAsync: Out << 'W'; break;
case CC_PreserveMost: Out << 'U'; break;
case CC_X86RegCall: Out << 'w'; break;
}
}
void MicrosoftCXXNameMangler::mangleCallingConvention(const FunctionType *T) {
mangleCallingConvention(T->getCallConv());
}
void MicrosoftCXXNameMangler::mangleThrowSpecification(
const FunctionProtoType *FT) {
if (FT->canThrow())
Out << 'Z';
else
Out << "_E";
}
void MicrosoftCXXNameMangler::mangleType(const UnresolvedUsingType *T,
Qualifiers, SourceRange Range) {
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
"cannot mangle this unresolved dependent type yet");
Diags.Report(Range.getBegin(), DiagID)
<< Range;
}
void MicrosoftCXXNameMangler::mangleTagTypeKind(TagTypeKind TTK) {
switch (TTK) {
case TTK_Union:
Out << 'T';
break;
case TTK_Struct:
case TTK_Interface:
Out << 'U';
break;
case TTK_Class:
Out << 'V';
break;
case TTK_Enum:
Out << "W4";
break;
}
}
void MicrosoftCXXNameMangler::mangleType(const EnumType *T, Qualifiers,
SourceRange) {
mangleType(cast<TagType>(T)->getDecl());
}
void MicrosoftCXXNameMangler::mangleType(const RecordType *T, Qualifiers,
SourceRange) {
mangleType(cast<TagType>(T)->getDecl());
}
void MicrosoftCXXNameMangler::mangleType(const TagDecl *TD) {
mangleTagTypeKind(TD->getTagKind());
mangleName(TD);
}
void MicrosoftCXXNameMangler::mangleArtificialTagType(
TagTypeKind TK, StringRef UnqualifiedName,
ArrayRef<StringRef> NestedNames) {
mangleTagTypeKind(TK);
mangleSourceName(UnqualifiedName);
for (StringRef N : llvm::reverse(NestedNames))
mangleSourceName(N);
Out << '@';
}
void MicrosoftCXXNameMangler::mangleDecayedArrayType(const ArrayType *T) {
manglePointerCVQualifiers(T->getElementType().getQualifiers());
mangleType(T->getElementType(), SourceRange());
}
void MicrosoftCXXNameMangler::mangleType(const ConstantArrayType *T, Qualifiers,
SourceRange) {
llvm_unreachable("Should have been special cased");
}
void MicrosoftCXXNameMangler::mangleType(const VariableArrayType *T, Qualifiers,
SourceRange) {
llvm_unreachable("Should have been special cased");
}
void MicrosoftCXXNameMangler::mangleType(const DependentSizedArrayType *T,
Qualifiers, SourceRange) {
llvm_unreachable("Should have been special cased");
}
void MicrosoftCXXNameMangler::mangleType(const IncompleteArrayType *T,
Qualifiers, SourceRange) {
llvm_unreachable("Should have been special cased");
}
void MicrosoftCXXNameMangler::mangleArrayType(const ArrayType *T) {
QualType ElementTy(T, 0);
SmallVector<llvm::APInt, 3> Dimensions;
for (;;) {
if (ElementTy->isConstantArrayType()) {
const ConstantArrayType *CAT =
getASTContext().getAsConstantArrayType(ElementTy);
Dimensions.push_back(CAT->getSize());
ElementTy = CAT->getElementType();
} else if (ElementTy->isIncompleteArrayType()) {
const IncompleteArrayType *IAT =
getASTContext().getAsIncompleteArrayType(ElementTy);
Dimensions.push_back(llvm::APInt(32, 0));
ElementTy = IAT->getElementType();
} else if (ElementTy->isVariableArrayType()) {
const VariableArrayType *VAT =
getASTContext().getAsVariableArrayType(ElementTy);
Dimensions.push_back(llvm::APInt(32, 0));
ElementTy = VAT->getElementType();
} else if (ElementTy->isDependentSizedArrayType()) {
const DependentSizedArrayType *DSAT =
getASTContext().getAsDependentSizedArrayType(ElementTy);
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
"cannot mangle this dependent-length array yet");
Diags.Report(DSAT->getSizeExpr()->getExprLoc(), DiagID)
<< DSAT->getBracketsRange();
return;
} else {
break;
}
}
Out << 'Y';
mangleNumber(Dimensions.size());
for (const llvm::APInt &Dimension : Dimensions)
mangleNumber(Dimension.getLimitedValue());
mangleType(ElementTy, SourceRange(), QMM_Escape);
}
void MicrosoftCXXNameMangler::mangleType(const MemberPointerType *T,
Qualifiers Quals, SourceRange Range) {
QualType PointeeType = T->getPointeeType();
manglePointerCVQualifiers(Quals);
manglePointerExtQualifiers(Quals, PointeeType);
if (const FunctionProtoType *FPT = PointeeType->getAs<FunctionProtoType>()) {
Out << '8';
mangleName(T->getClass()->castAs<RecordType>()->getDecl());
mangleFunctionType(FPT, nullptr, true);
} else {
mangleQualifiers(PointeeType.getQualifiers(), true);
mangleName(T->getClass()->castAs<RecordType>()->getDecl());
mangleType(PointeeType, Range, QMM_Drop);
}
}
void MicrosoftCXXNameMangler::mangleType(const TemplateTypeParmType *T,
Qualifiers, SourceRange Range) {
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
"cannot mangle this template type parameter type yet");
Diags.Report(Range.getBegin(), DiagID)
<< Range;
}
void MicrosoftCXXNameMangler::mangleType(const SubstTemplateTypeParmPackType *T,
Qualifiers, SourceRange Range) {
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
"cannot mangle this substituted parameter pack yet");
Diags.Report(Range.getBegin(), DiagID)
<< Range;
}
void MicrosoftCXXNameMangler::mangleType(const PointerType *T, Qualifiers Quals,
SourceRange Range) {
QualType PointeeType = T->getPointeeType();
manglePointerCVQualifiers(Quals);
manglePointerExtQualifiers(Quals, PointeeType);
LangAS AddrSpace = PointeeType.getQualifiers().getAddressSpace();
if (isPtrSizeAddressSpace(AddrSpace) || AddrSpace == LangAS::Default)
mangleType(PointeeType, Range);
else
mangleAddressSpaceType(PointeeType, PointeeType.getQualifiers(), Range);
}
void MicrosoftCXXNameMangler::mangleType(const ObjCObjectPointerType *T,
Qualifiers Quals, SourceRange Range) {
QualType PointeeType = T->getPointeeType();
switch (Quals.getObjCLifetime()) {
case Qualifiers::OCL_None:
case Qualifiers::OCL_ExplicitNone:
break;
case Qualifiers::OCL_Autoreleasing:
case Qualifiers::OCL_Strong:
case Qualifiers::OCL_Weak:
return mangleObjCLifetime(PointeeType, Quals, Range);
}
manglePointerCVQualifiers(Quals);
manglePointerExtQualifiers(Quals, PointeeType);
mangleType(PointeeType, Range);
}
void MicrosoftCXXNameMangler::mangleType(const LValueReferenceType *T,
Qualifiers Quals, SourceRange Range) {
QualType PointeeType = T->getPointeeType();
assert(!Quals.hasConst() && !Quals.hasVolatile() && "unexpected qualifier!");
Out << 'A';
manglePointerExtQualifiers(Quals, PointeeType);
mangleType(PointeeType, Range);
}
void MicrosoftCXXNameMangler::mangleType(const RValueReferenceType *T,
Qualifiers Quals, SourceRange Range) {
QualType PointeeType = T->getPointeeType();
assert(!Quals.hasConst() && !Quals.hasVolatile() && "unexpected qualifier!");
Out << "$$Q";
manglePointerExtQualifiers(Quals, PointeeType);
mangleType(PointeeType, Range);
}
void MicrosoftCXXNameMangler::mangleType(const ComplexType *T, Qualifiers,
SourceRange Range) {
QualType ElementType = T->getElementType();
llvm::SmallString<64> TemplateMangling;
llvm::raw_svector_ostream Stream(TemplateMangling);
MicrosoftCXXNameMangler Extra(Context, Stream);
Stream << "?$";
Extra.mangleSourceName("_Complex");
Extra.mangleType(ElementType, Range, QMM_Escape);
mangleArtificialTagType(TTK_Struct, TemplateMangling, {"__clang"});
}
bool MicrosoftCXXNameMangler::isArtificialTagType(QualType T) const {
const Type *ty = T.getTypePtr();
switch (ty->getTypeClass()) {
default:
return false;
case Type::Vector: {
return true;
}
}
}
void MicrosoftCXXNameMangler::mangleType(const VectorType *T, Qualifiers Quals,
SourceRange Range) {
const BuiltinType *ET = T->getElementType()->getAs<BuiltinType>();
assert(ET && "vectors with non-builtin elements are unsupported");
uint64_t Width = getASTContext().getTypeSize(T);
size_t OutSizeBefore = Out.tell();
if (!isa<ExtVectorType>(T)) {
if (getASTContext().getTargetInfo().getTriple().isX86()) {
if (Width == 64 && ET->getKind() == BuiltinType::LongLong) {
mangleArtificialTagType(TTK_Union, "__m64");
} else if (Width >= 128) {
if (ET->getKind() == BuiltinType::Float)
mangleArtificialTagType(TTK_Union, "__m" + llvm::utostr(Width));
else if (ET->getKind() == BuiltinType::LongLong)
mangleArtificialTagType(TTK_Union, "__m" + llvm::utostr(Width) + 'i');
else if (ET->getKind() == BuiltinType::Double)
mangleArtificialTagType(TTK_Struct, "__m" + llvm::utostr(Width) + 'd');
}
}
}
bool IsBuiltin = Out.tell() != OutSizeBefore;
if (!IsBuiltin) {
llvm::SmallString<64> TemplateMangling;
llvm::raw_svector_ostream Stream(TemplateMangling);
MicrosoftCXXNameMangler Extra(Context, Stream);
Stream << "?$";
Extra.mangleSourceName("__vector");
Extra.mangleType(QualType(ET, 0), Range, QMM_Escape);
Extra.mangleIntegerLiteral(llvm::APSInt::getUnsigned(T->getNumElements()));
mangleArtificialTagType(TTK_Union, TemplateMangling, {"__clang"});
}
}
void MicrosoftCXXNameMangler::mangleType(const ExtVectorType *T,
Qualifiers Quals, SourceRange Range) {
mangleType(static_cast<const VectorType *>(T), Quals, Range);
}
void MicrosoftCXXNameMangler::mangleType(const DependentVectorType *T,
Qualifiers, SourceRange Range) {
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(
DiagnosticsEngine::Error,
"cannot mangle this dependent-sized vector type yet");
Diags.Report(Range.getBegin(), DiagID) << Range;
}
void MicrosoftCXXNameMangler::mangleType(const DependentSizedExtVectorType *T,
Qualifiers, SourceRange Range) {
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
"cannot mangle this dependent-sized extended vector type yet");
Diags.Report(Range.getBegin(), DiagID)
<< Range;
}
void MicrosoftCXXNameMangler::mangleType(const ConstantMatrixType *T,
Qualifiers quals, SourceRange Range) {
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
"Cannot mangle this matrix type yet");
Diags.Report(Range.getBegin(), DiagID) << Range;
}
void MicrosoftCXXNameMangler::mangleType(const DependentSizedMatrixType *T,
Qualifiers quals, SourceRange Range) {
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(
DiagnosticsEngine::Error,
"Cannot mangle this dependent-sized matrix type yet");
Diags.Report(Range.getBegin(), DiagID) << Range;
}
void MicrosoftCXXNameMangler::mangleType(const DependentAddressSpaceType *T,
Qualifiers, SourceRange Range) {
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(
DiagnosticsEngine::Error,
"cannot mangle this dependent address space type yet");
Diags.Report(Range.getBegin(), DiagID) << Range;
}
void MicrosoftCXXNameMangler::mangleType(const ObjCInterfaceType *T, Qualifiers,
SourceRange) {
mangleTagTypeKind(TTK_Struct);
mangleName(T->getDecl());
}
void MicrosoftCXXNameMangler::mangleType(const ObjCObjectType *T,
Qualifiers Quals, SourceRange Range) {
if (T->isKindOfType())
return mangleObjCKindOfType(T, Quals, Range);
if (T->qual_empty() && !T->isSpecialized())
return mangleType(T->getBaseType(), Range, QMM_Drop);
ArgBackRefMap OuterFunArgsContext;
ArgBackRefMap OuterTemplateArgsContext;
BackRefVec OuterTemplateContext;
FunArgBackReferences.swap(OuterFunArgsContext);
TemplateArgBackReferences.swap(OuterTemplateArgsContext);
NameBackReferences.swap(OuterTemplateContext);
mangleTagTypeKind(TTK_Struct);
Out << "?$";
if (T->isObjCId())
mangleSourceName("objc_object");
else if (T->isObjCClass())
mangleSourceName("objc_class");
else
mangleSourceName(T->getInterface()->getName());
for (const auto &Q : T->quals())
mangleObjCProtocol(Q);
if (T->isSpecialized())
for (const auto &TA : T->getTypeArgs())
mangleType(TA, Range, QMM_Drop);
Out << '@';
Out << '@';
FunArgBackReferences.swap(OuterFunArgsContext);
TemplateArgBackReferences.swap(OuterTemplateArgsContext);
NameBackReferences.swap(OuterTemplateContext);
}
void MicrosoftCXXNameMangler::mangleType(const BlockPointerType *T,
Qualifiers Quals, SourceRange Range) {
QualType PointeeType = T->getPointeeType();
manglePointerCVQualifiers(Quals);
manglePointerExtQualifiers(Quals, PointeeType);
Out << "_E";
mangleFunctionType(PointeeType->castAs<FunctionProtoType>());
}
void MicrosoftCXXNameMangler::mangleType(const InjectedClassNameType *,
Qualifiers, SourceRange) {
llvm_unreachable("Cannot mangle injected class name type.");
}
void MicrosoftCXXNameMangler::mangleType(const TemplateSpecializationType *T,
Qualifiers, SourceRange Range) {
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
"cannot mangle this template specialization type yet");
Diags.Report(Range.getBegin(), DiagID)
<< Range;
}
void MicrosoftCXXNameMangler::mangleType(const DependentNameType *T, Qualifiers,
SourceRange Range) {
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
"cannot mangle this dependent name type yet");
Diags.Report(Range.getBegin(), DiagID)
<< Range;
}
void MicrosoftCXXNameMangler::mangleType(
const DependentTemplateSpecializationType *T, Qualifiers,
SourceRange Range) {
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
"cannot mangle this dependent template specialization type yet");
Diags.Report(Range.getBegin(), DiagID)
<< Range;
}
void MicrosoftCXXNameMangler::mangleType(const PackExpansionType *T, Qualifiers,
SourceRange Range) {
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
"cannot mangle this pack expansion yet");
Diags.Report(Range.getBegin(), DiagID)
<< Range;
}
void MicrosoftCXXNameMangler::mangleType(const TypeOfType *T, Qualifiers,
SourceRange Range) {
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
"cannot mangle this typeof(type) yet");
Diags.Report(Range.getBegin(), DiagID)
<< Range;
}
void MicrosoftCXXNameMangler::mangleType(const TypeOfExprType *T, Qualifiers,
SourceRange Range) {
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
"cannot mangle this typeof(expression) yet");
Diags.Report(Range.getBegin(), DiagID)
<< Range;
}
void MicrosoftCXXNameMangler::mangleType(const DecltypeType *T, Qualifiers,
SourceRange Range) {
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
"cannot mangle this decltype() yet");
Diags.Report(Range.getBegin(), DiagID)
<< Range;
}
void MicrosoftCXXNameMangler::mangleType(const UnaryTransformType *T,
Qualifiers, SourceRange Range) {
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
"cannot mangle this unary transform type yet");
Diags.Report(Range.getBegin(), DiagID)
<< Range;
}
void MicrosoftCXXNameMangler::mangleType(const AutoType *T, Qualifiers,
SourceRange Range) {
assert(T->getDeducedType().isNull() && "expecting a dependent type!");
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
"cannot mangle this 'auto' type yet");
Diags.Report(Range.getBegin(), DiagID)
<< Range;
}
void MicrosoftCXXNameMangler::mangleType(
const DeducedTemplateSpecializationType *T, Qualifiers, SourceRange Range) {
assert(T->getDeducedType().isNull() && "expecting a dependent type!");
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
"cannot mangle this deduced class template specialization type yet");
Diags.Report(Range.getBegin(), DiagID)
<< Range;
}
void MicrosoftCXXNameMangler::mangleType(const AtomicType *T, Qualifiers,
SourceRange Range) {
QualType ValueType = T->getValueType();
llvm::SmallString<64> TemplateMangling;
llvm::raw_svector_ostream Stream(TemplateMangling);
MicrosoftCXXNameMangler Extra(Context, Stream);
Stream << "?$";
Extra.mangleSourceName("_Atomic");
Extra.mangleType(ValueType, Range, QMM_Escape);
mangleArtificialTagType(TTK_Struct, TemplateMangling, {"__clang"});
}
void MicrosoftCXXNameMangler::mangleType(const PipeType *T, Qualifiers,
SourceRange Range) {
QualType ElementType = T->getElementType();
llvm::SmallString<64> TemplateMangling;
llvm::raw_svector_ostream Stream(TemplateMangling);
MicrosoftCXXNameMangler Extra(Context, Stream);
Stream << "?$";
Extra.mangleSourceName("ocl_pipe");
Extra.mangleType(ElementType, Range, QMM_Escape);
Extra.mangleIntegerLiteral(llvm::APSInt::get(T->isReadOnly()));
mangleArtificialTagType(TTK_Struct, TemplateMangling, {"__clang"});
}
void MicrosoftMangleContextImpl::mangleCXXName(GlobalDecl GD,
raw_ostream &Out) {
const NamedDecl *D = cast<NamedDecl>(GD.getDecl());
PrettyStackTraceDecl CrashInfo(D, SourceLocation(),
getASTContext().getSourceManager(),
"Mangling declaration");
msvc_hashing_ostream MHO(Out);
if (auto *CD = dyn_cast<CXXConstructorDecl>(D)) {
auto Type = GD.getCtorType();
MicrosoftCXXNameMangler mangler(*this, MHO, CD, Type);
return mangler.mangle(GD);
}
if (auto *DD = dyn_cast<CXXDestructorDecl>(D)) {
auto Type = GD.getDtorType();
MicrosoftCXXNameMangler mangler(*this, MHO, DD, Type);
return mangler.mangle(GD);
}
MicrosoftCXXNameMangler Mangler(*this, MHO);
return Mangler.mangle(GD);
}
void MicrosoftCXXNameMangler::mangleType(const BitIntType *T, Qualifiers,
SourceRange Range) {
llvm::SmallString<64> TemplateMangling;
llvm::raw_svector_ostream Stream(TemplateMangling);
MicrosoftCXXNameMangler Extra(Context, Stream);
Stream << "?$";
if (T->isUnsigned())
Extra.mangleSourceName("_UBitInt");
else
Extra.mangleSourceName("_BitInt");
Extra.mangleIntegerLiteral(llvm::APSInt::getUnsigned(T->getNumBits()));
mangleArtificialTagType(TTK_Struct, TemplateMangling, {"__clang"});
}
void MicrosoftCXXNameMangler::mangleType(const DependentBitIntType *T,
Qualifiers, SourceRange Range) {
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(
DiagnosticsEngine::Error, "cannot mangle this DependentBitInt type yet");
Diags.Report(Range.getBegin(), DiagID) << Range;
}
static void mangleThunkThisAdjustment(AccessSpecifier AS,
const ThisAdjustment &Adjustment,
MicrosoftCXXNameMangler &Mangler,
raw_ostream &Out) {
if (!Adjustment.Virtual.isEmpty()) {
Out << '$';
char AccessSpec;
switch (AS) {
case AS_none:
llvm_unreachable("Unsupported access specifier");
case AS_private:
AccessSpec = '0';
break;
case AS_protected:
AccessSpec = '2';
break;
case AS_public:
AccessSpec = '4';
}
if (Adjustment.Virtual.Microsoft.VBPtrOffset) {
Out << 'R' << AccessSpec;
Mangler.mangleNumber(
static_cast<uint32_t>(Adjustment.Virtual.Microsoft.VBPtrOffset));
Mangler.mangleNumber(
static_cast<uint32_t>(Adjustment.Virtual.Microsoft.VBOffsetOffset));
Mangler.mangleNumber(
static_cast<uint32_t>(Adjustment.Virtual.Microsoft.VtordispOffset));
Mangler.mangleNumber(static_cast<uint32_t>(Adjustment.NonVirtual));
} else {
Out << AccessSpec;
Mangler.mangleNumber(
static_cast<uint32_t>(Adjustment.Virtual.Microsoft.VtordispOffset));
Mangler.mangleNumber(-static_cast<uint32_t>(Adjustment.NonVirtual));
}
} else if (Adjustment.NonVirtual != 0) {
switch (AS) {
case AS_none:
llvm_unreachable("Unsupported access specifier");
case AS_private:
Out << 'G';
break;
case AS_protected:
Out << 'O';
break;
case AS_public:
Out << 'W';
}
Mangler.mangleNumber(-static_cast<uint32_t>(Adjustment.NonVirtual));
} else {
switch (AS) {
case AS_none:
llvm_unreachable("Unsupported access specifier");
case AS_private:
Out << 'A';
break;
case AS_protected:
Out << 'I';
break;
case AS_public:
Out << 'Q';
}
}
}
void MicrosoftMangleContextImpl::mangleVirtualMemPtrThunk(
const CXXMethodDecl *MD, const MethodVFTableLocation &ML,
raw_ostream &Out) {
msvc_hashing_ostream MHO(Out);
MicrosoftCXXNameMangler Mangler(*this, MHO);
Mangler.getStream() << '?';
Mangler.mangleVirtualMemPtrThunk(MD, ML);
}
void MicrosoftMangleContextImpl::mangleThunk(const CXXMethodDecl *MD,
const ThunkInfo &Thunk,
raw_ostream &Out) {
msvc_hashing_ostream MHO(Out);
MicrosoftCXXNameMangler Mangler(*this, MHO);
Mangler.getStream() << '?';
Mangler.mangleName(MD);
AccessSpecifier AS = Thunk.Return.isEmpty() ? MD->getAccess() : AS_public;
mangleThunkThisAdjustment(AS, Thunk.This, Mangler, MHO);
if (!Thunk.Return.isEmpty())
assert(Thunk.Method != nullptr &&
"Thunk info should hold the overridee decl");
const CXXMethodDecl *DeclForFPT = Thunk.Method ? Thunk.Method : MD;
Mangler.mangleFunctionType(
DeclForFPT->getType()->castAs<FunctionProtoType>(), MD);
}
void MicrosoftMangleContextImpl::mangleCXXDtorThunk(
const CXXDestructorDecl *DD, CXXDtorType Type,
const ThisAdjustment &Adjustment, raw_ostream &Out) {
assert(Type == Dtor_Deleting);
msvc_hashing_ostream MHO(Out);
MicrosoftCXXNameMangler Mangler(*this, MHO, DD, Type);
Mangler.getStream() << "??_E";
Mangler.mangleName(DD->getParent());
mangleThunkThisAdjustment(DD->getAccess(), Adjustment, Mangler, MHO);
Mangler.mangleFunctionType(DD->getType()->castAs<FunctionProtoType>(), DD);
}
void MicrosoftMangleContextImpl::mangleCXXVFTable(
const CXXRecordDecl *Derived, ArrayRef<const CXXRecordDecl *> BasePath,
raw_ostream &Out) {
msvc_hashing_ostream MHO(Out);
MicrosoftCXXNameMangler Mangler(*this, MHO);
if (Derived->hasAttr<DLLImportAttr>())
Mangler.getStream() << "??_S";
else
Mangler.getStream() << "??_7";
Mangler.mangleName(Derived);
Mangler.getStream() << "6B"; for (const CXXRecordDecl *RD : BasePath)
Mangler.mangleName(RD);
Mangler.getStream() << '@';
}
void MicrosoftMangleContextImpl::mangleCXXVBTable(
const CXXRecordDecl *Derived, ArrayRef<const CXXRecordDecl *> BasePath,
raw_ostream &Out) {
msvc_hashing_ostream MHO(Out);
MicrosoftCXXNameMangler Mangler(*this, MHO);
Mangler.getStream() << "??_8";
Mangler.mangleName(Derived);
Mangler.getStream() << "7B"; for (const CXXRecordDecl *RD : BasePath)
Mangler.mangleName(RD);
Mangler.getStream() << '@';
}
void MicrosoftMangleContextImpl::mangleCXXRTTI(QualType T, raw_ostream &Out) {
msvc_hashing_ostream MHO(Out);
MicrosoftCXXNameMangler Mangler(*this, MHO);
Mangler.getStream() << "??_R0";
Mangler.mangleType(T, SourceRange(), MicrosoftCXXNameMangler::QMM_Result);
Mangler.getStream() << "@8";
}
void MicrosoftMangleContextImpl::mangleCXXRTTIName(QualType T,
raw_ostream &Out) {
MicrosoftCXXNameMangler Mangler(*this, Out);
Mangler.getStream() << '.';
Mangler.mangleType(T, SourceRange(), MicrosoftCXXNameMangler::QMM_Result);
}
void MicrosoftMangleContextImpl::mangleCXXVirtualDisplacementMap(
const CXXRecordDecl *SrcRD, const CXXRecordDecl *DstRD, raw_ostream &Out) {
msvc_hashing_ostream MHO(Out);
MicrosoftCXXNameMangler Mangler(*this, MHO);
Mangler.getStream() << "??_K";
Mangler.mangleName(SrcRD);
Mangler.getStream() << "$C";
Mangler.mangleName(DstRD);
}
void MicrosoftMangleContextImpl::mangleCXXThrowInfo(QualType T, bool IsConst,
bool IsVolatile,
bool IsUnaligned,
uint32_t NumEntries,
raw_ostream &Out) {
msvc_hashing_ostream MHO(Out);
MicrosoftCXXNameMangler Mangler(*this, MHO);
Mangler.getStream() << "_TI";
if (IsConst)
Mangler.getStream() << 'C';
if (IsVolatile)
Mangler.getStream() << 'V';
if (IsUnaligned)
Mangler.getStream() << 'U';
Mangler.getStream() << NumEntries;
Mangler.mangleType(T, SourceRange(), MicrosoftCXXNameMangler::QMM_Result);
}
void MicrosoftMangleContextImpl::mangleCXXCatchableTypeArray(
QualType T, uint32_t NumEntries, raw_ostream &Out) {
msvc_hashing_ostream MHO(Out);
MicrosoftCXXNameMangler Mangler(*this, MHO);
Mangler.getStream() << "_CTA";
Mangler.getStream() << NumEntries;
Mangler.mangleType(T, SourceRange(), MicrosoftCXXNameMangler::QMM_Result);
}
void MicrosoftMangleContextImpl::mangleCXXCatchableType(
QualType T, const CXXConstructorDecl *CD, CXXCtorType CT, uint32_t Size,
uint32_t NVOffset, int32_t VBPtrOffset, uint32_t VBIndex,
raw_ostream &Out) {
MicrosoftCXXNameMangler Mangler(*this, Out);
Mangler.getStream() << "_CT";
llvm::SmallString<64> RTTIMangling;
{
llvm::raw_svector_ostream Stream(RTTIMangling);
msvc_hashing_ostream MHO(Stream);
mangleCXXRTTI(T, MHO);
}
Mangler.getStream() << RTTIMangling;
bool OmitCopyCtor = getASTContext().getLangOpts().isCompatibleWithMSVC(
LangOptions::MSVC2015) &&
!getASTContext().getLangOpts().isCompatibleWithMSVC(
LangOptions::MSVC2017_7);
llvm::SmallString<64> CopyCtorMangling;
if (!OmitCopyCtor && CD) {
llvm::raw_svector_ostream Stream(CopyCtorMangling);
msvc_hashing_ostream MHO(Stream);
mangleCXXName(GlobalDecl(CD, CT), MHO);
}
Mangler.getStream() << CopyCtorMangling;
Mangler.getStream() << Size;
if (VBPtrOffset == -1) {
if (NVOffset) {
Mangler.getStream() << NVOffset;
}
} else {
Mangler.getStream() << NVOffset;
Mangler.getStream() << VBPtrOffset;
Mangler.getStream() << VBIndex;
}
}
void MicrosoftMangleContextImpl::mangleCXXRTTIBaseClassDescriptor(
const CXXRecordDecl *Derived, uint32_t NVOffset, int32_t VBPtrOffset,
uint32_t VBTableOffset, uint32_t Flags, raw_ostream &Out) {
msvc_hashing_ostream MHO(Out);
MicrosoftCXXNameMangler Mangler(*this, MHO);
Mangler.getStream() << "??_R1";
Mangler.mangleNumber(NVOffset);
Mangler.mangleNumber(VBPtrOffset);
Mangler.mangleNumber(VBTableOffset);
Mangler.mangleNumber(Flags);
Mangler.mangleName(Derived);
Mangler.getStream() << "8";
}
void MicrosoftMangleContextImpl::mangleCXXRTTIBaseClassArray(
const CXXRecordDecl *Derived, raw_ostream &Out) {
msvc_hashing_ostream MHO(Out);
MicrosoftCXXNameMangler Mangler(*this, MHO);
Mangler.getStream() << "??_R2";
Mangler.mangleName(Derived);
Mangler.getStream() << "8";
}
void MicrosoftMangleContextImpl::mangleCXXRTTIClassHierarchyDescriptor(
const CXXRecordDecl *Derived, raw_ostream &Out) {
msvc_hashing_ostream MHO(Out);
MicrosoftCXXNameMangler Mangler(*this, MHO);
Mangler.getStream() << "??_R3";
Mangler.mangleName(Derived);
Mangler.getStream() << "8";
}
void MicrosoftMangleContextImpl::mangleCXXRTTICompleteObjectLocator(
const CXXRecordDecl *Derived, ArrayRef<const CXXRecordDecl *> BasePath,
raw_ostream &Out) {
llvm::SmallString<64> VFTableMangling;
llvm::raw_svector_ostream Stream(VFTableMangling);
mangleCXXVFTable(Derived, BasePath, Stream);
if (VFTableMangling.startswith("??@")) {
assert(VFTableMangling.endswith("@"));
Out << VFTableMangling << "??_R4@";
return;
}
assert(VFTableMangling.startswith("??_7") ||
VFTableMangling.startswith("??_S"));
Out << "??_R4" << VFTableMangling.str().drop_front(4);
}
void MicrosoftMangleContextImpl::mangleSEHFilterExpression(
const NamedDecl *EnclosingDecl, raw_ostream &Out) {
msvc_hashing_ostream MHO(Out);
MicrosoftCXXNameMangler Mangler(*this, MHO);
Mangler.getStream() << "?filt$" << SEHFilterIds[EnclosingDecl]++ << "@0@";
Mangler.mangleName(EnclosingDecl);
}
void MicrosoftMangleContextImpl::mangleSEHFinallyBlock(
const NamedDecl *EnclosingDecl, raw_ostream &Out) {
msvc_hashing_ostream MHO(Out);
MicrosoftCXXNameMangler Mangler(*this, MHO);
Mangler.getStream() << "?fin$" << SEHFinallyIds[EnclosingDecl]++ << "@0@";
Mangler.mangleName(EnclosingDecl);
}
void MicrosoftMangleContextImpl::mangleTypeName(QualType T, raw_ostream &Out) {
MicrosoftCXXNameMangler Mangler(*this, Out);
Mangler.getStream() << '?';
Mangler.mangleType(T, SourceRange());
}
void MicrosoftMangleContextImpl::mangleReferenceTemporary(
const VarDecl *VD, unsigned ManglingNumber, raw_ostream &Out) {
msvc_hashing_ostream MHO(Out);
MicrosoftCXXNameMangler Mangler(*this, MHO);
Mangler.getStream() << "?$RT" << ManglingNumber << '@';
Mangler.mangle(VD, "");
}
void MicrosoftMangleContextImpl::mangleThreadSafeStaticGuardVariable(
const VarDecl *VD, unsigned GuardNum, raw_ostream &Out) {
msvc_hashing_ostream MHO(Out);
MicrosoftCXXNameMangler Mangler(*this, MHO);
Mangler.getStream() << "?$TSS" << GuardNum << '@';
Mangler.mangleNestedName(VD);
Mangler.getStream() << "@4HA";
}
void MicrosoftMangleContextImpl::mangleStaticGuardVariable(const VarDecl *VD,
raw_ostream &Out) {
msvc_hashing_ostream MHO(Out);
MicrosoftCXXNameMangler Mangler(*this, MHO);
bool Visible = VD->isExternallyVisible();
if (Visible) {
Mangler.getStream() << (VD->getTLSKind() ? "??__J" : "??_B");
} else {
Mangler.getStream() << "?$S1@";
}
unsigned ScopeDepth = 0;
if (Visible && !getNextDiscriminator(VD, ScopeDepth))
Mangler.mangle(VD, "");
else
Mangler.mangleNestedName(VD);
Mangler.getStream() << (Visible ? "@5" : "@4IA");
if (ScopeDepth)
Mangler.mangleNumber(ScopeDepth);
}
void MicrosoftMangleContextImpl::mangleInitFiniStub(const VarDecl *D,
char CharCode,
raw_ostream &Out) {
msvc_hashing_ostream MHO(Out);
MicrosoftCXXNameMangler Mangler(*this, MHO);
Mangler.getStream() << "??__" << CharCode;
if (D->isStaticDataMember()) {
Mangler.getStream() << '?';
Mangler.mangleName(D);
Mangler.mangleVariableEncoding(D);
Mangler.getStream() << "@@";
} else {
Mangler.mangleName(D);
}
Mangler.getStream() << "YAXXZ";
}
void MicrosoftMangleContextImpl::mangleDynamicInitializer(const VarDecl *D,
raw_ostream &Out) {
mangleInitFiniStub(D, 'E', Out);
}
void
MicrosoftMangleContextImpl::mangleDynamicAtExitDestructor(const VarDecl *D,
raw_ostream &Out) {
mangleInitFiniStub(D, 'F', Out);
}
void MicrosoftMangleContextImpl::mangleStringLiteral(const StringLiteral *SL,
raw_ostream &Out) {
MicrosoftCXXNameMangler Mangler(*this, Out);
Mangler.getStream() << "??_C@_";
unsigned StringLength = getASTContext()
.getAsConstantArrayType(SL->getType())
->getSize()
.getZExtValue();
unsigned StringByteLength = StringLength * SL->getCharByteWidth();
if (SL->isWide())
Mangler.getStream() << '1';
else
Mangler.getStream() << '0';
Mangler.mangleNumber(StringByteLength);
auto GetLittleEndianByte = [&SL](unsigned Index) {
unsigned CharByteWidth = SL->getCharByteWidth();
if (Index / CharByteWidth >= SL->getLength())
return static_cast<char>(0);
uint32_t CodeUnit = SL->getCodeUnit(Index / CharByteWidth);
unsigned OffsetInCodeUnit = Index % CharByteWidth;
return static_cast<char>((CodeUnit >> (8 * OffsetInCodeUnit)) & 0xff);
};
auto GetBigEndianByte = [&SL](unsigned Index) {
unsigned CharByteWidth = SL->getCharByteWidth();
if (Index / CharByteWidth >= SL->getLength())
return static_cast<char>(0);
uint32_t CodeUnit = SL->getCodeUnit(Index / CharByteWidth);
unsigned OffsetInCodeUnit = (CharByteWidth - 1) - (Index % CharByteWidth);
return static_cast<char>((CodeUnit >> (8 * OffsetInCodeUnit)) & 0xff);
};
llvm::JamCRC JC;
for (unsigned I = 0, E = StringByteLength; I != E; ++I)
JC.update(GetLittleEndianByte(I));
Mangler.mangleNumber(JC.getCRC());
auto MangleByte = [&Mangler](char Byte) {
if (isAsciiIdentifierContinue(Byte, true)) {
Mangler.getStream() << Byte;
} else if (isLetter(Byte & 0x7f)) {
Mangler.getStream() << '?' << static_cast<char>(Byte & 0x7f);
} else {
const char SpecialChars[] = {',', '/', '\\', ':', '.',
' ', '\n', '\t', '\'', '-'};
const char *Pos = llvm::find(SpecialChars, Byte);
if (Pos != std::end(SpecialChars)) {
Mangler.getStream() << '?' << (Pos - std::begin(SpecialChars));
} else {
Mangler.getStream() << "?$";
Mangler.getStream() << static_cast<char>('A' + ((Byte >> 4) & 0xf));
Mangler.getStream() << static_cast<char>('A' + (Byte & 0xf));
}
}
};
unsigned MaxBytesToMangle = SL->isWide() ? 64U : 32U;
unsigned NumBytesToMangle = std::min(MaxBytesToMangle, StringByteLength);
for (unsigned I = 0; I != NumBytesToMangle; ++I) {
if (SL->isWide())
MangleByte(GetBigEndianByte(I));
else
MangleByte(GetLittleEndianByte(I));
}
Mangler.getStream() << '@';
}
MicrosoftMangleContext *MicrosoftMangleContext::create(ASTContext &Context,
DiagnosticsEngine &Diags,
bool IsAux) {
return new MicrosoftMangleContextImpl(Context, Diags, IsAux);
}