Address review comments.

Hi rsmith, doug.gregor, rjmccall, rnk, eli.friedman, cdavis5x,

http://llvm-reviews.chandlerc.com/D2204

CHANGE SINCE LAST DIFF
  http://llvm-reviews.chandlerc.com/D2204?vs=5612&id=6079#toc

Files:
  include/clang/AST/ASTContext.h
  include/clang/AST/Mangle.h
  include/clang/AST/MangleNumberingContext.h
  include/clang/Parse/Parser.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/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.
@@ -2154,6 +2155,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/Parse/Parser.h
===================================================================
--- include/clang/Parse/Parser.h
+++ include/clang/Parse/Parser.h
@@ -682,6 +682,12 @@
   //===--------------------------------------------------------------------===//
   // 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
   /// be created on the stack to coincide with the position where the
@@ -693,17 +699,28 @@
     ParseScope(const ParseScope &) LLVM_DELETED_FUNCTION;
     void operator=(const ParseScope &) LLVM_DELETED_FUNCTION;
 
+    void EnterScope(unsigned ScopeFlags, ManageScopeFlags ManageScope) {
+      if (ManageScope == EnteredScope)
+        Self->EnterScope(ScopeFlags);
+      else if (ManageScope == BeforeCompoundStmt)
+        Self->getCurScope()->incrementMSLocalManglingNumber();
+
+      if (ManageScope != EnteredScope)
+        Self = 0;
+    }
+
   public:
     // ParseScope - Construct a new object to manage a scope in the
     // 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)
       : Self(Self) {
-      if (ManageScope)
-        Self->EnterScope(ScopeFlags);
-      else
-        this->Self = 0;
+        EnterScope(ScopeFlags, ManageScope ? EnteredScope : NoScope);
+    }
+    ParseScope(Parser *Self, unsigned ScopeFlags, ManageScopeFlags ManageScope)
+        : Self(Self) {
+        EnterScope(ScopeFlags, ManageScope);
     }
 
     // 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) {
@@ -354,6 +386,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
@@ -8149,6 +8149,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,77 @@
   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,
+                                        uint64_t OffsetInVFTable,
+                                        raw_ostream &);
+  virtual void mangleThunk(const CXXMethodDecl *MD,
+                           const ThunkInfo &Thunk,
+                           raw_ostream &);
+  virtual void mangleCXXDtorThunk(const CXXDestructorDecl *DD, CXXDtorType Type,
+                                  const ThisAdjustment &ThisAdjustment,
+                                  raw_ostream &);
+  virtual void mangleCXXVFTable(const CXXRecordDecl *Derived,
+                                ArrayRef<const CXXRecordDecl *> BasePath,
+                                raw_ostream &Out);
+  virtual void mangleCXXVBTable(const CXXRecordDecl *Derived,
+                                ArrayRef<const CXXRecordDecl *> BasePath,
+                                raw_ostream &Out);
+  virtual void mangleCXXRTTI(QualType T, raw_ostream &);
+  virtual void mangleCXXRTTIName(QualType T, raw_ostream &);
+  virtual void mangleTypeName(QualType T, raw_ostream &);
+  virtual void mangleCXXCtor(const CXXConstructorDecl *D, CXXCtorType Type,
+                             raw_ostream &);
+  virtual void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type,
+                             raw_ostream &);
+  virtual void mangleReferenceTemporary(const VarDecl *, raw_ostream &);
+  virtual void mangleStaticGuardVariable(const VarDecl *D, raw_ostream &Out);
+  virtual void mangleDynamicInitializer(const VarDecl *D, raw_ostream &Out);
+  virtual void mangleDynamicAtExitDestructor(const VarDecl *D,
+                                             raw_ostream &Out);
+  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<TagDecl>(ND) && cast<TagDecl>(ND)->getName().empty()) {
+      disc = getAnonymousStructId(cast<TagDecl>(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
@@ -99,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),
@@ -126,7 +193,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; }
@@ -144,7 +211,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);
 
