summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp')
-rw-r--r--contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp1127
1 files changed, 798 insertions, 329 deletions
diff --git a/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp b/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp
index 5256501..e6a6d09 100644
--- a/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp
@@ -14,17 +14,21 @@
#include "clang/AST/Mangle.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Attr.h"
-#include "clang/AST/CharUnits.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/DeclTemplate.h"
+#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
+#include "clang/AST/VTableBuilder.h"
#include "clang/Basic/ABI.h"
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Basic/TargetInfo.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/MathExtras.h"
using namespace clang;
@@ -71,10 +75,114 @@ static const FunctionDecl *getStructor(const FunctionDecl *fn) {
return fn;
}
+static bool isLambda(const NamedDecl *ND) {
+ const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(ND);
+ if (!Record)
+ return false;
+
+ return Record->isLambda();
+}
+
+/// MicrosoftMangleContextImpl - Overrides the default MangleContext for the
+/// Microsoft Visual C++ ABI.
+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;
+
+public:
+ MicrosoftMangleContextImpl(ASTContext &Context, DiagnosticsEngine &Diags)
+ : MicrosoftMangleContext(Context, Diags) {}
+ bool shouldMangleCXXName(const NamedDecl *D) override;
+ bool shouldMangleStringLiteral(const StringLiteral *SL) override;
+ void mangleCXXName(const NamedDecl *D, raw_ostream &Out) override;
+ void mangleVirtualMemPtrThunk(const CXXMethodDecl *MD,
+ raw_ostream &) 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 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 mangleCXXCtor(const CXXConstructorDecl *D, CXXCtorType Type,
+ raw_ostream &) override;
+ void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type,
+ raw_ostream &) override;
+ void mangleReferenceTemporary(const VarDecl *, unsigned ManglingNumber,
+ raw_ostream &) override;
+ void mangleStaticGuardVariable(const VarDecl *D, raw_ostream &Out) override;
+ void mangleDynamicInitializer(const VarDecl *D, raw_ostream &Out) override;
+ void mangleDynamicAtExitDestructor(const VarDecl *D,
+ raw_ostream &Out) override;
+ void mangleStringLiteral(const StringLiteral *SL, raw_ostream &Out) override;
+ bool getNextDiscriminator(const NamedDecl *ND, unsigned &disc) {
+ // Lambda closure types are already numbered.
+ if (isLambda(ND))
+ return false;
+
+ const DeclContext *DC = getEffectiveDeclContext(ND);
+ if (!DC->isFunctionOrMethod())
+ return false;
+
+ // Use the canonical number for externally visible decls.
+ if (ND->isExternallyVisible()) {
+ disc = getASTContext().getManglingNumber(ND);
+ return true;
+ }
+
+ // Anonymous tags are already numbered.
+ if (const TagDecl *Tag = dyn_cast<TagDecl>(ND)) {
+ if (Tag->getName().empty() && !Tag->getTypedefNameForAnonDecl())
+ return false;
+ }
+
+ // Make up a reasonable number for internal decls.
+ unsigned &discriminator = Uniquifier[ND];
+ if (!discriminator)
+ discriminator = ++Discriminator[std::make_pair(DC, ND->getIdentifier())];
+ disc = discriminator;
+ return true;
+ }
+
+ 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;
+ }
+
+private:
+ void mangleInitFiniStub(const VarDecl *D, raw_ostream &Out, char CharCode);
+};
+
/// MicrosoftCXXNameMangler - Manage the mangling of a single name for the
/// Microsoft Visual C++ ABI.
class MicrosoftCXXNameMangler {
- MangleContext &Context;
+ MicrosoftMangleContextImpl &Context;
raw_ostream &Out;
/// The "structor" is the top-level declaration being mangled, if
@@ -85,9 +193,8 @@ class MicrosoftCXXNameMangler {
typedef llvm::StringMap<unsigned> BackRefMap;
BackRefMap NameBackReferences;
- bool UseNameBackReferences;
- typedef llvm::DenseMap<void*, unsigned> ArgBackRefMap;
+ typedef llvm::DenseMap<void *, unsigned> ArgBackRefMap;
ArgBackRefMap TypeBackReferences;
ASTContext &getASTContext() const { return Context.getASTContext(); }
@@ -99,37 +206,38 @@ class MicrosoftCXXNameMangler {
public:
enum QualifierMangleMode { QMM_Drop, QMM_Mangle, QMM_Escape, QMM_Result };
- MicrosoftCXXNameMangler(MangleContext &C, raw_ostream &Out_)
- : Context(C), Out(Out_),
- Structor(0), StructorType(-1),
- UseNameBackReferences(true),
- PointersAre64Bit(C.getASTContext().getTargetInfo().getPointerWidth(0) ==
- 64) { }
+ MicrosoftCXXNameMangler(MicrosoftMangleContextImpl &C, raw_ostream &Out_)
+ : Context(C), Out(Out_), Structor(nullptr), StructorType(-1),
+ PointersAre64Bit(C.getASTContext().getTargetInfo().getPointerWidth(0) ==
+ 64) {}
- MicrosoftCXXNameMangler(MangleContext &C, raw_ostream &Out_,
+ MicrosoftCXXNameMangler(MicrosoftMangleContextImpl &C, raw_ostream &Out_,
const CXXDestructorDecl *D, CXXDtorType Type)
- : Context(C), Out(Out_),
- Structor(getStructor(D)), StructorType(Type),
- UseNameBackReferences(true),
- PointersAre64Bit(C.getASTContext().getTargetInfo().getPointerWidth(0) ==
- 64) { }
+ : Context(C), Out(Out_), Structor(getStructor(D)), StructorType(Type),
+ PointersAre64Bit(C.getASTContext().getTargetInfo().getPointerWidth(0) ==
+ 64) {}
raw_ostream &getStream() const { return Out; }
void mangle(const NamedDecl *D, StringRef Prefix = "\01?");
void mangleName(const NamedDecl *ND);
- void mangleDeclaration(const NamedDecl *ND);
void mangleFunctionEncoding(const FunctionDecl *FD);
void mangleVariableEncoding(const VarDecl *VD);
+ void mangleMemberDataPointer(const CXXRecordDecl *RD, const ValueDecl *VD);
+ void mangleMemberFunctionPointer(const CXXRecordDecl *RD,
+ const CXXMethodDecl *MD);
+ void mangleVirtualMemPtrThunk(
+ const CXXMethodDecl *MD,
+ const MicrosoftVTableContext::MethodVFTableLocation &ML);
void mangleNumber(int64_t Number);
void mangleType(QualType T, SourceRange Range,
QualifierMangleMode QMM = QMM_Mangle);
- void mangleFunctionType(const FunctionType *T, const FunctionDecl *D = 0,
+ void mangleFunctionType(const FunctionType *T,
+ const FunctionDecl *D = nullptr,
bool ForceInstMethod = false);
- void manglePostfix(const DeclContext *DC, bool NoFunction = false);
+ void mangleNestedName(const NamedDecl *ND);
private:
- void disableBackReferences() { UseNameBackReferences = false; }
void mangleUnqualifiedName(const NamedDecl *ND) {
mangleUnqualifiedName(ND, ND->getDeclName());
}
@@ -138,13 +246,15 @@ private:
void mangleOperatorName(OverloadedOperatorKind OO, SourceLocation Loc);
void mangleCXXDtorType(CXXDtorType T);
void mangleQualifiers(Qualifiers Quals, bool IsMember);
- void manglePointerQualifiers(Qualifiers Quals);
+ void mangleRefQualifier(RefQualifierKind RefQualifier);
+ void manglePointerCVQualifiers(Qualifiers Quals);
+ void manglePointerExtQualifiers(Qualifiers Quals, const Type *PointeeType);
void mangleUnscopedTemplateName(const TemplateDecl *ND);
- void mangleTemplateInstantiationName(const TemplateDecl *TD,
- const TemplateArgumentList &TemplateArgs);
+ void
+ mangleTemplateInstantiationName(const TemplateDecl *TD,
+ const TemplateArgumentList &TemplateArgs);
void mangleObjCMethodName(const ObjCMethodDecl *MD);
- void mangleLocalName(const FunctionDecl *FD);
void mangleArgumentType(QualType T, SourceRange Range);
@@ -157,7 +267,7 @@ private:
#undef ABSTRACT_TYPE
#undef NON_CANONICAL_TYPE
#undef TYPE
-
+
void mangleType(const TagDecl *TD);
void mangleDecayedArrayType(const ArrayType *T);
void mangleArrayType(const ArrayType *T);
@@ -171,47 +281,6 @@ private:
const TemplateArgumentList &TemplateArgs);
void mangleTemplateArg(const TemplateDecl *TD, const TemplateArgument &TA);
};
-
-/// MicrosoftMangleContextImpl - Overrides the default MangleContext for the
-/// Microsoft Visual C++ ABI.
-class MicrosoftMangleContextImpl : public MicrosoftMangleContext {
-public:
- MicrosoftMangleContextImpl(ASTContext &Context, DiagnosticsEngine &Diags)
- : MicrosoftMangleContext(Context, Diags) {}
- virtual bool shouldMangleCXXName(const NamedDecl *D);
- virtual void mangleCXXName(const NamedDecl *D, raw_ostream &Out);
- virtual void mangleVirtualMemPtrThunk(const CXXMethodDecl *MD,
- uint64_t OffsetInVFTable,
- raw_ostream &);
- virtual void mangleThunk(const CXXMethodDecl *MD,
- const ThunkInfo &Thunk,
- raw_ostream &);
- virtual void mangleCXXDtorThunk(const CXXDestructorDecl *DD, CXXDtorType Type,
- const ThisAdjustment &ThisAdjustment,
- raw_ostream &);
- virtual void mangleCXXVFTable(const CXXRecordDecl *Derived,
- ArrayRef<const CXXRecordDecl *> BasePath,
- raw_ostream &Out);
- virtual void mangleCXXVBTable(const CXXRecordDecl *Derived,
- ArrayRef<const CXXRecordDecl *> BasePath,
- raw_ostream &Out);
- virtual void mangleCXXRTTI(QualType T, raw_ostream &);
- virtual void mangleCXXRTTIName(QualType T, raw_ostream &);
- virtual void mangleTypeName(QualType T, raw_ostream &);
- virtual void mangleCXXCtor(const CXXConstructorDecl *D, CXXCtorType Type,
- raw_ostream &);
- virtual void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type,
- raw_ostream &);
- virtual void mangleReferenceTemporary(const VarDecl *, raw_ostream &);
- virtual void mangleStaticGuardVariable(const VarDecl *D, raw_ostream &Out);
- virtual void mangleDynamicInitializer(const VarDecl *D, raw_ostream &Out);
- virtual void mangleDynamicAtExitDestructor(const VarDecl *D,
- raw_ostream &Out);
-
-private:
- void mangleInitFiniStub(const VarDecl *D, raw_ostream &Out, char CharCode);
-};
-
}
bool MicrosoftMangleContextImpl::shouldMangleCXXName(const NamedDecl *D) {
@@ -267,8 +336,14 @@ bool MicrosoftMangleContextImpl::shouldMangleCXXName(const NamedDecl *D) {
return true;
}
-void MicrosoftCXXNameMangler::mangle(const NamedDecl *D,
- StringRef Prefix) {
+bool
+MicrosoftMangleContextImpl::shouldMangleStringLiteral(const StringLiteral *SL) {
+ return SL->isAscii() || SL->isWide();
+ // TODO: This needs to be updated when MSVC gains support for Unicode
+ // literals.
+}
+
+void MicrosoftCXXNameMangler::mangle(const NamedDecl *D, StringRef Prefix) {
// MSVC doesn't mangle C++ names the same way it mangles extern "C" names.
// Therefore it's really important that we don't decorate the
// name with leading underscores or leading/trailing at signs. So, by
@@ -286,10 +361,9 @@ void MicrosoftCXXNameMangler::mangle(const NamedDecl *D,
// TODO: Fields? Can MSVC even mangle them?
// Issue a diagnostic for now.
DiagnosticsEngine &Diags = Context.getDiags();
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle this declaration yet");
- Diags.Report(D->getLocation(), DiagID)
- << D->getSourceRange();
+ unsigned DiagID = Diags.getCustomDiagID(
+ DiagnosticsEngine::Error, "cannot mangle this declaration yet");
+ Diags.Report(D->getLocation(), DiagID) << D->getSourceRange();
}
}
@@ -324,7 +398,7 @@ void MicrosoftCXXNameMangler::mangleVariableEncoding(const VarDecl *VD) {
// ::= 2 # public static member
// ::= 3 # global
// ::= 4 # static local
-
+
// The first character in the encoding (after the name) is the storage class.
if (VD->isStaticDataMember()) {
// If it's a static member, it also encodes the access level.
@@ -344,13 +418,13 @@ void MicrosoftCXXNameMangler::mangleVariableEncoding(const VarDecl *VD) {
// ::= <type> <pointee-cvr-qualifiers> # pointers, references
// Pointers and references are odd. The type of 'int * const foo;' gets
// mangled as 'QAHA' instead of 'PAHB', for example.
- TypeLoc TL = VD->getTypeSourceInfo()->getTypeLoc();
- QualType Ty = TL.getType();
+ SourceRange SR = VD->getSourceRange();
+ QualType Ty = VD->getType();
if (Ty->isPointerType() || Ty->isReferenceType() ||
Ty->isMemberPointerType()) {
- mangleType(Ty, TL.getSourceRange(), QMM_Drop);
- if (PointersAre64Bit)
- Out << 'E';
+ mangleType(Ty, SR, QMM_Drop);
+ manglePointerExtQualifiers(
+ Ty.getDesugaredType(getASTContext()).getLocalQualifiers(), nullptr);
if (const MemberPointerType *MPT = Ty->getAs<MemberPointerType>()) {
mangleQualifiers(MPT->getPointeeType().getQualifiers(), true);
// Member pointers are suffixed with a back reference to the member
@@ -366,25 +440,137 @@ void MicrosoftCXXNameMangler::mangleVariableEncoding(const VarDecl *VD) {
else
mangleQualifiers(Ty.getQualifiers(), false);
} else {
- mangleType(Ty, TL.getSourceRange(), QMM_Drop);
+ mangleType(Ty, SR, QMM_Drop);
mangleQualifiers(Ty.getLocalQualifiers(), false);
}
}
+void MicrosoftCXXNameMangler::mangleMemberDataPointer(const CXXRecordDecl *RD,
+ const ValueDecl *VD) {
+ // <member-data-pointer> ::= <integer-literal>
+ // ::= $F <number> <number>
+ // ::= $G <number> <number> <number>
+
+ int64_t FieldOffset;
+ int64_t VBTableOffset;
+ MSInheritanceAttr::Spelling IM = RD->getMSInheritanceModel();
+ if (VD) {
+ FieldOffset = getASTContext().getFieldOffset(VD);
+ assert(FieldOffset % getASTContext().getCharWidth() == 0 &&
+ "cannot take address of bitfield");
+ FieldOffset /= getASTContext().getCharWidth();
+
+ VBTableOffset = 0;
+ } else {
+ FieldOffset = RD->nullFieldOffsetIsZero() ? 0 : -1;
+
+ VBTableOffset = -1;
+ }
+
+ char Code = '\0';
+ switch (IM) {
+ case MSInheritanceAttr::Keyword_single_inheritance: Code = '0'; break;
+ case MSInheritanceAttr::Keyword_multiple_inheritance: Code = '0'; break;
+ case MSInheritanceAttr::Keyword_virtual_inheritance: Code = 'F'; break;
+ case MSInheritanceAttr::Keyword_unspecified_inheritance: Code = 'G'; break;
+ }
+
+ Out << '$' << Code;
+
+ mangleNumber(FieldOffset);
+
+ // The C++ standard doesn't allow base-to-derived member pointer conversions
+ // in template parameter contexts, so the vbptr offset of data member pointers
+ // is always zero.
+ if (MSInheritanceAttr::hasVBPtrOffsetField(IM))
+ mangleNumber(0);
+ if (MSInheritanceAttr::hasVBTableOffsetField(IM))
+ mangleNumber(VBTableOffset);
+}
+
+void
+MicrosoftCXXNameMangler::mangleMemberFunctionPointer(const CXXRecordDecl *RD,
+ const CXXMethodDecl *MD) {
+ // <member-function-pointer> ::= $1? <name>
+ // ::= $H? <name> <number>
+ // ::= $I? <name> <number> <number>
+ // ::= $J? <name> <number> <number> <number>
+
+ MSInheritanceAttr::Spelling IM = RD->getMSInheritanceModel();
+
+ char Code = '\0';
+ switch (IM) {
+ case MSInheritanceAttr::Keyword_single_inheritance: Code = '1'; break;
+ case MSInheritanceAttr::Keyword_multiple_inheritance: Code = 'H'; break;
+ case MSInheritanceAttr::Keyword_virtual_inheritance: Code = 'I'; break;
+ case MSInheritanceAttr::Keyword_unspecified_inheritance: Code = 'J'; break;
+ }
+
+ // If non-virtual, mangle the name. If virtual, mangle as a virtual memptr
+ // thunk.
+ uint64_t NVOffset = 0;
+ uint64_t VBTableOffset = 0;
+ uint64_t VBPtrOffset = 0;
+ if (MD) {
+ Out << '$' << Code << '?';
+ if (MD->isVirtual()) {
+ MicrosoftVTableContext *VTContext =
+ cast<MicrosoftVTableContext>(getASTContext().getVTableContext());
+ const MicrosoftVTableContext::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);
+ }
+ } else {
+ // Null single inheritance member functions are encoded as a simple nullptr.
+ if (IM == MSInheritanceAttr::Keyword_single_inheritance) {
+ Out << "$0A@";
+ return;
+ }
+ if (IM == MSInheritanceAttr::Keyword_unspecified_inheritance)
+ VBTableOffset = -1;
+ Out << '$' << Code;
+ }
+
+ if (MSInheritanceAttr::hasNVOffsetField(/*IsMemberFunction=*/true, IM))
+ mangleNumber(NVOffset);
+ if (MSInheritanceAttr::hasVBPtrOffsetField(IM))
+ mangleNumber(VBPtrOffset);
+ if (MSInheritanceAttr::hasVBTableOffsetField(IM))
+ mangleNumber(VBTableOffset);
+}
+
+void MicrosoftCXXNameMangler::mangleVirtualMemPtrThunk(
+ const CXXMethodDecl *MD,
+ const MicrosoftVTableContext::MethodVFTableLocation &ML) {
+ // Get the vftable offset.
+ 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';
+ Out << (PointersAre64Bit ? 'A' : 'E');
+}
+
void MicrosoftCXXNameMangler::mangleName(const NamedDecl *ND) {
// <name> ::= <unscoped-name> {[<named-scope>]+ | [<nested-name>]}? @
- const DeclContext *DC = ND->getDeclContext();
// Always start with the unqualified name.
- mangleUnqualifiedName(ND);
-
- // If this is an extern variable declared locally, the relevant DeclContext
- // is that of the containing namespace, or the translation unit.
- if (isa<FunctionDecl>(DC) && ND->hasLinkage())
- while (!DC->isNamespace() && !DC->isTranslationUnit())
- DC = DC->getParent();
+ mangleUnqualifiedName(ND);
- manglePostfix(DC);
+ mangleNestedName(ND);
// Terminate the whole name with an '@'.
Out << '@';
@@ -412,8 +598,8 @@ void MicrosoftCXXNameMangler::mangleNumber(int64_t Number) {
// in the range of ASCII characters 'A' to 'P'.
// The number 0x123450 would be encoded as 'BCDEFA'
char EncodedNumberBuffer[sizeof(uint64_t) * 2];
- llvm::MutableArrayRef<char> BufferRef(EncodedNumberBuffer);
- llvm::MutableArrayRef<char>::reverse_iterator I = BufferRef.rbegin();
+ MutableArrayRef<char> BufferRef(EncodedNumberBuffer);
+ MutableArrayRef<char>::reverse_iterator I = BufferRef.rbegin();
for (; Value != 0; Value >>= 4)
*I++ = 'A' + (Value & 0xf);
Out.write(I.base(), I - BufferRef.rbegin());
@@ -424,7 +610,7 @@ void MicrosoftCXXNameMangler::mangleNumber(int64_t Number) {
static const TemplateDecl *
isTemplate(const NamedDecl *ND, const TemplateArgumentList *&TemplateArgs) {
// Check if we have a function template.
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)){
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {
if (const TemplateDecl *TD = FD->getPrimaryTemplate()) {
TemplateArgs = FD->getTemplateSpecializationArgs();
return TD;
@@ -433,24 +619,30 @@ isTemplate(const NamedDecl *ND, const TemplateArgumentList *&TemplateArgs) {
// Check if we have a class template.
if (const ClassTemplateSpecializationDecl *Spec =
- dyn_cast<ClassTemplateSpecializationDecl>(ND)) {
+ dyn_cast<ClassTemplateSpecializationDecl>(ND)) {
+ TemplateArgs = &Spec->getTemplateArgs();
+ return Spec->getSpecializedTemplate();
+ }
+
+ // Check if we have a variable template.
+ if (const VarTemplateSpecializationDecl *Spec =
+ dyn_cast<VarTemplateSpecializationDecl>(ND)) {
TemplateArgs = &Spec->getTemplateArgs();
return Spec->getSpecializedTemplate();
}
- return 0;
+ return nullptr;
}
-void
-MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
- DeclarationName Name) {
+void MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
+ DeclarationName Name) {
// <unqualified-name> ::= <operator-name>
// ::= <ctor-dtor-name>
// ::= <source-name>
// ::= <template-name>
// Check if we have a template.
- const TemplateArgumentList *TemplateArgs = 0;
+ const TemplateArgumentList *TemplateArgs = nullptr;
if (const TemplateDecl *TD = isTemplate(ND, TemplateArgs)) {
// Function templates aren't considered for name back referencing. This
// makes sense since function templates aren't likely to occur multiple
@@ -458,10 +650,10 @@ MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
// FIXME: Test alias template mangling with MSVC 2013.
if (!isa<ClassTemplateDecl>(TD)) {
mangleTemplateInstantiationName(TD, *TemplateArgs);
+ Out << '@';
return;
}
- // We have a class template.
// Here comes the tricky thing: if we need to mangle something like
// void foo(A::X<Y>, B::X<Y>),
// the X<Y> part is aliased. However, if you need to mangle
@@ -473,30 +665,17 @@ MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
// type [ -> template-parameters]
// \-> namespace[s]
// What we do is we create a new mangler, mangle the same type (without
- // a namespace suffix) using the extra mangler with back references
- // disabled (to avoid infinite recursion) and then use the mangled type
- // name as a key to check the mangling of different types for aliasing.
-
- std::string BackReferenceKey;
- BackRefMap::iterator Found;
- if (UseNameBackReferences) {
- llvm::raw_string_ostream Stream(BackReferenceKey);
- MicrosoftCXXNameMangler Extra(Context, Stream);
- Extra.disableBackReferences();
- Extra.mangleUnqualifiedName(ND, Name);
- Stream.flush();
-
- Found = NameBackReferences.find(BackReferenceKey);
- }
- if (!UseNameBackReferences || Found == NameBackReferences.end()) {
- mangleTemplateInstantiationName(TD, *TemplateArgs);
- if (UseNameBackReferences && NameBackReferences.size() < 10) {
- size_t Size = NameBackReferences.size();
- NameBackReferences[BackReferenceKey] = Size;
- }
- } else {
- Out << Found->second;
- }
+ // a namespace suffix) to a string using the extra mangler and then use
+ // the mangled type name as a key to check the mangling of different types
+ // for aliasing.
+
+ llvm::SmallString<64> TemplateMangling;
+ llvm::raw_svector_ostream Stream(TemplateMangling);
+ MicrosoftCXXNameMangler Extra(Context, Stream);
+ Extra.mangleTemplateInstantiationName(TD, *TemplateArgs);
+ Stream.flush();
+
+ mangleSourceName(TemplateMangling);
return;
}
@@ -506,17 +685,31 @@ MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
mangleSourceName(II->getName());
break;
}
-
+
// Otherwise, an anonymous entity. We must have a declaration.
assert(ND && "mangling empty name without declaration");
-
+
if (const NamespaceDecl *NS = dyn_cast<NamespaceDecl>(ND)) {
if (NS->isAnonymousNamespace()) {
Out << "?A@";
break;
}
}
-
+
+ if (const VarDecl *VD = dyn_cast<VarDecl>(ND)) {
+ // We must have an anonymous union or struct declaration.
+ const CXXRecordDecl *RD = VD->getType()->getAsCXXRecordDecl();
+ assert(RD && "expected variable decl to have a record type");
+ // Anonymous types with no tag or typedef get the name of their
+ // declarator mangled in. If they have no declarator, number them with
+ // a $S prefix.
+ llvm::SmallString<64> Name("$S");
+ // Get a unique id for the anonymous struct.
+ Name += llvm::utostr(Context.getAnonymousStructId(RD) + 1);
+ mangleSourceName(Name.str());
+ break;
+ }
+
// We must have an anonymous struct.
const TagDecl *TD = cast<TagDecl>(ND);
if (const TypedefNameDecl *D = TD->getTypedefNameForAnonDecl()) {
@@ -528,26 +721,43 @@ MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
break;
}
+ if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(TD)) {
+ if (Record->isLambda()) {
+ llvm::SmallString<10> Name("<lambda_");
+ unsigned LambdaId;
+ if (Record->getLambdaManglingNumber())
+ LambdaId = Record->getLambdaManglingNumber();
+ else
+ LambdaId = Context.getLambdaId(Record);
+
+ Name += llvm::utostr(LambdaId);
+ Name += ">";
+
+ mangleSourceName(Name);
+ break;
+ }
+ }
+
+ llvm::SmallString<64> Name("<unnamed-type-");
if (TD->hasDeclaratorForAnonDecl()) {
// Anonymous types with no tag or typedef get the name of their
- // declarator mangled in.
- llvm::SmallString<64> Name("<unnamed-type-");
+ // declarator mangled in if they have one.
Name += TD->getDeclaratorForAnonDecl()->getName();
- Name += ">";
- mangleSourceName(Name.str());
} else {
- // Anonymous types with no tag, no typedef, or declarator get
- // '<unnamed-tag>'.
- mangleSourceName("<unnamed-tag>");
+ // Otherwise, number the types using a $S prefix.
+ Name += "$S";
+ Name += llvm::utostr(Context.getAnonymousStructId(TD));
}
+ Name += ">";
+ mangleSourceName(Name.str());
break;
}
-
+
case DeclarationName::ObjCZeroArgSelector:
case DeclarationName::ObjCOneArgSelector:
case DeclarationName::ObjCMultiArgSelector:
llvm_unreachable("Can't mangle Objective-C selector names here!");
-
+
case DeclarationName::CXXConstructorName:
if (ND == Structor) {
assert(StructorType == Ctor_Complete &&
@@ -555,7 +765,7 @@ MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
}
Out << "?0";
break;
-
+
case DeclarationName::CXXDestructorName:
if (ND == Structor)
// If the named decl is the C++ destructor we're mangling,
@@ -566,70 +776,69 @@ MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
// class with a destructor is declared within a destructor.
mangleCXXDtorType(Dtor_Base);
break;
-
+
case DeclarationName::CXXConversionFunctionName:
// <operator-name> ::= ?B # (cast)
// The target type is encoded as the return type.
Out << "?B";
break;
-
+
case DeclarationName::CXXOperatorName:
mangleOperatorName(Name.getCXXOverloadedOperator(), ND->getLocation());
break;
-
+
case DeclarationName::CXXLiteralOperatorName: {
- // FIXME: Was this added in VS2010? Does MS even know how to mangle this?
- DiagnosticsEngine Diags = Context.getDiags();
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle this literal operator yet");
- Diags.Report(ND->getLocation(), DiagID);
+ Out << "?__K";
+ mangleSourceName(Name.getCXXLiteralIdentifier()->getName());
break;
}
-
+
case DeclarationName::CXXUsingDirective:
llvm_unreachable("Can't mangle a using directive name!");
}
}
-void MicrosoftCXXNameMangler::manglePostfix(const DeclContext *DC,
- bool NoFunction) {
+void MicrosoftCXXNameMangler::mangleNestedName(const NamedDecl *ND) {
// <postfix> ::= <unqualified-name> [<postfix>]
// ::= <substitution> [<postfix>]
-
- if (!DC) return;
-
- while (isa<LinkageSpecDecl>(DC))
- DC = DC->getParent();
-
- if (DC->isTranslationUnit())
+ if (isLambda(ND))
return;
- if (const BlockDecl *BD = dyn_cast<BlockDecl>(DC)) {
- DiagnosticsEngine Diags = Context.getDiags();
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle a local inside this block yet");
- Diags.Report(BD->getLocation(), DiagID);
+ const DeclContext *DC = ND->getDeclContext();
- // FIXME: This is completely, utterly, wrong; see ItaniumMangle
- // for how this should be done.
- Out << "__block_invoke" << Context.getBlockId(BD, false);
- Out << '@';
- return manglePostfix(DC->getParent(), NoFunction);
- } else if (isa<CapturedDecl>(DC)) {
- // Skip CapturedDecl context.
- manglePostfix(DC->getParent(), NoFunction);
- return;
- }
+ while (!DC->isTranslationUnit()) {
+ if (isa<TagDecl>(ND) || isa<VarDecl>(ND)) {
+ unsigned Disc;
+ if (Context.getNextDiscriminator(ND, Disc)) {
+ Out << '?';
+ mangleNumber(Disc);
+ Out << '?';
+ }
+ }
- if (NoFunction && (isa<FunctionDecl>(DC) || isa<ObjCMethodDecl>(DC)))
- return;
- else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(DC))
- mangleObjCMethodName(Method);
- else if (const FunctionDecl *Func = dyn_cast<FunctionDecl>(DC))
- mangleLocalName(Func);
- else {
- mangleUnqualifiedName(cast<NamedDecl>(DC));
- manglePostfix(DC->getParent(), NoFunction);
+ if (const BlockDecl *BD = dyn_cast<BlockDecl>(DC)) {
+ DiagnosticsEngine &Diags = Context.getDiags();
+ unsigned DiagID =
+ Diags.getCustomDiagID(DiagnosticsEngine::Error,
+ "cannot mangle a local inside this block yet");
+ Diags.Report(BD->getLocation(), DiagID);
+
+ // FIXME: This is completely, utterly, wrong; see ItaniumMangle
+ // for how this should be done.
+ Out << "__block_invoke" << Context.getBlockId(BD, false);
+ Out << '@';
+ 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(FD, "?");
+ break;
+ } else
+ mangleUnqualifiedName(ND);
+ }
+ DC = DC->getParent();
}
}
@@ -768,7 +977,7 @@ void MicrosoftCXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO,
case OO_Array_New: Out << "?_U"; break;
// <operator-name> ::= ?_V # delete[]
case OO_Array_Delete: Out << "?_V"; break;
-
+
case OO_Conditional: {
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
@@ -776,7 +985,7 @@ void MicrosoftCXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO,
Diags.Report(Loc, DiagID);
break;
}
-
+
case OO_None:
case NUM_OVERLOADED_OPERATORS:
llvm_unreachable("Not an overloaded operator");
@@ -786,14 +995,19 @@ void MicrosoftCXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO,
void MicrosoftCXXNameMangler::mangleSourceName(StringRef Name) {
// <source name> ::= <identifier> @
BackRefMap::iterator Found;
- if (UseNameBackReferences)
+ if (NameBackReferences.size() < 10) {
+ size_t Size = NameBackReferences.size();
+ bool Inserted;
+ std::tie(Found, Inserted) =
+ NameBackReferences.insert(std::make_pair(Name, Size));
+ if (Inserted)
+ Found = NameBackReferences.end();
+ } else {
Found = NameBackReferences.find(Name);
- if (!UseNameBackReferences || Found == NameBackReferences.end()) {
+ }
+
+ if (Found == NameBackReferences.end()) {
Out << Name << '@';
- if (UseNameBackReferences && NameBackReferences.size() < 10) {
- size_t Size = NameBackReferences.size();
- NameBackReferences[Name] = Size;
- }
} else {
Out << Found->second;
}
@@ -803,47 +1017,8 @@ void MicrosoftCXXNameMangler::mangleObjCMethodName(const ObjCMethodDecl *MD) {
Context.mangleObjCMethodName(MD, Out);
}
-// Find out how many function decls live above this one and return an integer
-// suitable for use as the number in a numbered anonymous scope.
-// TODO: Memoize.
-static unsigned getLocalNestingLevel(const FunctionDecl *FD) {
- const DeclContext *DC = FD->getParent();
- int level = 1;
-
- while (DC && !DC->isTranslationUnit()) {
- if (isa<FunctionDecl>(DC) || isa<ObjCMethodDecl>(DC)) level++;
- DC = DC->getParent();
- }
-
- return 2*level;
-}
-
-void MicrosoftCXXNameMangler::mangleLocalName(const FunctionDecl *FD) {
- // <nested-name> ::= <numbered-anonymous-scope> ? <mangled-name>
- // <numbered-anonymous-scope> ::= ? <number>
- // Even though the name is rendered in reverse order (e.g.
- // A::B::C is rendered as C@B@A), VC numbers the scopes from outermost to
- // innermost. So a method bar in class C local to function foo gets mangled
- // as something like:
- // ?bar@C@?1??foo@@YAXXZ@QAEXXZ
- // This is more apparent when you have a type nested inside a method of a
- // type nested inside a function. A method baz in class D local to method
- // bar of class C local to function foo gets mangled as:
- // ?baz@D@?3??bar@C@?1??foo@@YAXXZ@QAEXXZ@QAEXXZ
- // This scheme is general enough to support GCC-style nested
- // functions. You could have a method baz of class C inside a function bar
- // inside a function foo, like so:
- // ?baz@C@?3??bar@?1??foo@@YAXXZ@YAXXZ@QAEXXZ
- unsigned NestLevel = getLocalNestingLevel(FD);
- Out << '?';
- mangleNumber(NestLevel);
- Out << '?';
- mangle(FD, "?");
-}
-
void MicrosoftCXXNameMangler::mangleTemplateInstantiationName(
- const TemplateDecl *TD,
- const TemplateArgumentList &TemplateArgs) {
+ const TemplateDecl *TD, const TemplateArgumentList &TemplateArgs) {
// <template-name> ::= <unscoped-template-name> <template-args>
// ::= <substitution>
// Always start with the unqualified name.
@@ -869,9 +1044,8 @@ MicrosoftCXXNameMangler::mangleUnscopedTemplateName(const TemplateDecl *TD) {
mangleUnqualifiedName(TD);
}
-void
-MicrosoftCXXNameMangler::mangleIntegerLiteral(const llvm::APSInt &Value,
- bool IsBoolean) {
+void MicrosoftCXXNameMangler::mangleIntegerLiteral(const llvm::APSInt &Value,
+ bool IsBoolean) {
// <integer-literal> ::= $0 <number>
Out << "$0";
// Make sure booleans are encoded as 0/1.
@@ -881,8 +1055,7 @@ MicrosoftCXXNameMangler::mangleIntegerLiteral(const llvm::APSInt &Value,
mangleNumber(Value.getSExtValue());
}
-void
-MicrosoftCXXNameMangler::mangleExpression(const Expr *E) {
+void MicrosoftCXXNameMangler::mangleExpression(const Expr *E) {
// See if this is a constant expression.
llvm::APSInt Value;
if (E->isIntegerConstantExpr(Value, Context.getASTContext())) {
@@ -890,7 +1063,10 @@ MicrosoftCXXNameMangler::mangleExpression(const Expr *E) {
return;
}
- const CXXUuidofExpr *UE = 0;
+ // Look through no-op casts like template parameter substitutions.
+ E = E->IgnoreParenNoopCasts(Context.getASTContext());
+
+ const CXXUuidofExpr *UE = nullptr;
if (const UnaryOperator *UO = dyn_cast<UnaryOperator>(E)) {
if (UO->getOpcode() == UO_AddrOf)
UE = dyn_cast<CXXUuidofExpr>(UO->getSubExpr());
@@ -919,26 +1095,30 @@ MicrosoftCXXNameMangler::mangleExpression(const Expr *E) {
// As bad as this diagnostic is, it's better than crashing.
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();
+ 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) {
- // <template-args> ::= {<type> | <integer-literal>}+ @
- unsigned NumTemplateArgs = TemplateArgs.size();
- for (unsigned i = 0; i < NumTemplateArgs; ++i) {
- const TemplateArgument &TA = TemplateArgs[i];
+void MicrosoftCXXNameMangler::mangleTemplateArgs(
+ const TemplateDecl *TD, const TemplateArgumentList &TemplateArgs) {
+ // <template-args> ::= <template-arg>+
+ for (const TemplateArgument &TA : TemplateArgs.asArray())
mangleTemplateArg(TD, TA);
- }
- Out << '@';
}
void MicrosoftCXXNameMangler::mangleTemplateArg(const TemplateDecl *TD,
const TemplateArgument &TA) {
+ // <template-arg> ::= <type>
+ // ::= <integer-literal>
+ // ::= <member-data-pointer>
+ // ::= <member-function-pointer>
+ // ::= $E? <name> <type-encoding>
+ // ::= $1? <name> <type-encoding>
+ // ::= $0A@
+ // ::= <template-args>
+
switch (TA.getKind()) {
case TemplateArgument::Null:
llvm_unreachable("Can't mangle null template arguments!");
@@ -951,25 +1131,54 @@ void MicrosoftCXXNameMangler::mangleTemplateArg(const TemplateDecl *TD,
}
case TemplateArgument::Declaration: {
const NamedDecl *ND = cast<NamedDecl>(TA.getAsDecl());
- mangle(ND, TA.isDeclForReferenceParam() ? "$E?" : "$1?");
+ if (isa<FieldDecl>(ND) || isa<IndirectFieldDecl>(ND)) {
+ mangleMemberDataPointer(
+ cast<CXXRecordDecl>(ND->getDeclContext())->getMostRecentDecl(),
+ 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()->getMostRecentDecl(), MD);
+ else
+ mangle(FD, "$1?");
+ } else {
+ mangle(ND, TA.isDeclForReferenceParam() ? "$E?" : "$1?");
+ }
break;
}
case TemplateArgument::Integral:
mangleIntegerLiteral(TA.getAsIntegral(),
TA.getIntegralType()->isBooleanType());
break;
- case TemplateArgument::NullPtr:
+ case TemplateArgument::NullPtr: {
+ QualType T = TA.getNullPtrType();
+ if (const MemberPointerType *MPT = T->getAs<MemberPointerType>()) {
+ const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl();
+ if (MPT->isMemberFunctionPointerType() && isa<ClassTemplateDecl>(TD)) {
+ mangleMemberFunctionPointer(RD, nullptr);
+ return;
+ }
+ if (MPT->isMemberDataPointer()) {
+ mangleMemberDataPointer(RD, nullptr);
+ return;
+ }
+ }
Out << "$0A@";
break;
+ }
case TemplateArgument::Expression:
mangleExpression(TA.getAsExpr());
break;
- case TemplateArgument::Pack:
- // Unlike Itanium, there is no character code to indicate an argument pack.
- for (TemplateArgument::pack_iterator I = TA.pack_begin(), E = TA.pack_end();
- I != E; ++I)
- mangleTemplateArg(TD, *I);
+ case TemplateArgument::Pack: {
+ ArrayRef<TemplateArgument> TemplateArgs = TA.getPackAsArray();
+ if (TemplateArgs.empty()) {
+ Out << "$S";
+ } else {
+ for (const TemplateArgument &PA : TemplateArgs)
+ mangleTemplateArg(TD, PA);
+ }
break;
+ }
case TemplateArgument::Template:
mangleType(cast<TagDecl>(
TA.getAsTemplate().getAsTemplateDecl()->getTemplatedDecl()));
@@ -1059,13 +1268,43 @@ void MicrosoftCXXNameMangler::mangleQualifiers(Qualifiers Quals,
// FIXME: For now, just drop all extension qualifiers on the floor.
}
-void MicrosoftCXXNameMangler::manglePointerQualifiers(Qualifiers Quals) {
- // <pointer-cvr-qualifiers> ::= P # no qualifiers
- // ::= Q # const
- // ::= R # volatile
- // ::= S # const volatile
+void
+MicrosoftCXXNameMangler::mangleRefQualifier(RefQualifierKind RefQualifier) {
+ // <ref-qualifier> ::= G # lvalue reference
+ // ::= H # rvalue-reference
+ switch (RefQualifier) {
+ case RQ_None:
+ break;
+
+ case RQ_LValue:
+ Out << 'G';
+ break;
+
+ case RQ_RValue:
+ Out << 'H';
+ break;
+ }
+}
+
+void
+MicrosoftCXXNameMangler::manglePointerExtQualifiers(Qualifiers Quals,
+ const Type *PointeeType) {
+ bool HasRestrict = Quals.hasRestrict();
+ if (PointersAre64Bit && (!PointeeType || !PointeeType->isFunctionType()))
+ Out << 'E';
+
+ if (HasRestrict)
+ Out << 'I';
+}
+
+void MicrosoftCXXNameMangler::manglePointerCVQualifiers(Qualifiers Quals) {
+ // <pointer-cv-qualifiers> ::= P # no qualifiers
+ // ::= Q # const
+ // ::= R # volatile
+ // ::= S # const volatile
bool HasConst = Quals.hasConst(),
HasVolatile = Quals.hasVolatile();
+
if (HasConst && HasVolatile) {
Out << 'S';
} else if (HasVolatile) {
@@ -1165,8 +1404,10 @@ void MicrosoftCXXNameMangler::mangleType(QualType T, SourceRange Range,
}
// We have to mangle these now, while we still have enough information.
- if (IsPointer)
- manglePointerQualifiers(Quals);
+ if (IsPointer) {
+ manglePointerCVQualifiers(Quals);
+ manglePointerExtQualifiers(Quals, T->getPointeeType().getTypePtr());
+ }
const Type *ty = T.getTypePtr();
switch (ty->getTypeClass()) {
@@ -1254,7 +1495,7 @@ void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T,
case BuiltinType::OCLImage3d: Out << "PAUocl_image3d@@"; break;
case BuiltinType::OCLSampler: Out << "PAUocl_sampler@@"; break;
case BuiltinType::OCLEvent: Out << "PAUocl_event@@"; break;
-
+
case BuiltinType::NullPtr: Out << "$$T"; break;
case BuiltinType::Char16:
@@ -1306,9 +1547,10 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T,
// If this is a C++ instance method, mangle the CVR qualifiers for the
// this pointer.
if (IsInstMethod) {
- if (PointersAre64Bit)
- Out << 'E';
- mangleQualifiers(Qualifiers::fromCVRMask(Proto->getTypeQuals()), false);
+ Qualifiers Quals = Qualifiers::fromCVRMask(Proto->getTypeQuals());
+ manglePointerExtQualifiers(Quals, nullptr);
+ mangleRefQualifier(Proto->getRefQualifier());
+ mangleQualifiers(Quals, false);
}
mangleCallingConvention(T);
@@ -1327,23 +1569,30 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T,
}
Out << '@';
} else {
- QualType ResultType = Proto->getResultType();
- if (ResultType->isVoidType())
- ResultType = ResultType.getUnqualifiedType();
- mangleType(ResultType, Range, QMM_Result);
+ QualType ResultType = Proto->getReturnType();
+ if (const auto *AT =
+ dyn_cast_or_null<AutoType>(ResultType->getContainedAutoType())) {
+ Out << '?';
+ mangleQualifiers(ResultType.getLocalQualifiers(), /*IsMember=*/false);
+ Out << '?';
+ mangleSourceName(AT->isDecltypeAuto() ? "<decltype-auto>" : "<auto>");
+ Out << '@';
+ } else {
+ if (ResultType->isVoidType())
+ ResultType = ResultType.getUnqualifiedType();
+ mangleType(ResultType, Range, QMM_Result);
+ }
}
// <argument-list> ::= X # void
// ::= <type>+ @
// ::= <type>* Z # varargs
- if (Proto->getNumArgs() == 0 && !Proto->isVariadic()) {
+ if (Proto->getNumParams() == 0 && !Proto->isVariadic()) {
Out << 'X';
} else {
// Happens for function pointer type arguments for example.
- for (FunctionProtoType::arg_type_iterator Arg = Proto->arg_type_begin(),
- ArgEnd = Proto->arg_type_end();
- Arg != ArgEnd; ++Arg)
- mangleArgumentType(*Arg, Range);
+ for (const QualType Arg : Proto->param_types())
+ mangleArgumentType(Arg, Range);
// <builtin-type> ::= Z # ellipsis
if (Proto->isVariadic())
Out << 'Z';
@@ -1465,7 +1714,7 @@ void MicrosoftCXXNameMangler::mangleType(const UnresolvedUsingType *T,
// <union-type> ::= T <name>
// <struct-type> ::= U <name>
// <class-type> ::= V <name>
-// <enum-type> ::= W <size> <name>
+// <enum-type> ::= W4 <name>
void MicrosoftCXXNameMangler::mangleType(const EnumType *T, SourceRange) {
mangleType(cast<TagType>(T)->getDecl());
}
@@ -1485,9 +1734,7 @@ void MicrosoftCXXNameMangler::mangleType(const TagDecl *TD) {
Out << 'V';
break;
case TTK_Enum:
- Out << 'W';
- Out << getASTContext().getTypeSizeInChars(
- cast<EnumDecl>(TD)->getIntegerType()).getQuantity();
+ Out << "W4";
break;
}
mangleName(TD);
@@ -1503,7 +1750,7 @@ void MicrosoftCXXNameMangler::mangleType(const TagDecl *TD) {
void MicrosoftCXXNameMangler::mangleDecayedArrayType(const ArrayType *T) {
// This isn't a recursive mangling, so now we have to do it all in this
// one call.
- manglePointerQualifiers(T->getElementType().getQualifiers());
+ manglePointerCVQualifiers(T->getElementType().getQualifiers());
mangleType(T->getElementType(), SourceRange());
}
void MicrosoftCXXNameMangler::mangleType(const ConstantArrayType *T,
@@ -1527,7 +1774,7 @@ void MicrosoftCXXNameMangler::mangleArrayType(const ArrayType *T) {
SmallVector<llvm::APInt, 3> Dimensions;
for (;;) {
if (const ConstantArrayType *CAT =
- getASTContext().getAsConstantArrayType(ElementTy)) {
+ getASTContext().getAsConstantArrayType(ElementTy)) {
Dimensions.push_back(CAT->getSize());
ElementTy = CAT->getElementType();
} else if (ElementTy->isVariableArrayType()) {
@@ -1550,7 +1797,7 @@ void MicrosoftCXXNameMangler::mangleArrayType(const ArrayType *T) {
<< DSAT->getBracketsRange();
return;
} else if (const IncompleteArrayType *IAT =
- getASTContext().getAsIncompleteArrayType(ElementTy)) {
+ getASTContext().getAsIncompleteArrayType(ElementTy)) {
Dimensions.push_back(llvm::APInt(32, 0));
ElementTy = IAT->getElementType();
}
@@ -1559,8 +1806,8 @@ void MicrosoftCXXNameMangler::mangleArrayType(const ArrayType *T) {
Out << 'Y';
// <dimension-count> ::= <number> # number of extra dimensions
mangleNumber(Dimensions.size());
- for (unsigned Dim = 0; Dim < Dimensions.size(); ++Dim)
- mangleNumber(Dimensions[Dim].getLimitedValue());
+ for (const llvm::APInt &Dimension : Dimensions)
+ mangleNumber(Dimension.getLimitedValue());
mangleType(ElementTy, SourceRange(), QMM_Escape);
}
@@ -1573,10 +1820,8 @@ void MicrosoftCXXNameMangler::mangleType(const MemberPointerType *T,
if (const FunctionProtoType *FPT = PointeeType->getAs<FunctionProtoType>()) {
Out << '8';
mangleName(T->getClass()->castAs<RecordType>()->getDecl());
- mangleFunctionType(FPT, 0, true);
+ mangleFunctionType(FPT, nullptr, true);
} else {
- if (PointersAre64Bit && !T->getPointeeType()->isFunctionType())
- Out << 'E';
mangleQualifiers(PointeeType.getQualifiers(), true);
mangleName(T->getClass()->castAs<RecordType>()->getDecl());
mangleType(PointeeType, Range, QMM_Drop);
@@ -1604,42 +1849,37 @@ void MicrosoftCXXNameMangler::mangleType(
// <type> ::= <pointer-type>
// <pointer-type> ::= E? <pointer-cvr-qualifiers> <cvr-qualifiers> <type>
-// # the E is required for 64-bit non static pointers
+// # the E is required for 64-bit non-static pointers
void MicrosoftCXXNameMangler::mangleType(const PointerType *T,
SourceRange Range) {
QualType PointeeTy = T->getPointeeType();
- if (PointersAre64Bit && !T->getPointeeType()->isFunctionType())
- Out << 'E';
mangleType(PointeeTy, Range);
}
void MicrosoftCXXNameMangler::mangleType(const ObjCObjectPointerType *T,
SourceRange Range) {
// Object pointers never have qualifiers.
Out << 'A';
- if (PointersAre64Bit && !T->getPointeeType()->isFunctionType())
- Out << 'E';
+ manglePointerExtQualifiers(Qualifiers(), T->getPointeeType().getTypePtr());
mangleType(T->getPointeeType(), Range);
}
// <type> ::= <reference-type>
// <reference-type> ::= A E? <cvr-qualifiers> <type>
-// # the E is required for 64-bit non static lvalue references
+// # the E is required for 64-bit non-static lvalue references
void MicrosoftCXXNameMangler::mangleType(const LValueReferenceType *T,
SourceRange Range) {
Out << 'A';
- if (PointersAre64Bit && !T->getPointeeType()->isFunctionType())
- Out << 'E';
+ manglePointerExtQualifiers(Qualifiers(), T->getPointeeType().getTypePtr());
mangleType(T->getPointeeType(), Range);
}
// <type> ::= <r-value-reference-type>
// <r-value-reference-type> ::= $$Q E? <cvr-qualifiers> <type>
-// # the E is required for 64-bit non static rvalue references
+// # the E is required for 64-bit non-static rvalue references
void MicrosoftCXXNameMangler::mangleType(const RValueReferenceType *T,
SourceRange Range) {
Out << "$$Q";
- if (PointersAre64Bit && !T->getPointeeType()->isFunctionType())
- Out << 'E';
+ manglePointerExtQualifiers(Qualifiers(), T->getPointeeType().getTypePtr());
mangleType(T->getPointeeType(), Range);
}
@@ -1804,6 +2044,8 @@ void MicrosoftCXXNameMangler::mangleType(const UnaryTransformType *T,
}
void MicrosoftCXXNameMangler::mangleType(const AutoType *T, 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");
@@ -1923,17 +2165,17 @@ static void mangleThunkThisAdjustment(const CXXMethodDecl *MD,
}
}
-void MicrosoftMangleContextImpl::mangleVirtualMemPtrThunk(
- const CXXMethodDecl *MD, uint64_t OffsetInVFTable, raw_ostream &Out) {
- bool Is64Bit = getASTContext().getTargetInfo().getPointerWidth(0) == 64;
+void
+MicrosoftMangleContextImpl::mangleVirtualMemPtrThunk(const CXXMethodDecl *MD,
+ raw_ostream &Out) {
+ MicrosoftVTableContext *VTContext =
+ cast<MicrosoftVTableContext>(getASTContext().getVTableContext());
+ const MicrosoftVTableContext::MethodVFTableLocation &ML =
+ VTContext->getMethodVFTableLocation(GlobalDecl(MD));
MicrosoftCXXNameMangler Mangler(*this, Out);
- Mangler.getStream() << "\01??_9";
- Mangler.mangleName(MD->getParent());
- Mangler.getStream() << "$B";
- Mangler.mangleNumber(OffsetInVFTable);
- Mangler.getStream() << "A";
- Mangler.getStream() << (Is64Bit ? "A" : "E");
+ Mangler.getStream() << "\01?";
+ Mangler.mangleVirtualMemPtrThunk(MD, ML);
}
void MicrosoftMangleContextImpl::mangleThunk(const CXXMethodDecl *MD,
@@ -1944,7 +2186,8 @@ void MicrosoftMangleContextImpl::mangleThunk(const CXXMethodDecl *MD,
Mangler.mangleName(MD);
mangleThunkThisAdjustment(MD, Thunk.This, Mangler, Out);
if (!Thunk.Return.isEmpty())
- assert(Thunk.Method != 0 && "Thunk info should hold the overridee decl");
+ assert(Thunk.Method != nullptr &&
+ "Thunk info should hold the overridee decl");
const CXXMethodDecl *DeclForFPT = Thunk.Method ? Thunk.Method : MD;
Mangler.mangleFunctionType(
@@ -1976,11 +2219,8 @@ void MicrosoftMangleContextImpl::mangleCXXVFTable(
Mangler.getStream() << "\01??_7";
Mangler.mangleName(Derived);
Mangler.getStream() << "6B"; // '6' for vftable, 'B' for const.
- for (ArrayRef<const CXXRecordDecl *>::iterator I = BasePath.begin(),
- E = BasePath.end();
- I != E; ++I) {
- Mangler.mangleName(*I);
- }
+ for (const CXXRecordDecl *RD : BasePath)
+ Mangler.mangleName(RD);
Mangler.getStream() << '@';
}
@@ -1995,28 +2235,68 @@ void MicrosoftMangleContextImpl::mangleCXXVBTable(
Mangler.getStream() << "\01??_8";
Mangler.mangleName(Derived);
Mangler.getStream() << "7B"; // '7' for vbtable, 'B' for const.
- for (ArrayRef<const CXXRecordDecl *>::iterator I = BasePath.begin(),
- E = BasePath.end();
- I != E; ++I) {
- Mangler.mangleName(*I);
- }
+ for (const CXXRecordDecl *RD : BasePath)
+ Mangler.mangleName(RD);
Mangler.getStream() << '@';
}
-void MicrosoftMangleContextImpl::mangleCXXRTTI(QualType T, raw_ostream &) {
- // FIXME: Give a location...
- unsigned DiagID = getDiags().getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle RTTI descriptors for type %0 yet");
- getDiags().Report(DiagID)
- << T.getBaseTypeIdentifier();
+void MicrosoftMangleContextImpl::mangleCXXRTTI(QualType T, raw_ostream &Out) {
+ MicrosoftCXXNameMangler Mangler(*this, Out);
+ Mangler.getStream() << "\01??_R0";
+ Mangler.mangleType(T, SourceRange(), MicrosoftCXXNameMangler::QMM_Result);
+ Mangler.getStream() << "@8";
}
-void MicrosoftMangleContextImpl::mangleCXXRTTIName(QualType T, raw_ostream &) {
- // FIXME: Give a location...
- unsigned DiagID = getDiags().getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle the name of type %0 into RTTI descriptors yet");
- getDiags().Report(DiagID)
- << T.getBaseTypeIdentifier();
+void MicrosoftMangleContextImpl::mangleCXXRTTIName(QualType T,
+ raw_ostream &Out) {
+ MicrosoftCXXNameMangler Mangler(*this, Out);
+ Mangler.getStream() << '.';
+ Mangler.mangleType(T, SourceRange(), MicrosoftCXXNameMangler::QMM_Result);
+}
+
+void MicrosoftMangleContextImpl::mangleCXXRTTIBaseClassDescriptor(
+ const CXXRecordDecl *Derived, uint32_t NVOffset, int32_t VBPtrOffset,
+ uint32_t VBTableOffset, uint32_t Flags, raw_ostream &Out) {
+ MicrosoftCXXNameMangler Mangler(*this, Out);
+ Mangler.getStream() << "\01??_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) {
+ MicrosoftCXXNameMangler Mangler(*this, Out);
+ Mangler.getStream() << "\01??_R2";
+ Mangler.mangleName(Derived);
+ Mangler.getStream() << "8";
+}
+
+void MicrosoftMangleContextImpl::mangleCXXRTTIClassHierarchyDescriptor(
+ const CXXRecordDecl *Derived, raw_ostream &Out) {
+ MicrosoftCXXNameMangler Mangler(*this, Out);
+ Mangler.getStream() << "\01??_R3";
+ Mangler.mangleName(Derived);
+ Mangler.getStream() << "8";
+}
+
+void MicrosoftMangleContextImpl::mangleCXXRTTICompleteObjectLocator(
+ const CXXRecordDecl *Derived, ArrayRef<const CXXRecordDecl *> BasePath,
+ raw_ostream &Out) {
+ // <mangled-name> ::= ?_R4 <class-name> <storage-class>
+ // <cvr-qualifiers> [<name>] @
+ // NOTE: <cvr-qualifiers> here is always 'B' (const). <storage-class>
+ // is always '6' for vftables.
+ MicrosoftCXXNameMangler Mangler(*this, Out);
+ Mangler.getStream() << "\01??_R4";
+ Mangler.mangleName(Derived);
+ Mangler.getStream() << "6B"; // '6' for vftable, 'B' for const.
+ for (const CXXRecordDecl *RD : BasePath)
+ Mangler.mangleName(RD);
+ Mangler.getStream() << '@';
}
void MicrosoftMangleContextImpl::mangleTypeName(QualType T, raw_ostream &Out) {
@@ -2042,6 +2322,7 @@ void MicrosoftMangleContextImpl::mangleCXXDtor(const CXXDestructorDecl *D,
}
void MicrosoftMangleContextImpl::mangleReferenceTemporary(const VarDecl *VD,
+ unsigned,
raw_ostream &) {
unsigned DiagID = getDiags().getCustomDiagID(DiagnosticsEngine::Error,
"cannot mangle this reference temporary yet");
@@ -2050,7 +2331,16 @@ void MicrosoftMangleContextImpl::mangleReferenceTemporary(const VarDecl *VD,
void MicrosoftMangleContextImpl::mangleStaticGuardVariable(const VarDecl *VD,
raw_ostream &Out) {
- // <guard-name> ::= ?_B <postfix> @51
+ // TODO: This is not correct, especially with respect to MSVC2013. MSVC2013
+ // utilizes thread local variables to implement thread safe, re-entrant
+ // initialization for statics. They no longer differentiate between an
+ // externally visible and non-externally visible static with respect to
+ // mangling, they all get $TSS <number>.
+ //
+ // N.B. This means that they can get more than 32 static variable guards in a
+ // scope. It also means that they broke compatibility with their own ABI.
+
+ // <guard-name> ::= ?_B <postfix> @5 <scope-depth>
// ::= ?$S <guard-num> @ <postfix> @4IA
// The first mangling is what MSVC uses to guard static locals in inline
@@ -2064,8 +2354,17 @@ void MicrosoftMangleContextImpl::mangleStaticGuardVariable(const VarDecl *VD,
bool Visible = VD->isExternallyVisible();
// <operator-name> ::= ?_B # local static guard
Mangler.getStream() << (Visible ? "\01??_B" : "\01?$S1@");
- Mangler.manglePostfix(VD->getDeclContext());
- Mangler.getStream() << (Visible ? "@51" : "@4IA");
+ unsigned ScopeDepth = 0;
+ if (Visible && !getNextDiscriminator(VD, ScopeDepth))
+ // If we do not have a discriminator and are emitting a guard variable for
+ // use at global scope, then mangling the nested name will not be enough to
+ // remove ambiguities.
+ Mangler.mangle(VD, "");
+ else
+ Mangler.mangleNestedName(VD);
+ Mangler.getStream() << (Visible ? "@5" : "@4IA");
+ if (ScopeDepth)
+ Mangler.mangleNumber(ScopeDepth);
}
void MicrosoftMangleContextImpl::mangleInitFiniStub(const VarDecl *D,
@@ -2074,6 +2373,10 @@ void MicrosoftMangleContextImpl::mangleInitFiniStub(const VarDecl *D,
MicrosoftCXXNameMangler Mangler(*this, Out);
Mangler.getStream() << "\01??__" << CharCode;
Mangler.mangleName(D);
+ if (D->isStaticDataMember()) {
+ Mangler.mangleVariableEncoding(D);
+ Mangler.getStream() << '@';
+ }
// This is the function class mangling. These stubs are global, non-variadic,
// cdecl functions that return void and take no args.
Mangler.getStream() << "YAXXZ";
@@ -2092,6 +2395,172 @@ MicrosoftMangleContextImpl::mangleDynamicAtExitDestructor(const VarDecl *D,
mangleInitFiniStub(D, Out, 'F');
}
+void MicrosoftMangleContextImpl::mangleStringLiteral(const StringLiteral *SL,
+ raw_ostream &Out) {
+ // <char-type> ::= 0 # char
+ // ::= 1 # wchar_t
+ // ::= ??? # char16_t/char32_t will need a mangling too...
+ //
+ // <literal-length> ::= <non-negative integer> # the length of the literal
+ //
+ // <encoded-crc> ::= <hex digit>+ @ # crc of the literal including
+ // # null-terminator
+ //
+ // <encoded-string> ::= <simple character> # uninteresting character
+ // ::= '?$' <hex digit> <hex digit> # these two nibbles
+ // # encode the byte for the
+ // # character
+ // ::= '?' [a-z] # \xe1 - \xfa
+ // ::= '?' [A-Z] # \xc1 - \xda
+ // ::= '?' [0-9] # [,/\:. \n\t'-]
+ //
+ // <literal> ::= '??_C@_' <char-type> <literal-length> <encoded-crc>
+ // <encoded-string> '@'
+ MicrosoftCXXNameMangler Mangler(*this, Out);
+ Mangler.getStream() << "\01??_C@_";
+
+ // <char-type>: The "kind" of string literal is encoded into the mangled name.
+ // TODO: This needs to be updated when MSVC gains support for unicode
+ // literals.
+ if (SL->isAscii())
+ Mangler.getStream() << '0';
+ else if (SL->isWide())
+ Mangler.getStream() << '1';
+ else
+ llvm_unreachable("unexpected string literal kind!");
+
+ // <literal-length>: The next part of the mangled name consists of the length
+ // of the string.
+ // The StringLiteral does not consider the NUL terminator byte(s) but the
+ // mangling does.
+ // N.B. The length is in terms of bytes, not characters.
+ Mangler.mangleNumber(SL->getByteLength() + SL->getCharByteWidth());
+
+ // We will use the "Rocksoft^tm Model CRC Algorithm" to describe the
+ // properties of our CRC:
+ // Width : 32
+ // Poly : 04C11DB7
+ // Init : FFFFFFFF
+ // RefIn : True
+ // RefOut : True
+ // XorOut : 00000000
+ // Check : 340BC6D9
+ uint32_t CRC = 0xFFFFFFFFU;
+
+ auto UpdateCRC = [&CRC](char Byte) {
+ for (unsigned i = 0; i < 8; ++i) {
+ bool Bit = CRC & 0x80000000U;
+ if (Byte & (1U << i))
+ Bit = !Bit;
+ CRC <<= 1;
+ if (Bit)
+ CRC ^= 0x04C11DB7U;
+ }
+ };
+
+ auto GetLittleEndianByte = [&Mangler, &SL](unsigned Index) {
+ unsigned CharByteWidth = SL->getCharByteWidth();
+ uint32_t CodeUnit = SL->getCodeUnit(Index / CharByteWidth);
+ unsigned OffsetInCodeUnit = Index % CharByteWidth;
+ return static_cast<char>((CodeUnit >> (8 * OffsetInCodeUnit)) & 0xff);
+ };
+
+ auto GetBigEndianByte = [&Mangler, &SL](unsigned Index) {
+ unsigned CharByteWidth = SL->getCharByteWidth();
+ uint32_t CodeUnit = SL->getCodeUnit(Index / CharByteWidth);
+ unsigned OffsetInCodeUnit = (CharByteWidth - 1) - (Index % CharByteWidth);
+ return static_cast<char>((CodeUnit >> (8 * OffsetInCodeUnit)) & 0xff);
+ };
+
+ // CRC all the bytes of the StringLiteral.
+ for (unsigned I = 0, E = SL->getByteLength(); I != E; ++I)
+ UpdateCRC(GetLittleEndianByte(I));
+
+ // The NUL terminator byte(s) were not present earlier,
+ // we need to manually process those bytes into the CRC.
+ for (unsigned NullTerminator = 0; NullTerminator < SL->getCharByteWidth();
+ ++NullTerminator)
+ UpdateCRC('\x00');
+
+ // The literature refers to the process of reversing the bits in the final CRC
+ // output as "reflection".
+ CRC = llvm::reverseBits(CRC);
+
+ // <encoded-crc>: The CRC is encoded utilizing the standard number mangling
+ // scheme.
+ Mangler.mangleNumber(CRC);
+
+ // <encoded-string>: The mangled name also contains the first 32 _characters_
+ // (including null-terminator bytes) of the StringLiteral.
+ // Each character is encoded by splitting them into bytes and then encoding
+ // the constituent bytes.
+ auto MangleByte = [&Mangler](char Byte) {
+ // There are five different manglings for characters:
+ // - [a-zA-Z0-9_$]: A one-to-one mapping.
+ // - ?[a-z]: The range from \xe1 to \xfa.
+ // - ?[A-Z]: The range from \xc1 to \xda.
+ // - ?[0-9]: The set of [,/\:. \n\t'-].
+ // - ?$XX: A fallback which maps nibbles.
+ if (isIdentifierBody(Byte, /*AllowDollar=*/true)) {
+ Mangler.getStream() << Byte;
+ } else if (isLetter(Byte & 0x7f)) {
+ Mangler.getStream() << '?' << static_cast<char>(Byte & 0x7f);
+ } else {
+ switch (Byte) {
+ case ',':
+ Mangler.getStream() << "?0";
+ break;
+ case '/':
+ Mangler.getStream() << "?1";
+ break;
+ case '\\':
+ Mangler.getStream() << "?2";
+ break;
+ case ':':
+ Mangler.getStream() << "?3";
+ break;
+ case '.':
+ Mangler.getStream() << "?4";
+ break;
+ case ' ':
+ Mangler.getStream() << "?5";
+ break;
+ case '\n':
+ Mangler.getStream() << "?6";
+ break;
+ case '\t':
+ Mangler.getStream() << "?7";
+ break;
+ case '\'':
+ Mangler.getStream() << "?8";
+ break;
+ case '-':
+ Mangler.getStream() << "?9";
+ break;
+ default:
+ Mangler.getStream() << "?$";
+ Mangler.getStream() << static_cast<char>('A' + ((Byte >> 4) & 0xf));
+ Mangler.getStream() << static_cast<char>('A' + (Byte & 0xf));
+ break;
+ }
+ }
+ };
+
+ // Enforce our 32 character max.
+ unsigned NumCharsToMangle = std::min(32U, SL->getLength());
+ for (unsigned I = 0, E = NumCharsToMangle * SL->getCharByteWidth(); I != E;
+ ++I)
+ MangleByte(GetBigEndianByte(I));
+
+ // Encode the NUL terminator if there is room.
+ if (NumCharsToMangle < 32)
+ for (unsigned NullTerminator = 0; NullTerminator < SL->getCharByteWidth();
+ ++NullTerminator)
+ MangleByte(0);
+
+ Mangler.getStream() << '@';
+}
+
MicrosoftMangleContext *
MicrosoftMangleContext::create(ASTContext &Context, DiagnosticsEngine &Diags) {
return new MicrosoftMangleContextImpl(Context, Diags);
OpenPOWER on IntegriCloud