summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp
diff options
context:
space:
mode:
authordim <dim@FreeBSD.org>2014-03-21 17:53:59 +0000
committerdim <dim@FreeBSD.org>2014-03-21 17:53:59 +0000
commit9cedb8bb69b89b0f0c529937247a6a80cabdbaec (patch)
treec978f0e9ec1ab92dc8123783f30b08a7fd1e2a39 /contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp
parent03fdc2934eb61c44c049a02b02aa974cfdd8a0eb (diff)
downloadFreeBSD-src-9cedb8bb69b89b0f0c529937247a6a80cabdbaec.zip
FreeBSD-src-9cedb8bb69b89b0f0c529937247a6a80cabdbaec.tar.gz
MFC 261991:
Upgrade our copy of llvm/clang to 3.4 release. This version supports all of the features in the current working draft of the upcoming C++ standard, provisionally named C++1y. The code generator's performance is greatly increased, and the loop auto-vectorizer is now enabled at -Os and -O2 in addition to -O3. The PowerPC backend has made several major improvements to code generation quality and compile time, and the X86, SPARC, ARM32, Aarch64 and SystemZ backends have all seen major feature work. Release notes for llvm and clang can be found here: <http://llvm.org/releases/3.4/docs/ReleaseNotes.html> <http://llvm.org/releases/3.4/tools/clang/docs/ReleaseNotes.html> MFC 262121 (by emaste): Update lldb for clang/llvm 3.4 import This commit largely restores the lldb source to the upstream r196259 snapshot with the addition of threaded inferior support and a few bug fixes. Specific upstream lldb revisions restored include: SVN git 181387 779e6ac 181703 7bef4e2 182099 b31044e 182650 f2dcf35 182683 0d91b80 183862 15c1774 183929 99447a6 184177 0b2934b 184948 4dc3761 184954 007e7bc 186990 eebd175 Sponsored by: DARPA, AFRL MFC 262186 (by emaste): Fix mismerge in r262121 A break statement was lost in the merge. The error had no functional impact, but restore it to reduce the diff against upstream. MFC 262303: Pull in r197521 from upstream clang trunk (by rdivacky): Use the integrated assembler by default on FreeBSD/ppc and ppc64. Requested by: jhibbits MFC 262611: Pull in r196874 from upstream llvm trunk: Fix a crash that occurs when PWD is invalid. MCJIT needs to be able to run in hostile environments, even when PWD is invalid. There's no need to crash MCJIT in this case. The obvious fix is to simply leave MCContext's CompilationDir empty when PWD can't be determined. This way, MCJIT clients, and other clients that link with LLVM don't need a valid working directory. If we do want to guarantee valid CompilationDir, that should be done only for clients of getCompilationDir(). This is as simple as checking for an empty string. The only current use of getCompilationDir is EmitGenDwarfInfo, which won't conceivably run with an invalid working dir. However, in the purely hypothetically and untestable case that this happens, the AT_comp_dir will be omitted from the compilation_unit DIE. This should help fix assertions occurring with ports-mgmt/tinderbox, when it is using jails, and sometimes invalidates clang's current working directory. Reported by: decke MFC 262809: Pull in r203007 from upstream clang trunk: Don't produce an alias between destructors with different calling conventions. Fixes pr19007. (Please note that is an LLVM PR identifier, not a FreeBSD one.) This should fix Firefox and/or libxul crashes (due to problems with regparm/stdcall calling conventions) on i386. Reported by: multiple users on freebsd-current PR: bin/187103 MFC 263048: Repair recognition of "CC" as an alias for the C++ compiler, since it was silently broken by upstream for a Windows-specific use-case. Apparently some versions of CMake still rely on this archaic feature... Reported by: rakuco MFC 263049: Garbage collect the old way of adding the libstdc++ include directories in clang's InitHeaderSearch.cpp. This has been superseded by David Chisnall's commit in r255321. Moreover, if libc++ is used, the libstdc++ include directories should not be in the search path at all. These directories are now only used if you pass -stdlib=libstdc++.
Diffstat (limited to 'contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp')
-rw-r--r--contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp990
1 files changed, 644 insertions, 346 deletions
diff --git a/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp b/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp
index 58088bb..5256501 100644
--- a/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp
@@ -15,6 +15,7 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/Attr.h"
#include "clang/AST/CharUnits.h"
+#include "clang/AST/CXXInheritance.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
@@ -22,12 +23,47 @@
#include "clang/AST/ExprCXX.h"
#include "clang/Basic/ABI.h"
#include "clang/Basic/DiagnosticOptions.h"
-#include <map>
+#include "clang/Basic/TargetInfo.h"
+#include "llvm/ADT/StringMap.h"
using namespace clang;
namespace {
+/// \brief Retrieve the declaration context that should be used when mangling
+/// the given declaration.
+static const DeclContext *getEffectiveDeclContext(const Decl *D) {
+ // The ABI assumes that lambda closure types that occur within
+ // default arguments live in the context of the function. However, due to
+ // the way in which Clang parses and creates function declarations, this is
+ // not the case: the lambda closure type ends up living in the context
+ // where the function itself resides, because the function declaration itself
+ // had not yet been created. Fix the context here.
+ if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) {
+ if (RD->isLambda())
+ if (ParmVarDecl *ContextParam =
+ dyn_cast_or_null<ParmVarDecl>(RD->getLambdaContextDecl()))
+ return ContextParam->getDeclContext();
+ }
+
+ // Perform the same check for block literals.
+ 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 (const CapturedDecl *CD = dyn_cast<CapturedDecl>(DC))
+ return getEffectiveDeclContext(CD);
+
+ return DC;
+}
+
+static const DeclContext *getEffectiveParentContext(const DeclContext *DC) {
+ return getEffectiveDeclContext(cast<Decl>(DC));
+}
+
static const FunctionDecl *getStructor(const FunctionDecl *fn) {
if (const FunctionTemplateDecl *ftd = fn->getPrimaryTemplate())
return ftd->getTemplatedDecl();
@@ -47,9 +83,7 @@ class MicrosoftCXXNameMangler {
const NamedDecl *Structor;
unsigned StructorType;
- // FIXME: audit the performance of BackRefMap as it might do way too many
- // copying of strings.
- typedef std::map<std::string, unsigned> BackRefMap;
+ typedef llvm::StringMap<unsigned> BackRefMap;
BackRefMap NameBackReferences;
bool UseNameBackReferences;
@@ -58,30 +92,41 @@ class MicrosoftCXXNameMangler {
ASTContext &getASTContext() const { return Context.getASTContext(); }
+ // FIXME: If we add support for __ptr32/64 qualifiers, then we should push
+ // this check into mangleQualifiers().
+ const bool PointersAre64Bit;
+
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) { }
+ UseNameBackReferences(true),
+ PointersAre64Bit(C.getASTContext().getTargetInfo().getPointerWidth(0) ==
+ 64) { }
MicrosoftCXXNameMangler(MangleContext &C, raw_ostream &Out_,
const CXXDestructorDecl *D, CXXDtorType Type)
: Context(C), Out(Out_),
Structor(getStructor(D)), StructorType(Type),
- UseNameBackReferences(true) { }
+ UseNameBackReferences(true),
+ 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 mangleNumber(int64_t Number);
- void mangleNumber(const llvm::APSInt &Value);
void mangleType(QualType T, SourceRange Range,
QualifierMangleMode QMM = QMM_Mangle);
+ void mangleFunctionType(const FunctionType *T, const FunctionDecl *D = 0,
+ bool ForceInstMethod = false);
+ void manglePostfix(const DeclContext *DC, bool NoFunction = false);
private:
void disableBackReferences() { UseNameBackReferences = false; }
@@ -89,8 +134,7 @@ private:
mangleUnqualifiedName(ND, ND->getDeclName());
}
void mangleUnqualifiedName(const NamedDecl *ND, DeclarationName Name);
- void mangleSourceName(const IdentifierInfo *II);
- void manglePostfix(const DeclContext *DC, bool NoFunction=false);
+ void mangleSourceName(StringRef Name);
void mangleOperatorName(OverloadedOperatorKind OO, SourceLocation Loc);
void mangleCXXDtorType(CXXDtorType T);
void mangleQualifiers(Qualifiers Quals, bool IsMember);
@@ -114,98 +158,111 @@ private:
#undef NON_CANONICAL_TYPE
#undef TYPE
- void mangleType(const TagType*);
- void mangleFunctionType(const FunctionType *T, const FunctionDecl *D,
- bool IsStructor, bool IsInstMethod);
- void mangleDecayedArrayType(const ArrayType *T, bool IsGlobal);
- void mangleArrayType(const ArrayType *T, Qualifiers Quals);
+ void mangleType(const TagDecl *TD);
+ void mangleDecayedArrayType(const ArrayType *T);
+ void mangleArrayType(const ArrayType *T);
void mangleFunctionClass(const FunctionDecl *FD);
- void mangleCallingConvention(const FunctionType *T, bool IsInstMethod = false);
+ void mangleCallingConvention(const FunctionType *T);
void mangleIntegerLiteral(const llvm::APSInt &Number, bool IsBoolean);
void mangleExpression(const Expr *E);
void mangleThrowSpecification(const FunctionProtoType *T);
void mangleTemplateArgs(const TemplateDecl *TD,
const TemplateArgumentList &TemplateArgs);
-
+ void mangleTemplateArg(const TemplateDecl *TD, const TemplateArgument &TA);
};
-/// MicrosoftMangleContext - Overrides the default MangleContext for the
+/// MicrosoftMangleContextImpl - Overrides the default MangleContext for the
/// Microsoft Visual C++ ABI.
-class MicrosoftMangleContext : public MangleContext {
+class MicrosoftMangleContextImpl : public MicrosoftMangleContext {
public:
- MicrosoftMangleContext(ASTContext &Context,
- DiagnosticsEngine &Diags) : MangleContext(Context, Diags) { }
- virtual bool shouldMangleDeclName(const NamedDecl *D);
- virtual void mangleName(const NamedDecl *D, raw_ostream &Out);
+ 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 mangleCXXVTable(const CXXRecordDecl *RD,
- raw_ostream &);
- virtual void mangleCXXVTT(const CXXRecordDecl *RD,
- raw_ostream &);
- virtual void mangleCXXCtorVTable(const CXXRecordDecl *RD, int64_t Offset,
- const CXXRecordDecl *Type,
- 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 clang::VarDecl *,
- 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);
-static bool isInCLinkageSpecification(const Decl *D) {
- D = D->getCanonicalDecl();
- for (const DeclContext *DC = D->getDeclContext();
- !DC->isTranslationUnit(); DC = DC->getParent()) {
- if (const LinkageSpecDecl *Linkage = dyn_cast<LinkageSpecDecl>(DC))
- return Linkage->getLanguage() == LinkageSpecDecl::lang_c;
- }
+private:
+ void mangleInitFiniStub(const VarDecl *D, raw_ostream &Out, char CharCode);
+};
- return false;
}
-bool MicrosoftMangleContext::shouldMangleDeclName(const NamedDecl *D) {
- // In C, functions with no attributes never need to be mangled. Fastpath them.
- if (!getASTContext().getLangOpts().CPlusPlus && !D->hasAttrs())
- return false;
+bool MicrosoftMangleContextImpl::shouldMangleCXXName(const NamedDecl *D) {
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ LanguageLinkage L = FD->getLanguageLinkage();
+ // Overloadable functions need mangling.
+ if (FD->hasAttr<OverloadableAttr>())
+ return true;
+
+ // The ABI expects that we would never mangle "typical" user-defined entry
+ // points regardless of visibility or freestanding-ness.
+ //
+ // N.B. This is distinct from asking about "main". "main" has a lot of
+ // special rules associated with it in the standard while these
+ // user-defined entry points are outside of the purview of the standard.
+ // For example, there can be only one definition for "main" in a standards
+ // compliant program; however nothing forbids the existence of wmain and
+ // WinMain in the same translation unit.
+ if (FD->isMSVCRTEntryPoint())
+ return false;
- // Any decl can be declared with __asm("foo") on it, and this takes precedence
- // over all other naming in the .o file.
- if (D->hasAttr<AsmLabelAttr>())
- return true;
+ // C++ functions and those whose names are not a simple identifier need
+ // mangling.
+ if (!FD->getDeclName().isIdentifier() || L == CXXLanguageLinkage)
+ return true;
- // Clang's "overloadable" attribute extension to C/C++ implies name mangling
- // (always) as does passing a C++ member function and a function
- // whose name is not a simple identifier.
- const FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
- if (FD && (FD->hasAttr<OverloadableAttr>() || isa<CXXMethodDecl>(FD) ||
- !FD->getDeclName().isIdentifier()))
- return true;
+ // C functions are not mangled.
+ if (L == CLanguageLinkage)
+ return false;
+ }
// Otherwise, no mangling is done outside C++ mode.
if (!getASTContext().getLangOpts().CPlusPlus)
return false;
- // Variables at global scope with internal linkage are not mangled.
- if (!FD) {
- const DeclContext *DC = D->getDeclContext();
- if (DC->isTranslationUnit() && D->getLinkage() == InternalLinkage)
+ if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
+ // C variables are not mangled.
+ if (VD->isExternC())
return false;
- }
- // C functions and "main" are not mangled.
- if ((FD && FD->isMain()) || isInCLinkageSpecification(D))
- return false;
+ // Variables at global scope with non-internal linkage are not mangled.
+ const DeclContext *DC = getEffectiveDeclContext(D);
+ // Check for extern variable declared locally.
+ if (DC->isFunctionOrMethod() && D->hasLinkage())
+ while (!DC->isNamespace() && !DC->isTranslationUnit())
+ DC = getEffectiveParentContext(DC);
+
+ if (DC->isTranslationUnit() && D->getFormalLinkage() == InternalLinkage &&
+ !isa<VarTemplateSpecializationDecl>(D))
+ return false;
+ }
return true;
}
@@ -218,14 +275,6 @@ void MicrosoftCXXNameMangler::mangle(const NamedDecl *D,
// default, we emit an asm marker at the start so we get the name right.
// Callers can override this with a custom prefix.
- // Any decl can be declared with __asm("foo") on it, and this takes precedence
- // over all other naming in the .o file.
- if (const AsmLabelAttr *ALA = D->getAttr<AsmLabelAttr>()) {
- // If we have an asm name, then we use it as the mangling.
- Out << '\01' << ALA->getLabel();
- return;
- }
-
// <mangled-name> ::= ? <name> <type-encoding>
Out << Prefix;
mangleName(D);
@@ -247,27 +296,25 @@ void MicrosoftCXXNameMangler::mangle(const NamedDecl *D,
void MicrosoftCXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD) {
// <type-encoding> ::= <function-class> <function-type>
- // Don't mangle in the type if this isn't a decl we should typically mangle.
- if (!Context.shouldMangleDeclName(FD))
- return;
-
+ // Since MSVC operates on the type as written and not the canonical type, it
+ // actually matters which decl we have here. MSVC appears to choose the
+ // first, since it is most likely to be the declaration in a header file.
+ FD = FD->getFirstDecl();
+
// We should never ever see a FunctionNoProtoType at this point.
// We don't even know how to mangle their types anyway :).
const FunctionProtoType *FT = FD->getType()->castAs<FunctionProtoType>();
- bool InStructor = false, InInstMethod = false;
- const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD);
- if (MD) {
- if (MD->isInstance())
- InInstMethod = true;
- if (isa<CXXConstructorDecl>(MD) || isa<CXXDestructorDecl>(MD))
- InStructor = true;
- }
-
- // First, the function class.
- mangleFunctionClass(FD);
+ // extern "C" functions can hold entities that must be mangled.
+ // As it stands, these functions still need to get expressed in the full
+ // external name. They have their class and type omitted, replaced with '9'.
+ if (Context.shouldMangleDeclName(FD)) {
+ // First, the function class.
+ mangleFunctionClass(FD);
- mangleFunctionType(FT, FD, InStructor, InInstMethod);
+ mangleFunctionType(FT, FD);
+ } else
+ Out << '9';
}
void MicrosoftCXXNameMangler::mangleVariableEncoding(const VarDecl *VD) {
@@ -299,12 +346,21 @@ void MicrosoftCXXNameMangler::mangleVariableEncoding(const VarDecl *VD) {
// mangled as 'QAHA' instead of 'PAHB', for example.
TypeLoc TL = VD->getTypeSourceInfo()->getTypeLoc();
QualType Ty = TL.getType();
- if (Ty->isPointerType() || Ty->isReferenceType()) {
+ if (Ty->isPointerType() || Ty->isReferenceType() ||
+ Ty->isMemberPointerType()) {
mangleType(Ty, TL.getSourceRange(), QMM_Drop);
- mangleQualifiers(Ty->getPointeeType().getQualifiers(), false);
+ if (PointersAre64Bit)
+ Out << 'E';
+ if (const MemberPointerType *MPT = Ty->getAs<MemberPointerType>()) {
+ mangleQualifiers(MPT->getPointeeType().getQualifiers(), true);
+ // Member pointers are suffixed with a back reference to the member
+ // pointer's class name.
+ mangleName(MPT->getClass()->getAsCXXRecordDecl());
+ } else
+ mangleQualifiers(Ty->getPointeeType().getQualifiers(), false);
} else if (const ArrayType *AT = getASTContext().getAsArrayType(Ty)) {
// Global arrays are funny, too.
- mangleDecayedArrayType(AT, true);
+ mangleDecayedArrayType(AT);
if (AT->getElementType()->isArrayType())
Out << 'A';
else
@@ -335,39 +391,32 @@ void MicrosoftCXXNameMangler::mangleName(const NamedDecl *ND) {
}
void MicrosoftCXXNameMangler::mangleNumber(int64_t Number) {
- llvm::APSInt APSNumber(/*BitWidth=*/64, /*isUnsigned=*/false);
- APSNumber = Number;
- mangleNumber(APSNumber);
-}
-
-void MicrosoftCXXNameMangler::mangleNumber(const llvm::APSInt &Value) {
- // <number> ::= [?] <decimal digit> # 1 <= Number <= 10
- // ::= [?] <hex digit>+ @ # 0 or > 9; A = 0, B = 1, etc...
- // ::= [?] @ # 0 (alternate mangling, not emitted by VC)
- if (Value.isSigned() && Value.isNegative()) {
+ // <non-negative integer> ::= A@ # when Number == 0
+ // ::= <decimal digit> # when 1 <= Number <= 10
+ // ::= <hex digit>+ @ # when Number >= 10
+ //
+ // <number> ::= [?] <non-negative integer>
+
+ uint64_t Value = static_cast<uint64_t>(Number);
+ if (Number < 0) {
+ Value = -Value;
Out << '?';
- mangleNumber(llvm::APSInt(Value.abs()));
- return;
}
- llvm::APSInt Temp(Value);
- // There's a special shorter mangling for 0, but Microsoft
- // chose not to use it. Instead, 0 gets mangled as "A@". Oh well...
- if (Value.uge(1) && Value.ule(10)) {
- --Temp;
- Temp.print(Out, false);
- } else {
- // We have to build up the encoding in reverse order, so it will come
- // out right when we write it out.
- char Encoding[64];
- char *EndPtr = Encoding+sizeof(Encoding);
- char *CurPtr = EndPtr;
- llvm::APSInt NibbleMask(Value.getBitWidth(), Value.isUnsigned());
- NibbleMask = 0xf;
- do {
- *--CurPtr = 'A' + Temp.And(NibbleMask).getLimitedValue(0xf);
- Temp = Temp.lshr(4);
- } while (Temp != 0);
- Out.write(CurPtr, EndPtr-CurPtr);
+
+ if (Value == 0)
+ Out << "A@";
+ else if (Value >= 1 && Value <= 10)
+ Out << (Value - 1);
+ else {
+ // Numbers that are not encoded as decimal digits are represented as nibbles
+ // 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();
+ for (; Value != 0; Value >>= 4)
+ *I++ = 'A' + (Value & 0xf);
+ Out.write(I.base(), I - BufferRef.rbegin());
Out << '@';
}
}
@@ -403,7 +452,16 @@ MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
// Check if we have a template.
const TemplateArgumentList *TemplateArgs = 0;
if (const TemplateDecl *TD = isTemplate(ND, TemplateArgs)) {
- // We have a template.
+ // Function templates aren't considered for name back referencing. This
+ // makes sense since function templates aren't likely to occur multiple
+ // times in a symbol.
+ // FIXME: Test alias template mangling with MSVC 2013.
+ if (!isa<ClassTemplateDecl>(TD)) {
+ mangleTemplateInstantiationName(TD, *TemplateArgs);
+ 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
@@ -445,7 +503,7 @@ MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
switch (Name.getNameKind()) {
case DeclarationName::Identifier: {
if (const IdentifierInfo *II = Name.getAsIdentifierInfo()) {
- mangleSourceName(II);
+ mangleSourceName(II->getName());
break;
}
@@ -466,13 +524,22 @@ MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
"Typedef should not be in another decl context!");
assert(D->getDeclName().getAsIdentifierInfo() &&
"Typedef was not named!");
- mangleSourceName(D->getDeclName().getAsIdentifierInfo());
+ mangleSourceName(D->getDeclName().getAsIdentifierInfo()->getName());
break;
}
- // When VC encounters an anonymous type with no tag and no typedef,
- // it literally emits '<unnamed-tag>'.
- Out << "<unnamed-tag>";
+ if (TD->hasDeclaratorForAnonDecl()) {
+ // Anonymous types with no tag or typedef get the name of their
+ // declarator mangled in.
+ llvm::SmallString<64> Name("<unnamed-type-");
+ Name += TD->getDeclaratorForAnonDecl()->getName();
+ Name += ">";
+ mangleSourceName(Name.str());
+ } else {
+ // Anonymous types with no tag, no typedef, or declarator get
+ // '<unnamed-tag>'.
+ mangleSourceName("<unnamed-tag>");
+ }
break;
}
@@ -495,9 +562,9 @@ MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
// use the type we were given.
mangleCXXDtorType(static_cast<CXXDtorType>(StructorType));
else
- // Otherwise, use the complete destructor name. This is relevant if a
+ // Otherwise, use the base destructor name. This is relevant if a
// class with a destructor is declared within a destructor.
- mangleCXXDtorType(Dtor_Complete);
+ mangleCXXDtorType(Dtor_Base);
break;
case DeclarationName::CXXConversionFunctionName:
@@ -538,9 +605,20 @@ void MicrosoftCXXNameMangler::manglePostfix(const DeclContext *DC,
return;
if (const BlockDecl *BD = dyn_cast<BlockDecl>(DC)) {
- Context.mangleBlock(BD, Out);
+ 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 << '@';
return manglePostfix(DC->getParent(), NoFunction);
+ } else if (isa<CapturedDecl>(DC)) {
+ // Skip CapturedDecl context.
+ manglePostfix(DC->getParent(), NoFunction);
+ return;
}
if (NoFunction && (isa<FunctionDecl>(DC) || isa<ObjCMethodDecl>(DC)))
@@ -556,18 +634,19 @@ void MicrosoftCXXNameMangler::manglePostfix(const DeclContext *DC,
}
void MicrosoftCXXNameMangler::mangleCXXDtorType(CXXDtorType T) {
+ // Microsoft uses the names on the case labels for these dtor variants. Clang
+ // uses the Itanium terminology internally. Everything in this ABI delegates
+ // towards the base dtor.
switch (T) {
- case Dtor_Deleting:
- Out << "?_G";
- return;
- case Dtor_Base:
- // FIXME: We should be asked to mangle base dtors.
- // However, fixing this would require larger changes to the CodeGenModule.
- // Please put llvm_unreachable here when CGM is changed.
- // For now, just mangle a base dtor the same way as a complete dtor...
- case Dtor_Complete:
- Out << "?1";
- return;
+ // <operator-name> ::= ?1 # destructor
+ case Dtor_Base: Out << "?1"; return;
+ // <operator-name> ::= ?_D # vbase destructor
+ case Dtor_Complete: Out << "?_D"; return;
+ // <operator-name> ::= ?_G # scalar deleting destructor
+ case Dtor_Deleting: Out << "?_G"; return;
+ // <operator-name> ::= ?_E # vector deleting destructor
+ // FIXME: Add a vector deleting dtor type. It goes in the vtable, so we need
+ // it.
}
llvm_unreachable("Unsupported dtor type?");
}
@@ -704,17 +783,16 @@ void MicrosoftCXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO,
}
}
-void MicrosoftCXXNameMangler::mangleSourceName(const IdentifierInfo *II) {
+void MicrosoftCXXNameMangler::mangleSourceName(StringRef Name) {
// <source name> ::= <identifier> @
- std::string key = II->getNameStart();
BackRefMap::iterator Found;
if (UseNameBackReferences)
- Found = NameBackReferences.find(key);
+ Found = NameBackReferences.find(Name);
if (!UseNameBackReferences || Found == NameBackReferences.end()) {
- Out << II->getName() << '@';
+ Out << Name << '@';
if (UseNameBackReferences && NameBackReferences.size() < 10) {
size_t Size = NameBackReferences.size();
- NameBackReferences[key] = Size;
+ NameBackReferences[Name] = Size;
}
} else {
Out << Found->second;
@@ -756,7 +834,7 @@ void MicrosoftCXXNameMangler::mangleLocalName(const FunctionDecl *FD) {
// 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
- int NestLevel = getLocalNestingLevel(FD);
+ unsigned NestLevel = getLocalNestingLevel(FD);
Out << '?';
mangleNumber(NestLevel);
Out << '?';
@@ -800,7 +878,7 @@ MicrosoftCXXNameMangler::mangleIntegerLiteral(const llvm::APSInt &Value,
if (IsBoolean && Value.getBoolValue())
mangleNumber(1);
else
- mangleNumber(Value);
+ mangleNumber(Value.getSExtValue());
}
void
@@ -812,6 +890,33 @@ MicrosoftCXXNameMangler::mangleExpression(const Expr *E) {
return;
}
+ const CXXUuidofExpr *UE = 0;
+ if (const UnaryOperator *UO = dyn_cast<UnaryOperator>(E)) {
+ if (UO->getOpcode() == UO_AddrOf)
+ UE = dyn_cast<CXXUuidofExpr>(UO->getSubExpr());
+ } else
+ UE = dyn_cast<CXXUuidofExpr>(E);
+
+ if (UE) {
+ // This CXXUuidofExpr is mangled as-if it were actually a VarDecl from
+ // const __s_GUID _GUID_{lower case UUID with underscores}
+ StringRef Uuid = UE->getUuidAsStringRef(Context.getASTContext());
+ std::string Name = "_GUID_" + Uuid.lower();
+ std::replace(Name.begin(), Name.end(), '-', '_');
+
+ // If we had to peek through an address-of operator, treat this like we are
+ // dealing with a pointer type. Otherwise, treat it like a const reference.
+ //
+ // N.B. This matches up with the handling of TemplateArgument::Declaration
+ // in mangleTemplateArg
+ if (UE == E)
+ Out << "$E?";
+ else
+ Out << "$1?";
+ Out << Name << "@@3U__s_GUID@@B";
+ return;
+ }
+
// As bad as this diagnostic is, it's better than crashing.
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
@@ -827,44 +932,51 @@ MicrosoftCXXNameMangler::mangleTemplateArgs(const TemplateDecl *TD,
unsigned NumTemplateArgs = TemplateArgs.size();
for (unsigned i = 0; i < NumTemplateArgs; ++i) {
const TemplateArgument &TA = TemplateArgs[i];
- switch (TA.getKind()) {
- case TemplateArgument::Null:
- llvm_unreachable("Can't mangle null template arguments!");
- case TemplateArgument::Type: {
- QualType T = TA.getAsType();
- mangleType(T, SourceRange(), QMM_Escape);
- break;
- }
- case TemplateArgument::Declaration:
- mangle(cast<NamedDecl>(TA.getAsDecl()), "$1?");
- break;
- case TemplateArgument::Integral:
- mangleIntegerLiteral(TA.getAsIntegral(),
- TA.getIntegralType()->isBooleanType());
- break;
- case TemplateArgument::Expression:
- mangleExpression(TA.getAsExpr());
- break;
- case TemplateArgument::Template:
- case TemplateArgument::TemplateExpansion:
- case TemplateArgument::NullPtr:
- case TemplateArgument::Pack: {
- // Issue a diagnostic.
- DiagnosticsEngine &Diags = Context.getDiags();
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle template argument %0 of kind %select{ERROR|ERROR|"
- "pointer/reference|nullptr|integral|template|template pack expansion|"
- "ERROR|parameter pack}1 yet");
- Diags.Report(TD->getLocation(), DiagID)
- << i + 1
- << TA.getKind()
- << TD->getSourceRange();
- }
- }
+ mangleTemplateArg(TD, TA);
}
Out << '@';
}
+void MicrosoftCXXNameMangler::mangleTemplateArg(const TemplateDecl *TD,
+ const TemplateArgument &TA) {
+ 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 = cast<NamedDecl>(TA.getAsDecl());
+ mangle(ND, TA.isDeclForReferenceParam() ? "$E?" : "$1?");
+ break;
+ }
+ case TemplateArgument::Integral:
+ mangleIntegerLiteral(TA.getAsIntegral(),
+ TA.getIntegralType()->isBooleanType());
+ break;
+ case TemplateArgument::NullPtr:
+ 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);
+ break;
+ case TemplateArgument::Template:
+ mangleType(cast<TagDecl>(
+ TA.getAsTemplate().getAsTemplateDecl()->getTemplatedDecl()));
+ break;
+ }
+}
+
void MicrosoftCXXNameMangler::mangleQualifiers(Qualifiers Quals,
bool IsMember) {
// <cvr-qualifiers> ::= [E] [F] [I] <base-cvr-qualifiers>
@@ -921,6 +1033,7 @@ void MicrosoftCXXNameMangler::mangleQualifiers(Qualifiers Quals,
// ::= 5 # not really based
bool HasConst = Quals.hasConst(),
HasVolatile = Quals.hasVolatile();
+
if (!IsMember) {
if (HasConst && HasVolatile) {
Out << 'D';
@@ -966,20 +1079,32 @@ void MicrosoftCXXNameMangler::manglePointerQualifiers(Qualifiers Quals) {
void MicrosoftCXXNameMangler::mangleArgumentType(QualType T,
SourceRange Range) {
- void *TypePtr = getASTContext().getCanonicalType(T).getAsOpaquePtr();
+ // MSVC will backreference two canonically equivalent types that have slightly
+ // different manglings when mangled alone.
+
+ // Decayed types do not match up with non-decayed versions of the same type.
+ //
+ // e.g.
+ // void (*x)(void) will not form a backreference with void x(void)
+ void *TypePtr;
+ if (const DecayedType *DT = T->getAs<DecayedType>()) {
+ TypePtr = DT->getOriginalType().getCanonicalType().getAsOpaquePtr();
+ // If the original parameter was textually written as an array,
+ // instead treat the decayed parameter like it's const.
+ //
+ // e.g.
+ // int [] -> int * const
+ if (DT->getOriginalType()->isArrayType())
+ T = T.withConst();
+ } else
+ TypePtr = T.getCanonicalType().getAsOpaquePtr();
+
ArgBackRefMap::iterator Found = TypeBackReferences.find(TypePtr);
if (Found == TypeBackReferences.end()) {
size_t OutSizeBefore = Out.GetNumBytesInBuffer();
- if (const ArrayType *AT = getASTContext().getAsArrayType(T)) {
- mangleDecayedArrayType(AT, false);
- } else if (const FunctionType *FT = T->getAs<FunctionType>()) {
- Out << "P6";
- mangleFunctionType(FT, 0, false, false);
- } else {
- mangleType(T, Range, QMM_Drop);
- }
+ mangleType(T, Range, QMM_Drop);
// See if it's worth creating a back reference.
// Only types longer than 1 character are considered
@@ -996,16 +1121,18 @@ void MicrosoftCXXNameMangler::mangleArgumentType(QualType T,
void MicrosoftCXXNameMangler::mangleType(QualType T, SourceRange Range,
QualifierMangleMode QMM) {
- // Only operate on the canonical type!
- T = getASTContext().getCanonicalType(T);
+ // Don't use the canonical types. MSVC includes things like 'const' on
+ // pointer arguments to function pointers that canonicalization strips away.
+ T = T.getDesugaredType(getASTContext());
Qualifiers Quals = T.getLocalQualifiers();
-
- if (const ArrayType *AT = dyn_cast<ArrayType>(T)) {
+ if (const ArrayType *AT = getASTContext().getAsArrayType(T)) {
+ // If there were any Quals, getAsArrayType() pushed them onto the array
+ // element type.
if (QMM == QMM_Mangle)
Out << 'A';
else if (QMM == QMM_Escape || QMM == QMM_Result)
Out << "$$B";
- mangleArrayType(AT, Quals);
+ mangleArrayType(AT);
return;
}
@@ -1018,7 +1145,7 @@ void MicrosoftCXXNameMangler::mangleType(QualType T, SourceRange Range,
case QMM_Mangle:
if (const FunctionType *FT = dyn_cast<FunctionType>(T)) {
Out << '6';
- mangleFunctionType(FT, 0, false, false);
+ mangleFunctionType(FT);
return;
}
mangleQualifiers(Quals, false);
@@ -1151,7 +1278,7 @@ void MicrosoftCXXNameMangler::mangleType(const FunctionProtoType *T,
// structor type.
// FIXME: This may not be lambda-friendly.
Out << "$$A6";
- mangleFunctionType(T, NULL, false, false);
+ mangleFunctionType(T);
}
void MicrosoftCXXNameMangler::mangleType(const FunctionNoProtoType *T,
SourceRange) {
@@ -1160,18 +1287,31 @@ void MicrosoftCXXNameMangler::mangleType(const FunctionNoProtoType *T,
void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T,
const FunctionDecl *D,
- bool IsStructor,
- bool IsInstMethod) {
+ bool ForceInstMethod) {
// <function-type> ::= <this-cvr-qualifiers> <calling-convention>
// <return-type> <argument-list> <throw-spec>
const FunctionProtoType *Proto = cast<FunctionProtoType>(T);
+ SourceRange Range;
+ if (D) Range = D->getSourceRange();
+
+ bool IsStructor = false, IsInstMethod = ForceInstMethod;
+ if (const CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(D)) {
+ if (MD->isInstance())
+ IsInstMethod = true;
+ if (isa<CXXConstructorDecl>(MD) || isa<CXXDestructorDecl>(MD))
+ IsStructor = true;
+ }
+
// If this is a C++ instance method, mangle the CVR qualifiers for the
// this pointer.
- if (IsInstMethod)
+ if (IsInstMethod) {
+ if (PointersAre64Bit)
+ Out << 'E';
mangleQualifiers(Qualifiers::fromCVRMask(Proto->getTypeQuals()), false);
+ }
- mangleCallingConvention(T, IsInstMethod);
+ mangleCallingConvention(T);
// <return-type> ::= <type>
// ::= @ # structors (they have no declared return type)
@@ -1182,12 +1322,15 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T,
// However, the FunctionType generated has 0 arguments.
// FIXME: This is a temporary hack.
// Maybe should fix the FunctionType creation instead?
- Out << "PAXI@Z";
+ Out << (PointersAre64Bit ? "PEAXI@Z" : "PAXI@Z");
return;
}
Out << '@';
} else {
- mangleType(Proto->getResultType(), SourceRange(), QMM_Result);
+ QualType ResultType = Proto->getResultType();
+ if (ResultType->isVoidType())
+ ResultType = ResultType.getUnqualifiedType();
+ mangleType(ResultType, Range, QMM_Result);
}
// <argument-list> ::= X # void
@@ -1196,23 +1339,11 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T,
if (Proto->getNumArgs() == 0 && !Proto->isVariadic()) {
Out << 'X';
} else {
- if (D) {
- // If we got a decl, use the type-as-written to make sure arrays
- // get mangled right. Note that we can't rely on the TSI
- // existing if (for example) the parameter was synthesized.
- for (FunctionDecl::param_const_iterator Parm = D->param_begin(),
- ParmEnd = D->param_end(); Parm != ParmEnd; ++Parm) {
- TypeSourceInfo *TSI = (*Parm)->getTypeSourceInfo();
- QualType Type = TSI ? TSI->getType() : (*Parm)->getType();
- mangleArgumentType(Type, (*Parm)->getSourceRange());
- }
- } 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, SourceRange());
- }
+ // 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);
// <builtin-type> ::= Z # ellipsis
if (Proto->isVariadic())
Out << 'Z';
@@ -1224,35 +1355,34 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T,
}
void MicrosoftCXXNameMangler::mangleFunctionClass(const FunctionDecl *FD) {
- // <function-class> ::= A # private: near
- // ::= B # private: far
- // ::= C # private: static near
- // ::= D # private: static far
- // ::= E # private: virtual near
- // ::= F # private: virtual far
- // ::= G # private: thunk near
- // ::= H # private: thunk far
- // ::= I # protected: near
- // ::= J # protected: far
- // ::= K # protected: static near
- // ::= L # protected: static far
- // ::= M # protected: virtual near
- // ::= N # protected: virtual far
- // ::= O # protected: thunk near
- // ::= P # protected: thunk far
- // ::= Q # public: near
- // ::= R # public: far
- // ::= S # public: static near
- // ::= T # public: static far
- // ::= U # public: virtual near
- // ::= V # public: virtual far
- // ::= W # public: thunk near
- // ::= X # public: thunk far
- // ::= Y # global near
- // ::= Z # global far
+ // <function-class> ::= <member-function> E? # E designates a 64-bit 'this'
+ // # pointer. in 64-bit mode *all*
+ // # 'this' pointers are 64-bit.
+ // ::= <global-function>
+ // <member-function> ::= A # private: near
+ // ::= B # private: far
+ // ::= C # private: static near
+ // ::= D # private: static far
+ // ::= E # private: virtual near
+ // ::= F # private: virtual far
+ // ::= I # protected: near
+ // ::= J # protected: far
+ // ::= K # protected: static near
+ // ::= L # protected: static far
+ // ::= M # protected: virtual near
+ // ::= N # protected: virtual far
+ // ::= Q # public: near
+ // ::= R # public: far
+ // ::= S # public: static near
+ // ::= T # public: static far
+ // ::= U # public: virtual near
+ // ::= V # public: virtual far
+ // <global-function> ::= Y # global near
+ // ::= Z # global far
if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
switch (MD->getAccess()) {
- default:
+ case AS_none:
+ llvm_unreachable("Unsupported access specifier");
case AS_private:
if (MD->isStatic())
Out << 'C';
@@ -1280,8 +1410,7 @@ void MicrosoftCXXNameMangler::mangleFunctionClass(const FunctionDecl *FD) {
} else
Out << 'Y';
}
-void MicrosoftCXXNameMangler::mangleCallingConvention(const FunctionType *T,
- bool IsInstMethod) {
+void MicrosoftCXXNameMangler::mangleCallingConvention(const FunctionType *T) {
// <calling-convention> ::= A # __cdecl
// ::= B # __export __cdecl
// ::= C # __pascal
@@ -1298,22 +1427,11 @@ void MicrosoftCXXNameMangler::mangleCallingConvention(const FunctionType *T,
// that they could be in a DLL and somebody from another module could call
// them.)
CallingConv CC = T->getCallConv();
- if (CC == CC_Default) {
- if (IsInstMethod) {
- const FunctionProtoType *FPT =
- T->getCanonicalTypeUnqualified().castAs<FunctionProtoType>();
- bool isVariadic = FPT->isVariadic();
- CC = getASTContext().getDefaultCXXMethodCallConv(isVariadic);
- } else {
- CC = CC_C;
- }
- }
switch (CC) {
default:
llvm_unreachable("Unsupported CC for mangling");
case CC_X86_64Win64:
case CC_X86_64SysV:
- case CC_Default:
case CC_C: Out << 'A'; break;
case CC_X86Pascal: Out << 'C'; break;
case CC_X86ThisCall: Out << 'E'; break;
@@ -1349,13 +1467,13 @@ void MicrosoftCXXNameMangler::mangleType(const UnresolvedUsingType *T,
// <class-type> ::= V <name>
// <enum-type> ::= W <size> <name>
void MicrosoftCXXNameMangler::mangleType(const EnumType *T, SourceRange) {
- mangleType(cast<TagType>(T));
+ mangleType(cast<TagType>(T)->getDecl());
}
void MicrosoftCXXNameMangler::mangleType(const RecordType *T, SourceRange) {
- mangleType(cast<TagType>(T));
+ mangleType(cast<TagType>(T)->getDecl());
}
-void MicrosoftCXXNameMangler::mangleType(const TagType *T) {
- switch (T->getDecl()->getTagKind()) {
+void MicrosoftCXXNameMangler::mangleType(const TagDecl *TD) {
+ switch (TD->getTagKind()) {
case TTK_Union:
Out << 'T';
break;
@@ -1369,30 +1487,23 @@ void MicrosoftCXXNameMangler::mangleType(const TagType *T) {
case TTK_Enum:
Out << 'W';
Out << getASTContext().getTypeSizeInChars(
- cast<EnumDecl>(T->getDecl())->getIntegerType()).getQuantity();
+ cast<EnumDecl>(TD)->getIntegerType()).getQuantity();
break;
}
- mangleName(T->getDecl());
+ mangleName(TD);
}
// <type> ::= <array-type>
// <array-type> ::= <pointer-cvr-qualifiers> <cvr-qualifiers>
// [Y <dimension-count> <dimension>+]
-// <element-type> # as global
-// ::= Q <cvr-qualifiers> [Y <dimension-count> <dimension>+]
-// <element-type> # as param
+// <element-type> # as global, E is never required
// It's supposed to be the other way around, but for some strange reason, it
// isn't. Today this behavior is retained for the sole purpose of backwards
// compatibility.
-void MicrosoftCXXNameMangler::mangleDecayedArrayType(const ArrayType *T,
- bool IsGlobal) {
+void MicrosoftCXXNameMangler::mangleDecayedArrayType(const ArrayType *T) {
// This isn't a recursive mangling, so now we have to do it all in this
// one call.
- if (IsGlobal) {
- manglePointerQualifiers(T->getElementType().getQualifiers());
- } else {
- Out << 'Q';
- }
+ manglePointerQualifiers(T->getElementType().getQualifiers());
mangleType(T->getElementType(), SourceRange());
}
void MicrosoftCXXNameMangler::mangleType(const ConstantArrayType *T,
@@ -1411,8 +1522,7 @@ void MicrosoftCXXNameMangler::mangleType(const IncompleteArrayType *T,
SourceRange) {
llvm_unreachable("Should have been special cased");
}
-void MicrosoftCXXNameMangler::mangleArrayType(const ArrayType *T,
- Qualifiers Quals) {
+void MicrosoftCXXNameMangler::mangleArrayType(const ArrayType *T) {
QualType ElementTy(T, 0);
SmallVector<llvm::APInt, 3> Dimensions;
for (;;) {
@@ -1451,8 +1561,7 @@ void MicrosoftCXXNameMangler::mangleArrayType(const ArrayType *T,
mangleNumber(Dimensions.size());
for (unsigned Dim = 0; Dim < Dimensions.size(); ++Dim)
mangleNumber(Dimensions[Dim].getLimitedValue());
- mangleType(getASTContext().getQualifiedType(ElementTy.getTypePtr(), Quals),
- SourceRange(), QMM_Escape);
+ mangleType(ElementTy, SourceRange(), QMM_Escape);
}
// <type> ::= <pointer-to-member-type>
@@ -1464,8 +1573,10 @@ void MicrosoftCXXNameMangler::mangleType(const MemberPointerType *T,
if (const FunctionProtoType *FPT = PointeeType->getAs<FunctionProtoType>()) {
Out << '8';
mangleName(T->getClass()->castAs<RecordType>()->getDecl());
- mangleFunctionType(FPT, NULL, false, true);
+ mangleFunctionType(FPT, 0, true);
} else {
+ if (PointersAre64Bit && !T->getPointeeType()->isFunctionType())
+ Out << 'E';
mangleQualifiers(PointeeType.getQualifiers(), true);
mangleName(T->getClass()->castAs<RecordType>()->getDecl());
mangleType(PointeeType, Range, QMM_Drop);
@@ -1492,32 +1603,43 @@ void MicrosoftCXXNameMangler::mangleType(
}
// <type> ::= <pointer-type>
-// <pointer-type> ::= <pointer-cvr-qualifiers> <cvr-qualifiers> <type>
+// <pointer-type> ::= E? <pointer-cvr-qualifiers> <cvr-qualifiers> <type>
+// # 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';
mangleType(T->getPointeeType(), Range);
}
// <type> ::= <reference-type>
-// <reference-type> ::= A <cvr-qualifiers> <type>
+// <reference-type> ::= A E? <cvr-qualifiers> <type>
+// # 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';
mangleType(T->getPointeeType(), Range);
}
// <type> ::= <r-value-reference-type>
-// <r-value-reference-type> ::= $$Q <cvr-qualifiers> <type>
+// <r-value-reference-type> ::= $$Q E? <cvr-qualifiers> <type>
+// # 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';
mangleType(T->getPointeeType(), Range);
}
@@ -1600,16 +1722,12 @@ void MicrosoftCXXNameMangler::mangleType(const BlockPointerType *T,
Out << "_E";
QualType pointee = T->getPointeeType();
- mangleFunctionType(pointee->castAs<FunctionProtoType>(), NULL, false, false);
+ mangleFunctionType(pointee->castAs<FunctionProtoType>());
}
-void MicrosoftCXXNameMangler::mangleType(const InjectedClassNameType *T,
- SourceRange Range) {
- DiagnosticsEngine &Diags = Context.getDiags();
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle this injected class name type yet");
- Diags.Report(Range.getBegin(), DiagID)
- << Range;
+void MicrosoftCXXNameMangler::mangleType(const InjectedClassNameType *,
+ SourceRange) {
+ llvm_unreachable("Cannot mangle injected class name type.");
}
void MicrosoftCXXNameMangler::mangleType(const TemplateSpecializationType *T,
@@ -1702,8 +1820,8 @@ void MicrosoftCXXNameMangler::mangleType(const AtomicType *T,
<< Range;
}
-void MicrosoftMangleContext::mangleName(const NamedDecl *D,
- raw_ostream &Out) {
+void MicrosoftMangleContextImpl::mangleCXXName(const NamedDecl *D,
+ raw_ostream &Out) {
assert((isa<FunctionDecl>(D) || isa<VarDecl>(D)) &&
"Invalid mangleName() call, argument is not a variable or function!");
assert(!isa<CXXConstructorDecl>(D) && !isa<CXXDestructorDecl>(D) &&
@@ -1716,85 +1834,265 @@ void MicrosoftMangleContext::mangleName(const NamedDecl *D,
MicrosoftCXXNameMangler Mangler(*this, Out);
return Mangler.mangle(D);
}
-void MicrosoftMangleContext::mangleThunk(const CXXMethodDecl *MD,
- const ThunkInfo &Thunk,
- raw_ostream &) {
- unsigned DiagID = getDiags().getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle thunk for this method yet");
- getDiags().Report(MD->getLocation(), DiagID);
+
+// <this-adjustment> ::= <no-adjustment> | <static-adjustment> |
+// <virtual-adjustment>
+// <no-adjustment> ::= A # private near
+// ::= B # private far
+// ::= I # protected near
+// ::= J # protected far
+// ::= Q # public near
+// ::= R # public far
+// <static-adjustment> ::= G <static-offset> # private near
+// ::= H <static-offset> # private far
+// ::= O <static-offset> # protected near
+// ::= P <static-offset> # protected far
+// ::= W <static-offset> # public near
+// ::= X <static-offset> # public far
+// <virtual-adjustment> ::= $0 <virtual-shift> <static-offset> # private near
+// ::= $1 <virtual-shift> <static-offset> # private far
+// ::= $2 <virtual-shift> <static-offset> # protected near
+// ::= $3 <virtual-shift> <static-offset> # protected far
+// ::= $4 <virtual-shift> <static-offset> # public near
+// ::= $5 <virtual-shift> <static-offset> # public far
+// <virtual-shift> ::= <vtordisp-shift> | <vtordispex-shift>
+// <vtordisp-shift> ::= <offset-to-vtordisp>
+// <vtordispex-shift> ::= <offset-to-vbptr> <vbase-offset-offset>
+// <offset-to-vtordisp>
+static void mangleThunkThisAdjustment(const CXXMethodDecl *MD,
+ const ThisAdjustment &Adjustment,
+ MicrosoftCXXNameMangler &Mangler,
+ raw_ostream &Out) {
+ if (!Adjustment.Virtual.isEmpty()) {
+ Out << '$';
+ char AccessSpec;
+ switch (MD->getAccess()) {
+ 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 (MD->getAccess()) {
+ 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 (MD->getAccess()) {
+ 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 MicrosoftMangleContext::mangleCXXDtorThunk(const CXXDestructorDecl *DD,
- CXXDtorType Type,
- const ThisAdjustment &,
- raw_ostream &) {
- unsigned DiagID = getDiags().getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle thunk for this destructor yet");
- getDiags().Report(DD->getLocation(), DiagID);
+
+void MicrosoftMangleContextImpl::mangleVirtualMemPtrThunk(
+ const CXXMethodDecl *MD, uint64_t OffsetInVFTable, raw_ostream &Out) {
+ bool Is64Bit = getASTContext().getTargetInfo().getPointerWidth(0) == 64;
+
+ 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");
}
-void MicrosoftMangleContext::mangleCXXVTable(const CXXRecordDecl *RD,
+
+void MicrosoftMangleContextImpl::mangleThunk(const CXXMethodDecl *MD,
+ const ThunkInfo &Thunk,
raw_ostream &Out) {
- // <mangled-name> ::= ? <operator-name> <class-name> <storage-class>
- // <cvr-qualifiers> [<name>] @
- // <operator-name> ::= _7 # vftable
- // ::= _8 # vbtable
+ MicrosoftCXXNameMangler Mangler(*this, Out);
+ Out << "\01?";
+ Mangler.mangleName(MD);
+ mangleThunkThisAdjustment(MD, Thunk.This, Mangler, Out);
+ if (!Thunk.Return.isEmpty())
+ assert(Thunk.Method != 0 && "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) {
+ // FIXME: Actually, the dtor thunk should be emitted for vector deleting
+ // dtors rather than scalar deleting dtors. Just use the vector deleting dtor
+ // mangling manually until we support both deleting dtor types.
+ assert(Type == Dtor_Deleting);
+ MicrosoftCXXNameMangler Mangler(*this, Out, DD, Type);
+ Out << "\01??_E";
+ Mangler.mangleName(DD->getParent());
+ mangleThunkThisAdjustment(DD, Adjustment, Mangler, Out);
+ Mangler.mangleFunctionType(DD->getType()->castAs<FunctionProtoType>(), DD);
+}
+
+void MicrosoftMangleContextImpl::mangleCXXVFTable(
+ const CXXRecordDecl *Derived, ArrayRef<const CXXRecordDecl *> BasePath,
+ raw_ostream &Out) {
+ // <mangled-name> ::= ?_7 <class-name> <storage-class>
+ // <cvr-qualifiers> [<name>] @
// NOTE: <cvr-qualifiers> here is always 'B' (const). <storage-class>
- // is always '6' for vftables and '7' for vbtables. (The difference is
- // beyond me.)
- // TODO: vbtables.
+ // is always '6' for vftables.
MicrosoftCXXNameMangler Mangler(*this, Out);
Mangler.getStream() << "\01??_7";
- Mangler.mangleName(RD);
- Mangler.getStream() << "6B";
- // TODO: If the class has more than one vtable, mangle in the class it came
- // from.
+ 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);
+ }
Mangler.getStream() << '@';
}
-void MicrosoftMangleContext::mangleCXXVTT(const CXXRecordDecl *RD,
- raw_ostream &) {
- llvm_unreachable("The MS C++ ABI does not have virtual table tables!");
-}
-void MicrosoftMangleContext::mangleCXXCtorVTable(const CXXRecordDecl *RD,
- int64_t Offset,
- const CXXRecordDecl *Type,
- raw_ostream &) {
- llvm_unreachable("The MS C++ ABI does not have constructor vtables!");
+
+void MicrosoftMangleContextImpl::mangleCXXVBTable(
+ const CXXRecordDecl *Derived, ArrayRef<const CXXRecordDecl *> BasePath,
+ raw_ostream &Out) {
+ // <mangled-name> ::= ?_8 <class-name> <storage-class>
+ // <cvr-qualifiers> [<name>] @
+ // NOTE: <cvr-qualifiers> here is always 'B' (const). <storage-class>
+ // is always '7' for vbtables.
+ MicrosoftCXXNameMangler Mangler(*this, Out);
+ 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);
+ }
+ Mangler.getStream() << '@';
}
-void MicrosoftMangleContext::mangleCXXRTTI(QualType T,
- raw_ostream &) {
+
+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 MicrosoftMangleContext::mangleCXXRTTIName(QualType T,
- raw_ostream &) {
+
+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 MicrosoftMangleContext::mangleCXXCtor(const CXXConstructorDecl *D,
- CXXCtorType Type,
- raw_ostream & Out) {
+
+void MicrosoftMangleContextImpl::mangleTypeName(QualType T, raw_ostream &Out) {
+ // This is just a made up unique string for the purposes of tbaa. undname
+ // does *not* know how to demangle it.
+ MicrosoftCXXNameMangler Mangler(*this, Out);
+ Mangler.getStream() << '?';
+ Mangler.mangleType(T, SourceRange());
+}
+
+void MicrosoftMangleContextImpl::mangleCXXCtor(const CXXConstructorDecl *D,
+ CXXCtorType Type,
+ raw_ostream &Out) {
MicrosoftCXXNameMangler mangler(*this, Out);
mangler.mangle(D);
}
-void MicrosoftMangleContext::mangleCXXDtor(const CXXDestructorDecl *D,
- CXXDtorType Type,
- raw_ostream & Out) {
+
+void MicrosoftMangleContextImpl::mangleCXXDtor(const CXXDestructorDecl *D,
+ CXXDtorType Type,
+ raw_ostream &Out) {
MicrosoftCXXNameMangler mangler(*this, Out, D, Type);
mangler.mangle(D);
}
-void MicrosoftMangleContext::mangleReferenceTemporary(const clang::VarDecl *VD,
- raw_ostream &) {
+
+void MicrosoftMangleContextImpl::mangleReferenceTemporary(const VarDecl *VD,
+ raw_ostream &) {
unsigned DiagID = getDiags().getCustomDiagID(DiagnosticsEngine::Error,
"cannot mangle this reference temporary yet");
getDiags().Report(VD->getLocation(), DiagID);
}
-MangleContext *clang::createMicrosoftMangleContext(ASTContext &Context,
- DiagnosticsEngine &Diags) {
- return new MicrosoftMangleContext(Context, Diags);
+void MicrosoftMangleContextImpl::mangleStaticGuardVariable(const VarDecl *VD,
+ raw_ostream &Out) {
+ // <guard-name> ::= ?_B <postfix> @51
+ // ::= ?$S <guard-num> @ <postfix> @4IA
+
+ // The first mangling is what MSVC uses to guard static locals in inline
+ // functions. It uses a different mangling in external functions to support
+ // guarding more than 32 variables. MSVC rejects inline functions with more
+ // than 32 static locals. We don't fully implement the second mangling
+ // because those guards are not externally visible, and instead use LLVM's
+ // default renaming when creating a new guard variable.
+ MicrosoftCXXNameMangler Mangler(*this, Out);
+
+ 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");
+}
+
+void MicrosoftMangleContextImpl::mangleInitFiniStub(const VarDecl *D,
+ raw_ostream &Out,
+ char CharCode) {
+ MicrosoftCXXNameMangler Mangler(*this, Out);
+ Mangler.getStream() << "\01??__" << CharCode;
+ Mangler.mangleName(D);
+ // This is the function class mangling. These stubs are global, non-variadic,
+ // cdecl functions that return void and take no args.
+ Mangler.getStream() << "YAXXZ";
+}
+
+void MicrosoftMangleContextImpl::mangleDynamicInitializer(const VarDecl *D,
+ raw_ostream &Out) {
+ // <initializer-name> ::= ?__E <name> YAXXZ
+ mangleInitFiniStub(D, Out, 'E');
+}
+
+void
+MicrosoftMangleContextImpl::mangleDynamicAtExitDestructor(const VarDecl *D,
+ raw_ostream &Out) {
+ // <destructor-name> ::= ?__F <name> YAXXZ
+ mangleInitFiniStub(D, Out, 'F');
+}
+
+MicrosoftMangleContext *
+MicrosoftMangleContext::create(ASTContext &Context, DiagnosticsEngine &Diags) {
+ return new MicrosoftMangleContextImpl(Context, Diags);
}
OpenPOWER on IntegriCloud