#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"
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;
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);
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);
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.
-//===--- LambdaMangleContext.h - Context for mangling lambdas ---*- C++ -*-===//
+//=== MangleNumberingContext.h - Context for mangling numbers ---*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
//
//===----------------------------------------------------------------------===//
//
-// 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
#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"
/// 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.
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 {
/// 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.
///
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;
}
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;
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)) {
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(),
// 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;
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.
-//===--- 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();
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];
+}
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());
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);
// 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.
}
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;
// 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;
/// 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();
/// 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)
// 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);
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() {
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,
(*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;
}
}
// 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 {
// 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;
- (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];
};
// 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];
};
};
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
+ }
+}