Index: include/clang/AST/ASTContext.h =================================================================== --- include/clang/AST/ASTContext.h +++ include/clang/AST/ASTContext.h @@ -365,6 +365,7 @@ /// \brief Side-table of mangling numbers for declarations which rarely /// need them (like static local vars). llvm::DenseMap MangleNumbers; + llvm::DenseMap StaticLocalNumbers; /// \brief Mapping that stores parameterIndex values for ParmVarDecls when /// that value exceeds the bitfield size of ParmVarDeclBits.ParameterIndex. @@ -2171,6 +2172,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 GlobalBlockIds; llvm::DenseMap LocalBlockIds; + llvm::DenseMap 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::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" @@ -33,9 +34,9 @@ class MangleNumberingContext : public RefCountedBase { llvm::DenseMap ManglingNumbers; - llvm::DenseMap TagManglingNumbers; public: + MangleNumberingContext() {} virtual ~MangleNumberingContext() {} /// \brief Retrieve the mangling number of a new lambda expression with the @@ -46,13 +47,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/Parse/Parser.h =================================================================== --- include/clang/Parse/Parser.h +++ include/clang/Parse/Parser.h @@ -722,6 +722,11 @@ public: //===--------------------------------------------------------------------===// // Scope manipulation + enum ManageScopeFlags { + NoScope, + EnteredScope, + BeforeCompoundStmt + }; /// ParseScope - Introduces a new scope for parsing. The kind of /// scope is determined by ScopeFlags. Objects of this type should @@ -739,12 +744,17 @@ // parser Self where the new Scope is created with the flags // ScopeFlags, but only when ManageScope is true (the default). If // ManageScope is false, this object does nothing. - ParseScope(Parser *Self, unsigned ScopeFlags, bool ManageScope = true) + ParseScope(Parser *Self, unsigned ScopeFlags, bool EnteredScope = true, + bool BeforeCompoundStmt = false) : Self(Self) { - if (ManageScope) + if (EnteredScope && !BeforeCompoundStmt) Self->EnterScope(ScopeFlags); - else + else { + if (BeforeCompoundStmt) + Self->getCurScope()->incrementMSLocalManglingNumber(); + this->Self = 0; + } } // Exit - Exit the scope associated with this object now, rather Index: include/clang/Sema/Scope.h =================================================================== --- include/clang/Sema/Scope.h +++ include/clang/Sema/Scope.h @@ -18,6 +18,12 @@ #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" +namespace llvm { + +class raw_ostream; + +} + namespace clang { class Decl; @@ -109,6 +115,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 +130,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 +192,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 +248,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) { @@ -359,6 +391,9 @@ /// variables accordingly. /// void AddFlags(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 @@ -8052,6 +8052,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_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 VarManglingNumbers; + llvm::DenseMap 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 AnonStructIds; typedef std::pair DiscriminatorKeyTy; llvm::DenseMap Discriminator; llvm::DenseMap Uniquifier; @@ -115,13 +114,6 @@ DiagnosticsEngine &Diags) : ItaniumMangleContext(Context, Diags) {} - uint64_t getAnonymousStructId(const TagDecl *TD) { - std::pair::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 @@ -72,10 +72,76 @@ return fn; } +/// MicrosoftMangleContextImpl - Overrides the default MangleContext for the +/// Microsoft Visual C++ ABI. +class MicrosoftMangleContextImpl : public MicrosoftMangleContext { + typedef std::pair DiscriminatorKeyTy; + llvm::DenseMap Discriminator; + llvm::DenseMap 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, + 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 BasePath, + raw_ostream &Out); + virtual void mangleCXXVBTable(const CXXRecordDecl *Derived, + ArrayRef BasePath, + raw_ostream &Out); + virtual void mangleCXXRTTI(QualType T, raw_ostream &); + virtual void mangleCXXRTTIName(QualType T, raw_ostream &); + virtual void mangleTypeName(QualType T, raw_ostream &); + virtual void mangleCXXCtor(const CXXConstructorDecl *D, CXXCtorType Type, + raw_ostream &); + virtual void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type, + raw_ostream &); + virtual void mangleReferenceTemporary(const VarDecl *, raw_ostream &); + virtual void mangleStaticGuardVariable(const VarDecl *D, raw_ostream &Out); + virtual void mangleDynamicInitializer(const VarDecl *D, raw_ostream &Out); + virtual void mangleDynamicAtExitDestructor(const VarDecl *D, + raw_ostream &Out); + 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()) { + disc = getASTContext().getManglingNumber(ND); + return true; + } + + if (isa(ND) && cast(ND)->getName().empty()) { + disc = getAnonymousStructId(cast(ND)); + return true; + } + + // Make up a reasonable number for internal decls. + unsigned &discriminator = Uniquifier[ND]; + if (!discriminator) + discriminator = ++Discriminator[std::make_pair(DC, ND->getIdentifier())]; + disc = discriminator; + return true; + } + +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 @@ -100,14 +166,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), @@ -133,7 +199,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; } @@ -152,7 +218,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); @@ -179,46 +244,6 @@ const TemplateArgumentList &TemplateArgs); void mangleTemplateArg(const TemplateDecl *TD, const TemplateArgument &TA); }; - -/// MicrosoftMangleContextImpl - Overrides the default MangleContext for the -/// Microsoft Visual C++ ABI. -class MicrosoftMangleContextImpl : public MicrosoftMangleContext { -public: - MicrosoftMangleContextImpl(ASTContext &Context, DiagnosticsEngine &Diags) - : MicrosoftMangleContext(Context, Diags) {} - virtual bool shouldMangleCXXName(const NamedDecl *D); - virtual void mangleCXXName(const NamedDecl *D, raw_ostream &Out); - virtual void mangleVirtualMemPtrThunk(const CXXMethodDecl *MD, - 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 BasePath, - raw_ostream &Out); - virtual void mangleCXXVBTable(const CXXRecordDecl *Derived, - ArrayRef BasePath, - raw_ostream &Out); - virtual void mangleCXXRTTI(QualType T, raw_ostream &); - virtual void mangleCXXRTTIName(QualType T, raw_ostream &); - virtual void mangleTypeName(QualType T, raw_ostream &); - virtual void mangleCXXCtor(const CXXConstructorDecl *D, CXXCtorType Type, - raw_ostream &); - virtual void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type, - raw_ostream &); - virtual void mangleReferenceTemporary(const VarDecl *, raw_ostream &); - virtual void mangleStaticGuardVariable(const VarDecl *D, raw_ostream &Out); - virtual void mangleDynamicInitializer(const VarDecl *D, raw_ostream &Out); - virtual void mangleDynamicAtExitDestructor(const VarDecl *D, - raw_ostream &Out); - -private: - void mangleInitFiniStub(const VarDecl *D, raw_ostream &Out, char CharCode); -}; - } bool MicrosoftMangleContextImpl::shouldMangleCXXName(const NamedDecl *D) { @@ -497,18 +522,11 @@ void MicrosoftCXXNameMangler::mangleName(const NamedDecl *ND) { // ::= {[]+ | []}? @ - 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(DC) && ND->hasLinkage()) - while (!DC->isNamespace() && !DC->isTranslationUnit()) - DC = DC->getParent(); - - manglePostfix(DC); + mangleNestedName(ND); // Terminate the whole name with an '@'. Out << '@'; @@ -721,45 +739,44 @@ } } -void MicrosoftCXXNameMangler::manglePostfix(const DeclContext *DC, - bool NoFunction) { +void MicrosoftCXXNameMangler::mangleNestedName(const NamedDecl *ND) { // ::= [] // ::= [] + const DeclContext *DC = ND->getDeclContext(); - if (!DC) return; + while (!DC->isTranslationUnit()) { + if (isa(ND) || isa(ND)) { + uint64_t Disc; + if (Context.getNextDiscriminator(ND, Disc)) { + Out << '?'; + mangleNumber(Disc); + Out << '?'; + } + } - while (isa(DC)) + if (const BlockDecl *BD = dyn_cast(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(DC)) { + mangleObjCMethodName(Method); + } else if (isa(DC)) { + ND = cast(DC); + if (const FunctionDecl *FD = dyn_cast(ND)) { + mangle(FD, "?"); + break; + } else + mangleUnqualifiedName(ND); + } DC = DC->getParent(); - - if (DC->isTranslationUnit()) - return; - - if (const BlockDecl *BD = dyn_cast(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(DC)) { - // Skip CapturedDecl context. - manglePostfix(DC->getParent(), NoFunction); - return; - } - - if (NoFunction && (isa(DC) || isa(DC))) - return; - else if (const ObjCMethodDecl *Method = dyn_cast(DC)) - mangleObjCMethodName(Method); - else if (const FunctionDecl *Func = dyn_cast(DC)) - mangleLocalName(Func); - else { - mangleUnqualifiedName(cast(DC)); - manglePostfix(DC->getParent(), NoFunction); } } @@ -933,44 +950,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(DC) || isa(DC)) level++; - DC = DC->getParent(); - } - - return 2*level; -} - -void MicrosoftCXXNameMangler::mangleLocalName(const FunctionDecl *FD) { - // ::= ? - // ::= ? - // 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) { @@ -2228,7 +2207,7 @@ // N.B. This means that they can get more than 32 static variable guards in a // scope. It also means that they broke compatibility with their own ABI. - // ::= ?_B @51 + // ::= ?_B @5 // ::= ?$S @ @4IA // The first mangling is what MSVC uses to guard static locals in inline @@ -2242,8 +2221,13 @@ bool Visible = VD->isExternallyVisible(); // ::= ?_B # local static guard Mangler.getStream() << (Visible ? "\01??_B" : "\01?$S1@"); - Mangler.manglePostfix(VD->getDeclContext()); - Mangler.getStream() << (Visible ? "@51" : "@4IA"); + Mangler.mangleNestedName(VD); + Mangler.getStream() << (Visible ? "@5" : "@4IA"); + if (Visible) { + uint64_t ScopeDepth; + getNextDiscriminator(VD, ScopeDepth); + Mangler.mangleNumber(ScopeDepth); + } } void MicrosoftMangleContextImpl::mangleInitFiniStub(const VarDecl *D, Index: lib/CodeGen/MicrosoftCXXABI.cpp =================================================================== --- lib/CodeGen/MicrosoftCXXABI.cpp +++ lib/CodeGen/MicrosoftCXXABI.cpp @@ -1291,7 +1291,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 @@ -1078,8 +1078,7 @@ // 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)); + ParseScope InnerScope(this, Scope::DeclScope, C99orCXX, Tok.is(tok::l_brace)); // Read the 'then' stmt. SourceLocation ThenStmtLoc = Tok.getLocation(); @@ -1111,8 +1110,7 @@ // 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)); + ParseScope InnerScope(this, Scope::DeclScope, C99orCXX, Tok.is(tok::l_brace)); ElseStmt = ParseStatement(); @@ -1215,8 +1213,7 @@ // condition and a new scope for substatement in C++. // getCurScope()->AddFlags(Scope::BreakScope); - ParseScope InnerScope(this, Scope::DeclScope, - C99orCXX && Tok.isNot(tok::l_brace)); + ParseScope InnerScope(this, Scope::DeclScope, C99orCXX, Tok.is(tok::l_brace)); // Read the body statement. StmtResult Body(ParseStatement(TrailingElseLoc)); @@ -1293,8 +1290,7 @@ // 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)); + ParseScope InnerScope(this, Scope::DeclScope, C99orCXX, Tok.is(tok::l_brace)); // Read the body statement. StmtResult Body(ParseStatement(TrailingElseLoc)); @@ -1335,9 +1331,8 @@ // 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 C99orCXX = getLangOpts().C99 || getLangOpts().CPlusPlus; + ParseScope InnerScope(this, Scope::DeclScope, C99orCXX, Tok.is(tok::l_brace)); // Read the body statement. StmtResult Body(ParseStatement()); @@ -1624,8 +1619,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)); + ParseScope InnerScope(this, Scope::DeclScope, C99orCXXorObjC, + Tok.is(tok::l_brace)); + // 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 (C99orCXXorObjC) + 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/raw_ostream.h" using namespace clang; @@ -36,16 +37,24 @@ 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; @@ -53,6 +62,16 @@ // 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()->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(); @@ -84,3 +103,77 @@ Flags |= FlagsToSet; } +void Scope::dump() const { dumpImpl(llvm::errs()); } + +void Scope::dumpImpl(raw_ostream &OS) const { + unsigned Flags = getFlags(); + bool HasFlags = Flags != 0; + + if (HasFlags) + OS << "Flags: "; + + while (Flags) { + if (Flags & FnScope) { + OS << "FnScope"; + Flags &= ~FnScope; + } else if (Flags & BreakScope) { + OS << "BreakScope"; + Flags &= ~BreakScope; + } else if (Flags & ContinueScope) { + OS << "ContinueScope"; + Flags &= ~ContinueScope; + } else if (Flags & DeclScope) { + OS << "DeclScope"; + Flags &= ~DeclScope; + } else if (Flags & ControlScope) { + OS << "ControlScope"; + Flags &= ~ControlScope; + } else if (Flags & ClassScope) { + OS << "ClassScope"; + Flags &= ~ClassScope; + } else if (Flags & BlockScope) { + OS << "BlockScope"; + Flags &= ~BlockScope; + } else if (Flags & TemplateParamScope) { + OS << "TemplateParamScope"; + Flags &= ~TemplateParamScope; + } else if (Flags & FunctionPrototypeScope) { + OS << "FunctionPrototypeScope"; + Flags &= ~FunctionPrototypeScope; + } else if (Flags & FunctionDeclarationScope) { + OS << "FunctionDeclarationScope"; + Flags &= ~FunctionDeclarationScope; + } else if (Flags & AtCatchScope) { + OS << "AtCatchScope"; + Flags &= ~AtCatchScope; + } else if (Flags & ObjCMethodScope) { + OS << "ObjCMethodScope"; + Flags &= ~ObjCMethodScope; + } else if (Flags & SwitchScope) { + OS << "SwitchScope"; + Flags &= ~SwitchScope; + } else if (Flags & TryScope) { + OS << "TryScope"; + Flags &= ~TryScope; + } else if (Flags & FnTryCatchScope) { + OS << "FnTryCatchScope"; + Flags &= ~FnTryCatchScope; + } else if (Flags & OpenMPDirectiveScope) { + OS << "OpenMPDirectiveScope"; + Flags &= ~OpenMPDirectiveScope; + } + + if (Flags) + OS << " | "; + } + if (HasFlags) + 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 @@ -3157,7 +3157,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; @@ -3168,7 +3168,7 @@ return; MangleNumberingContext &MCtx = S.Context.getManglingNumberContext(Tag->getParent()); - S.Context.setManglingNumber(Tag, MCtx.getManglingNumber(Tag)); + S.Context.setManglingNumber(Tag, MCtx.getManglingNumber(Tag, TagScope)); return; } @@ -3177,7 +3177,7 @@ if (MangleNumberingContext *MCtx = S.getCurrentMangleNumberContext(Tag->getDeclContext(), ManglingContextDecl)) { - S.Context.setManglingNumber(Tag, MCtx->getManglingNumber(Tag)); + S.Context.setManglingNumber(Tag, MCtx->getManglingNumber(Tag, TagScope)); } } @@ -3210,7 +3210,7 @@ } if (Tag) { - HandleTagNumbering(*this, Tag); + HandleTagNumbering(*this, Tag, S); Tag->setFreeStanding(); if (Tag->isInvalidDecl()) return Tag; @@ -5470,7 +5470,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)); } } @@ -8990,7 +8991,7 @@ if (DeclSpec::isDeclRep(DS.getTypeSpecType())) { if (TagDecl *Tag = dyn_cast_or_null(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 @@ -3636,6 +3636,7 @@ // 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. 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/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@?0??StaticLocal@@YAXXZ@4IA" +// CHECK: store i32 {{.*}}, i32* @"\01?$S1@?0??StaticLocal@@YAXXZ@4IA" // CHECK: ret void MultipleStatics() { @@ -66,7 +66,7 @@ static S S35; } // CHECK-LABEL: define void @"\01?MultipleStatics@@YAXXZ"() -// CHECK: load i32* @"\01?$S1@?1??MultipleStatics@@YAXXZ@4IA" +// CHECK: load i32* @"\01?$S1@?0??MultipleStatics@@YAXXZ@4IA" // CHECK: and i32 {{.*}}, 1 // CHECK: and i32 {{.*}}, 2 // CHECK: and i32 {{.*}}, 4 @@ -74,7 +74,7 @@ // CHECK: and i32 {{.*}}, 16 // ... // CHECK: and i32 {{.*}}, -2147483648 -// CHECK: load i32* @"\01?$S1@?1??MultipleStatics@@YAXXZ@4IA1" +// CHECK: load i32* @"\01?$S1@?0??MultipleStatics@@YAXXZ@4IA1" // CHECK: and i32 {{.*}}, 1 // CHECK: and i32 {{.*}}, 2 // CHECK: and i32 {{.*}}, 4