diff options
Diffstat (limited to 'clang/lib')
| -rw-r--r-- | clang/lib/AST/Expr.cpp | 7 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CGExprCXX.cpp | 1 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaExprCXX.cpp | 37 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaInit.cpp | 14 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaLambda.cpp | 10 |
5 files changed, 26 insertions, 43 deletions
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index b9606876e43..f284baf2b66 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -3255,11 +3255,8 @@ bool Expr::HasSideEffects(const ASTContext &Ctx, case LambdaExprClass: { const LambdaExpr *LE = cast<LambdaExpr>(this); - for (LambdaExpr::capture_iterator I = LE->capture_begin(), - E = LE->capture_end(); I != E; ++I) - if (I->getCaptureKind() == LCK_ByCopy) - // FIXME: Only has a side-effect if the variable is volatile or if - // the copy would invoke a non-trivial copy constructor. + for (Expr *E : LE->capture_inits()) + if (E->HasSideEffects(Ctx, IncludePossibleEffects)) return true; return false; } diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp index 393a4aa7870..ae6653ec483 100644 --- a/clang/lib/CodeGen/CGExprCXX.cpp +++ b/clang/lib/CodeGen/CGExprCXX.cpp @@ -2252,7 +2252,6 @@ llvm::Value *CodeGenFunction::EmitDynamicCast(Address ThisAddr, } void CodeGenFunction::EmitLambdaExpr(const LambdaExpr *E, AggValueSlot Slot) { - RunCleanupsScope Scope(*this); LValue SlotLV = MakeAddrLValue(Slot.getAddress(), E->getType()); CXXRecordDecl::field_iterator CurField = E->getLambdaClass()->field_begin(); diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index dd5dfaacf24..eb1dd8975d1 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -7764,41 +7764,24 @@ Sema::CorrectDelayedTyposInExpr(Expr *E, VarDecl *InitDecl, ExprResult Sema::ActOnFinishFullExpr(Expr *FE, SourceLocation CC, bool DiscardedValue, - bool IsConstexpr, - bool IsLambdaInitCaptureInitializer) { + bool IsConstexpr) { ExprResult FullExpr = FE; if (!FullExpr.get()) return ExprError(); - // If we are an init-expression in a lambdas init-capture, we should not - // diagnose an unexpanded pack now (will be diagnosed once lambda-expr - // containing full-expression is done). - // template<class ... Ts> void test(Ts ... t) { - // test([&a(t)]() { <-- (t) is an init-expr that shouldn't be diagnosed now. - // return a; - // }() ...); - // } - // FIXME: This is a hack. It would be better if we pushed the lambda scope - // when we parse the lambda introducer, and teach capturing (but not - // unexpanded pack detection) to walk over LambdaScopeInfos which don't have a - // corresponding class yet (that is, have LambdaScopeInfo either represent a - // lambda where we've entered the introducer but not the body, or represent a - // lambda where we've entered the body, depending on where the - // parser/instantiation has got to). - if (!IsLambdaInitCaptureInitializer && - DiagnoseUnexpandedParameterPack(FullExpr.get())) + if (DiagnoseUnexpandedParameterPack(FullExpr.get())) return ExprError(); - // Top-level expressions default to 'id' when we're in a debugger. - if (DiscardedValue && getLangOpts().DebuggerCastResultToId && - FullExpr.get()->getType() == Context.UnknownAnyTy) { - FullExpr = forceUnknownAnyToType(FullExpr.get(), Context.getObjCIdType()); - if (FullExpr.isInvalid()) - return ExprError(); - } - if (DiscardedValue) { + // Top-level expressions default to 'id' when we're in a debugger. + if (getLangOpts().DebuggerCastResultToId && + FullExpr.get()->getType() == Context.UnknownAnyTy) { + FullExpr = forceUnknownAnyToType(FullExpr.get(), Context.getObjCIdType()); + if (FullExpr.isInvalid()) + return ExprError(); + } + FullExpr = CheckPlaceholderExpr(FullExpr.get()); if (FullExpr.isInvalid()) return ExprError(); diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 958dd66612c..71f3c4e34b5 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -6786,6 +6786,20 @@ static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path, return; } + // The lifetime of an init-capture is that of the closure object constructed + // by a lambda-expression. + if (auto *LE = dyn_cast<LambdaExpr>(Init)) { + for (Expr *E : LE->capture_inits()) { + if (!E) + continue; + if (E->isGLValue()) + visitLocalsRetainedByReferenceBinding(Path, E, RK_ReferenceBinding, + Visit); + else + visitLocalsRetainedByInitializer(Path, E, Visit, true); + } + } + if (isa<CallExpr>(Init) || isa<CXXConstructExpr>(Init)) return visitLifetimeBoundArguments(Path, Init, Visit); diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp index 8000cb4fbfd..803b253e458 100644 --- a/clang/lib/Sema/SemaLambda.cpp +++ b/clang/lib/Sema/SemaLambda.cpp @@ -775,16 +775,6 @@ QualType Sema::buildLambdaInitCaptureInitialization(SourceLocation Loc, if (Result.isInvalid()) return QualType(); - Init = Result.getAs<Expr>(); - - // The init-capture initialization is a full-expression that must be - // processed as one before we enter the declcontext of the lambda's - // call-operator. - Result = ActOnFinishFullExpr(Init, Loc, /*DiscardedValue*/ false, - /*IsConstexpr*/ false, - /*IsLambdaInitCaptureInitializer*/ true); - if (Result.isInvalid()) - return QualType(); Init = Result.getAs<Expr>(); return DeducedType; |

