Move the computation of the lambda mangling information (mangling
number + context) to the point where we initially start defining the lambda, so that the linkage won't change when that information is made available. Fixes the assertion in <rdar://problem/11182962>. Plus, actually mangle the context of lambdas properly. llvm-svn: 154029
This commit is contained in:
parent
f18c03e49e
commit
b61e809b42
|
@ -621,7 +621,7 @@ class CXXRecordDecl : public RecordDecl {
|
|||
"queried lambda property of non-lambda class");
|
||||
return static_cast<LambdaDefinitionData &>(*DefinitionData);
|
||||
}
|
||||
|
||||
|
||||
/// \brief The template or declaration that this declaration
|
||||
/// describes or was instantiated from, respectively.
|
||||
///
|
||||
|
@ -1503,6 +1503,13 @@ public:
|
|||
return getLambdaData().ContextDecl;
|
||||
}
|
||||
|
||||
/// \brief Set the mangling number and context declaration for a lambda
|
||||
/// class.
|
||||
void setLambdaMangling(unsigned ManglingNumber, Decl *ContextDecl) {
|
||||
getLambdaData().ManglingNumber = ManglingNumber;
|
||||
getLambdaData().ContextDecl = ContextDecl;
|
||||
}
|
||||
|
||||
/// \brief Determine whether this lambda expression was known to be dependent
|
||||
/// at the time it was created, even if its context does not appear to be
|
||||
/// dependent.
|
||||
|
|
|
@ -1231,9 +1231,7 @@ private:
|
|||
ArrayRef<Expr *> CaptureInits,
|
||||
ArrayRef<VarDecl *> ArrayIndexVars,
|
||||
ArrayRef<unsigned> ArrayIndexStarts,
|
||||
SourceLocation ClosingBrace,
|
||||
unsigned ManglingNumber,
|
||||
Decl *ContextDecl);
|
||||
SourceLocation ClosingBrace);
|
||||
|
||||
/// \brief Construct an empty lambda expression.
|
||||
LambdaExpr(EmptyShell Empty, unsigned NumCaptures, bool HasArrayIndexVars)
|
||||
|
@ -1271,9 +1269,7 @@ public:
|
|||
ArrayRef<Expr *> CaptureInits,
|
||||
ArrayRef<VarDecl *> ArrayIndexVars,
|
||||
ArrayRef<unsigned> ArrayIndexStarts,
|
||||
SourceLocation ClosingBrace,
|
||||
unsigned ManglingNumber,
|
||||
Decl *ContextDecl);
|
||||
SourceLocation ClosingBrace);
|
||||
|
||||
/// \brief Construct a new lambda expression that will be deserialized from
|
||||
/// an external source.
|
||||
|
|
|
@ -3700,7 +3700,10 @@ public:
|
|||
SourceRange IntroducerRange,
|
||||
TypeSourceInfo *MethodType,
|
||||
SourceLocation EndLoc,
|
||||
llvm::ArrayRef<ParmVarDecl *> Params);
|
||||
llvm::ArrayRef<ParmVarDecl *> Params,
|
||||
llvm::Optional<unsigned> ManglingNumber
|
||||
= llvm::Optional<unsigned>(),
|
||||
Decl *ContextDecl = 0);
|
||||
|
||||
/// \brief Introduce the scope for a lambda expression.
|
||||
sema::LambdaScopeInfo *enterLambdaScope(CXXMethodDecl *CallOperator,
|
||||
|
@ -3733,9 +3736,6 @@ public:
|
|||
/// was successfully completed.
|
||||
ExprResult ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body,
|
||||
Scope *CurScope,
|
||||
llvm::Optional<unsigned> ManglingNumber
|
||||
= llvm::Optional<unsigned>(),
|
||||
Decl *ContextDecl = 0,
|
||||
bool IsInstantiation = false);
|
||||
|
||||
/// \brief Define the "body" of the conversion from a lambda object to a
|
||||
|
|
|
@ -796,9 +796,7 @@ LambdaExpr::LambdaExpr(QualType T,
|
|||
ArrayRef<Expr *> CaptureInits,
|
||||
ArrayRef<VarDecl *> ArrayIndexVars,
|
||||
ArrayRef<unsigned> ArrayIndexStarts,
|
||||
SourceLocation ClosingBrace,
|
||||
unsigned ManglingNumber,
|
||||
Decl *ContextDecl)
|
||||
SourceLocation ClosingBrace)
|
||||
: Expr(LambdaExprClass, T, VK_RValue, OK_Ordinary,
|
||||
T->isDependentType(), T->isDependentType(), T->isDependentType(),
|
||||
/*ContainsUnexpandedParameterPack=*/false),
|
||||
|
@ -819,8 +817,6 @@ LambdaExpr::LambdaExpr(QualType T,
|
|||
ASTContext &Context = Class->getASTContext();
|
||||
Data.NumCaptures = NumCaptures;
|
||||
Data.NumExplicitCaptures = 0;
|
||||
Data.ManglingNumber = ManglingNumber;
|
||||
Data.ContextDecl = ContextDecl;
|
||||
Data.Captures = (Capture *)Context.Allocate(sizeof(Capture) * NumCaptures);
|
||||
Capture *ToCapture = Data.Captures;
|
||||
for (unsigned I = 0, N = Captures.size(); I != N; ++I) {
|
||||
|
@ -848,9 +844,6 @@ LambdaExpr::LambdaExpr(QualType T,
|
|||
sizeof(unsigned) * Captures.size());
|
||||
getArrayIndexStarts()[Captures.size()] = ArrayIndexVars.size();
|
||||
}
|
||||
|
||||
if (ManglingNumber)
|
||||
Class->ClearLinkageCache();
|
||||
}
|
||||
|
||||
LambdaExpr *LambdaExpr::Create(ASTContext &Context,
|
||||
|
@ -863,9 +856,7 @@ LambdaExpr *LambdaExpr::Create(ASTContext &Context,
|
|||
ArrayRef<Expr *> CaptureInits,
|
||||
ArrayRef<VarDecl *> ArrayIndexVars,
|
||||
ArrayRef<unsigned> ArrayIndexStarts,
|
||||
SourceLocation ClosingBrace,
|
||||
unsigned ManglingNumber,
|
||||
Decl *ContextDecl) {
|
||||
SourceLocation ClosingBrace) {
|
||||
// Determine the type of the expression (i.e., the type of the
|
||||
// function object we're creating).
|
||||
QualType T = Context.getTypeDeclType(Class);
|
||||
|
@ -878,7 +869,7 @@ LambdaExpr *LambdaExpr::Create(ASTContext &Context,
|
|||
return new (Mem) LambdaExpr(T, IntroducerRange, CaptureDefault,
|
||||
Captures, ExplicitParams, ExplicitResultType,
|
||||
CaptureInits, ArrayIndexVars, ArrayIndexStarts,
|
||||
ClosingBrace, ManglingNumber, ContextDecl);
|
||||
ClosingBrace);
|
||||
}
|
||||
|
||||
LambdaExpr *LambdaExpr::CreateDeserialized(ASTContext &C, unsigned NumCaptures,
|
||||
|
|
|
@ -535,6 +535,14 @@ isTemplate(const NamedDecl *ND, const TemplateArgumentList *&TemplateArgs) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool isLambda(const NamedDecl *ND) {
|
||||
const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(ND);
|
||||
if (!Record)
|
||||
return false;
|
||||
|
||||
return Record->isLambda();
|
||||
}
|
||||
|
||||
void CXXNameMangler::mangleName(const NamedDecl *ND) {
|
||||
// <name> ::= <nested-name>
|
||||
// ::= <unscoped-name>
|
||||
|
@ -545,7 +553,9 @@ void CXXNameMangler::mangleName(const NamedDecl *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())
|
||||
// FIXME: This is a hack; extern variables declared locally should have
|
||||
// a proper semantic declaration context!
|
||||
if (isa<FunctionDecl>(DC) && ND->hasLinkage() && !isLambda(ND))
|
||||
while (!DC->isNamespace() && !DC->isTranslationUnit())
|
||||
DC = getEffectiveParentContext(DC);
|
||||
else if (GetLocalClassDecl(ND)) {
|
||||
|
|
|
@ -36,11 +36,27 @@ CXXRecordDecl *Sema::createLambdaClosureType(SourceRange IntroducerRange,
|
|||
return Class;
|
||||
}
|
||||
|
||||
/// \brief Determine whether the given context is or is enclosed in an inline
|
||||
/// function.
|
||||
static bool isInInlineFunction(const DeclContext *DC) {
|
||||
while (!DC->isFileContext()) {
|
||||
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(DC))
|
||||
if (FD->isInlined())
|
||||
return true;
|
||||
|
||||
DC = DC->getLexicalParent();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class,
|
||||
SourceRange IntroducerRange,
|
||||
TypeSourceInfo *MethodType,
|
||||
SourceLocation EndLoc,
|
||||
llvm::ArrayRef<ParmVarDecl *> Params) {
|
||||
SourceRange IntroducerRange,
|
||||
TypeSourceInfo *MethodType,
|
||||
SourceLocation EndLoc,
|
||||
llvm::ArrayRef<ParmVarDecl *> Params,
|
||||
llvm::Optional<unsigned> ManglingNumber,
|
||||
Decl *ContextDecl) {
|
||||
// C++11 [expr.prim.lambda]p5:
|
||||
// The closure type for a lambda-expression has a public inline function
|
||||
// call operator (13.5.4) whose parameters and return type are described by
|
||||
|
@ -83,6 +99,63 @@ CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class,
|
|||
(*P)->setOwningFunction(Method);
|
||||
}
|
||||
|
||||
// If we don't already have a mangling number for this lambda expression,
|
||||
// allocate one now.
|
||||
if (!ManglingNumber) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
switch (Kind) {
|
||||
case Normal:
|
||||
if (CurContext->isDependentContext() || isInInlineFunction(CurContext))
|
||||
ManglingNumber = Context.getLambdaManglingNumber(Method);
|
||||
else
|
||||
ManglingNumber = 0;
|
||||
|
||||
// There is no special context for this lambda.
|
||||
ContextDecl = 0;
|
||||
break;
|
||||
|
||||
case StaticDataMember:
|
||||
if (!CurContext->isDependentContext()) {
|
||||
ManglingNumber = 0;
|
||||
ContextDecl = 0;
|
||||
break;
|
||||
}
|
||||
// Fall through to assign a mangling number.
|
||||
|
||||
case DataMember:
|
||||
case DefaultArgument:
|
||||
ManglingNumber = ExprEvalContexts.back().getLambdaMangleContext()
|
||||
.getManglingNumber(Method);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Class->setLambdaMangling(*ManglingNumber, ContextDecl);
|
||||
return Method;
|
||||
}
|
||||
|
||||
|
@ -491,25 +564,9 @@ static void addBlockPointerConversion(Sema &S,
|
|||
Conversion->setImplicit(true);
|
||||
Class->addDecl(Conversion);
|
||||
}
|
||||
|
||||
/// \brief Determine whether the given context is or is enclosed in an inline
|
||||
/// function.
|
||||
static bool isInInlineFunction(const DeclContext *DC) {
|
||||
while (!DC->isFileContext()) {
|
||||
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(DC))
|
||||
if (FD->isInlined())
|
||||
return true;
|
||||
|
||||
DC = DC->getLexicalParent();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body,
|
||||
Scope *CurScope,
|
||||
llvm::Optional<unsigned> ManglingNumber,
|
||||
Decl *ContextDecl,
|
||||
bool IsInstantiation) {
|
||||
// Collect information from the lambda scope.
|
||||
llvm::SmallVector<LambdaExpr::Capture, 4> Captures;
|
||||
|
@ -655,69 +712,12 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body,
|
|||
|
||||
if (LambdaExprNeedsCleanups)
|
||||
ExprNeedsCleanups = true;
|
||||
|
||||
// If we don't already have a mangling number for this lambda expression,
|
||||
// allocate one now.
|
||||
if (!ManglingNumber) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
switch (Kind) {
|
||||
case Normal:
|
||||
if (CurContext->isDependentContext() || isInInlineFunction(CurContext))
|
||||
ManglingNumber = Context.getLambdaManglingNumber(CallOperator);
|
||||
else
|
||||
ManglingNumber = 0;
|
||||
|
||||
// There is no special context for this lambda.
|
||||
ContextDecl = 0;
|
||||
break;
|
||||
|
||||
case StaticDataMember:
|
||||
if (!CurContext->isDependentContext()) {
|
||||
ManglingNumber = 0;
|
||||
ContextDecl = 0;
|
||||
break;
|
||||
}
|
||||
// Fall through to assign a mangling number.
|
||||
|
||||
case DataMember:
|
||||
case DefaultArgument:
|
||||
ManglingNumber = ExprEvalContexts.back().getLambdaMangleContext()
|
||||
.getManglingNumber(CallOperator);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
LambdaExpr *Lambda = LambdaExpr::Create(Context, Class, IntroducerRange,
|
||||
CaptureDefault, Captures,
|
||||
ExplicitParams, ExplicitResultType,
|
||||
CaptureInits, ArrayIndexVars,
|
||||
ArrayIndexStarts, Body->getLocEnd(),
|
||||
*ManglingNumber, ContextDecl);
|
||||
ArrayIndexStarts, Body->getLocEnd());
|
||||
|
||||
// C++11 [expr.prim.lambda]p2:
|
||||
// A lambda-expression shall not appear in an unevaluated operand
|
||||
|
|
|
@ -7815,7 +7815,8 @@ ExprResult
|
|||
TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
|
||||
// Create the local class that will describe the lambda.
|
||||
CXXRecordDecl *Class
|
||||
= getSema().createLambdaClosureType(E->getIntroducerRange());
|
||||
= getSema().createLambdaClosureType(E->getIntroducerRange(),
|
||||
/*KnownDependent=*/false);
|
||||
getDerived().transformedLocalDecl(E->getLambdaClass(), Class);
|
||||
|
||||
// Transform the type of the lambda parameters and start the definition of
|
||||
|
@ -7836,11 +7837,15 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
|
|||
Invalid = true;
|
||||
|
||||
// Build the call operator.
|
||||
// Note: Once a lambda mangling number and context declaration have been
|
||||
// assigned, they never change.
|
||||
unsigned ManglingNumber = E->getLambdaClass()->getLambdaManglingNumber();
|
||||
Decl *ContextDecl = E->getLambdaClass()->getLambdaContextDecl();
|
||||
CXXMethodDecl *CallOperator
|
||||
= getSema().startLambdaDefinition(Class, E->getIntroducerRange(),
|
||||
MethodTy,
|
||||
E->getCallOperator()->getLocEnd(),
|
||||
Params);
|
||||
Params, ManglingNumber, ContextDecl);
|
||||
getDerived().transformAttrs(E->getCallOperator(), CallOperator);
|
||||
|
||||
// FIXME: Instantiation-specific.
|
||||
|
@ -7953,14 +7958,8 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
|
|||
return ExprError();
|
||||
}
|
||||
|
||||
// Note: Once a lambda mangling number and context declaration have been
|
||||
// assigned, they never change.
|
||||
unsigned ManglingNumber = E->getLambdaClass()->getLambdaManglingNumber();
|
||||
Decl *ContextDecl = E->getLambdaClass()->getLambdaContextDecl();
|
||||
return getSema().ActOnLambdaExpr(E->getLocStart(), Body.take(),
|
||||
/*CurScope=*/0, ManglingNumber,
|
||||
ContextDecl,
|
||||
/*IsInstantiation=*/true);
|
||||
/*CurScope=*/0, /*IsInstantiation=*/true);
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
|
|
|
@ -150,6 +150,8 @@ void use_func_template() {
|
|||
func_template<int>();
|
||||
}
|
||||
|
||||
// CHECK: define linkonce_odr void @_Z1fIZZNK23TestNestedInstantiationclEvENKUlvE_clEvEUlvE_EvT_
|
||||
|
||||
struct Members {
|
||||
int x = [] { return 1; }() + [] { return 2; }();
|
||||
int y = [] { return 3; }();
|
||||
|
@ -165,6 +167,20 @@ void test_Members() {
|
|||
// CHECK: ret void
|
||||
}
|
||||
|
||||
template<typename P> void f(P) { }
|
||||
|
||||
struct TestNestedInstantiation {
|
||||
void operator()() const {
|
||||
[]() -> void {
|
||||
return f([]{});
|
||||
}();
|
||||
}
|
||||
};
|
||||
|
||||
void test_NestedInstantiation() {
|
||||
TestNestedInstantiation()();
|
||||
}
|
||||
|
||||
// Check the linkage of the lambdas used in test_Members.
|
||||
// CHECK: define linkonce_odr i32 @_ZNK7Members1xMUlvE_clEv
|
||||
// CHECK: ret i32 1
|
||||
|
|
Loading…
Reference in New Issue