aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaLambda.cpp
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2012-02-10 16:13:20 +0000
committerDouglas Gregor <dgregor@apple.com>2012-02-10 16:13:20 +0000
commitb555971345750350c21d541afe135054c7402933 (patch)
tree1b56d499f7a8837a305745bd3c590b5e48a64ea7 /lib/Sema/SemaLambda.cpp
parentd37b360bf9f954af119c9805fdc79ab9d30e06c6 (diff)
Don't introduce a lambda's operator() into the class until after we
have finished parsing the body, so that name lookup will never find anything within the closure type. Then, add this operator() and the conversion function (if available) before completing the class. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@150252 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaLambda.cpp')
-rw-r--r--lib/Sema/SemaLambda.cpp100
1 files changed, 51 insertions, 49 deletions
diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp
index ed05eff8e1..64fe7f7dce 100644
--- a/lib/Sema/SemaLambda.cpp
+++ b/lib/Sema/SemaLambda.cpp
@@ -102,7 +102,6 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
/*isConstExpr=*/false,
EndLoc);
Method->setAccess(AS_public);
- Class->addDecl(Method);
// Temporarily set the lexical declaration context to the current
// context, so that the Scope stack matches the lexical nesting.
@@ -393,17 +392,63 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc,
CallOperator->setType(FunctionTy);
}
- // Finalize the lambda class.
- SmallVector<Decl*, 4> Fields(Class->field_begin(), Class->field_end());
- ActOnFields(0, Class->getLocation(), Class, Fields,
- SourceLocation(), SourceLocation(), 0);
- CheckCompletedCXXClass(Class);
+ // C++11 [expr.prim.lambda]p6:
+ // The closure type for a lambda-expression with no lambda-capture
+ // has a public non-virtual non-explicit const conversion function
+ // to pointer to function having the same parameter and return
+ // types as the closure type's function call operator.
+ if (Captures.empty() && CaptureDefault == LCD_None) {
+ const FunctionProtoType *Proto
+ = CallOperator->getType()->getAs<FunctionProtoType>();
+ QualType FunctionPtrTy;
+ {
+ FunctionProtoType::ExtProtoInfo ExtInfo = Proto->getExtProtoInfo();
+ ExtInfo.TypeQuals = 0;
+ QualType FunctionTy
+ = Context.getFunctionType(Proto->getResultType(),
+ Proto->arg_type_begin(),
+ Proto->getNumArgs(),
+ ExtInfo);
+ FunctionPtrTy = Context.getPointerType(FunctionTy);
+ }
+
+ FunctionProtoType::ExtProtoInfo ExtInfo;
+ ExtInfo.TypeQuals = Qualifiers::Const;
+ QualType ConvTy = Context.getFunctionType(FunctionPtrTy, 0, 0, ExtInfo);
+
+ SourceLocation Loc = IntroducerRange.getBegin();
+ DeclarationName Name
+ = Context.DeclarationNames.getCXXConversionFunctionName(
+ Context.getCanonicalType(FunctionPtrTy));
+ DeclarationNameLoc NameLoc;
+ NameLoc.NamedType.TInfo = Context.getTrivialTypeSourceInfo(FunctionPtrTy,
+ Loc);
+ CXXConversionDecl *Conversion
+ = CXXConversionDecl::Create(Context, Class, Loc,
+ DeclarationNameInfo(Name, Loc, NameLoc),
+ ConvTy,
+ Context.getTrivialTypeSourceInfo(ConvTy,
+ Loc),
+ /*isInline=*/false, /*isExplicit=*/false,
+ /*isConstexpr=*/false, Body->getLocEnd());
+ Conversion->setAccess(AS_public);
+ Conversion->setImplicit(true);
+ Class->addDecl(Conversion);
+ }
// C++ [expr.prim.lambda]p7:
// The lambda-expression's compound-statement yields the
// function-body (8.4) of the function call operator [...].
ActOnFinishFunctionBody(CallOperator, Body, /*IsInstantation=*/false);
+
+ // Finalize the lambda class.
+ SmallVector<Decl*, 4> Fields(Class->field_begin(), Class->field_end());
CallOperator->setLexicalDeclContext(Class);
+ Class->addDecl(CallOperator);
+ ActOnFields(0, Class->getLocation(), Class, Fields,
+ SourceLocation(), SourceLocation(), 0);
+ CheckCompletedCXXClass(Class);
+
}
if (LambdaExprNeedsCleanups)
@@ -432,48 +477,5 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc,
break;
}
- // C++11 [expr.prim.lambda]p6:
- // The closure type for a lambda-expression with no lambda-capture
- // has a public non-virtual non-explicit const conversion function
- // to pointer to function having the same parameter and return
- // types as the closure type's function call operator.
- if (Captures.empty() && CaptureDefault == LCD_None) {
- const FunctionProtoType *Proto
- = CallOperator->getType()->getAs<FunctionProtoType>();
- QualType FunctionPtrTy;
- {
- FunctionProtoType::ExtProtoInfo ExtInfo = Proto->getExtProtoInfo();
- ExtInfo.TypeQuals = 0;
- QualType FunctionTy
- = Context.getFunctionType(Proto->getResultType(),
- Proto->arg_type_begin(),
- Proto->getNumArgs(),
- ExtInfo);
- FunctionPtrTy = Context.getPointerType(FunctionTy);
- }
-
- FunctionProtoType::ExtProtoInfo ExtInfo;
- ExtInfo.TypeQuals = Qualifiers::Const;
- QualType ConvTy = Context.getFunctionType(FunctionPtrTy, 0, 0, ExtInfo);
-
- SourceLocation Loc = IntroducerRange.getBegin();
- DeclarationName Name
- = Context.DeclarationNames.getCXXConversionFunctionName(
- Context.getCanonicalType(FunctionPtrTy));
- DeclarationNameLoc NameLoc;
- NameLoc.NamedType.TInfo = Context.getTrivialTypeSourceInfo(FunctionPtrTy,
- Loc);
- CXXConversionDecl *Conversion
- = CXXConversionDecl::Create(Context, Class, Loc,
- DeclarationNameInfo(Name, Loc, NameLoc),
- ConvTy,
- Context.getTrivialTypeSourceInfo(ConvTy, Loc),
- /*isInline=*/false, /*isExplicit=*/false,
- /*isConstexpr=*/false, Body->getLocEnd());
- Conversion->setAccess(AS_public);
- Conversion->setImplicit(true);
- Class->addDecl(Conversion);
- }
-
return MaybeBindToTemporary(Lambda);
}