Hi rsmith, doug.gregor, rjmccall,
The MSVC ABI appears to mangle the lexical scope into the names of
statics. Specifically, a counter is incremented whenever a scope is
entered where things can be declared in such a way that an ambiguity can
arise. For example, a class scope inside of a class scope doesn't do
anything interesting because the nested class cannot collide with
another nested class.
There are problems with this scheme:
- It is unreliable. The counter is only incremented when a previously
never encountered scope is entered. There are cases where this will
cause ambiguity amongst declarations that have the same name where one
was introduced in a deep scope while the other was introduced right
after in the previous lexical scope.
- It is wasteful. Statements like: {{{{{{{ static int foo = a; }}}}}}}
will make the mangling of "foo" larger than it need be because the
scope counter has been incremented many times.
Because of these problems, and practical implementation concerns. We
choose not to implement this scheme if the local static or local type
isn't visible. The mangling of these declarations will look very
similar but the numbering will make far more sense, this scheme is
lifted from the Itanium ABI implementation.
Depends on D2203.
http://llvm-reviews.chandlerc.com/D2204
Files:
include/clang/AST/ASTContext.h
include/clang/AST/Mangle.h
include/clang/AST/MangleNumberingContext.h
include/clang/Sema/Scope.h
lib/AST/ASTContext.cpp
lib/AST/ItaniumCXXABI.cpp
lib/AST/ItaniumMangle.cpp
lib/AST/MangleNumberingContext.cpp
lib/AST/MicrosoftCXXABI.cpp
lib/AST/MicrosoftMangle.cpp
lib/CodeGen/MicrosoftCXXABI.cpp
lib/Parse/ParseStmt.cpp
lib/Sema/Scope.cpp
lib/Sema/SemaDecl.cpp
lib/Sema/SemaTemplateInstantiateDecl.cpp
test/CodeGenCXX/mangle-ms-abi-examples.cpp
test/CodeGenCXX/mangle-template.cpp
test/CodeGenCXX/microsoft-abi-static-initializers.cpp
Index: include/clang/AST/ASTContext.h
===================================================================
--- include/clang/AST/ASTContext.h
+++ include/clang/AST/ASTContext.h
@@ -364,6 +364,7 @@
/// \brief Side-table of mangling numbers for declarations which rarely
/// need them (like static local vars).
llvm::DenseMap<const NamedDecl *, unsigned> MangleNumbers;
+ llvm::DenseMap<const VarDecl *, unsigned> StaticLocalNumbers;
/// \brief Mapping that stores parameterIndex values for ParmVarDecls when
/// that value exceeds the bitfield size of ParmVarDeclBits.ParameterIndex.
@@ -2139,6 +2140,9 @@
void setManglingNumber(const NamedDecl *ND, unsigned Number);
unsigned getManglingNumber(const NamedDecl *ND) const;
+ void setStaticLocalNumber(const VarDecl *VD, unsigned Number);
+ unsigned getStaticLocalNumber(const VarDecl *VD) const;
+
/// \brief Retrieve the context for computing mangling numbers in the given
/// DeclContext.
MangleNumberingContext &getManglingNumberContext(const DeclContext *DC);
Index: include/clang/AST/Mangle.h
===================================================================
--- include/clang/AST/Mangle.h
+++ include/clang/AST/Mangle.h
@@ -80,6 +80,7 @@
llvm::DenseMap<const BlockDecl*, unsigned> GlobalBlockIds;
llvm::DenseMap<const BlockDecl*, unsigned> LocalBlockIds;
+ llvm::DenseMap<const TagDecl*, uint64_t> AnonStructIds;
public:
ManglerKind getKind() const { return Kind; }
@@ -104,6 +105,13 @@
Result = BlockIds.insert(std::make_pair(BD, BlockIds.size()));
return Result.first->second;
}
+
+ uint64_t getAnonymousStructId(const TagDecl *TD) {
+ std::pair<llvm::DenseMap<const TagDecl *,
+ uint64_t>::iterator, bool> Result =
+ AnonStructIds.insert(std::make_pair(TD, AnonStructIds.size()));
+ return Result.first->second;
+ }
/// @name Mangler Entry Points
/// @{
Index: include/clang/AST/MangleNumberingContext.h
===================================================================
--- include/clang/AST/MangleNumberingContext.h
+++ include/clang/AST/MangleNumberingContext.h
@@ -16,6 +16,7 @@
#define LLVM_CLANG_MANGLENUMBERINGCONTEXT_H
#include "clang/Basic/LLVM.h"
+#include "clang/Sema/Scope.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
@@ -32,10 +33,11 @@
/// literals within a particular context.
class MangleNumberingContext
: public RefCountedBase<MangleNumberingContext> {
+ unsigned NumStaticLocals;
llvm::DenseMap<const Type *, unsigned> ManglingNumbers;
- llvm::DenseMap<IdentifierInfo*, unsigned> TagManglingNumbers;
public:
+ MangleNumberingContext() : NumStaticLocals(0) {}
virtual ~MangleNumberingContext() {}
/// \brief Retrieve the mangling number of a new lambda expression with the
@@ -46,13 +48,16 @@
/// context.
unsigned getManglingNumber(const BlockDecl *BD);
+ /// Static locals are numbered by source order.
+ unsigned getStaticLocalNumber(const VarDecl *VD);
+
/// \brief Retrieve the mangling number of a static local variable within
/// this context.
- virtual unsigned getManglingNumber(const VarDecl *VD) = 0;
+ virtual unsigned getManglingNumber(const VarDecl *VD, Scope *S) = 0;
/// \brief Retrieve the mangling number of a static local variable within
/// this context.
- unsigned getManglingNumber(const TagDecl *TD);
+ virtual unsigned getManglingNumber(const TagDecl *TD, Scope *S) = 0;
};
} // end namespace clang
Index: include/clang/Sema/Scope.h
===================================================================
--- include/clang/Sema/Scope.h
+++ include/clang/Sema/Scope.h
@@ -17,6 +17,7 @@
#include "clang/Basic/Diagnostic.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/raw_ostream.h"
namespace clang {
@@ -109,6 +110,10 @@
/// interrelates with other control flow statements.
unsigned short Flags;
+ /// \brief Declarations with static linkage are mangled with the number of
+ /// scopes seen as a component.
+ unsigned short MSLocalManglingNumber;
+
/// PrototypeDepth - This is the number of function prototype scopes
/// enclosing this scope, including this scope.
unsigned short PrototypeDepth;
@@ -120,6 +125,7 @@
/// FnParent - If this scope has a parent scope that is a function body, this
/// pointer is non-null and points to it. This is used for label processing.
Scope *FnParent;
+ Scope *MSLocalManglingParent;
/// BreakParent/ContinueParent - This is a direct link to the innermost
/// BreakScope/ContinueScope which contains the contents of this scope
@@ -181,6 +187,11 @@
const Scope *getFnParent() const { return FnParent; }
Scope *getFnParent() { return FnParent; }
+ const Scope *getMSLocalManglingParent() const {
+ return MSLocalManglingParent;
+ }
+ Scope *getMSLocalManglingParent() { return MSLocalManglingParent; }
+
/// getContinueParent - Return the closest scope that a continue statement
/// would be affected by.
Scope *getContinueParent() {
@@ -232,6 +243,22 @@
DeclsInScope.erase(D);
}
+ void incrementMSLocalManglingNumber() {
+ if (Scope *MSLMP = getMSLocalManglingParent())
+ MSLMP->MSLocalManglingNumber += 1;
+ }
+
+ void decrementMSLocalManglingNumber() {
+ if (Scope *MSLMP = getMSLocalManglingParent())
+ MSLMP->MSLocalManglingNumber -= 1;
+ }
+
+ unsigned short getMSLocalManglingNumber() const {
+ if (const Scope *MSLMP = getMSLocalManglingParent())
+ return MSLMP->MSLocalManglingNumber;
+ return 1;
+ }
+
/// isDeclScope - Return true if this is the scope that the specified decl is
/// declared in.
bool isDeclScope(Decl *D) {
@@ -342,6 +369,9 @@
/// Init - This is used by the parser to implement scope caching.
///
void Init(Scope *parent, unsigned flags);
+
+ void dumpImpl(raw_ostream &OS) const;
+ void dump() const;
};
} // end namespace clang
Index: lib/AST/ASTContext.cpp
===================================================================
--- lib/AST/ASTContext.cpp
+++ lib/AST/ASTContext.cpp
@@ -8071,6 +8071,17 @@
return I != MangleNumbers.end() ? I->second : 1;
}
+void ASTContext::setStaticLocalNumber(const VarDecl *VD, unsigned Number) {
+ if (Number > 1)
+ StaticLocalNumbers[VD] = Number;
+}
+
+unsigned ASTContext::getStaticLocalNumber(const VarDecl *VD) const {
+ llvm::DenseMap<const VarDecl *, unsigned>::const_iterator I =
+ StaticLocalNumbers.find(VD);
+ return I != StaticLocalNumbers.end() ? I->second : 1;
+}
+
MangleNumberingContext &
ASTContext::getManglingNumberContext(const DeclContext *DC) {
assert(LangOpts.CPlusPlus); // We don't need mangling numbers for plain C.
Index: lib/AST/ItaniumCXXABI.cpp
===================================================================
--- lib/AST/ItaniumCXXABI.cpp
+++ lib/AST/ItaniumCXXABI.cpp
@@ -33,12 +33,17 @@
/// literals within a particular context.
class ItaniumNumberingContext : public MangleNumberingContext {
llvm::DenseMap<IdentifierInfo*, unsigned> VarManglingNumbers;
+ llvm::DenseMap<IdentifierInfo*, unsigned> TagManglingNumbers;
public:
/// Variable decls are numbered by identifier.
- virtual unsigned getManglingNumber(const VarDecl *VD) {
+ virtual unsigned getManglingNumber(const VarDecl *VD, Scope *) {
return ++VarManglingNumbers[VD->getIdentifier()];
}
+
+ virtual unsigned getManglingNumber(const TagDecl *TD, Scope *) {
+ return ++TagManglingNumbers[TD->getIdentifier()];
+ }
};
class ItaniumCXXABI : public CXXABI {
Index: lib/AST/ItaniumMangle.cpp
===================================================================
--- lib/AST/ItaniumMangle.cpp
+++ lib/AST/ItaniumMangle.cpp
@@ -105,7 +105,6 @@
static const unsigned UnknownArity = ~0U;
class ItaniumMangleContextImpl : public ItaniumMangleContext {
- llvm::DenseMap<const TagDecl *, uint64_t> AnonStructIds;
typedef std::pair<const DeclContext*, IdentifierInfo*> DiscriminatorKeyTy;
llvm::DenseMap<DiscriminatorKeyTy, unsigned> Discriminator;
llvm::DenseMap<const NamedDecl*, unsigned> Uniquifier;
@@ -115,13 +114,6 @@
DiagnosticsEngine &Diags)
: ItaniumMangleContext(Context, Diags) {}
- uint64_t getAnonymousStructId(const TagDecl *TD) {
- std::pair<llvm::DenseMap<const TagDecl *,
- uint64_t>::iterator, bool> Result =
- AnonStructIds.insert(std::make_pair(TD, AnonStructIds.size()));
- return Result.first->second;
- }
-
/// @name Mangler Entry Points
/// @{
Index: lib/AST/MangleNumberingContext.cpp
===================================================================
--- lib/AST/MangleNumberingContext.cpp
+++ lib/AST/MangleNumberingContext.cpp
@@ -38,6 +38,8 @@
}
unsigned
-MangleNumberingContext::getManglingNumber(const TagDecl *TD) {
- return ++TagManglingNumbers[TD->getIdentifier()];
+MangleNumberingContext::getStaticLocalNumber(const VarDecl *VD) {
+ // FIXME: Compute a BlockPointerType? Not obvious how.
+ const Type *Ty = 0;
+ return ++ManglingNumbers[Ty];
}
Index: lib/AST/MicrosoftCXXABI.cpp
===================================================================
--- lib/AST/MicrosoftCXXABI.cpp
+++ lib/AST/MicrosoftCXXABI.cpp
@@ -28,15 +28,13 @@
/// \brief Numbers things which need to correspond across multiple TUs.
/// Typically these are things like static locals, lambdas, or blocks.
class MicrosoftNumberingContext : public MangleNumberingContext {
- unsigned NumStaticLocals;
-
public:
- MicrosoftNumberingContext() : NumStaticLocals(0) { }
+ virtual unsigned getManglingNumber(const VarDecl *VD, Scope *S) {
+ return S->getMSLocalManglingNumber();
+ }
- /// Static locals are numbered by source order.
- virtual unsigned getManglingNumber(const VarDecl *VD) {
- assert(VD->isStaticLocal());
- return ++NumStaticLocals;
+ virtual unsigned getManglingNumber(const TagDecl *TD, Scope *S) {
+ return S->getMSLocalManglingNumber();
}
};
Index: lib/AST/MicrosoftMangle.cpp
===================================================================
--- lib/AST/MicrosoftMangle.cpp
+++ lib/AST/MicrosoftMangle.cpp
@@ -71,10 +71,79 @@
return fn;
}
+/// 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;
+
+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,
+ int 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 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);
+ bool getNextDiscriminator(const NamedDecl *ND, uint64_t &disc) {
+ const DeclContext *DC = getEffectiveDeclContext(ND);
+ if (!DC->isFunctionOrMethod())
+ return false;
+
+ // Use the canonical number for externally visible decls.
+ if (ND->isExternallyVisible()) {
+ if (isa<TagDecl>(ND) || cast<VarDecl>(ND)->isStaticLocal()) {
+ disc = getASTContext().getManglingNumber(ND);
+ return true;
+ }
+ }
+
+ if (isa<TagDecl>(ND))
+ return false;
+ // return getAnonymousStructId(cast<TagDecl>(ND));
+
+ // Make up a reasonable number for internal decls.
+ unsigned &discriminator = Uniquifier[ND];
+ if (!discriminator)
+ discriminator = ++Discriminator[std::make_pair(DC, ND->getIdentifier())];
+ if (discriminator == 1)
+ return false;
+ //disc = discriminator - 2;
+ disc = discriminator;
+ return true;
+ }
+
+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
@@ -99,14 +168,14 @@
public:
enum QualifierMangleMode { QMM_Drop, QMM_Mangle, QMM_Escape, QMM_Result };
- MicrosoftCXXNameMangler(MangleContext &C, raw_ostream &Out_)
+ MicrosoftCXXNameMangler(MicrosoftMangleContextImpl &C, raw_ostream &Out_)
: Context(C), Out(Out_),
Structor(0), StructorType(-1),
UseNameBackReferences(true),
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),
@@ -127,7 +196,7 @@
QualifierMangleMode QMM = QMM_Mangle);
void mangleFunctionType(const FunctionType *T, const FunctionDecl *D = 0,
bool ForceInstMethod = false);
- void manglePostfix(const DeclContext *DC, bool NoFunction = false);
+ void mangleNestedName(const NamedDecl *ND);
private:
void disableBackReferences() { UseNameBackReferences = false; }
@@ -145,7 +214,6 @@
void mangleTemplateInstantiationName(const TemplateDecl *TD,
const TemplateArgumentList &TemplateArgs);
void mangleObjCMethodName(const ObjCMethodDecl *MD);
- void mangleLocalName(const FunctionDecl *FD);
void mangleArgumentType(QualType T, SourceRange Range);
@@ -173,44 +241,6 @@
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,
- int 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 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) {
@@ -372,18 +402,11 @@
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 << '@';
@@ -594,45 +617,44 @@
}
}
-void MicrosoftCXXNameMangler::manglePostfix(const DeclContext *DC,
- bool NoFunction) {
+void MicrosoftCXXNameMangler::mangleNestedName(const NamedDecl *ND) {
// <postfix> ::= <unqualified-name> [<postfix>]
// ::= <substitution> [<postfix>]
+ const DeclContext *DC = ND->getDeclContext();
- if (!DC) return;
+ while (!DC->isTranslationUnit()) {
+ if (isa<TagDecl>(ND) || isa<VarDecl>(ND)) {
+ uint64_t Disc;
+ if (Context.getNextDiscriminator(ND, Disc)) {
+ Out << '?';
+ mangleNumber(Disc);
+ Out << '?';
+ }
+ }
- while (isa<LinkageSpecDecl>(DC))
+ 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();
-
- if (DC->isTranslationUnit())
- 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);
-
- // 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)))
- 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);
}
}
@@ -807,44 +829,6 @@
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) {
@@ -2056,7 +2040,7 @@
bool Visible = VD->isExternallyVisible();
// <operator-name> ::= ?_B # local static guard
Mangler.getStream() << (Visible ? "\01??_B" : "\01?$S1@");
- Mangler.manglePostfix(VD->getDeclContext());
+ Mangler.mangleNestedName(VD);
Mangler.getStream() << (Visible ? "@51" : "@4IA");
}
Index: lib/CodeGen/MicrosoftCXXABI.cpp
===================================================================
--- lib/CodeGen/MicrosoftCXXABI.cpp
+++ lib/CodeGen/MicrosoftCXXABI.cpp
@@ -1166,7 +1166,7 @@
if (D.isExternallyVisible()) {
// Externally visible variables have to be numbered in Sema to properly
// handle unreachable VarDecls.
- BitIndex = getContext().getManglingNumber(&D);
+ BitIndex = getContext().getStaticLocalNumber(&D);
assert(BitIndex > 0);
BitIndex--;
} else {
Index: lib/Parse/ParseStmt.cpp
===================================================================
--- lib/Parse/ParseStmt.cpp
+++ lib/Parse/ParseStmt.cpp
@@ -1077,8 +1077,10 @@
// would have to notify ParseStatement not to create a new scope. It's
// simpler to let it create a new scope.
//
- ParseScope InnerScope(this, Scope::DeclScope,
- C99orCXX && Tok.isNot(tok::l_brace));
+ bool SubStmtIsScope = C99orCXX && Tok.isNot(tok::l_brace);
+ ParseScope InnerScope(this, Scope::DeclScope, SubStmtIsScope);
+ if (!SubStmtIsScope)
+ getCurScope()->incrementMSLocalManglingNumber();
// Read the 'then' stmt.
SourceLocation ThenStmtLoc = Tok.getLocation();
@@ -1110,8 +1112,10 @@
// The substatement in a selection-statement (each substatement, in the else
// form of the if statement) implicitly defines a local scope.
//
- ParseScope InnerScope(this, Scope::DeclScope,
- C99orCXX && Tok.isNot(tok::l_brace));
+ bool SubStmtIsScope = C99orCXX && Tok.isNot(tok::l_brace);
+ ParseScope InnerScope(this, Scope::DeclScope, SubStmtIsScope);
+ if (!SubStmtIsScope)
+ getCurScope()->incrementMSLocalManglingNumber();
ElseStmt = ParseStatement();
@@ -1213,8 +1217,10 @@
// See comments in ParseIfStatement for why we create a scope for the
// condition and a new scope for substatement in C++.
//
- ParseScope InnerScope(this, Scope::DeclScope,
- C99orCXX && Tok.isNot(tok::l_brace));
+ bool SubStmtIsScope = C99orCXX && Tok.isNot(tok::l_brace);
+ ParseScope InnerScope(this, Scope::DeclScope, SubStmtIsScope);
+ if (!SubStmtIsScope)
+ getCurScope()->incrementMSLocalManglingNumber();
// Read the body statement.
StmtResult Body(ParseStatement(TrailingElseLoc));
@@ -1291,8 +1297,10 @@
// See comments in ParseIfStatement for why we create a scope for the
// condition and a new scope for substatement in C++.
//
- ParseScope InnerScope(this, Scope::DeclScope,
- C99orCXX && Tok.isNot(tok::l_brace));
+ bool SubStmtIsScope = C99orCXX && Tok.isNot(tok::l_brace);
+ ParseScope InnerScope(this, Scope::DeclScope, SubStmtIsScope);
+ if (!SubStmtIsScope)
+ getCurScope()->incrementMSLocalManglingNumber();
// Read the body statement.
StmtResult Body(ParseStatement(TrailingElseLoc));
@@ -1325,17 +1333,20 @@
ParseScope DoScope(this, ScopeFlags);
+ bool C99orCXX = getLangOpts().C99 || getLangOpts().CPlusPlus;
+
// C99 6.8.5p5 - In C99, the body of the if statement is a scope, even if
// there is no compound stmt. C90 does not have this clause. We only do this
// if the body isn't a compound statement to avoid push/pop in common cases.
//
// C++ 6.5p2:
// The substatement in an iteration-statement implicitly defines a local scope
// which is entered and exited each time through the loop.
//
- ParseScope InnerScope(this, Scope::DeclScope,
- (getLangOpts().C99 || getLangOpts().CPlusPlus) &&
- Tok.isNot(tok::l_brace));
+ bool SubStmtIsScope = C99orCXX && Tok.isNot(tok::l_brace);
+ ParseScope InnerScope(this, Scope::DeclScope, SubStmtIsScope);
+ if (!SubStmtIsScope)
+ getCurScope()->incrementMSLocalManglingNumber();
// Read the body statement.
StmtResult Body(ParseStatement());
@@ -1622,8 +1633,14 @@
// See comments in ParseIfStatement for why we create a scope for
// for-init-statement/condition and a new scope for substatement in C++.
//
- ParseScope InnerScope(this, Scope::DeclScope,
- C99orCXXorObjC && Tok.isNot(tok::l_brace));
+ bool SubStmtIsScope = C99orCXXorObjC && Tok.isNot(tok::l_brace);
+ ParseScope InnerScope(this, Scope::DeclScope, SubStmtIsScope);
+ // The body of the for loop has the same local mangling number as the
+ // for-init-statement.
+ // It will only be incremented if the body contains other things that would
+ // normally increment the mangling number (like a compound statement).
+ if (SubStmtIsScope)
+ getCurScope()->decrementMSLocalManglingNumber();
// Read the body statement.
StmtResult Body(ParseStatement(TrailingElseLoc));
Index: lib/Sema/Scope.cpp
===================================================================
--- lib/Sema/Scope.cpp
+++ lib/Sema/Scope.cpp
@@ -13,6 +13,7 @@
//===----------------------------------------------------------------------===//
#include "clang/Sema/Scope.h"
+#include "llvm/Support/MathExtras.h"
using namespace clang;
@@ -31,28 +32,47 @@
if (parent) {
Depth = parent->Depth + 1;
+ FnParent = parent->FnParent;
PrototypeDepth = parent->PrototypeDepth;
PrototypeIndex = 0;
FnParent = parent->FnParent;
BlockParent = parent->BlockParent;
TemplateParamParent = parent->TemplateParamParent;
+ MSLocalManglingParent = parent->MSLocalManglingParent;
} else {
Depth = 0;
PrototypeDepth = 0;
PrototypeIndex = 0;
- FnParent = BlockParent = 0;
+ MSLocalManglingParent = FnParent = BlockParent = 0;
TemplateParamParent = 0;
+ MSLocalManglingNumber = 1;
}
// If this scope is a function or contains breaks/continues, remember it.
if (flags & FnScope) FnParent = this;
+ // The MS mangler uses the number of scopes that can hold declarations as
+ // part of an external name.
+ if (Flags & (ClassScope | FnScope)) {
+ MSLocalManglingNumber = getMSLocalManglingNumber();
+ MSLocalManglingParent = this;
+ }
if (flags & BreakScope) BreakParent = this;
if (flags & ContinueScope) ContinueParent = this;
if (flags & BlockScope) BlockParent = this;
if (flags & TemplateParamScope) TemplateParamParent = this;
// If this is a prototype scope, record that.
if (flags & FunctionPrototypeScope) PrototypeDepth++;
+ if (flags & DeclScope) {
+ if (flags & FunctionPrototypeScope)
+ ; // Prototype scopes are uninteresting.
+ else if ((flags & ClassScope) && getParent() && getParent()->isClassScope())
+ ; // Nested class scopes aren't ambiguous.
+ else if ((flags & ClassScope) && getParent()->getFlags() == DeclScope)
+ ; // Classes inside of namespaces aren't ambiguous.
+ else
+ incrementMSLocalManglingNumber();
+ }
DeclsInScope.clear();
UsingDirectives.clear();
@@ -69,3 +89,111 @@
}
return false;
}
+
+void Scope::dump() const { dumpImpl(llvm::errs()); }
+
+void Scope::dumpImpl(raw_ostream &OS) const {
+ unsigned Flags = getFlags();
+
+ if (Flags)
+ OS << "Flags: ";
+
+ bool IsFirstIteration = true;
+ bool IsOnlyIteration = llvm::isPowerOf2_32(Flags);
+ while (Flags) {
+ if (!IsFirstIteration && !IsOnlyIteration)
+ OS << " | ";
+ IsFirstIteration = false;
+
+ if (Flags & FnScope) {
+ OS << "FnScope";
+ Flags &= ~FnScope;
+ continue;
+ }
+ if (Flags & BreakScope) {
+ OS << "BreakScope";
+ Flags &= ~BreakScope;
+ continue;
+ }
+ if (Flags & ContinueScope) {
+ OS << "ContinueScope";
+ Flags &= ~ContinueScope;
+ continue;
+ }
+ if (Flags & DeclScope) {
+ OS << "DeclScope";
+ Flags &= ~DeclScope;
+ continue;
+ }
+ if (Flags & ControlScope) {
+ OS << "ControlScope";
+ Flags &= ~ControlScope;
+ continue;
+ }
+ if (Flags & ClassScope) {
+ OS << "ClassScope";
+ Flags &= ~ClassScope;
+ continue;
+ }
+ if (Flags & BlockScope) {
+ OS << "BlockScope";
+ Flags &= ~BlockScope;
+ continue;
+ }
+ if (Flags & TemplateParamScope) {
+ OS << "TemplateParamScope";
+ Flags &= ~TemplateParamScope;
+ continue;
+ }
+ if (Flags & FunctionPrototypeScope) {
+ OS << "FunctionPrototypeScope";
+ Flags &= ~FunctionPrototypeScope;
+ continue;
+ }
+ if (Flags & FunctionDeclarationScope) {
+ OS << "FunctionDeclarationScope";
+ Flags &= ~FunctionDeclarationScope;
+ continue;
+ }
+ if (Flags & AtCatchScope) {
+ OS << "AtCatchScope";
+ Flags &= ~AtCatchScope;
+ continue;
+ }
+ if (Flags & ObjCMethodScope) {
+ OS << "ObjCMethodScope";
+ Flags &= ~ObjCMethodScope;
+ continue;
+ }
+ if (Flags & SwitchScope) {
+ OS << "SwitchScope";
+ Flags &= ~SwitchScope;
+ continue;
+ }
+ if (Flags & TryScope) {
+ OS << "TryScope";
+ Flags &= ~TryScope;
+ continue;
+ }
+ if (Flags & FnTryCatchScope) {
+ OS << "FnTryCatchScope";
+ Flags &= ~FnTryCatchScope;
+ continue;
+ }
+ if (Flags & OpenMPDirectiveScope) {
+ OS << "OpenMPDirectiveScope";
+ Flags &= ~OpenMPDirectiveScope;
+ continue;
+ }
+ }
+ if (getFlags())
+ OS << '\n';
+
+ if (const Scope *Parent = getParent())
+ OS << "Parent: (clang::Scope*)" << Parent << '\n';
+
+ OS << "Depth: " << Depth << '\n';
+ OS << "MSLocalManglingNumber: " << getMSLocalManglingNumber() << '\n';
+ if (const DeclContext *DC = getEntity())
+ OS << "Entity : (clang::DeclContext*)" << DC << '\n';
+}
Index: lib/Sema/SemaDecl.cpp
===================================================================
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -3156,7 +3156,7 @@
return ParsedFreeStandingDeclSpec(S, AS, DS, MultiTemplateParamsArg());
}
-static void HandleTagNumbering(Sema &S, const TagDecl *Tag) {
+static void HandleTagNumbering(Sema &S, const TagDecl *Tag, Scope *TagScope) {
if (!S.Context.getLangOpts().CPlusPlus)
return;
@@ -3167,16 +3167,16 @@
return;
MangleNumberingContext &MCtx =
S.Context.getManglingNumberContext(Tag->getParent());
- S.Context.setManglingNumber(Tag, MCtx.getManglingNumber(Tag));
+ S.Context.setManglingNumber(Tag, MCtx.getManglingNumber(Tag, TagScope));
return;
}
// If this tag isn't a direct child of a class, number it if it is local.
Decl *ManglingContextDecl;
if (MangleNumberingContext *MCtx =
S.getCurrentMangleNumberContext(Tag->getDeclContext(),
ManglingContextDecl)) {
- S.Context.setManglingNumber(Tag, MCtx->getManglingNumber(Tag));
+ S.Context.setManglingNumber(Tag, MCtx->getManglingNumber(Tag, TagScope));
}
}
@@ -3209,7 +3209,7 @@
}
if (Tag) {
- HandleTagNumbering(*this, Tag);
+ HandleTagNumbering(*this, Tag, S);
Tag->setFreeStanding();
if (Tag->isInvalidDecl())
return Tag;
@@ -5461,7 +5461,8 @@
if (MangleNumberingContext *MCtx =
getCurrentMangleNumberContext(NewVD->getDeclContext(),
ManglingContextDecl)) {
- Context.setManglingNumber(NewVD, MCtx->getManglingNumber(NewVD));
+ Context.setManglingNumber(NewVD, MCtx->getManglingNumber(NewVD, S));
+ Context.setStaticLocalNumber(NewVD, MCtx->getStaticLocalNumber(NewVD));
}
}
@@ -8974,7 +8975,7 @@
if (DeclSpec::isDeclRep(DS.getTypeSpecType())) {
if (TagDecl *Tag = dyn_cast_or_null<TagDecl>(DS.getRepAsDecl())) {
- HandleTagNumbering(*this, Tag);
+ HandleTagNumbering(*this, Tag, S);
if (!Tag->hasNameForLinkage() && !Tag->hasDeclaratorForAnonDecl())
Tag->setDeclaratorForAnonDecl(FirstDeclaratorInGroup);
}
Index: lib/Sema/SemaTemplateInstantiateDecl.cpp
===================================================================
--- lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -639,6 +639,8 @@
Enum->setInstantiationOfMemberEnum(D, TSK_ImplicitInstantiation);
Enum->setAccess(D->getAccess());
+ // Forward the mangling number from the template to the instantiated decl.
+ SemaRef.Context.setManglingNumber(Enum, SemaRef.Context.getManglingNumber(D));
if (SubstQualifier(D, Enum)) return 0;
Owner->addDecl(Enum);
@@ -1126,6 +1128,10 @@
SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Record);
}
+ // Forward the mangling number from the template to the instantiated decl.
+ SemaRef.Context.setManglingNumber(Record,
+ SemaRef.Context.getManglingNumber(D));
+
Owner->addDecl(Record);
return Record;
}
@@ -1235,6 +1241,10 @@
if (D->isLocalExternDecl())
Function->setLocalExternDecl();
+ // Forward the mangling number from the template to the instantiated decl.
+ SemaRef.Context.setManglingNumber(Function,
+ SemaRef.Context.getManglingNumber(D));
+
DeclContext *LexicalDC = Owner;
if (!isFriend && D->isOutOfLine() && !D->isLocalExternDecl()) {
assert(D->getDeclContext()->isFileContext());
@@ -1693,6 +1703,10 @@
if (D->isDeletedAsWritten())
SemaRef.SetDeclDeleted(Method, Method->getLocation());
+ // Forward the mangling number from the template to the instantiated decl.
+ SemaRef.Context.setManglingNumber(Method,
+ SemaRef.Context.getManglingNumber(D));
+
// If there's a function template, let our caller handle it.
if (FunctionTemplate) {
// do nothing
@@ -3435,6 +3449,10 @@
NewVar->setInstantiationOfStaticDataMember(OldVar,
TSK_ImplicitInstantiation);
+ // Forward the mangling number from the template to the instantiated decl.
+ Context.setManglingNumber(NewVar, Context.getManglingNumber(OldVar));
+ Context.setStaticLocalNumber(NewVar, Context.getStaticLocalNumber(OldVar));
+
// Delay instantiation of the initializer for variable templates until a
// definition of the variable is needed.
if (!isa<VarTemplateSpecializationDecl>(NewVar) && !InstantiatingVarTemplate)
Index: test/CodeGenCXX/mangle-ms-abi-examples.cpp
===================================================================
--- test/CodeGenCXX/mangle-ms-abi-examples.cpp
+++ test/CodeGenCXX/mangle-ms-abi-examples.cpp
@@ -11,7 +11,7 @@
B();
}
};
-void foo () {
+inline void foo () {
struct C {
struct D { virtual ~D() {} };
void bar () {
@@ -25,4 +25,6 @@
C::D();
C().bar();
}
-
+void call () {
+ foo();
+}
Index: test/CodeGenCXX/mangle-template.cpp
===================================================================
--- test/CodeGenCXX/mangle-template.cpp
+++ test/CodeGenCXX/mangle-template.cpp
@@ -182,3 +182,24 @@
template short returnShort<-32768>();
// CHECK: @_ZN6test1311returnShortILsn32768EEEsv()
}
+namespace test14 {
+ template <typename> inline int inl(bool b) {
+ if (b) {
+ static struct {
+ int field;
+ } a;
+ // CHECK: @_ZZN6test143inlIvEEibE1a
+
+ return a.field;
+ } else {
+ static struct {
+ int field;
+ } a;
+ // CHECK: @_ZZN6test143inlIvEEibE1a_0
+
+ return a.field;
+ }
+ }
+
+ int call(bool b) { return inl<void>(b); }
+}
Index: test/CodeGenCXX/microsoft-abi-static-initializers.cpp
===================================================================
--- test/CodeGenCXX/microsoft-abi-static-initializers.cpp
+++ test/CodeGenCXX/microsoft-abi-static-initializers.cpp
@@ -24,8 +24,8 @@
static S TheS;
}
// CHECK-LABEL: define void @"\01?StaticLocal@@YAXXZ"()
-// CHECK: load i32* @"\01?$S1@?1??StaticLocal@@YAXXZ@4IA"
-// CHECK: store i32 {{.*}}, i32* @"\01?$S1@?1??StaticLocal@@YAXXZ@4IA"
+// CHECK: load i32* @"\01?$S1@?StaticLocal@@YAXXZ@4IA"
+// CHECK: store i32 {{.*}}, i32* @"\01?$S1@?StaticLocal@@YAXXZ@4IA"
// CHECK: ret
void MultipleStatics() {
@@ -66,15 +66,15 @@
static S S35;
}
// CHECK-LABEL: define void @"\01?MultipleStatics@@YAXXZ"()
-// CHECK: load i32* @"\01?$S1@?1??MultipleStatics@@YAXXZ@4IA"
+// CHECK: load i32* @"\01?$S1@?MultipleStatics@@YAXXZ@4IA"
// CHECK: and i32 {{.*}}, 1
// CHECK: and i32 {{.*}}, 2
// CHECK: and i32 {{.*}}, 4
// CHECK: and i32 {{.*}}, 8
// CHECK: and i32 {{.*}}, 16
// ...
// CHECK: and i32 {{.*}}, -2147483648
-// CHECK: load i32* @"\01?$S1@?1??MultipleStatics@@YAXXZ@4IA1"
+// CHECK: load i32* @"\01?$S1@?MultipleStatics@@YAXXZ@4IA1"
// CHECK: and i32 {{.*}}, 1
// CHECK: and i32 {{.*}}, 2
// CHECK: and i32 {{.*}}, 4
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits