Skip to content
This repository was archived by the owner on Nov 1, 2021. It is now read-only.

Commit f54486a

Browse files
committed
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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@154029 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 8e86b2d commit f54486a

File tree

8 files changed

+130
-111
lines changed

8 files changed

+130
-111
lines changed

Diff for: include/clang/AST/DeclCXX.h

+8-1
Original file line numberDiff line numberDiff line change
@@ -621,7 +621,7 @@ class CXXRecordDecl : public RecordDecl {
621621
"queried lambda property of non-lambda class");
622622
return static_cast<LambdaDefinitionData &>(*DefinitionData);
623623
}
624-
624+
625625
/// \brief The template or declaration that this declaration
626626
/// describes or was instantiated from, respectively.
627627
///
@@ -1503,6 +1503,13 @@ class CXXRecordDecl : public RecordDecl {
15031503
return getLambdaData().ContextDecl;
15041504
}
15051505

1506+
/// \brief Set the mangling number and context declaration for a lambda
1507+
/// class.
1508+
void setLambdaMangling(unsigned ManglingNumber, Decl *ContextDecl) {
1509+
getLambdaData().ManglingNumber = ManglingNumber;
1510+
getLambdaData().ContextDecl = ContextDecl;
1511+
}
1512+
15061513
/// \brief Determine whether this lambda expression was known to be dependent
15071514
/// at the time it was created, even if its context does not appear to be
15081515
/// dependent.

Diff for: include/clang/AST/ExprCXX.h

+2-6
Original file line numberDiff line numberDiff line change
@@ -1231,9 +1231,7 @@ class LambdaExpr : public Expr {
12311231
ArrayRef<Expr *> CaptureInits,
12321232
ArrayRef<VarDecl *> ArrayIndexVars,
12331233
ArrayRef<unsigned> ArrayIndexStarts,
1234-
SourceLocation ClosingBrace,
1235-
unsigned ManglingNumber,
1236-
Decl *ContextDecl);
1234+
SourceLocation ClosingBrace);
12371235

12381236
/// \brief Construct an empty lambda expression.
12391237
LambdaExpr(EmptyShell Empty, unsigned NumCaptures, bool HasArrayIndexVars)
@@ -1271,9 +1269,7 @@ class LambdaExpr : public Expr {
12711269
ArrayRef<Expr *> CaptureInits,
12721270
ArrayRef<VarDecl *> ArrayIndexVars,
12731271
ArrayRef<unsigned> ArrayIndexStarts,
1274-
SourceLocation ClosingBrace,
1275-
unsigned ManglingNumber,
1276-
Decl *ContextDecl);
1272+
SourceLocation ClosingBrace);
12771273

12781274
/// \brief Construct a new lambda expression that will be deserialized from
12791275
/// an external source.

Diff for: include/clang/Sema/Sema.h

+4-4
Original file line numberDiff line numberDiff line change
@@ -3700,7 +3700,10 @@ class Sema {
37003700
SourceRange IntroducerRange,
37013701
TypeSourceInfo *MethodType,
37023702
SourceLocation EndLoc,
3703-
llvm::ArrayRef<ParmVarDecl *> Params);
3703+
llvm::ArrayRef<ParmVarDecl *> Params,
3704+
llvm::Optional<unsigned> ManglingNumber
3705+
= llvm::Optional<unsigned>(),
3706+
Decl *ContextDecl = 0);
37043707

