Fix mangling for block literals.
authorEli Friedman <eli.friedman@gmail.com>
Mon, 1 Jul 2013 20:22:57 +0000 (20:22 +0000)
committerEli Friedman <eli.friedman@gmail.com>
Mon, 1 Jul 2013 20:22:57 +0000 (20:22 +0000)
Blocks, like lambdas, can be written in contexts which are required to be
treated as the same under ODR.  Unlike lambdas, it isn't possible to actually
take the address of a block, so the mangling of the block itself doesn't
matter. However, objects like static variables inside a block do need to
be mangled in a consistent way.

There are basically three components here. One, block literals need a
consistent numbering.  Two, objects/types inside a block literal need
to be mangled using it.  Three, objects/types inside a block literal need
to have their linkage computed correctly.

llvm-svn: 185372

15 files changed:
clang/include/clang/AST/ASTContext.h
clang/include/clang/AST/Decl.h
clang/include/clang/AST/MangleNumberingContext.h [moved from clang/include/clang/AST/LambdaMangleContext.h with 50% similarity]
clang/include/clang/Sema/Sema.h
clang/lib/AST/ASTContext.cpp
clang/lib/AST/Decl.cpp
clang/lib/AST/ItaniumMangle.cpp
clang/lib/AST/MangleNumberingContext.cpp [moved from clang/lib/AST/LambdaMangleContext.cpp with 71% similarity]
clang/lib/CodeGen/CGDecl.cpp
clang/lib/CodeGen/CodeGenModule.cpp
clang/lib/CodeGen/CodeGenModule.h
clang/lib/Sema/SemaExpr.cpp
clang/lib/Sema/SemaLambda.cpp
clang/test/CXX/expr/expr.prim/expr.prim.lambda/blocks-irgen.mm
clang/test/CodeGenObjCXX/mangle-blocks.mm

index 3f810f9..7c2cea2 100644 (file)
@@ -19,7 +19,7 @@
 #include "clang/AST/CanonicalType.h"
 #include "clang/AST/CommentCommandTraits.h"
 #include "clang/AST/Decl.h"
-#include "clang/AST/LambdaMangleContext.h"
+#include "clang/AST/MangleNumberingContext.h"
 #include "clang/AST/NestedNameSpecifier.h"
 #include "clang/AST/PrettyPrinter.h"
 #include "clang/AST/RawCommentList.h"
@@ -338,9 +338,11 @@ class ASTContext : public RefCountedBase<ASTContext> {
   typedef llvm::TinyPtrVector<const CXXMethodDecl*> CXXMethodVector;
   llvm::DenseMap<const CXXMethodDecl *, CXXMethodVector> OverriddenMethods;
 
-  /// \brief Mapping from each declaration context to its corresponding lambda 
-  /// mangling context.
-  llvm::DenseMap<const DeclContext *, LambdaMangleContext> LambdaMangleContexts;
+  /// \brief Mapping from each declaration context to its corresponding
+  /// mangling numbering context (used for constructs like lambdas which
+  /// need to be consistently numbered for the mangler).
+  llvm::DenseMap<const DeclContext *, MangleNumberingContext>
+      MangleNumberingContexts;
 
   llvm::DenseMap<const DeclContext *, unsigned> UnnamedMangleContexts;
   llvm::DenseMap<const TagDecl *, unsigned> UnnamedMangleNumbers;
@@ -2087,9 +2089,10 @@ public:
   void addUnnamedTag(const TagDecl *Tag);
   int getUnnamedTagManglingNumber(const TagDecl *Tag) const;
 
-  /// \brief Retrieve the lambda mangling number for a lambda expression.
-  unsigned getLambdaManglingNumber(CXXMethodDecl *CallOperator);
-  
+  /// \brief Retrieve the context for computing mangling numbers in the given
+  /// DeclContext.
+  MangleNumberingContext &getManglingNumberContext(DeclContext *DC);
+
   /// \brief Used by ParmVarDecl to store on the side the
   /// index of the parameter when it exceeds the size of the normal bitfield.
   void setParameterIndex(const ParmVarDecl *D, unsigned index);
index 8342f79..e90f454 100644 (file)
@@ -3115,13 +3115,17 @@ private:
   Capture *Captures;
   unsigned NumCaptures;
 
+  unsigned ManglingNumber;
+  Decl *ManglingContextDecl;
+
 protected:
   BlockDecl(DeclContext *DC, SourceLocation CaretLoc)
     : Decl(Block, DC, CaretLoc), DeclContext(Block),
       IsVariadic(false), CapturesCXXThis(false),
       BlockMissingReturnType(true), IsConversionFromLambda(false),
       ParamInfo(0), NumParams(0), Body(0),
-      SignatureAsWritten(0), Captures(0), NumCaptures(0) {}
+      SignatureAsWritten(0), Captures(0), NumCaptures(0),
+      ManglingNumber(0), ManglingContextDecl(0) {}
 
 public:
   static BlockDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L); 
