summaryrefslogtreecommitdiff
path: root/contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp')
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp89
1 files changed, 49 insertions, 40 deletions
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp
index 884add26e43a..0b3af262cd61 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp
@@ -66,17 +66,20 @@ getStackIndexOfNearestEnclosingCaptureReadyLambda(
// Label failure to capture.
const Optional<unsigned> NoLambdaIsCaptureReady;
+ // Ignore all inner captured regions.
+ unsigned CurScopeIndex = FunctionScopes.size() - 1;
+ while (CurScopeIndex > 0 && isa<clang::sema::CapturedRegionScopeInfo>(
+ FunctionScopes[CurScopeIndex]))
+ --CurScopeIndex;
assert(
- isa<clang::sema::LambdaScopeInfo>(
- FunctionScopes[FunctionScopes.size() - 1]) &&
+ isa<clang::sema::LambdaScopeInfo>(FunctionScopes[CurScopeIndex]) &&
"The function on the top of sema's function-info stack must be a lambda");
-
+
// If VarToCapture is null, we are attempting to capture 'this'.
const bool IsCapturingThis = !VarToCapture;
const bool IsCapturingVariable = !IsCapturingThis;
// Start with the current lambda at the top of the stack (highest index).
- unsigned CurScopeIndex = FunctionScopes.size() - 1;
DeclContext *EnclosingDC =
cast<sema::LambdaScopeInfo>(FunctionScopes[CurScopeIndex])->CallOperator;
@@ -311,18 +314,21 @@ Sema::getCurrentMangleNumberContext(const DeclContext *DC,
bool IsInNonspecializedTemplate =
!ActiveTemplateInstantiations.empty() || CurContext->isDependentContext();
switch (Kind) {
- case Normal:
+ case Normal: {
// -- the bodies of non-exported nonspecialized template functions
// -- the bodies of inline functions
if ((IsInNonspecializedTemplate &&
!(ManglingContextDecl && isa<ParmVarDecl>(ManglingContextDecl))) ||
isInInlineFunction(CurContext)) {
ManglingContextDecl = nullptr;
+ while (auto *CD = dyn_cast<CapturedDecl>(DC))
+ DC = CD->getParent();
return &Context.getManglingNumberContext(DC);
}
ManglingContextDecl = nullptr;
return nullptr;
+ }
case StaticDataMember:
// -- the initializers of nonspecialized static members of template classes
@@ -414,11 +420,10 @@ CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class,
// Add parameters.
if (!Params.empty()) {
Method->setParams(Params);
- CheckParmsForFunctionDef(const_cast<ParmVarDecl **>(Params.begin()),
- const_cast<ParmVarDecl **>(Params.end()),
+ CheckParmsForFunctionDef(Params,
/*CheckParameterNames=*/false);
-
- for (auto P : Method->params())
+
+ for (auto P : Method->parameters())
P->setOwningFunction(Method);
}
@@ -617,6 +622,8 @@ void Sema::deduceClosureReturnType(CapturingScopeInfo &CSI) {
assert(CSI.HasImplicitReturnType);
// If it was ever a placeholder, it had to been deduced to DependentTy.
assert(CSI.ReturnType.isNull() || !CSI.ReturnType->isUndeducedType());
+ assert((!isa<LambdaScopeInfo>(CSI) || !getLangOpts().CPlusPlus14) &&
+ "lambda expressions use auto deduction in C++14 onwards");
// C++ core issue 975:
// If a lambda-expression does not include a trailing-return-type,
@@ -807,19 +814,13 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
bool KnownDependent = false;
LambdaScopeInfo *const LSI = getCurLambda();
assert(LSI && "LambdaScopeInfo should be on stack!");
- TemplateParameterList *TemplateParams =
- getGenericLambdaTemplateParameterList(LSI, *this);
-
- if (Scope *TmplScope = CurScope->getTemplateParamParent()) {
- // Since we have our own TemplateParams, so check if an outer scope
- // has template params, only then are we in a dependent scope.
- if (TemplateParams) {
- TmplScope = TmplScope->getParent();
- TmplScope = TmplScope ? TmplScope->getTemplateParamParent() : nullptr;
- }
- if (TmplScope && !TmplScope->decl_empty())
- KnownDependent = true;
- }
+
+ // The lambda-expression's closure type might be dependent even if its
+ // semantic context isn't, if it appears within a default argument of a
+ // function template.
+ if (CurScope->getTemplateParamParent())
+ KnownDependent = true;
+
// Determine the signature of the call operator.
TypeSourceInfo *MethodTyInfo;
bool ExplicitParams = true;
@@ -922,7 +923,12 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
= Intro.Default == LCD_None? Intro.Range.getBegin() : Intro.DefaultLoc;
for (auto C = Intro.Captures.begin(), E = Intro.Captures.end(); C != E;
PrevCaptureLoc = C->Loc, ++C) {
- if (C->Kind == LCK_This) {
+ if (C->Kind == LCK_This || C->Kind == LCK_StarThis) {
+ if (C->Kind == LCK_StarThis)
+ Diag(C->Loc, !getLangOpts().CPlusPlus1z
+ ? diag::ext_star_this_lambda_capture_cxx1z
+ : diag::warn_cxx14_compat_star_this_lambda_capture);
+
// C++11 [expr.prim.lambda]p8:
// An identifier or this shall not appear more than once in a
// lambda-capture.
@@ -934,10 +940,12 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
continue;
}
- // C++11 [expr.prim.lambda]p8:
- // If a lambda-capture includes a capture-default that is =, the
- // lambda-capture shall not contain this [...].
- if (Intro.Default == LCD_ByCopy) {
+ // C++1z [expr.prim.lambda]p8:
+ // If a lambda-capture includes a capture-default that is =, each
+ // simple-capture of that lambda-capture shall be of the form "&
+ // identifier" or "* this". [ Note: The form [&,this] is redundant but
+ // accepted for compatibility with ISO C++14. --end note ]
+ if (Intro.Default == LCD_ByCopy && C->Kind != LCK_StarThis) {
Diag(C->Loc, diag::err_this_capture_with_copy_default)
<< FixItHint::CreateRemoval(
SourceRange(getLocForEndOfToken(PrevCaptureLoc), C->Loc));
@@ -953,7 +961,9 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
continue;
}
- CheckCXXThisCapture(C->Loc, /*Explicit=*/true);
+ CheckCXXThisCapture(C->Loc, /*Explicit=*/true, /*BuildAndDiagnose*/ true,
+ /*FunctionScopeIndexToStopAtPtr*/ nullptr,
+ C->Kind == LCK_StarThis);
continue;
}
@@ -1144,8 +1154,8 @@ static void addFunctionPointerConversion(Sema &S,
CXXMethodDecl *CallOperator) {
// This conversion is explicitly disabled if the lambda's function has
// pass_object_size attributes on any of its parameters.
- if (std::any_of(CallOperator->param_begin(), CallOperator->param_end(),
- std::mem_fn(&ParmVarDecl::hasAttr<PassObjectSizeAttr>)))
+ if (llvm::any_of(CallOperator->parameters(),
+ std::mem_fn(&ParmVarDecl::hasAttr<PassObjectSizeAttr>)))
return;
// Add the conversion to function pointer.
@@ -1493,7 +1503,7 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc,
SourceRange IntroducerRange;
bool ExplicitParams;
bool ExplicitResultType;
- bool LambdaExprNeedsCleanups;
+ CleanupInfo LambdaCleanup;
bool ContainsUnexpandedParameterPack;
SmallVector<VarDecl *, 4> ArrayIndexVars;
SmallVector<unsigned, 4> ArrayIndexStarts;
@@ -1503,7 +1513,7 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc,
IntroducerRange = LSI->IntroducerRange;
ExplicitParams = LSI->ExplicitParams;
ExplicitResultType = !LSI->HasImplicitReturnType;
- LambdaExprNeedsCleanups = LSI->ExprNeedsCleanups;
+ LambdaCleanup = LSI->Cleanup;
ContainsUnexpandedParameterPack = LSI->ContainsUnexpandedParameterPack;
CallOperator->setLexicalDeclContext(Class);
@@ -1527,10 +1537,9 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc,
// Handle 'this' capture.
if (From.isThisCapture()) {
Captures.push_back(
- LambdaCapture(From.getLocation(), IsImplicit, LCK_This));
- CaptureInits.push_back(new (Context) CXXThisExpr(From.getLocation(),
- getCurrentThisType(),
- /*isImplicit=*/true));
+ LambdaCapture(From.getLocation(), IsImplicit,
+ From.isCopyCapture() ? LCK_StarThis : LCK_This));
+ CaptureInits.push_back(From.getInitExpr());
ArrayIndexStarts.push_back(ArrayIndexVars.size());
continue;
}
@@ -1585,9 +1594,8 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc,
CheckCompletedCXXClass(Class);
}
- if (LambdaExprNeedsCleanups)
- ExprNeedsCleanups = true;
-
+ Cleanup.mergeFrom(LambdaCleanup);
+
LambdaExpr *Lambda = LambdaExpr::Create(Context, Class, IntroducerRange,
CaptureDefault, CaptureDefaultLoc,
Captures,
@@ -1619,6 +1627,7 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc,
ExprEvalContexts.back().Lambdas.push_back(Lambda);
break;
+ case DiscardedStatement:
case PotentiallyEvaluated:
case PotentiallyEvaluatedIfUsed:
break;
@@ -1697,7 +1706,7 @@ ExprResult Sema::BuildBlockForLambdaConversion(SourceLocation CurrentLocation,
// Create the block literal expression.
Expr *BuildBlock = new (Context) BlockExpr(Block, Conv->getConversionType());
ExprCleanupObjects.push_back(Block);
- ExprNeedsCleanups = true;
+ Cleanup.setExprNeedsCleanups(true);
return BuildBlock;
}