37053708
/// \brief Introduce the scope for a lambda expression.
37063709
sema::LambdaScopeInfo *enterLambdaScope(CXXMethodDecl *CallOperator,
@@ -3733,9 +3736,6 @@ class Sema {
37333736
/// was successfully completed.
37343737
ExprResult ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body,
37353738
Scope *CurScope,
3736-
llvm::Optional<unsigned> ManglingNumber
3737-
= llvm::Optional<unsigned>(),
3738-
Decl *ContextDecl = 0,
37393739
bool IsInstantiation = false);
37403740

37413741
/// \brief Define the "body" of the conversion from a lambda object to a

Diff for: lib/AST/ExprCXX.cpp

+3-12
Original file line numberDiff line numberDiff line change
@@ -796,9 +796,7 @@ LambdaExpr::LambdaExpr(QualType T,
796796
ArrayRef<Expr *> CaptureInits,
797797
ArrayRef<VarDecl *> ArrayIndexVars,
798798
ArrayRef<unsigned> ArrayIndexStarts,
799-
SourceLocation ClosingBrace,
800-
unsigned ManglingNumber,
801-
Decl *ContextDecl)
799+
SourceLocation ClosingBrace)
802800
: Expr(LambdaExprClass, T, VK_RValue, OK_Ordinary,
803801
T->isDependentType(), T->isDependentType(), T->isDependentType(),
804802
/*ContainsUnexpandedParameterPack=*/false),
@@ -819,8 +817,6 @@ LambdaExpr::LambdaExpr(QualType T,
819817
ASTContext &Context = Class->getASTContext();
820818
Data.NumCaptures = NumCaptures;
821819
Data.NumExplicitCaptures = 0;
822-
Data.ManglingNumber = ManglingNumber;
823-
Data.ContextDecl = ContextDecl;
824820
Data.Captures = (Capture *)Context.Allocate(sizeof(Capture) * NumCaptures);
825821
Capture *ToCapture = Data.Captures;
826822
for (unsigned I = 0, N = Captures.size(); I != N; ++I) {
@@ -848,9 +844,6 @@ LambdaExpr::LambdaExpr(QualType T,
848844
sizeof(unsigned) * Captures.size());
849845
getArrayIndexStarts()[Captures.size()] = ArrayIndexVars.size();
850846
}
851-
852-
if (ManglingNumber)
853-
Class->ClearLinkageCache();
854847
}
855848