@@ -172,46 +238,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,
-                                        uint64_t OffsetInVFTable,
-                                        raw_ostream &);
-  virtual void mangleThunk(const CXXMethodDecl *MD,
-                           const ThunkInfo &Thunk,
-                           raw_ostream &);
-  virtual void mangleCXXDtorThunk(const CXXDestructorDecl *DD, CXXDtorType Type,
-                                  const ThisAdjustment &ThisAdjustment,
-                                  raw_ostream &);
-  virtual void mangleCXXVFTable(const CXXRecordDecl *Derived,
-                                ArrayRef<const CXXRecordDecl *> BasePath,
-                                raw_ostream &Out);
-  virtual void mangleCXXVBTable(const CXXRecordDecl *Derived,
-                                ArrayRef<const CXXRecordDecl *> BasePath,
-                                raw_ostream &Out);
-  virtual void mangleCXXRTTI(QualType T, raw_ostream &);
-  virtual void mangleCXXRTTIName(QualType T, raw_ostream &);
-  virtual void mangleTypeName(QualType T, raw_ostream &);
-  virtual void mangleCXXCtor(const CXXConstructorDecl *D, CXXCtorType Type,
-                             raw_ostream &);
-  virtual void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type,
-                             raw_ostream &);
-  virtual void mangleReferenceTemporary(const VarDecl *, raw_ostream &);
-  virtual void mangleStaticGuardVariable(const VarDecl *D, raw_ostream &Out);
-  virtual void mangleDynamicInitializer(const VarDecl *D, raw_ostream &Out);
-  virtual void mangleDynamicAtExitDestructor(const VarDecl *D,
-                                             raw_ostream &Out);
-
-private:
-  void mangleInitFiniStub(const VarDecl *D, raw_ostream &Out, char CharCode);
-};
-
 }
 
 bool MicrosoftMangleContextImpl::shouldMangleCXXName(const NamedDecl *D) {
@@ -373,18 +399,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);    
+  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();
-
-  manglePostfix(DC);
+  mangleNestedName(ND);
 
   // Terminate the whole name with an '@'.
   Out << '@';
@@ -591,45 +610,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);
   }
 }
 
@@ -803,44 +821,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) {
@@ -2062,7 +2042,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
@@ -1168,7 +1168,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,13 @@
   //    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));
+  ManageScopeFlags ManageScope = NoScope;
+  if (C99orCXX) {
+    ManageScope = EnteredScope;
+    if (Tok.is(tok::l_brace))
+      ManageScope = BeforeCompoundStmt;
+  }
+  ParseScope InnerScope(this, Scope::DeclScope, ManageScope);
 
   // Read the 'then' stmt.
   SourceLocation ThenStmtLoc = Tok.getLocation();
@@ -1110,8 +1115,13 @@
     // 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));
+    ManageScopeFlags ManageScope = NoScope;
+    if (C99orCXX) {
+      ManageScope = EnteredScope;
+      if (Tok.is(tok::l_brace))
+        ManageScope = BeforeCompoundStmt;
+    }
+    ParseScope InnerScope(this, Scope::DeclScope, ManageScope);
 
     ElseStmt = ParseStatement();
 
@@ -1213,8 +1223,13 @@
   // 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));
+  ManageScopeFlags ManageScope = NoScope;
+  if (C99orCXX) {
+    ManageScope = EnteredScope;
+    if (Tok.is(tok::l_brace))
+      ManageScope = BeforeCompoundStmt;
+  }
+  ParseScope InnerScope(this, Scope::DeclScope, ManageScope);
 
   // Read the body statement.
   StmtResult Body(ParseStatement(TrailingElseLoc));
@@ -1291,8 +1306,13 @@
   // 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));
+  ManageScopeFlags ManageScope = NoScope;
+  if (C99orCXX) {
+    ManageScope = EnteredScope;
+    if (Tok.is(tok::l_brace))
+      ManageScope = BeforeCompoundStmt;
+  }
+  ParseScope InnerScope(this, Scope::DeclScope, ManageScope);
 
   // Read the body statement.
   StmtResult Body(ParseStatement(TrailingElseLoc));
@@ -1333,9 +1353,14 @@
   // 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;
+  ManageScopeFlags ManageScope = NoScope;
+  if (C99orCXX) {
+    ManageScope = EnteredScope;
+    if (Tok.is(tok::l_brace))
+      ManageScope = BeforeCompoundStmt;
+  }
+  ParseScope InnerScope(this, Scope::DeclScope, ManageScope);
 
   // Read the body statement.
   StmtResult Body(ParseStatement());
@@ -1622,8 +1647,19 @@
   // 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));
+  ManageScopeFlags ManageScope = NoScope;
+  if (C99orCXXorObjC) {
+    ManageScope = EnteredScope;
+    if (Tok.is(tok::l_brace))
+      ManageScope = BeforeCompoundStmt;
+  }
+  ParseScope InnerScope(this, Scope::DeclScope, ManageScope);
+  // 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,23 +37,41 @@
     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 +88,78 @@
   }
   return false;
 }
+
+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
@@ -3163,7 +3163,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;
 
@@ -3174,16 +3174,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));
   }
 }
 
@@ -3216,7 +3216,7 @@
   }
 
   if (Tag) {
-    HandleTagNumbering(*this, Tag);
+    HandleTagNumbering(*this, Tag, S);
     Tag->setFreeStanding();
     if (Tag->isInvalidDecl())
       return Tag;
@@ -5503,7 +5503,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));
     }
   }
 
@@ -9020,7 +9021,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
@@ -3465,6 +3465,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,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@?0??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@?0??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

Reply via email to