diff options
author | Douglas Gregor <dgregor@apple.com> | 2012-02-10 16:13:20 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2012-02-10 16:13:20 +0000 |
commit | b555971345750350c21d541afe135054c7402933 (patch) | |
tree | 1b56d499f7a8837a305745bd3c590b5e48a64ea7 /lib/Sema/SemaLambda.cpp | |
parent | d37b360bf9f954af119c9805fdc79ab9d30e06c6 (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.cpp | 100 |
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); } |