@@ -3191,6 +3195,18 @@ public:
                    const Capture *end,
                    bool capturesCXXThis);
 
+   unsigned getBlockManglingNumber() const {
+     return ManglingNumber;
+   }
+   Decl *getBlockManglingContextDecl() const {
+     return ManglingContextDecl;    
+   }
+
+  void setBlockMangling(unsigned Number, Decl *Ctx) {
+    ManglingNumber = Number;
+    ManglingContextDecl = Ctx;
+  }
+
   virtual SourceRange getSourceRange() const LLVM_READONLY;
 
   // Implement isa/cast/dyncast/etc.
@@ -1,4 +1,4 @@
-//===--- LambdaMangleContext.h - Context for mangling lambdas ---*- C++ -*-===//
+//=== MangleNumberingContext.h - Context for mangling numbers ---*- C++ -*-===//
 //
 //                     The LLVM Compiler Infrastructure
 //
@@ -7,12 +7,13 @@
 //
 //===----------------------------------------------------------------------===//
 //
-//  This file defines the LambdaMangleContext interface, which keeps track of
-//  the Itanium C++ ABI mangling numbers for lambda expressions.
+//  This file defines the LambdaBlockMangleContext interface, which keeps track
+//  of the Itanium C++ ABI mangling numbers for lambda expressions and block
+//  literals.
 //
 //===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_LAMBDAMANGLECONTEXT_H
