[cfe-commits] r154029 - in /cfe/trunk: include/clang/AST/DeclCXX.h include/clang/AST/ExprCXX.h include/clang/Sema/Sema.h lib/AST/ExprCXX.cpp lib/AST/ItaniumMangle.cpp lib/Sema/SemaLambda.cpp lib/Sema/TreeTransform.h test/CodeGenCXX/mangle-lambdas.cpp
Douglas Gregor
dgregor at apple.com
Wed Apr 4 10:40:11 PDT 2012
Author: dgregor
Date: Wed Apr 4 12:40:10 2012
New Revision: 154029
URL: http://llvm.org/viewvc/llvm-project?rev=154029&view=rev
Log:
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.
Modified:
cfe/trunk/include/clang/AST/DeclCXX.h
cfe/trunk/include/clang/AST/ExprCXX.h
cfe/trunk/include/clang/Sema/Sema.h
cfe/trunk/lib/AST/ExprCXX.cpp
cfe/trunk/lib/AST/ItaniumMangle.cpp
cfe/trunk/lib/Sema/SemaLambda.cpp
cfe/trunk/lib/Sema/TreeTransform.h
cfe/trunk/test/CodeGenCXX/mangle-lambdas.cpp
Modified: cfe/trunk/include/clang/AST/DeclCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=154029&r1=154028&r2=154029&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Wed Apr 4 12:40:10 2012
@@ -621,7 +621,7 @@
"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 @@
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.
Modified: cfe/trunk/include/clang/AST/ExprCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExprCXX.h?rev=154029&r1=154028&r2=154029&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ExprCXX.h (original)
+++ cfe/trunk/include/clang/AST/ExprCXX.h Wed Apr 4 12:40:10 2012
@@ -1231,9 +1231,7 @@
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 @@
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.
Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=154029&r1=154028&r2=154029&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Wed Apr 4 12:40:10 2012
@@ -3700,7 +3700,10 @@
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 @@
/// 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
Modified: cfe/trunk/lib/AST/ExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprCXX.cpp?rev=154029&r1=154028&r2=154029&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprCXX.cpp (original)
+++ cfe/trunk/lib/AST/ExprCXX.cpp Wed Apr 4 12:40:10 2012
@@ -796,9 +796,7 @@
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 @@
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 @@
sizeof(unsigned) * Captures.size());
getArrayIndexStarts()[Captures.size()] = ArrayIndexVars.size();
}
-
- if (ManglingNumber)
- Class->ClearLinkageCache();
}
LambdaExpr *LambdaExpr::Create(ASTContext &Context,
@@ -863,9 +856,7 @@
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 @@
return new (Mem) LambdaExpr(T, IntroducerRange, CaptureDefault,
Captures, ExplicitParams, ExplicitResultType,
CaptureInits, ArrayIndexVars, ArrayIndexStarts,
- ClosingBrace, ManglingNumber, ContextDecl);
+ ClosingBrace);
}
LambdaExpr *LambdaExpr::CreateDeserialized(ASTContext &C, unsigned NumCaptures,
Modified: cfe/trunk/lib/AST/ItaniumMangle.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ItaniumMangle.cpp?rev=154029&r1=154028&r2=154029&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ItaniumMangle.cpp (original)
+++ cfe/trunk/lib/AST/ItaniumMangle.cpp Wed Apr 4 12:40:10 2012
@@ -535,6 +535,14 @@
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 @@
// 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)) {
Modified: cfe/trunk/lib/Sema/SemaLambda.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLambda.cpp?rev=154029&r1=154028&r2=154029&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaLambda.cpp (original)
+++ cfe/trunk/lib/Sema/SemaLambda.cpp Wed Apr 4 12:40:10 2012
@@ -36,11 +36,27 @@
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 @@
(*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 @@
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 @@
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
Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=154029&r1=154028&r2=154029&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Wed Apr 4 12:40:10 2012
@@ -7815,7 +7815,8 @@
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 @@
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 @@
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>
Modified: cfe/trunk/test/CodeGenCXX/mangle-lambdas.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/mangle-lambdas.cpp?rev=154029&r1=154028&r2=154029&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/mangle-lambdas.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/mangle-lambdas.cpp Wed Apr 4 12:40:10 2012
@@ -150,6 +150,8 @@
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 @@
// 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
More information about the cfe-commits
mailing list