856849
LambdaExpr *LambdaExpr::Create(ASTContext &Context,
@@ -863,9 +856,7 @@ LambdaExpr *LambdaExpr::Create(ASTContext &Context,
863856
ArrayRef<Expr *> CaptureInits,
864857
ArrayRef<VarDecl *> ArrayIndexVars,
865858
ArrayRef<unsigned> ArrayIndexStarts,
866-
SourceLocation ClosingBrace,
867-
unsigned ManglingNumber,
868-
Decl *ContextDecl) {
859+
SourceLocation ClosingBrace) {
869860
// Determine the type of the expression (i.e., the type of the
870861
// function object we're creating).
871862
QualType T = Context.getTypeDeclType(Class);
@@ -878,7 +869,7 @@ LambdaExpr *LambdaExpr::Create(ASTContext &Context,
878869
return new (Mem) LambdaExpr(T, IntroducerRange, CaptureDefault,
879870
Captures, ExplicitParams, ExplicitResultType,
880871
CaptureInits, ArrayIndexVars, ArrayIndexStarts,
881-
ClosingBrace, ManglingNumber, ContextDecl);
872+
ClosingBrace);
882873
}
883874

884875
LambdaExpr *LambdaExpr::CreateDeserialized(ASTContext &C, unsigned NumCaptures,

Diff for: lib/AST/ItaniumMangle.cpp

+11-1
Original file line numberDiff line numberDiff line change
@@ -535,6 +535,14 @@ isTemplate(const NamedDecl *ND, const TemplateArgumentList *&TemplateArgs) {
535535
return 0;
536536
}
537537

538+
static bool isLambda(const NamedDecl *ND) {
539+
const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(ND);
540+
if (!Record)
541+
return false;
542+
543+
return Record->isLambda();
544+
}
545+
538546
void CXXNameMangler::mangleName(const NamedDecl *ND) {
539547
// <name> ::= <nested-name>
540548
// ::= <unscoped-name>
@@ -545,7 +553,9 @@ void CXXNameMangler::mangleName(const NamedDecl *ND) {
545553

546554
// If this is an extern variable declared locally, the relevant DeclContext
547555
// is that of the containing namespace, or the translation unit.
548-
if (isa<FunctionDecl>(DC) && ND->hasLinkage())
556+
// FIXME: This is a hack; extern variables declared locally should have
557+
// a proper semantic declaration context!
558+
if (isa<FunctionDecl>(DC) && ND->hasLinkage() && !isLambda(ND))
549559
while (!DC->isNamespace() && !DC->isTranslationUnit())
550560
DC = getEffectiveParentContext(DC);
551561
else if (GetLocalClassDecl(ND)) {

Diff for: lib/Sema/SemaLambda.cpp

+78-78
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,27 @@ CXXRecordDecl *Sema::createLambdaClosureType(SourceRange IntroducerRange,
3636
return Class;
3737
}
3838

39+
/// \brief Determine whether the given context is or is enclosed in an inline
40+
/// function.
41+
static bool isInInlineFunction(const DeclContext *DC) {
42+
while (!DC->isFileContext()) {
43+
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(DC))
44+
if (FD->isInlined())
45+
return true;
46+
47+
DC = DC->getLexicalParent();
48+
}
49+
50+
return false;
51+
}
52+
3953
CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class,
40-
SourceRange IntroducerRange,
41-
TypeSourceInfo *MethodType,
42-
SourceLocation EndLoc,
43-
llvm::ArrayRef<ParmVarDecl *> Params) {
54+
SourceRange IntroducerRange,
55+
TypeSourceInfo *MethodType,
56+
SourceLocation EndLoc,
57+
llvm::ArrayRef<ParmVarDecl *> Params,
58+
llvm::Optional<unsigned> ManglingNumber,
59+
Decl *ContextDecl) {
4460
// C++11 [expr.prim.lambda]p5:
4561
// The closure type for a lambda-expression has a public inline function
4662
// call operator (13.5.4) whose parameters and return type are described by
@@ -83,6 +99,63 @@ CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class,
8399
(*P)->setOwningFunction(Method);
84100
}
85101

102+
// If we don't already have a mangling number for this lambda expression,
103+
// allocate one now.
104+
if (!ManglingNumber) {
105+
ContextDecl = ExprEvalContexts.back().LambdaContextDecl;
106+
107+
enum ContextKind {
108+
Normal,
109+
DefaultArgument,
110+
DataMember,
111+
StaticDataMember
112+
} Kind = Normal;
113+
114+
// Default arguments of member function parameters that appear in a class
115+
// definition, as well as the initializers of data members, receive special
116+
// treatment. Identify them.
117+
if (ContextDecl) {
118+
if (ParmVarDecl *Param = dyn_cast<ParmVarDecl>(ContextDecl)) {
119+
if (const DeclContext *LexicalDC
120+
= Param->getDeclContext()->getLexicalParent())
121+
if (LexicalDC->isRecord())
122+
Kind = DefaultArgument;
123+
} else if (VarDecl *Var = dyn_cast<VarDecl>(ContextDecl)) {
124+
if (Var->getDeclContext()->isRecord())
125+
Kind = StaticDataMember;
126+
} else if (isa<FieldDecl>(ContextDecl)) {
127+
Kind = DataMember;
128+
}
129+
}
130+
131+
switch (Kind) {
132+
case Normal:
133+
if (CurContext->isDependentContext() || isInInlineFunction(CurContext))
134+
ManglingNumber = Context.getLambdaManglingNumber(Method);
135+
else
136+
ManglingNumber = 0;
137+
138+
// There is no special context for this lambda.
139+
ContextDecl = 0;
140+
break;
141+
142+
case StaticDataMember:
143+
if (!CurContext->isDependentContext()) {
144+
ManglingNumber = 0;
145+
ContextDecl = 0;
146+
break;
147+
}
148+
// Fall through to assign a mangling number.
149+
150+
case DataMember:
151+
case DefaultArgument:
152+
ManglingNumber = ExprEvalContexts.back().getLambdaMangleContext()
153+
.getManglingNumber(Method);
154+
break;
155+
}
156+
}
157+
158+
Class->setLambdaMangling(*ManglingNumber, ContextDecl);
86159
return Method;
87160
}
88161

@@ -491,25 +564,9 @@ static void addBlockPointerConversion(Sema &S,
491564
Conversion->setImplicit(true);
492565
Class->addDecl(Conversion);
493566
}
494-
495-
/// \brief Determine whether the given context is or is enclosed in an inline
496-
/// function.
497-
static bool isInInlineFunction(const DeclContext *DC) {
498-
while (!DC->isFileContext()) {
499-
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(DC))
500-
if (FD->isInlined())
501-
return true;
502-
503-
DC = DC->getLexicalParent();
504-
}
505-
506-
return false;
507-
}
508567

509568
ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body,
510569
Scope *CurScope,
511-
llvm::Optional<unsigned> ManglingNumber,
512-
Decl *ContextDecl,
513570
bool IsInstantiation) {
514571
// Collect information from the lambda scope.
515572
llvm::SmallVector<LambdaExpr::Capture, 4> Captures;
@@ -655,69 +712,12 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body,
655712

656713
if (LambdaExprNeedsCleanups)
657714
ExprNeedsCleanups = true;
658-
659-
// If we don't already have a mangling number for this lambda expression,
660-
// allocate one now.
661-
if (!ManglingNumber) {
662-
ContextDecl = ExprEvalContexts.back().LambdaContextDecl;
663-
664-
enum ContextKind {
665-
Normal,
666-
DefaultArgument,
667-
DataMember,
668-
StaticDataMember
669-
} Kind = Normal;
670-
671-
// Default arguments of member function parameters that appear in a class
672-
// definition, as well as the initializers of data members, receive special
673-
// treatment. Identify them.
674-
if (ContextDecl) {
675-
if (ParmVarDecl *Param = dyn_cast<ParmVarDecl>(ContextDecl)) {
676-
if (const DeclContext *LexicalDC
677-
= Param->getDeclContext()->getLexicalParent())
678-
if (LexicalDC->isRecord())
679-
Kind = DefaultArgument;
680-
} else if (VarDecl *Var = dyn_cast<VarDecl>(ContextDecl)) {
681-
if (Var->getDeclContext()->isRecord())
682-
Kind = StaticDataMember;
683-
} else if (isa<FieldDecl>(ContextDecl)) {
684-
Kind = DataMember;
685-
}
686-
}
687-
688-
switch (Kind) {
689-
case Normal:
690-
if (CurContext->isDependentContext() || isInInlineFunction(CurContext))
691-
ManglingNumber = Context.getLambdaManglingNumber(CallOperator);
692-
else
693-
ManglingNumber = 0;
694-
695-
// There is no special context for this lambda.
696-
ContextDecl = 0;
697-
break;
698-
699-
case StaticDataMember:
700-
if (!CurContext->isDependentContext()) {
701-
ManglingNumber = 0;
702-
ContextDecl = 0;
703-
break;
704-
}
705-
// Fall through to assign a mangling number.
706-
707-
case DataMember:
708-
case DefaultArgument:
709-
ManglingNumber = ExprEvalContexts.back().getLambdaMangleContext()
710-
.getManglingNumber(CallOperator);
711-
break;
712-
}
713-
}
714715

715716
LambdaExpr *Lambda = LambdaExpr::Create(Context, Class, IntroducerRange,
716717
CaptureDefault, Captures,
717718
ExplicitParams, ExplicitResultType,
718719
CaptureInits, ArrayIndexVars,
719-
ArrayIndexStarts, Body->getLocEnd(),
720-
*ManglingNumber, ContextDecl);
720+
ArrayIndexStarts, Body->getLocEnd());
721721

