When completing a lambda expression, make sure to check and attach the
body of the lambda to the function call operator. llvm-svn: 150087
This commit is contained in:
parent
c68bf4c036
commit
21f4692c62
|
@ -1226,8 +1226,7 @@ public:
|
|||
}
|
||||
|
||||
/// \brief Retrieve the iterator pointing one past the last
|
||||
/// initialization argument for this lambda expression (which
|
||||
/// initializes the first capture field).
|
||||
/// initialization argument for this lambda expression.
|
||||
capture_init_iterator capture_init_end() const {
|
||||
return capture_init_begin() + NumCaptures;
|
||||
}
|
||||
|
|
|
@ -280,6 +280,9 @@ public:
|
|||
/// \brief The class that describes the lambda.
|
||||
CXXRecordDecl *Lambda;
|
||||
|
||||
/// \brief The class that describes the lambda.
|
||||
CXXMethodDecl *CallOperator;
|
||||
|
||||
/// \brief Source range covering the lambda introducer [...].
|
||||
SourceRange IntroducerRange;
|
||||
|
||||
|
@ -292,9 +295,10 @@ public:
|
|||
/// \brief Whether the (empty) parameter list is explicit.
|
||||
bool ExplicitParams;
|
||||
|
||||
LambdaScopeInfo(DiagnosticsEngine &Diag, CXXRecordDecl *Lambda)
|
||||
LambdaScopeInfo(DiagnosticsEngine &Diag, CXXRecordDecl *Lambda,
|
||||
CXXMethodDecl *CallOperator)
|
||||
: CapturingScopeInfo(Diag, ImpCap_None), Lambda(Lambda),
|
||||
NumExplicitCaptures(0), Mutable(false)
|
||||
CallOperator(CallOperator), NumExplicitCaptures(0), Mutable(false)
|
||||
{
|
||||
Kind = SK_Lambda;
|
||||
}
|
||||
|
|
|
@ -732,7 +732,7 @@ public:
|
|||
|
||||
void PushFunctionScope();
|
||||
void PushBlockScope(Scope *BlockScope, BlockDecl *Block);
|
||||
void PushLambdaScope(CXXRecordDecl *Lambda);
|
||||
void PushLambdaScope(CXXRecordDecl *Lambda, CXXMethodDecl *CallOperator);
|
||||
void PopFunctionScopeInfo(const sema::AnalysisBasedWarnings::Policy *WP =0,
|
||||
const Decl *D = 0, const BlockExpr *blkExpr = 0);
|
||||
|
||||
|
|
|
@ -831,8 +831,10 @@ void Sema::PushBlockScope(Scope *BlockScope, BlockDecl *Block) {
|
|||
BlockScope, Block));
|
||||
}
|
||||
|
||||
void Sema::PushLambdaScope(CXXRecordDecl *Lambda) {
|
||||
FunctionScopes.push_back(new LambdaScopeInfo(getDiagnostics(), Lambda));
|
||||
void Sema::PushLambdaScope(CXXRecordDecl *Lambda,
|
||||
CXXMethodDecl *CallOperator) {
|
||||
FunctionScopes.push_back(new LambdaScopeInfo(getDiagnostics(), Lambda,
|
||||
CallOperator));
|
||||
}
|
||||
|
||||
void Sema::PopFunctionScopeInfo(const AnalysisBasedWarnings::Policy *WP,
|
||||
|
|
|
@ -7236,7 +7236,8 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
|
|||
computeNRVO(Body, getCurFunction());
|
||||
}
|
||||
|
||||
assert(FD == getCurFunctionDecl() && "Function parsing confused");
|
||||
assert((FD == getCurFunctionDecl() || getCurLambda()->CallOperator == FD) &&
|
||||
"Function parsing confused");
|
||||
} else if (ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(dcl)) {
|
||||
assert(MD == getCurMethodDecl() && "Method parsing confused");
|
||||
MD->setBody(Body);
|
||||
|
|
|
@ -9722,8 +9722,6 @@ void Sema::TryCaptureVar(VarDecl *var, SourceLocation loc,
|
|||
// of the copy/move done to move a __block variable to the heap.
|
||||
type.addConst();
|
||||
|
||||
// FIXME: Add an initialized entity for lambda capture.
|
||||
// FIXME: Won't work for arrays, although we do need this behavior.
|
||||
Expr *declRef = new (Context) DeclRefExpr(var, type, VK_LValue, loc);
|
||||
ExprResult result =
|
||||
PerformCopyInitialization(
|
||||
|
|
|
@ -4896,6 +4896,7 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
|
|||
QualType MethodTy;
|
||||
TypeSourceInfo *MethodTyInfo;
|
||||
bool ExplicitParams = true;
|
||||
SourceLocation EndLoc;
|
||||
if (ParamInfo.getNumTypeObjects() == 0) {
|
||||
// C++11 [expr.prim.lambda]p4:
|
||||
// If a lambda-expression does not include a lambda-declarator, it is as
|
||||
|
@ -4906,6 +4907,7 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
|
|||
/*Args=*/0, /*NumArgs=*/0, EPI);
|
||||
MethodTyInfo = Context.getTrivialTypeSourceInfo(MethodTy);
|
||||
ExplicitParams = false;
|
||||
EndLoc = Intro.Range.getEnd();
|
||||
} else {
|
||||
assert(ParamInfo.isFunctionDeclarator() &&
|
||||
"lambda-declarator is a function");
|
||||
|
@ -4928,6 +4930,7 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
|
|||
assert(MethodTyInfo && "no type from lambda-declarator");
|
||||
MethodTy = MethodTyInfo->getType();
|
||||
assert(!MethodTy.isNull() && "no type from lambda declarator");
|
||||
EndLoc = ParamInfo.getSourceRange().getEnd();
|
||||
}
|
||||
|
||||
// C++11 [expr.prim.lambda]p5:
|
||||
|
@ -4937,19 +4940,22 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
|
|||
// trailing-return-type respectively.
|
||||
DeclarationName MethodName
|
||||
= Context.DeclarationNames.getCXXOperatorName(OO_Call);
|
||||
DeclarationNameLoc MethodNameLoc;
|
||||
MethodNameLoc.CXXOperatorName.BeginOpNameLoc
|
||||
= Intro.Range.getBegin().getRawEncoding();
|
||||
MethodNameLoc.CXXOperatorName.EndOpNameLoc
|
||||
= Intro.Range.getEnd().getRawEncoding();
|
||||
CXXMethodDecl *Method
|
||||
= CXXMethodDecl::Create(Context,
|
||||
Class,
|
||||
ParamInfo.getSourceRange().getEnd(),
|
||||
DeclarationNameInfo(MethodName,
|
||||
/*NameLoc=*/SourceLocation()),
|
||||
MethodTy,
|
||||
MethodTyInfo,
|
||||
= CXXMethodDecl::Create(Context, Class, EndLoc,
|
||||
DeclarationNameInfo(MethodName,
|
||||
Intro.Range.getBegin(),
|
||||
MethodNameLoc),
|
||||
MethodTy, MethodTyInfo,
|
||||
/*isStatic=*/false,
|
||||
SC_None,
|
||||
/*isInline=*/true,
|
||||
/*isConstExpr=*/false,
|
||||
ParamInfo.getSourceRange().getEnd());
|
||||
EndLoc);
|
||||
Method->setAccess(AS_public);
|
||||
Class->addDecl(Method);
|
||||
Method->setLexicalDeclContext(DC); // FIXME: Minor hack.
|
||||
|
@ -4963,7 +4969,7 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
|
|||
PushDeclContext(CurScope, Method);
|
||||
|
||||
// Introduce the lambda scope.
|
||||
PushLambdaScope(Class);
|
||||
PushLambdaScope(Class, Method);
|
||||
LambdaScopeInfo *LSI = getCurLambda();
|
||||
if (Intro.Default == LCD_ByCopy)
|
||||
LSI->ImpCaptureStyle = LambdaScopeInfo::ImpCap_LambdaByval;
|
||||
|
@ -5123,9 +5129,6 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc,
|
|||
DiscardCleanupsInEvaluationContext();
|
||||
PopExpressionEvaluationContext();
|
||||
|
||||
// Leave the context of the lambda.
|
||||
PopDeclContext();
|
||||
|
||||
// FIXME: End-of-lambda checking
|
||||
|
||||
// Collect information from the lambda scope.
|
||||
|
@ -5184,7 +5187,10 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc,
|
|||
break;
|
||||
}
|
||||
|
||||
PopFunctionScopeInfo();
|
||||
// C++ [expr.prim.lambda]p7:
|
||||
// The lambda-expression’s compound-statement yields the
|
||||
// function-body (8.4) of the function call operator [...].
|
||||
ActOnFinishFunctionBody(LSI->CallOperator, Body, /*IsInstantation=*/false);
|
||||
}
|
||||
|
||||
Expr *Lambda = LambdaExpr::Create(Context, Class, IntroducerRange,
|
||||
|
|
|
@ -5,6 +5,6 @@ class NonCopyable {
|
|||
};
|
||||
|
||||
void capture_by_ref(NonCopyable nc, NonCopyable &ncr) {
|
||||
[&nc] {}; // expected-error{{lambda expressions are not supported yet}}
|
||||
[&ncr] {}; // expected-error{{lambda expressions are not supported yet}}
|
||||
[&nc] () -> void {}; // expected-error{{lambda expressions are not supported yet}}
|
||||
[&ncr] () -> void {}; // expected-error{{lambda expressions are not supported yet}}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify
|
||||
|
||||
// Check that analysis-based warnings work in lambda bodies.
|
||||
void analysis_based_warnings() {
|
||||
[]() -> int { }; // expected-warning{{control reaches end of non-void function}} \
|
||||
// expected-error{{lambda expressions are not supported yet}}
|
||||
}
|
||||
|
||||
// FIXME: Also check translation of captured vars to data members,
|
||||
// most of which isn't in the AST.
|
||||
|
||||
|
Loading…
Reference in New Issue