aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaLambda.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema/SemaLambda.cpp')
-rw-r--r--lib/Sema/SemaLambda.cpp73
1 files changed, 57 insertions, 16 deletions
diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp
index a0d574915eba..7a9a8ff911aa 100644
--- a/lib/Sema/SemaLambda.cpp
+++ b/lib/Sema/SemaLambda.cpp
@@ -312,7 +312,7 @@ Sema::getCurrentMangleNumberContext(const DeclContext *DC,
// In the following contexts [...] the one-definition rule requires closure
// types in different translation units to "correspond":
bool IsInNonspecializedTemplate =
- !ActiveTemplateInstantiations.empty() || CurContext->isDependentContext();
+ inTemplateInstantiation() || CurContext->isDependentContext();
switch (Kind) {
case Normal: {
// -- the bodies of non-exported nonspecialized template functions
@@ -763,7 +763,7 @@ QualType Sema::buildLambdaInitCaptureInitialization(SourceLocation Loc,
// call-operator.
Result = ActOnFinishFullExpr(Init, Loc, /*DiscardedValue*/ false,
/*IsConstexpr*/ false,
- /*IsLambdaInitCaptureInitalizer*/ true);
+ /*IsLambdaInitCaptureInitializer*/ true);
if (Result.isInvalid())
return QualType();
@@ -1127,7 +1127,8 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
// Enter a new evaluation context to insulate the lambda from any
// cleanups from the enclosing full-expression.
- PushExpressionEvaluationContext(PotentiallyEvaluated);
+ PushExpressionEvaluationContext(
+ ExpressionEvaluationContext::PotentiallyEvaluated);
}
void Sema::ActOnLambdaError(SourceLocation StartLoc, Scope *CurScope,
@@ -1384,7 +1385,7 @@ static void addBlockPointerConversion(Sema &S,
}
static ExprResult performLambdaVarCaptureInitialization(
- Sema &S, LambdaScopeInfo::Capture &Capture, FieldDecl *Field) {
+ Sema &S, const LambdaScopeInfo::Capture &Capture, FieldDecl *Field) {
assert(Capture.isVariableCapture() && "not a variable capture");
auto *Var = Capture.getVariable();
@@ -1438,6 +1439,43 @@ mapImplicitCaptureStyle(CapturingScopeInfo::ImplicitCaptureStyle ICS) {
llvm_unreachable("Unknown implicit capture style");
}
+bool Sema::CaptureHasSideEffects(const LambdaScopeInfo::Capture &From) {
+ if (!From.isVLATypeCapture()) {
+ Expr *Init = From.getInitExpr();
+ if (Init && Init->HasSideEffects(Context))
+ return true;
+ }
+
+ if (!From.isCopyCapture())
+ return false;
+
+ const QualType T = From.isThisCapture()
+ ? getCurrentThisType()->getPointeeType()
+ : From.getCaptureType();
+
+ if (T.isVolatileQualified())
+ return true;
+
+ const Type *BaseT = T->getBaseElementTypeUnsafe();
+ if (const CXXRecordDecl *RD = BaseT->getAsCXXRecordDecl())
+ return !RD->isCompleteDefinition() || !RD->hasTrivialCopyConstructor() ||
+ !RD->hasTrivialDestructor();
+
+ return false;
+}
+
+void Sema::DiagnoseUnusedLambdaCapture(const LambdaScopeInfo::Capture &From) {
+ if (CaptureHasSideEffects(From))
+ return;
+
+ auto diag = Diag(From.getLocation(), diag::warn_unused_lambda_capture);
+ if (From.isThisCapture())
+ diag << "'this'";
+ else
+ diag << From.getVariable();
+ diag << From.isNonODRUsed();
+}
+
ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc,
LambdaScopeInfo *LSI) {
// Collect information from the lambda scope.
@@ -1476,10 +1514,14 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc,
// Translate captures.
auto CurField = Class->field_begin();
for (unsigned I = 0, N = LSI->Captures.size(); I != N; ++I, ++CurField) {
- LambdaScopeInfo::Capture From = LSI->Captures[I];
+ const LambdaScopeInfo::Capture &From = LSI->Captures[I];
assert(!From.isBlockCapture() && "Cannot capture __block variables");
bool IsImplicit = I >= LSI->NumExplicitCaptures;
+ // Warn about unused explicit captures.
+ if (!CurContext->isDependentContext() && !IsImplicit && !From.isODRUsed())
+ DiagnoseUnusedLambdaCapture(From);
+
// Handle 'this' capture.
if (From.isThisCapture()) {
Captures.push_back(
@@ -1564,9 +1606,9 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc,
// C++11 [expr.prim.lambda]p2:
// A lambda-expression shall not appear in an unevaluated operand
// (Clause 5).
- case Unevaluated:
- case UnevaluatedList:
- case UnevaluatedAbstract:
+ case ExpressionEvaluationContext::Unevaluated:
+ case ExpressionEvaluationContext::UnevaluatedList:
+ case ExpressionEvaluationContext::UnevaluatedAbstract:
// C++1y [expr.const]p2:
// A conditional-expression e is a core constant expression unless the
// evaluation of e, following the rules of the abstract machine, would
@@ -1576,16 +1618,16 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc,
// where this should be allowed. We should probably fix this when DR1607 is
// ratified, it lays out the exact set of conditions where we shouldn't
// allow a lambda-expression.
- case ConstantEvaluated:
+ case ExpressionEvaluationContext::ConstantEvaluated:
// We don't actually diagnose this case immediately, because we
// could be within a context where we might find out later that
// the expression is potentially evaluated (e.g., for typeid).
ExprEvalContexts.back().Lambdas.push_back(Lambda);
break;
- case DiscardedStatement:
- case PotentiallyEvaluated:
- case PotentiallyEvaluatedIfUsed:
+ case ExpressionEvaluationContext::DiscardedStatement:
+ case ExpressionEvaluationContext::PotentiallyEvaluated:
+ case ExpressionEvaluationContext::PotentiallyEvaluatedIfUsed:
break;
}
}
@@ -1607,10 +1649,9 @@ ExprResult Sema::BuildBlockForLambdaConversion(SourceLocation CurrentLocation,
CallOperator->markUsed(Context);
ExprResult Init = PerformCopyInitialization(
- InitializedEntity::InitializeBlock(ConvLocation,
- Src->getType(),
- /*NRVO=*/false),
- CurrentLocation, Src);
+ InitializedEntity::InitializeLambdaToBlock(ConvLocation, Src->getType(),
+ /*NRVO=*/false),
+ CurrentLocation, Src);
if (!Init.isInvalid())
Init = ActOnFinishFullExpr(Init.get());