722722
// C++11 [expr.prim.lambda]p2:
723723
// A lambda-expression shall not appear in an unevaluated operand

Diff for: lib/Sema/TreeTransform.h

+8-9
Original file line numberDiff line numberDiff line change
@@ -7815,7 +7815,8 @@ ExprResult
78157815
TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
78167816
// Create the local class that will describe the lambda.
78177817
CXXRecordDecl *Class
7818-
= getSema().createLambdaClosureType(E->getIntroducerRange());
7818+
= getSema().createLambdaClosureType(E->getIntroducerRange(),
7819+
/*KnownDependent=*/false);
78197820
getDerived().transformedLocalDecl(E->getLambdaClass(), Class);
78207821

78217822
// Transform the type of the lambda parameters and start the definition of
@@ -7836,11 +7837,15 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
78367837
Invalid = true;
78377838

78387839
// Build the call operator.
7840+
// Note: Once a lambda mangling number and context declaration have been
7841+
// assigned, they never change.
7842+
unsigned ManglingNumber = E->getLambdaClass()->getLambdaManglingNumber();
7843+
Decl *ContextDecl = E->getLambdaClass()->getLambdaContextDecl();
78397844
CXXMethodDecl *CallOperator
78407845
= getSema().startLambdaDefinition(Class, E->getIntroducerRange(),
78417846
MethodTy,
78427847
E->getCallOperator()->getLocEnd(),
7843-
Params);
7848+
Params, ManglingNumber, ContextDecl);
78447849
getDerived().transformAttrs(E->getCallOperator(), CallOperator);
78457850

78467851
// FIXME: Instantiation-specific.
@@ -7953,14 +7958,8 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
79537958
return ExprError();
79547959
}
79557960

7956-
// Note: Once a lambda mangling number and context declaration have been
7957-
// assigned, they never change.
7958-
unsigned ManglingNumber = E->getLambdaClass()->getLambdaManglingNumber();
7959-
Decl *ContextDecl = E->getLambdaClass()->getLambdaContextDecl();
79607961
return getSema().ActOnLambdaExpr(E->getLocStart(), Body.take(),
7961-
/*CurScope=*/0, ManglingNumber,
7962-
ContextDecl,
7963-
/*IsInstantiation=*/true);
7962+
/*CurScope=*/0, /*IsInstantiation=*/true);
79647963
}
79657964

79667965
template<typename Derived>

0 commit comments

Comments
 (0)