-#define LLVM_CLANG_LAMBDAMANGLECONTEXT_H
+#ifndef LLVM_CLANG_MANGLENUMBERINGCONTEXT_H
+#define LLVM_CLANG_MANGLENUMBERINGCONTEXT_H
 
 #include "clang/Basic/LLVM.h"
 #include "llvm/ADT/DenseMap.h"
 
 namespace clang {
 
+class BlockDecl;
 class CXXMethodDecl;
-class FunctionProtoType;
+class Type;
 
-/// \brief Keeps track of the mangled names of lambda expressions within a
-/// particular context.
-class LambdaMangleContext : public RefCountedBase<LambdaMangleContext> {
-  llvm::DenseMap<const FunctionProtoType *, unsigned> ManglingNumbers;
+/// \brief Keeps track of the mangled names of lambda expressions and block
+/// literals within a particular context.
+class MangleNumberingContext 
+    : public RefCountedBase<MangleNumberingContext> {
+  llvm::DenseMap<const Type *, unsigned> ManglingNumbers;
   
 public:
   /// \brief Retrieve the mangling number of a new lambda expression with the
-  /// given call operator within this lambda context.
+  /// given call operator within this context.
   unsigned getManglingNumber(CXXMethodDecl *CallOperator);
+
+  /// \brief Retrieve the mangling number of a new block literal within this
+  /// context.
+  unsigned getManglingNumber(BlockDecl *BD);
 };
   
 } // end namespace clang
index f984636..1b076a4 100644 (file)
@@ -20,7 +20,7 @@
 #include "clang/AST/Expr.h"
 #include "clang/AST/ExprObjC.h"
 #include "clang/AST/ExternalASTSource.h"
-#include "clang/AST/LambdaMangleContext.h"
+#include "clang/AST/MangleNumberingContext.h"
 #include "clang/AST/NSAPI.h"
 #include "clang/AST/PrettyPrinter.h"
 #include "clang/AST/TypeLoc.h"
@@ -662,17 +662,17 @@ public:
     /// is indeed an unevaluated context.
     SmallVector<LambdaExpr *, 2> Lambdas;
 
-    /// \brief The declaration that provides context for the lambda expression
-    /// if the normal declaration context does not suffice, e.g., in a
-    /// default function argument.
-    Decl *LambdaContextDecl;
+    /// \brief The declaration that provides context for lambda expressions
+    /// and block literals if the normal declaration context does not
+    /// suffice, e.g., in a default function argument.
+    Decl *ManglingContextDecl;
 
     /// \brief The context information used to mangle lambda expressions
-    /// within this context.
+    /// and block literals within this context.
     ///
     /// This mangling information is allocated lazily, since most contexts
-    /// do not have lambda expressions.
-    IntrusiveRefCntPtr<LambdaMangleContext> LambdaMangle;
+    /// do not have lambda expressions or block literals.
+    IntrusiveRefCntPtr<MangleNumberingContext> MangleNumbering;
 
     /// \brief If we are processing a decltype type, a set of call expressions
     /// for which we have deferred checking the completeness of the return type.
@@ -685,18 +685,19 @@ public:
     ExpressionEvaluationContextRecord(ExpressionEvaluationContext Context,
                                       unsigned NumCleanupObjects,
                                       bool ParentNeedsCleanups,
-                                      Decl *LambdaContextDecl,
+                                      Decl *ManglingContextDecl,
                                       bool IsDecltype)
       : Context(Context), ParentNeedsCleanups(ParentNeedsCleanups),
         IsDecltype(IsDecltype), NumCleanupObjects(NumCleanupObjects),
-        LambdaContextDecl(LambdaContextDecl), LambdaMangle() { }
-
-    /// \brief Retrieve the mangling context for lambdas.
-    LambdaMangleContext &getLambdaMangleContext() {
-      assert(LambdaContextDecl && "Need to have a lambda context declaration");
-      if (!LambdaMangle)
-        LambdaMangle = new LambdaMangleContext;
-      return *LambdaMangle;
+        ManglingContextDecl(ManglingContextDecl), MangleNumbering() { }
+
+    /// \brief Retrieve the mangling numbering context, used to consistently
+    /// number constructs like lambdas for mangling.
+    MangleNumberingContext &getMangleNumberingContext() {
+      assert(ManglingContextDecl && "Need to have a context declaration");
+      if (!MangleNumbering)
+        MangleNumbering = new MangleNumberingContext;
+      return *MangleNumbering;
     }
 
     bool isUnevaluated() const {
@@ -707,6 +708,18 @@ public:
   /// A stack of expression evaluation contexts.
   SmallVector<ExpressionEvaluationContextRecord, 8> ExprEvalContexts;
 
+  /// \brief Compute the mangling number context for a lambda expression or
+  /// block literal.
+  ///
+  /// \param DC - The DeclContext containing the lambda expression or
+  /// block literal.
+  /// \param[out] ManglingContextDecl - Returns the ManglingContextDecl
+  /// associated with the context, if relevant.
+  MangleNumberingContext *getCurrentMangleNumberContext(
+    DeclContext *DC,
+    Decl *&ManglingContextDecl);
+
+
   /// SpecialMemberOverloadResult - The overloading result for a special member
   /// function.
   ///
index 8374316..7f02f59 100644 (file)
@@ -8007,13 +8007,10 @@ int ASTContext::getUnnamedTagManglingNumber(const TagDecl *Tag) const {
   return I != UnnamedMangleNumbers.end() ? I->second : -1;
 }
 
-unsigned ASTContext::getLambdaManglingNumber(CXXMethodDecl *CallOperator) {
-  CXXRecordDecl *Lambda = CallOperator->getParent();
-  return LambdaMangleContexts[Lambda->getDeclContext()]
-           .getManglingNumber(CallOperator);
+MangleNumberingContext &ASTContext::getManglingNumberContext(DeclContext *DC) {
+  return MangleNumberingContexts[DC];
 }
 
-
 void ASTContext::setParameterIndex(const ParmVarDecl *D, unsigned int index) {
   ParamIndices[D] = index;
 }
index 5267789..0ad15fc 100644 (file)
@@ -287,13 +287,12 @@ getLVForTemplateParameterList(const TemplateParameterList *params,
 static LinkageInfo getLVForDecl(const NamedDecl *D,
                                 LVComputationKind computation);
 
-static const FunctionDecl *getOutermostFunctionContext(const Decl *D) {
-  const FunctionDecl *Ret = NULL;
+static const Decl *getOutermostFuncOrBlockContext(const Decl *D) {
+  const Decl *Ret = NULL;
   const DeclContext *DC = D->getDeclContext();
   while (DC->getDeclKind() != Decl::TranslationUnit) {
-    const FunctionDecl *F = dyn_cast<FunctionDecl>(DC);
-    if (F)
-      Ret = F;
+    if (isa<FunctionDecl>(DC) || isa<BlockDecl>(DC))
+      Ret = cast<Decl>(DC);
     DC = DC->getParent();
   }
   return Ret;
@@ -996,6 +995,22 @@ NamedDecl::getExplicitVisibility(ExplicitVisibilityKind kind) const {
   return None;
 }
 
+static LinkageInfo getLVForClosure(const DeclContext *DC, Decl *ContextDecl,
+                                   LVComputationKind computation) {
+  // This lambda has its linkage/visibility determined by its owner.
+  if (ContextDecl) {
+    if (isa<ParmVarDecl>(ContextDecl))
+      DC = ContextDecl->getDeclContext()->getRedeclContext();
+    else
+      return getLVForDecl(cast<NamedDecl>(ContextDecl), computation);
+  }
+
+  if (const NamedDecl *ND = dyn_cast<NamedDecl>(DC))
+    return getLVForDecl(ND, computation);
+
+  return LinkageInfo::external();
+}
+
 static LinkageInfo getLVForLocalDecl(const NamedDecl *D,
                                      LVComputationKind computation) {
   if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
@@ -1052,14 +1067,25 @@ static LinkageInfo getLVForLocalDecl(const NamedDecl *D,
   if (!Context.getLangOpts().CPlusPlus)
     return LinkageInfo::none();
 
-  const FunctionDecl *FD = getOutermostFunctionContext(D);
-  if (!FD)
+  const Decl *OuterD = getOutermostFuncOrBlockContext(D);
+  if (!OuterD)
     return LinkageInfo::none();
 
-  if (!FD->isInlined() && FD->getTemplateSpecializationKind() == TSK_Undeclared)
-    return LinkageInfo::none();
+  LinkageInfo LV;
+  if (const BlockDecl *BD = dyn_cast<BlockDecl>(OuterD)) {
+    if (!BD->getBlockManglingNumber())
+      return LinkageInfo::none();
+
+    LV = getLVForClosure(BD->getDeclContext()->getRedeclContext(),
+                         BD->getBlockManglingContextDecl(), computation);
+  } else {
+    const FunctionDecl *FD = cast<FunctionDecl>(OuterD);
+    if (!FD->isInlined() &&
+        FD->getTemplateSpecializationKind() == TSK_Undeclared)
+      return LinkageInfo::none();
 
-  LinkageInfo LV = getLVForDecl(FD, computation);
+    LV = getLVForDecl(FD, computation);
+  }
   if (!isExternallyVisible(LV.getLinkage()))
     return LinkageInfo::none();
   return LinkageInfo(VisibleNoLinkage, LV.getVisibility(),
@@ -1095,20 +1121,10 @@ static LinkageInfo computeLVForDecl(const NamedDecl *D,
           // This lambda has no mangling number, so it's internal.
           return LinkageInfo::internal();
         }
-        
-        // This lambda has its linkage/visibility determined by its owner.
-        const DeclContext *DC = D->getDeclContext()->getRedeclContext();
-        if (Decl *ContextDecl = Record->getLambdaContextDecl()) {
-          if (isa<ParmVarDecl>(ContextDecl))
-            DC = ContextDecl->getDeclContext()->getRedeclContext();
-          else
-            return getLVForDecl(cast<NamedDecl>(ContextDecl), computation);
-        }
 
-        if (const NamedDecl *ND = dyn_cast<NamedDecl>(DC))
-          return getLVForDecl(ND, computation);
-        
-        return LinkageInfo::external();
+        // This lambda has its linkage/visibility determined by its owner.
+        return getLVForClosure(D->getDeclContext()->getRedeclContext(),
+                               Record->getLambdaContextDecl(), computation);
       }
       
       break;
index cf1e512..bbdf0f9 100644 (file)
@@ -1416,15 +1416,22 @@ void CXXNameMangler::manglePrefix(const DeclContext *DC, bool NoFunction) {
     return;
 
   if (const BlockDecl *Block = dyn_cast<BlockDecl>(DC)) {
-    // The symbol we're adding a prefix for isn't externally
-    // visible; make up something sane.
-    // FIXME: This isn't always true!
-    SmallString<16> BlockPrefix;
-    BlockPrefix += "__block_prefix_internal";
-    unsigned Number = Context.getBlockId(Block, false);
+    // Reflect the lambda mangling rules, except that we don't have an
+    // actual function declaration.
+    if (NoFunction)
+      return;
+
+    manglePrefix(getEffectiveParentContext(DC), NoFunction);
+    // If we have a block mangling number, use it.
+    unsigned Number = Block->getBlockManglingNumber();
+    // Otherwise, just make up a number. It doesn't matter what it is because
+    // the symbol in question isn't externally visible.
+    if (!Number)
+      Number = Context.getBlockId(Block, false);
+    Out << "Ub";
     if (Number > 1)
-      BlockPrefix += llvm::utostr_32(Number - 2);
-    Out << BlockPrefix.size() << BlockPrefix;
+      Out << Number - 2;
+    Out << '_';
     return;
   } else if (isa<CapturedDecl>(DC)) {
     // Skip CapturedDecl context.
similarity index 71%
rename from clang/lib/AST/LambdaMangleContext.cpp
rename to clang/lib/AST/MangleNumberingContext.cpp
index 10b01a6..a4c8a27 100644 (file)
@@ -1,4 +1,4 @@
-//===--- LambdaMangleContext.cpp - Context for mangling lambdas -*- C++ -*-===//
+//===--- MangleNumberingContext.cpp - Context for mangling numbers --------===//
 //
 //                     The LLVM Compiler Infrastructure
 //
 //
 //===----------------------------------------------------------------------===//
 
-#include "clang/AST/LambdaMangleContext.h"
+#include "clang/AST/MangleNumberingContext.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/DeclCXX.h"
 
 using namespace clang;
 
-unsigned LambdaMangleContext::getManglingNumber(CXXMethodDecl *CallOperator) {
+unsigned
+MangleNumberingContext::getManglingNumber(CXXMethodDecl *CallOperator) {
   const FunctionProtoType *Proto
     = CallOperator->getType()->getAs<FunctionProtoType>();
   ASTContext &Context = CallOperator->getASTContext();
@@ -28,3 +29,10 @@ unsigned LambdaMangleContext::getManglingNumber(CXXMethodDecl *CallOperator) {
   Key = Context.getCanonicalType(Key);
   return ++ManglingNumbers[Key->castAs<FunctionProtoType>()];
 }
+
+unsigned
+MangleNumberingContext::getManglingNumber(BlockDecl *BD) {
+  // FIXME: Compute a BlockPointerType?  Not obvious how.
+  const Type *Ty = 0;
+  return ++ManglingNumbers[Ty];
+}
index 519f03a..62cd744 100644 (file)
@@ -130,9 +130,27 @@ void CodeGenFunction::EmitVarDecl(const VarDecl &D) {
     if (D.isExternallyVisible()) {
       const Decl *D = CurCodeDecl;
       while (true) {
-        if (isa<BlockDecl>(D)) {
-          // FIXME: Handle this case properly!  (Should be similar to the
-          // way we handle lambdas in computeLVForDecl in Decl.cpp.)
+        if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) {
+          if (!BD->getBlockManglingNumber())
+            break;
+
+          // This block has the linkage/visibility of its contained variables
+          // determined by its owner.
+          const DeclContext *DC = D->getDeclContext()->getRedeclContext();
+          if (Decl *ContextDecl = BD->getBlockManglingContextDecl()) {
+            if (isa<ParmVarDecl>(ContextDecl)) {
+              DC = ContextDecl->getDeclContext()->getRedeclContext();
+            } else {
+              D = ContextDecl;
+              continue;
+            }
+          }
+
+          if (const NamedDecl *ND = dyn_cast<NamedDecl>(DC)) {
+            D = ND;
+            continue;
+          }
+
           break;
         } else if (isa<CapturedDecl>(D)) {
           D = cast<Decl>(cast<CapturedDecl>(D)->getParent());
@@ -140,13 +158,26 @@ void CodeGenFunction::EmitVarDecl(const VarDecl &D) {
           break;
         }
       }
-      // FIXME: Do we really only care about FunctionDecls here?
+      llvm::GlobalValue::LinkageTypes ParentLinkage;
       if (isa<FunctionDecl>(D)) {
-        llvm::GlobalValue::LinkageTypes ParentLinkage =
-            CGM.getFunctionLinkage(cast<FunctionDecl>(D));
-        if (llvm::GlobalValue::isWeakForLinker(ParentLinkage))
-          Linkage = ParentLinkage;
+        ParentLinkage = CGM.getFunctionLinkage(cast<FunctionDecl>(D));
+      } else if (isa<VarDecl>(D)) {
+        // FIXME: I'm pretty sure this is wrong...
+        ParentLinkage = CGM.GetLLVMLinkageVarDefinition(cast<VarDecl>(D),
+                                                        /*constant*/false);
+      } else {
+        assert(isa<FieldDecl>(D) && "Expect function, variable, or field");
+        // FIXME: Is this right?
+        ParentLinkage = llvm::GlobalValue::LinkOnceODRLinkage;
       }
+
+      if (llvm::GlobalValue::isWeakForLinker(ParentLinkage))
+        Linkage = ParentLinkage;
+
+      // FIXME: We need to force the emission/use of a guard variable for
+      // some variables even if we can constant-evaluate them because
+      // we can't guarantee every translation unit will constant-evaluate them.
+      // Also, we might need to fix up the linkage.
     }
 
     return EmitStaticVarDecl(D, Linkage);
index 3298d5a..cfb9e78 100644 (file)
@@ -1797,7 +1797,7 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
 
   // Set the llvm linkage type as appropriate.
   llvm::GlobalValue::LinkageTypes Linkage = 
-    GetLLVMLinkageVarDefinition(D, GV);
+    GetLLVMLinkageVarDefinition(D, GV->isConstant());
   GV->setLinkage(Linkage);
   if (Linkage == llvm::GlobalVariable::CommonLinkage)
     // common vars aren't constant even if declared const.
@@ -1828,8 +1828,7 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
 }
 
 llvm::GlobalValue::LinkageTypes
-CodeGenModule::GetLLVMLinkageVarDefinition(const VarDecl *D,
-                                           llvm::GlobalVariable *GV) {
+CodeGenModule::GetLLVMLinkageVarDefinition(const VarDecl *D, bool isConstant) {
   GVALinkage Linkage = getContext().GetGVALinkageForVariable(D);
   if (Linkage == GVA_Internal)
     return llvm::Function::InternalLinkage;
@@ -1844,7 +1843,7 @@ CodeGenModule::GetLLVMLinkageVarDefinition(const VarDecl *D,
     // http://msdn.microsoft.com/en-us/library/5tkz6s71.aspx
     return llvm::GlobalVariable::WeakODRLinkage;
   } else if (D->hasAttr<WeakAttr>()) {
-    if (GV->isConstant())
+    if (isConstant)
       return llvm::GlobalVariable::WeakODRLinkage;
     else
       return llvm::GlobalVariable::WeakAnyLinkage;
index 6e5985d..a5fca36 100644 (file)
@@ -942,8 +942,7 @@ public:
   /// GetLLVMLinkageVarDefinition - Returns LLVM linkage for a global 
   /// variable.
   llvm::GlobalValue::LinkageTypes 
-  GetLLVMLinkageVarDefinition(const VarDecl *D,
-                              llvm::GlobalVariable *GV);
+  GetLLVMLinkageVarDefinition(const VarDecl *D, bool isConstant);
   
   /// Emit all the global annotations.
   void EmitGlobalAnnotations();
index 1523563..2f5961d 100644 (file)
@@ -9810,6 +9810,17 @@ ExprResult Sema::ActOnChooseExpr(SourceLocation BuiltinLoc,
 /// ActOnBlockStart - This callback is invoked when a block literal is started.
 void Sema::ActOnBlockStart(SourceLocation CaretLoc, Scope *CurScope) {
   BlockDecl *Block = BlockDecl::Create(Context, CurContext, CaretLoc);
+
+  {
+    Decl *ManglingContextDecl;
+    if (MangleNumberingContext *MCtx =
+            getCurrentMangleNumberContext(Block->getDeclContext(),
+                                          ManglingContextDecl)) {
+      unsigned ManglingNumber = MCtx->getManglingNumber(Block);
+      Block->setBlockMangling(ManglingNumber, ManglingContextDecl);
+    }
+  }
+
   PushBlockScope(CurScope, Block);
   CurContext->addDecl(Block);
   if (CurScope)
@@ -9929,11 +9940,7 @@ void Sema::ActOnBlockArguments(SourceLocation CaretLoc, Declarator &ParamInfo,
   // Finally we can process decl attributes.
   ProcessDeclAttributes(CurScope, CurBlock->TheDecl, ParamInfo);
 
-  // Put the parameter variables in scope.  We can bail out immediately
-  // if we don't have any.
-  if (Params.empty())
-    return;
-
+  // Put the parameter variables in scope.
   for (BlockDecl::param_iterator AI = CurBlock->TheDecl->param_begin(),
          E = CurBlock->TheDecl->param_end(); AI != E; ++AI) {
     (*AI)->setOwningFunction(CurBlock->TheDecl);
@@ -10641,8 +10648,8 @@ void
 Sema::PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext,
                                       ReuseLambdaContextDecl_t,
                                       bool IsDecltype) {
-  Decl *LambdaContextDecl = ExprEvalContexts.back().LambdaContextDecl;
-  PushExpressionEvaluationContext(NewContext, LambdaContextDecl, IsDecltype);
+  Decl *ClosureContextDecl = ExprEvalContexts.back().ManglingContextDecl;
+  PushExpressionEvaluationContext(NewContext, ClosureContextDecl, IsDecltype);
 }
 
 void Sema::PopExpressionEvaluationContext() {
index 32cc176..bc99d58 100644 (file)
@@ -52,6 +52,72 @@ static bool isInInlineFunction(const DeclContext *DC) {
   return false;
 }
 
+MangleNumberingContext *
+Sema::getCurrentMangleNumberContext(DeclContext *DC,
+                                    Decl *&ManglingContextDecl) {
+  // Compute the context for allocating mangling numbers in the current
+  // expression, if the ABI requires them.
+  ManglingContextDecl = ExprEvalContexts.back().ManglingContextDecl;
+
+  enum ContextKind {
+    Normal,
+    DefaultArgument,
+    DataMember,
+    StaticDataMember
+  } Kind = Normal;
+
+  // Default arguments of member function parameters that appear in a class
+  // definition, as well as the initializers of data members, receive special
+  // treatment. Identify them.
+  if (ManglingContextDecl) {
+    if (ParmVarDecl *Param = dyn_cast<ParmVarDecl>(ManglingContextDecl)) {
+      if (const DeclContext *LexicalDC
+          = Param->getDeclContext()->getLexicalParent())
+        if (LexicalDC->isRecord())
+          Kind = DefaultArgument;
+    } else if (VarDecl *Var = dyn_cast<VarDecl>(ManglingContextDecl)) {
+      if (Var->getDeclContext()->isRecord())
+        Kind = StaticDataMember;
+    } else if (isa<FieldDecl>(ManglingContextDecl)) {
+      Kind = DataMember;
+    }
+  }
+
+  // Itanium ABI [5.1.7]:
+  //   In the following contexts [...] the one-definition rule requires closure
+  //   types in different translation units to "correspond":
+  bool IsInNonspecializedTemplate =
+    !ActiveTemplateInstantiations.empty() || CurContext->isDependentContext();
+  switch (Kind) {
+  case Normal:
+    //  -- the bodies of non-exported nonspecialized template functions
+    //  -- the bodies of inline functions
+    if ((IsInNonspecializedTemplate &&
+         !(ManglingContextDecl && isa<ParmVarDecl>(ManglingContextDecl))) ||
+        isInInlineFunction(CurContext)) {
+      ManglingContextDecl = 0;
+      return &Context.getManglingNumberContext(DC);
+    }
+
+    ManglingContextDecl = 0;
+    return 0;
+
+  case StaticDataMember:
+    //  -- the initializers of nonspecialized static members of template classes
+    if (!IsInNonspecializedTemplate) {
+      ManglingContextDecl = 0;
+      return 0;
+    }
+    // Fall through to get the current context.
+
+  case DataMember:
+    //  -- the in-class initializers of class members
+  case DefaultArgument:
+    //  -- default arguments appearing in class definitions
+    return &ExprEvalContexts.back().getMangleNumberingContext();
+  }
+}
+
 CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class,
                  SourceRange IntroducerRange,
                  TypeSourceInfo *MethodType,
@@ -98,75 +164,14 @@ CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class,
       (*P)->setOwningFunction(Method);
   }
 
-  // Allocate a mangling number for this lambda expression, if the ABI
-  // requires one.
-  Decl *ContextDecl = ExprEvalContexts.back().LambdaContextDecl;
-
-  enum ContextKind {
-    Normal,
-    DefaultArgument,
-    DataMember,
-    StaticDataMember
-  } Kind = Normal;
-
-  // Default arguments of member function parameters that appear in a class
-  // definition, as well as the initializers of data members, receive special
-  // treatment. Identify them.
-  if (ContextDecl) {
-    if (ParmVarDecl *Param = dyn_cast<ParmVarDecl>(ContextDecl)) {
-      if (const DeclContext *LexicalDC
-          = Param->getDeclContext()->getLexicalParent())
-        if (LexicalDC->isRecord())
-          Kind = DefaultArgument;
-    } else if (VarDecl *Var = dyn_cast<VarDecl>(ContextDecl)) {
-      if (Var->getDeclContext()->isRecord())
-        Kind = StaticDataMember;
-    } else if (isa<FieldDecl>(ContextDecl)) {
-      Kind = DataMember;
-    }
-  }
-
-  // Itanium ABI [5.1.7]:
-  //   In the following contexts [...] the one-definition rule requires closure
-  //   types in different translation units to "correspond":
-  bool IsInNonspecializedTemplate =
-    !ActiveTemplateInstantiations.empty() || CurContext->isDependentContext();
-  unsigned ManglingNumber;
-  switch (Kind) {
-  case Normal:
-    //  -- the bodies of non-exported nonspecialized template functions
-    //  -- the bodies of inline functions
-    if ((IsInNonspecializedTemplate &&
-         !(ContextDecl && isa<ParmVarDecl>(ContextDecl))) ||
-        isInInlineFunction(CurContext))
-      ManglingNumber = Context.getLambdaManglingNumber(Method);
-    else
-      ManglingNumber = 0;
-
-    // There is no special context for this lambda.
-    ContextDecl = 0;
-    break;
-
-  case StaticDataMember:
-    //  -- the initializers of nonspecialized static members of template classes
-    if (!IsInNonspecializedTemplate) {
-      ManglingNumber = 0;
-      ContextDecl = 0;
-      break;
-    }
-    // Fall through to assign a mangling number.
-
-  case DataMember:
-    //  -- the in-class initializers of class members
-  case DefaultArgument:
-    //  -- default arguments appearing in class definitions
-    ManglingNumber = ExprEvalContexts.back().getLambdaMangleContext()
-                       .getManglingNumber(Method);
-    break;
+  Decl *ManglingContextDecl;
+  if (MangleNumberingContext *MCtx =
+          getCurrentMangleNumberContext(Class->getDeclContext(),
+                                        ManglingContextDecl)) {
+    unsigned ManglingNumber = MCtx->getManglingNumber(Method);
+    Class->setLambdaMangling(ManglingNumber, ManglingContextDecl);
   }
 
-  Class->setLambdaMangling(ManglingNumber, ContextDecl);
-
   return Method;
 }
 
index cb2bf75..39f59a3 100644 (file)
@@ -14,7 +14,7 @@ namespace PR12746 {
   }
 
   // CHECK: define internal zeroext i1 @___ZN7PR127462f1EPi_block_invoke
-  // CHECK: call zeroext i1 @"_ZNK23__block_prefix_internal3$_0clEv"
+  // CHECK: call zeroext i1 @"_ZNK7PR127462f1Ub_3$_0clEv"
 
   bool f2(int *x) {
     auto outer = [&]() -> bool {
index 20cc7b4..6493135 100644 (file)
@@ -1,13 +1,14 @@
 // RUN: %clang_cc1 -emit-llvm -fblocks -o - -triple x86_64-apple-darwin10 -fobjc-runtime=macosx-fragile-10.5 %s | FileCheck %s
 
-// CHECK: @_ZGVN23__block_prefix_internal5valueE = internal global i64 0
-// CHECK: @_ZN24__block_prefix_internal35namebE = internal global i8*
+// CHECK: @_ZGVN3fooUb_5valueE = internal global i64 0
+// CHECK: @_ZN26externally_visible_statics1SUb_1jE = linkonce_odr global i32 0
+// CHECK: @_ZN26externally_visible_statics10inlinefuncUb_1iE = linkonce_odr global i32 0
 
 int f();
 
 void foo() {
   // CHECK: define internal i32 @___Z3foov_block_invoke
-  // CHECK: call i32 @__cxa_guard_acquire(i64* @_ZGVN23__block_prefix_internal5valueE
+  // CHECK: call i32 @__cxa_guard_acquire(i64* @_ZGVN3fooUb_5valueE
   (void)^(int x) { 
     static int value = f();
     return x + value;
@@ -25,7 +26,7 @@ int i = ^(int x) { return x;}(i);
 - (void)method { 
   // CHECK: define internal signext i8 @"__11-[A method]_block_invoke"
   (void)^(int x) {
-    // CHECK: @_ZN24__block_prefix_internal04nameE
+    // CHECK: @"_ZN11-[A method]Ub0_4nameE"
     static const char *name = "hello";
     return name[x];
   };
@@ -43,7 +44,7 @@ namespace N {
   // CHECK: define internal signext i8 @___Z3fooi_block_invoke
   void bar() {
     (void)^(int x) { 
-      // CHECK: @_ZN24__block_prefix_internal14nameE
+      // CHECK: @_ZN1N3barUb2_4nameE
       static const char *name = "hello";
       return name[x];
     };
@@ -55,8 +56,33 @@ class C {
 };
 C::C() {
   (void)^(int x) { 
-    // CHECK: @_ZN24__block_prefix_internal35namebE
+    // CHECK: @_ZN1CC1Ub3_5namebE
     static const char *nameb = "hello";
     return nameb[x];
   };
 }
+
+int f();
+namespace externally_visible_statics {
+  inline void inlinefunc() {
+    ^{
+      static int i = f();
+    }();
+  }
+  struct S {
+    int x = ^{
+      static int j = f();
+      return j;
+    }();
+    void foo(int y = ^{ static int k = f(); return k; }()) {}
+  };
+  void g() {
+    inlinefunc();
+    S s;
+#if 0
+    // FIXME: We know how to mangle k, but crash trying to mangle the
+    // block itself.
+    s.foo();
+#endif
+  }
+}