WIP Patch: Introduce a proper mangling scheme for block literals
Eli Friedman
eli.friedman at gmail.com
Fri Jun 21 18:19:55 PDT 2013
On Tue, Jun 18, 2013 at 6:41 PM, John McCall <rjmccall at apple.com> wrote:
> On Jun 12, 2013, at 4:42 PM, Eli Friedman <eli.friedman at gmail.com> wrote:
>
> Take a C++ function like the following:
>
> inline void f() {
> ^{
> static int i = 0;
> printf("%d\n", ++i);
> }();
> }
>
> Looks pretty simple, right? Unfortunately, trunk clang doesn't handle
> this correctly. The primary issue here is we haven't defined the correct
> way to mangle the name of "i", and clang's current scheme is unusable
> because it depends on the details of IRGen. (There's also the matter that
> we don't compute the linkage correctly, but that's a simple IRGen bug.)
>
> I'm attaching a patch which expands the scheme we use for mangling lambda
> expressions in this sort of context to also work for block literals. The
> patch is still a bit of a mess: there's a bunch of copy-paste code I still
> need to clean up, I haven't included tests, and it would probably be nice
> to include the parameter types of the block in the mangling. That said, it
> essentially implements everything necessary.
>
>
> Unlike lambdas, we never actually need to mangle a block declaration; we
> just encounter it as a context for local statics and types. And much like
> we do with lambdas, we should just ignore the block as a context and mangle
> the static/type as a local declaration within the actual enclosing
> declaration.
>
We discussed this in person; basically, we do in fact mangle lambdas into
the context.
> Note that this doesn't touch the mangling scheme for the actual function
> definitions for blocks; they don't need to be externally visible, so we
> don't need to change the current mangling.
>
> I'd like some feedback to make sure my patch is actually implementing
> something sane.
>
>
> Other than the mangling scheme, this seems reasonable.
>
> Any suggestions for a better name than LambdaBlockMangleContext are also
> welcome.
>
>
> How about ClosureOwningContext?
>
I ended up choosing MangleNumberingContext, given that we might need to add
more to it in the future (e.g. static local variables).
Attaching updated patch; this fixes some details like avoiding some of the
code duplication, fixing the mangling so it makes a bit more sense, and
includes some fixes to make our linkage computations for static local
variables a bit more accurate.
-Eli
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20130621/57891b1b/attachment.html>
-------------- next part --------------
Index: include/clang/AST/ASTContext.h
===================================================================
--- include/clang/AST/ASTContext.h (revision 184607)
+++ include/clang/AST/ASTContext.h (working copy)
@@ -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"
@@ -337,9 +337,11 @@
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;
@@ -2104,9 +2106,10 @@
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: include/clang/AST/Decl.h
===================================================================
--- include/clang/AST/Decl.h (revision 184607)
+++ include/clang/AST/Decl.h (working copy)
@@ -3137,13 +3137,17 @@
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);
@@ -3213,6 +3217,18 @@
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.
Index: include/clang/AST/LambdaMangleContext.h
===================================================================
--- include/clang/AST/LambdaMangleContext.h (revision 184607)
+++ include/clang/AST/LambdaMangleContext.h (working copy)
@@ -1,38 +0,0 @@
-//===--- LambdaMangleContext.h - Context for mangling lambdas ---*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines the LambdaMangleContext interface, which keeps track of
-// the Itanium C++ ABI mangling numbers for lambda expressions.
-//
-//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_LAMBDAMANGLECONTEXT_H
-#define LLVM_CLANG_LAMBDAMANGLECONTEXT_H
-
-#include "clang/Basic/LLVM.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/IntrusiveRefCntPtr.h"
-
-namespace clang {
-
-class CXXMethodDecl;
-class FunctionProtoType;
-
-/// \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;
-
-public:
- /// \brief Retrieve the mangling number of a new lambda expression with the
- /// given call operator within this lambda context.
- unsigned getManglingNumber(CXXMethodDecl *CallOperator);
-};
-
-} // end namespace clang
-#endif
Index: include/clang/AST/MangleNumberingContext.h
===================================================================
--- include/clang/AST/MangleNumberingContext.h (working copy)
+++ include/clang/AST/MangleNumberingContext.h (working copy)
@@ -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"
@@ -20,18 +21,24 @@
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: include/clang/Sema/Sema.h
===================================================================
--- include/clang/Sema/Sema.h (revision 184607)
+++ include/clang/Sema/Sema.h (working copy)
@@ -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 @@
/// 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 @@
ExpressionEvaluationContextRecord(ExpressionEvaluationContext Context,
unsigned NumCleanupObjects,
bool ParentNeedsCleanups,
- Decl *LambdaContextDecl,
+ Decl *ManglingContextDecl,
bool IsDecltype)
: Context(Context), ParentNeedsCleanups(ParentNeedsCleanups),
IsDecltype(IsDecltype), NumCleanupObjects(NumCleanupObjects),
- LambdaContextDecl(LambdaContextDecl), LambdaMangle() { }
+ ManglingContextDecl(ManglingContextDecl), MangleNumbering() { }
- /// \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;
+ /// \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 @@
/// 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: lib/AST/ASTContext.cpp
===================================================================
--- lib/AST/ASTContext.cpp (revision 184607)
+++ lib/AST/ASTContext.cpp (working copy)
@@ -8017,13 +8017,10 @@
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: lib/AST/Decl.cpp
===================================================================
--- lib/AST/Decl.cpp (revision 184607)
+++ lib/AST/Decl.cpp (working copy)
@@ -287,13 +287,12 @@
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 @@
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 @@
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();
- LinkageInfo LV = getLVForDecl(FD, computation);
+ 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();
+
+ LV = getLVForDecl(FD, computation);
+ }
if (!isExternallyVisible(LV.getLinkage()))
return LinkageInfo::none();
return LinkageInfo(VisibleNoLinkage, LV.getVisibility(),
@@ -1095,20 +1121,10 @@
// 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();
+ return getLVForClosure(D->getDeclContext()->getRedeclContext(),
+ Record->getLambdaContextDecl(), computation);
}
break;
Index: lib/AST/ItaniumMangle.cpp
===================================================================
--- lib/AST/ItaniumMangle.cpp (revision 184607)
+++ lib/AST/ItaniumMangle.cpp (working copy)
@@ -1415,12 +1415,24 @@
return;
if (const BlockDecl *Block = dyn_cast<BlockDecl>(DC)) {
- manglePrefix(getEffectiveParentContext(DC), NoFunction);
- SmallString<64> Name;
- llvm::raw_svector_ostream NameStream(Name);
- Context.mangleBlock(Block, NameStream);
- NameStream.flush();
- Out << Name.size() << Name;
+ manglePrefix(getEffectiveParentContext(DC), NoFunction);
+ if (unsigned Number = Block->getBlockManglingNumber()) {
+ // If we have a mangling number, add a prefix for the block.
+ SmallString<16> BlockPrefix;
+ BlockPrefix += "__block_prefix";
+ if (Number > 1)
+ BlockPrefix += llvm::utostr_32(Number - 2);
+ Out << BlockPrefix.size() << BlockPrefix;
+ return;
+ }
+ // Otherwise, the symbol we're adding a prefix for isn't externally
+ // visible; make up something sane.
+ SmallString<16> BlockPrefix;
+ BlockPrefix += "__block_prefix_internal";
+ unsigned Number = Context.getBlockId(Block, false);
+ if (Number > 1)
+ BlockPrefix += llvm::utostr_32(Number - 2);
+ Out << BlockPrefix.size() << BlockPrefix;
return;
} else if (isa<CapturedDecl>(DC)) {
// Skip CapturedDecl context.
Index: lib/AST/LambdaMangleContext.cpp
===================================================================
--- lib/AST/LambdaMangleContext.cpp (revision 184607)
+++ lib/AST/LambdaMangleContext.cpp (working copy)
@@ -1,30 +0,0 @@
-//===--- LambdaMangleContext.cpp - Context for mangling lambdas -*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines the LambdaMangleContext class, which keeps track of
-// the Itanium C++ ABI mangling numbers for lambda expressions.
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/AST/LambdaMangleContext.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/DeclCXX.h"
-
-using namespace clang;
-
-unsigned LambdaMangleContext::getManglingNumber(CXXMethodDecl *CallOperator) {
- const FunctionProtoType *Proto
- = CallOperator->getType()->getAs<FunctionProtoType>();
- ASTContext &Context = CallOperator->getASTContext();
-
- QualType Key = Context.getFunctionType(Context.VoidTy, Proto->getArgTypes(),
- FunctionProtoType::ExtProtoInfo());
- Key = Context.getCanonicalType(Key);
- return ++ManglingNumbers[Key->castAs<FunctionProtoType>()];
-}
Index: lib/AST/MangleNumberingContext.cpp
===================================================================
--- lib/AST/MangleNumberingContext.cpp (working copy)
+++ lib/AST/MangleNumberingContext.cpp (working copy)
@@ -1,4 +1,4 @@
-//===--- LambdaMangleContext.cpp - Context for mangling lambdas -*- C++ -*-===//
+//===--- MangleNumberingContext.cpp - Context for mangling numbers --------===//
//
// The LLVM Compiler Infrastructure
//
@@ -12,13 +12,14 @@
//
//===----------------------------------------------------------------------===//
-#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 @@
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: lib/CodeGen/CGDecl.cpp
===================================================================
--- lib/CodeGen/CGDecl.cpp (revision 184607)
+++ lib/CodeGen/CGDecl.cpp (working copy)
@@ -130,9 +130,27 @@
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 @@
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: lib/CodeGen/CodeGenModule.cpp
===================================================================
--- lib/CodeGen/CodeGenModule.cpp (revision 184607)
+++ lib/CodeGen/CodeGenModule.cpp (working copy)
@@ -1789,7 +1789,7 @@
// 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.
@@ -1820,8 +1820,7 @@
}
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;
@@ -1836,7 +1835,7 @@
// 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: lib/CodeGen/CodeGenModule.h
===================================================================
--- lib/CodeGen/CodeGenModule.h (revision 184607)
+++ lib/CodeGen/CodeGenModule.h (working copy)
@@ -942,8 +942,7 @@
/// 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: lib/Sema/SemaExpr.cpp
===================================================================
--- lib/Sema/SemaExpr.cpp (revision 184607)
+++ lib/Sema/SemaExpr.cpp (working copy)
@@ -9816,6 +9816,17 @@
/// 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)
@@ -9935,11 +9946,7 @@
// 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);
@@ -10647,8 +10654,8 @@
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: lib/Sema/SemaLambda.cpp
===================================================================
--- lib/Sema/SemaLambda.cpp (revision 184607)
+++ lib/Sema/SemaLambda.cpp (working copy)
@@ -52,6 +52,72 @@
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 @@
(*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;
- }
+ Decl *ManglingContextDecl;
+ if (MangleNumberingContext *MCtx =
+ getCurrentMangleNumberContext(Class->getDeclContext(),
+ ManglingContextDecl)) {
+ unsigned ManglingNumber = MCtx->getManglingNumber(Method);
+ Class->setLambdaMangling(ManglingNumber, ManglingContextDecl);
}
- // 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;
- }
-
- Class->setLambdaMangling(ManglingNumber, ContextDecl);
-
return Method;
}
Index: test/CXX/expr/expr.prim/expr.prim.lambda/blocks-irgen.mm
===================================================================
--- test/CXX/expr/expr.prim/expr.prim.lambda/blocks-irgen.mm (revision 184607)
+++ test/CXX/expr/expr.prim/expr.prim.lambda/blocks-irgen.mm (working copy)
@@ -14,7 +14,7 @@
}
// CHECK: define internal zeroext i1 @___ZN7PR127462f1EPi_block_invoke
- // CHECK: call zeroext i1 @"_ZNK7PR127462f132___ZN7PR127462f1EPi_block_invoke3$_0clEv"
+ // CHECK: call zeroext i1 @"_ZNK7PR127462f123__block_prefix_internal3$_0clEv"
bool f2(int *x) {
auto outer = [&]() -> bool {
Index: test/CodeGenObjCXX/mangle-blocks.mm
===================================================================
--- test/CodeGenObjCXX/mangle-blocks.mm (revision 184607)
+++ test/CodeGenObjCXX/mangle-blocks.mm (working copy)
@@ -1,12 +1,14 @@
// RUN: %clang_cc1 -emit-llvm -fblocks -o - -triple x86_64-apple-darwin10 -fobjc-runtime=macosx-fragile-10.5 %s | FileCheck %s
-// CHECK: @_ZGVN3foo22___Z3foov_block_invoke5valueE = internal global i64 0
+// CHECK: @_ZGVN3foo23__block_prefix_internal5valueE = internal global i64 0
+// CHECK: @_ZN26externally_visible_statics1S14__block_prefix1jE = linkonce_odr global i32 0
+// CHECK: @_ZN26externally_visible_statics10inlinefunc14__block_prefix1iE = linkonce_odr global i32 0
int f();
void foo() {
// CHECK: define internal i32 @___Z3foov_block_invoke
- // CHECK: call i32 @__cxa_guard_acquire(i64* @_ZGVN3foo22___Z3foov_block_invoke5valueE
+ // CHECK: call i32 @__cxa_guard_acquire(i64* @_ZGVN3foo23__block_prefix_internal5valueE
(void)^(int x) {
static int value = f();
return x + value;
@@ -24,7 +26,7 @@
- (void)method {
// CHECK: define internal signext i8 @"__11-[A method]_block_invoke"
(void)^(int x) {
- // CHECK: @"_ZN11-[A method]28__11-[A method]_block_invoke4nameE"
+ // CHECK: @"_ZN11-[A method]24__block_prefix_internal04nameE"
static const char *name = "hello";
return name[x];
};
@@ -42,9 +44,35 @@
// CHECK: define internal signext i8 @___Z3fooi_block_invoke
void bar() {
(void)^(int x) {
- // CHECK: @_ZN1N3bar26___ZN1N3barEv_block_invoke4nameE
+ // CHECK: @_ZN1N3bar24__block_prefix_internal24nameE
static const char *name = "hello";
return name[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
+ }
+}
+
More information about the cfe-commits
mailing list