diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index d06e72ca6872cd1d9472916c244c41499ee844be..41b6758bdc71076f3f3d484afc1850558f86d8cc 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -2877,8 +2877,7 @@ private: Stmt *SubExpr; ExprWithCleanups(EmptyShell, unsigned NumObjects); - ExprWithCleanups(Expr *SubExpr, bool CleanupsHaveSideEffects, - ArrayRef<CleanupObject> Objects); + ExprWithCleanups(Expr *SubExpr, ArrayRef<CleanupObject> Objects); friend TrailingObjects; friend class ASTStmtReader; @@ -2888,7 +2887,6 @@ public: unsigned numObjects); static ExprWithCleanups *Create(const ASTContext &C, Expr *subexpr, - bool CleanupsHaveSideEffects, ArrayRef<CleanupObject> objects); ArrayRef<CleanupObject> getObjects() const { @@ -2905,9 +2903,6 @@ public: Expr *getSubExpr() { return cast<Expr>(SubExpr); } const Expr *getSubExpr() const { return cast<Expr>(SubExpr); } - bool cleanupsHaveSideEffects() const { - return ExprWithCleanupsBits.CleanupsHaveSideEffects; - } /// As with any mutator of the AST, be very careful /// when modifying an existing AST to preserve its invariants. diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h index 7549f88108c347e72398fd1379adbe75df5d6ed3..b6ed6c547cc4c5965ab96a3df84d0976c4915aa0 100644 --- a/include/clang/AST/Stmt.h +++ b/include/clang/AST/Stmt.h @@ -192,10 +192,7 @@ protected: unsigned : NumExprBits; - // When false, it must not have side effects. - bool CleanupsHaveSideEffects : 1; - - unsigned NumObjects : 32 - 1 - NumExprBits; + unsigned NumObjects : 32 - NumExprBits; }; class PseudoObjectExprBitfields { diff --git a/include/clang/Sema/CleanupInfo.h b/include/clang/Sema/CleanupInfo.h deleted file mode 100644 index 751bfb63b4423d31df2839536b3f1c7d2188c939..0000000000000000000000000000000000000000 --- a/include/clang/Sema/CleanupInfo.h +++ /dev/null @@ -1,47 +0,0 @@ -//===--- CleanupInfo.cpp - Cleanup Control in Sema ------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements a set of operations on whether generating an -// ExprWithCleanups in a full expression. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_SEMA_CLEANUP_INFO_H -#define LLVM_CLANG_SEMA_CLEANUP_INFO_H - -namespace clang { - -class CleanupInfo { - bool ExprNeedsCleanups = false; - bool CleanupsHaveSideEffects = false; - -public: - bool exprNeedsCleanups() const { return ExprNeedsCleanups; } - - bool cleanupsHaveSideEffects() const { return CleanupsHaveSideEffects; } - - void setExprNeedsCleanups(bool SideEffects) { - ExprNeedsCleanups = true; - CleanupsHaveSideEffects |= SideEffects; - } - - void reset() { - ExprNeedsCleanups = false; - CleanupsHaveSideEffects = false; - } - - void mergeFrom(CleanupInfo Rhs) { - ExprNeedsCleanups |= Rhs.ExprNeedsCleanups; - CleanupsHaveSideEffects |= Rhs.CleanupsHaveSideEffects; - } -}; - -} // end namespace clang - -#endif diff --git a/include/clang/Sema/ScopeInfo.h b/include/clang/Sema/ScopeInfo.h index ce487f19efb7a995d40aa240970d851887df229e..112859b0627cb24a88f65b85f581b57199f36423 100644 --- a/include/clang/Sema/ScopeInfo.h +++ b/include/clang/Sema/ScopeInfo.h @@ -19,7 +19,6 @@ #include "clang/AST/Type.h" #include "clang/Basic/CapturedStmt.h" #include "clang/Basic/PartialDiagnostic.h" -#include "clang/Sema/CleanupInfo.h" #include "clang/Sema/Ownership.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallSet.h" @@ -683,7 +682,7 @@ public: bool ExplicitParams; /// \brief Whether any of the capture expressions requires cleanups. - CleanupInfo Cleanup; + bool ExprNeedsCleanups; /// \brief Whether the lambda contains an unexpanded parameter pack. bool ContainsUnexpandedParameterPack; @@ -731,7 +730,7 @@ public: LambdaScopeInfo(DiagnosticsEngine &Diag) : CapturingScopeInfo(Diag, ImpCap_None), Lambda(nullptr), CallOperator(nullptr), NumExplicitCaptures(0), Mutable(false), - ExplicitParams(false), Cleanup{}, + ExplicitParams(false), ExprNeedsCleanups(false), ContainsUnexpandedParameterPack(false), AutoTemplateParameterDepth(0), GLTemplateParameterList(nullptr) { Kind = SK_Lambda; diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 0d15a9b26fbfc3c1d4560e4607fa769ca5e4ec1a..62f37fda52d35b029d21100cf557e219b1cb1200 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -34,7 +34,6 @@ #include "clang/Basic/TemplateKinds.h" #include "clang/Basic/TypeTraits.h" #include "clang/Sema/AnalysisBasedWarnings.h" -#include "clang/Sema/CleanupInfo.h" #include "clang/Sema/DeclSpec.h" #include "clang/Sema/ExternalSemaSource.h" #include "clang/Sema/IdentifierResolver.h" @@ -441,8 +440,9 @@ public: /// if Sema is already doing so, which would cause infinite recursions. bool IsBuildingRecoveryCallExpr; - /// Used to control the generation of ExprWithCleanups. - CleanupInfo Cleanup; + /// ExprNeedsCleanups - True if the current evaluation context + /// requires cleanups to be run at its conclusion. + bool ExprNeedsCleanups; /// ExprCleanupObjects - This is the stack of objects requiring /// cleanup that are created by the current full expression. The @@ -830,7 +830,7 @@ public: ExpressionEvaluationContext Context; /// \brief Whether the enclosing context needed a cleanup. - CleanupInfo ParentCleanup; + bool ParentNeedsCleanups; /// \brief Whether we are in a decltype expression. bool IsDecltype; @@ -871,10 +871,10 @@ public: ExpressionEvaluationContextRecord(ExpressionEvaluationContext Context, unsigned NumCleanupObjects, - CleanupInfo ParentCleanup, + bool ParentNeedsCleanups, Decl *ManglingContextDecl, bool IsDecltype) - : Context(Context), ParentCleanup(ParentCleanup), + : Context(Context), ParentNeedsCleanups(ParentNeedsCleanups), IsDecltype(IsDecltype), NumCleanupObjects(NumCleanupObjects), NumTypos(0), ManglingContextDecl(ManglingContextDecl), MangleNumbering() { } @@ -4872,10 +4872,6 @@ public: Stmt *MaybeCreateStmtWithCleanups(Stmt *SubStmt); ExprResult MaybeCreateExprWithCleanups(ExprResult SubExpr); - MaterializeTemporaryExpr * - CreateMaterializeTemporaryExpr(QualType T, Expr *Temporary, - bool BoundToLvalueReference); - ExprResult ActOnFinishFullExpr(Expr *Expr) { return ActOnFinishFullExpr(Expr, Expr ? Expr->getExprLoc() : SourceLocation()); diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index dc87c0a8e265c4a49474e3f1c0bf6ce5a1002ca3..4c0492c393596585f3a1c501359a808eb322175a 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -2890,6 +2890,7 @@ bool Expr::HasSideEffects(const ASTContext &Ctx, case CXXThrowExprClass: case CXXNewExprClass: case CXXDeleteExprClass: + case ExprWithCleanupsClass: case CoawaitExprClass: case CoyieldExprClass: // These always have a side-effect. @@ -2902,12 +2903,6 @@ bool Expr::HasSideEffects(const ASTContext &Ctx, return Finder.hasSideEffects(); } - case ExprWithCleanupsClass: - if (IncludePossibleEffects) - if (cast<ExprWithCleanups>(this)->cleanupsHaveSideEffects()) - return true; - break; - case ParenExprClass: case ArraySubscriptExprClass: case OMPArraySectionExprClass: diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp index 7978b0a90aa8fbb3c3063ae68273ec6b64675452..dbfe58c8b3d094fe96dde16325253253f011b3c5 100644 --- a/lib/AST/ExprCXX.cpp +++ b/lib/AST/ExprCXX.cpp @@ -1039,7 +1039,6 @@ bool LambdaExpr::isMutable() const { } ExprWithCleanups::ExprWithCleanups(Expr *subexpr, - bool CleanupsHaveSideEffects, ArrayRef<CleanupObject> objects) : Expr(ExprWithCleanupsClass, subexpr->getType(), subexpr->getValueKind(), subexpr->getObjectKind(), @@ -1047,19 +1046,16 @@ ExprWithCleanups::ExprWithCleanups(Expr *subexpr, subexpr->isInstantiationDependent(), subexpr->containsUnexpandedParameterPack()), SubExpr(subexpr) { - ExprWithCleanupsBits.CleanupsHaveSideEffects = CleanupsHaveSideEffects; ExprWithCleanupsBits.NumObjects = objects.size(); for (unsigned i = 0, e = objects.size(); i != e; ++i) getTrailingObjects<CleanupObject>()[i] = objects[i]; } ExprWithCleanups *ExprWithCleanups::Create(const ASTContext &C, Expr *subexpr, - bool CleanupsHaveSideEffects, ArrayRef<CleanupObject> objects) { void *buffer = C.Allocate(totalSizeToAlloc<CleanupObject>(objects.size()), llvm::alignOf<ExprWithCleanups>()); - return new (buffer) - ExprWithCleanups(subexpr, CleanupsHaveSideEffects, objects); + return new (buffer) ExprWithCleanups(subexpr, objects); } ExprWithCleanups::ExprWithCleanups(EmptyShell empty, unsigned numObjects) diff --git a/lib/Analysis/Consumed.cpp b/lib/Analysis/Consumed.cpp index f2a7d904a54e41acd5c5950699f6ccff03d74853..9df23923b014b924fb0c47c101d5a84758c89f7d 100644 --- a/lib/Analysis/Consumed.cpp +++ b/lib/Analysis/Consumed.cpp @@ -466,15 +466,9 @@ class ConsumedStmtVisitor : public ConstStmtVisitor<ConsumedStmtVisitor> { MapType PropagationMap; InfoEntry findInfo(const Expr *E) { - if (auto Cleanups = dyn_cast<ExprWithCleanups>(E)) - if (!Cleanups->cleanupsHaveSideEffects()) - E = Cleanups->getSubExpr(); return PropagationMap.find(E->IgnoreParens()); } ConstInfoEntry findInfo(const Expr *E) const { - if (auto Cleanups = dyn_cast<ExprWithCleanups>(E)) - if (!Cleanups->cleanupsHaveSideEffects()) - E = Cleanups->getSubExpr(); return PropagationMap.find(E->IgnoreParens()); } void insertInfo(const Expr *E, const PropagationInfo &PI) { diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp index b15c3e9e148698c7c8d8959db1c65d04828fc97e..d64c5876ee2d6a280c6ad4f79b1f3ae4d0face02 100644 --- a/lib/CodeGen/CGExprConstant.cpp +++ b/lib/CodeGen/CGExprConstant.cpp @@ -764,12 +764,6 @@ public: return Visit(DIE->getExpr()); } - llvm::Constant *VisitExprWithCleanups(ExprWithCleanups *E) { - if (!E->cleanupsHaveSideEffects()) - return Visit(E->getSubExpr()); - return nullptr; - } - llvm::Constant *VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E) { return Visit(E->GetTemporaryExpr()); } diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index d7697bfc9beefc35d7e2b2877583e1decfed164c..e7708e044d26770d8e901c23d0926d96c03bb42e 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -88,7 +88,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, ConstSegStack(nullptr), CodeSegStack(nullptr), CurInitSeg(nullptr), VisContext(nullptr), IsBuildingRecoveryCallExpr(false), - Cleanup{}, LateTemplateParser(nullptr), + ExprNeedsCleanups(false), LateTemplateParser(nullptr), LateTemplateParserCleanup(nullptr), OpaqueParser(nullptr), IdResolver(pp), StdInitializerList(nullptr), CXXTypeInfoDecl(nullptr), MSVCGuidDecl(nullptr), @@ -124,8 +124,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, // Tell diagnostics how to render things from the AST library. Diags.SetArgToStringFn(&FormatASTNodeDiagnosticArgument, &Context); - ExprEvalContexts.emplace_back(PotentiallyEvaluated, 0, CleanupInfo{}, nullptr, - false); + ExprEvalContexts.emplace_back(PotentiallyEvaluated, 0, false, nullptr, false); FunctionScopes.push_back(new FunctionScopeInfo(Diags)); diff --git a/lib/Sema/SemaCast.cpp b/lib/Sema/SemaCast.cpp index d27500d3f13b5d64cde205fc72603bae0215e9e2..df32dbdb1501421a10278d1da10c9db98a163689 100644 --- a/lib/Sema/SemaCast.cpp +++ b/lib/Sema/SemaCast.cpp @@ -641,8 +641,8 @@ void CastOperation::CheckDynamicCast() { // If we're dynamic_casting from a prvalue to an rvalue reference, we need // to materialize the prvalue before we bind the reference to it. if (SrcExpr.get()->isRValue()) - SrcExpr = Self.CreateMaterializeTemporaryExpr( - SrcType, SrcExpr.get(), /*IsLValueReference*/ false); + SrcExpr = new (Self.Context) MaterializeTemporaryExpr( + SrcType, SrcExpr.get(), /*IsLValueReference*/false); SrcPointee = SrcType; } @@ -1649,8 +1649,8 @@ static TryCastResult TryConstCast(Sema &Self, ExprResult &SrcExpr, if (NeedToMaterializeTemporary) // This is a const_cast from a class prvalue to an rvalue reference type. // Materialize a temporary to store the result of the conversion. - SrcExpr = Self.CreateMaterializeTemporaryExpr(SrcType, SrcExpr.get(), - /*IsLValueReference*/ false); + SrcExpr = new (Self.Context) MaterializeTemporaryExpr( + SrcType, SrcExpr.get(), /*IsLValueReference*/ false); return TC_Success; } diff --git a/lib/Sema/SemaCoroutine.cpp b/lib/Sema/SemaCoroutine.cpp index c8715fff41596a5a51df84b3a3d9c807eb69a429..4b4fd6b16a068ea6b5d9efe103857591f3f33519 100644 --- a/lib/Sema/SemaCoroutine.cpp +++ b/lib/Sema/SemaCoroutine.cpp @@ -244,7 +244,7 @@ ExprResult Sema::BuildCoawaitExpr(SourceLocation Loc, Expr *E) { // If the expression is a temporary, materialize it as an lvalue so that we // can use it multiple times. if (E->getValueKind() == VK_RValue) - E = CreateMaterializeTemporaryExpr(E->getType(), E, true); + E = new (Context) MaterializeTemporaryExpr(E->getType(), E, true); // Build the await_ready, await_suspend, await_resume calls. ReadySuspendResumeResult RSS = buildCoawaitCalls(*this, Loc, E); @@ -311,7 +311,7 @@ ExprResult Sema::BuildCoyieldExpr(SourceLocation Loc, Expr *E) { // If the expression is a temporary, materialize it as an lvalue so that we // can use it multiple times. if (E->getValueKind() == VK_RValue) - E = CreateMaterializeTemporaryExpr(E->getType(), E, true); + E = new (Context) MaterializeTemporaryExpr(E->getType(), E, true); // Build the await_ready, await_suspend, await_resume calls. ReadySuspendResumeResult RSS = buildCoawaitCalls(*this, Loc, E); diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 632532ad44ee8573c0d972c021e23842c218ef53..fab72f36605e589748af1fda5917d55f3a276bda 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -11648,7 +11648,7 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, assert(ExprCleanupObjects.size() == ExprEvalContexts.back().NumCleanupObjects && "Leftover temporaries in function"); - assert(!Cleanup.exprNeedsCleanups() && "Unaccounted cleanups in function"); + assert(!ExprNeedsCleanups && "Unaccounted cleanups in function"); assert(MaybeODRUseExprs.empty() && "Leftover expressions for odr-use checking"); } diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 784dd7c45376b73ada3f21781411653a085f4edf..f4a5dea8f94c991b6db0d0d5a3712f9e3bee34b7 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -712,7 +712,7 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) { // balance that. if (getLangOpts().ObjCAutoRefCount && E->getType().getObjCLifetime() == Qualifiers::OCL_Weak) - Cleanup.setExprNeedsCleanups(true); + ExprNeedsCleanups = true; ExprResult Res = ImplicitCastExpr::Create(Context, T, CK_LValueToRValue, E, nullptr, VK_RValue); @@ -4573,15 +4573,15 @@ ExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc, // bound temporaries; see the comment in PR5810. // We don't need to do that with block decls, though, because // blocks in default argument expression can never capture anything. - if (auto Init = dyn_cast<ExprWithCleanups>(Param->getInit())) { + if (isa<ExprWithCleanups>(Param->getInit())) { // Set the "needs cleanups" bit regardless of whether there are // any explicit objects. - Cleanup.setExprNeedsCleanups(Init->cleanupsHaveSideEffects()); + ExprNeedsCleanups = true; // Append all the objects to the cleanup list. Right now, this // should always be a no-op, because blocks in default argument // expressions should never be able to capture anything. - assert(!Init->getNumObjects() && + assert(!cast<ExprWithCleanups>(Param->getInit())->getNumObjects() && "default argument expression has capturing blocks?"); } @@ -5596,7 +5596,7 @@ void Sema::maybeExtendBlockObject(ExprResult &E) { E = ImplicitCastExpr::Create(Context, E.get()->getType(), CK_ARCExtendBlockObject, E.get(), /*base path*/ nullptr, VK_RValue); - Cleanup.setExprNeedsCleanups(true); + ExprNeedsCleanups = true; } /// Prepare a conversion of the given expression to an ObjC object @@ -10382,8 +10382,8 @@ QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) { if (sfinae) return QualType(); // Materialize the temporary as an lvalue so that we can take its address. - OrigOp = op = - CreateMaterializeTemporaryExpr(op->getType(), OrigOp.get(), true); + OrigOp = op = new (Context) + MaterializeTemporaryExpr(op->getType(), OrigOp.get(), true); } else if (isa<ObjCSelectorExpr>(op)) { return Context.getPointerType(op->getType()); } else if (lval == Expr::LV_MemberFunction) { @@ -11596,8 +11596,7 @@ Sema::ActOnStmtExpr(SourceLocation LPLoc, Stmt *SubStmt, if (hasAnyUnrecoverableErrorsInThisFunction()) DiscardCleanupsInEvaluationContext(); - assert(!Cleanup.exprNeedsCleanups() && - "cleanups within StmtExpr not correctly bound!"); + assert(!ExprNeedsCleanups && "cleanups within StmtExpr not correctly bound!"); PopExpressionEvaluationContext(); // FIXME: there are a variety of strange constraints to enforce here, for @@ -12065,8 +12064,7 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, // Leave the expression-evaluation context. if (hasAnyUnrecoverableErrorsInThisFunction()) DiscardCleanupsInEvaluationContext(); - assert(!Cleanup.exprNeedsCleanups() && - "cleanups within block not correctly bound!"); + assert(!ExprNeedsCleanups && "cleanups within block not correctly bound!"); PopExpressionEvaluationContext(); BlockScopeInfo *BSI = cast<BlockScopeInfo>(FunctionScopes.back()); @@ -12157,7 +12155,7 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, if (Result->getBlockDecl()->hasCaptures()) { // First, this expression has a new cleanup object. ExprCleanupObjects.push_back(Result->getBlockDecl()); - Cleanup.setExprNeedsCleanups(true); + ExprNeedsCleanups = true; // It also gets a branch-protected scope if any of the captured // variables needs destruction. @@ -12794,9 +12792,10 @@ void Sema::PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext, Decl *LambdaContextDecl, bool IsDecltype) { - ExprEvalContexts.emplace_back(NewContext, ExprCleanupObjects.size(), Cleanup, - LambdaContextDecl, IsDecltype); - Cleanup.reset(); + ExprEvalContexts.emplace_back(NewContext, ExprCleanupObjects.size(), + ExprNeedsCleanups, LambdaContextDecl, + IsDecltype); + ExprNeedsCleanups = false; if (!MaybeODRUseExprs.empty()) std::swap(MaybeODRUseExprs, ExprEvalContexts.back().SavedMaybeODRUseExprs); } @@ -12847,12 +12846,12 @@ void Sema::PopExpressionEvaluationContext() { if (Rec.isUnevaluated() || Rec.Context == ConstantEvaluated) { ExprCleanupObjects.erase(ExprCleanupObjects.begin() + Rec.NumCleanupObjects, ExprCleanupObjects.end()); - Cleanup = Rec.ParentCleanup; + ExprNeedsCleanups = Rec.ParentNeedsCleanups; CleanupVarDeclMarking(); std::swap(MaybeODRUseExprs, Rec.SavedMaybeODRUseExprs); // Otherwise, merge the contexts together. } else { - Cleanup.mergeFrom(Rec.ParentCleanup); + ExprNeedsCleanups |= Rec.ParentNeedsCleanups; MaybeODRUseExprs.insert(Rec.SavedMaybeODRUseExprs.begin(), Rec.SavedMaybeODRUseExprs.end()); } @@ -12871,7 +12870,7 @@ void Sema::DiscardCleanupsInEvaluationContext() { ExprCleanupObjects.erase( ExprCleanupObjects.begin() + ExprEvalContexts.back().NumCleanupObjects, ExprCleanupObjects.end()); - Cleanup.reset(); + ExprNeedsCleanups = false; MaybeODRUseExprs.clear(); } diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 7562a178e2e01e8c2c63fa6e82f9f6875bfbf3cc..4b1be6483c4fcb0fe7d1bb022f83c466ea574705 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -5551,7 +5551,7 @@ ExprResult Sema::MaybeBindToTemporary(Expr *E) { if (!ReturnsRetained && E->getType()->isObjCARCImplicitlyUnretainedType()) return E; - Cleanup.setExprNeedsCleanups(true); + ExprNeedsCleanups = true; CastKind ck = (ReturnsRetained ? CK_ARCConsumeObject : CK_ARCReclaimReturnedObject); @@ -5604,7 +5604,7 @@ ExprResult Sema::MaybeBindToTemporary(Expr *E) { return E; // We need a cleanup, but we don't need to remember the temporary. - Cleanup.setExprNeedsCleanups(true); + ExprNeedsCleanups = true; } CXXTemporary *Temp = CXXTemporary::Create(Context, Destructor); @@ -5631,16 +5631,14 @@ Expr *Sema::MaybeCreateExprWithCleanups(Expr *SubExpr) { unsigned FirstCleanup = ExprEvalContexts.back().NumCleanupObjects; assert(ExprCleanupObjects.size() >= FirstCleanup); - assert(Cleanup.exprNeedsCleanups() || - ExprCleanupObjects.size() == FirstCleanup); - if (!Cleanup.exprNeedsCleanups()) + assert(ExprNeedsCleanups || ExprCleanupObjects.size() == FirstCleanup); + if (!ExprNeedsCleanups) return SubExpr; auto Cleanups = llvm::makeArrayRef(ExprCleanupObjects.begin() + FirstCleanup, ExprCleanupObjects.size() - FirstCleanup); - auto *E = ExprWithCleanups::Create( - Context, SubExpr, Cleanup.cleanupsHaveSideEffects(), Cleanups); + Expr *E = ExprWithCleanups::Create(Context, SubExpr, Cleanups); DiscardCleanupsInEvaluationContext(); return E; @@ -5651,7 +5649,7 @@ Stmt *Sema::MaybeCreateStmtWithCleanups(Stmt *SubStmt) { CleanupVarDeclMarking(); - if (!Cleanup.exprNeedsCleanups()) + if (!ExprNeedsCleanups) return SubStmt; // FIXME: In order to attach the temporaries, wrap the statement into @@ -5757,7 +5755,7 @@ ExprResult Sema::ActOnDecltypeExpression(Expr *E) { return ExprError(); // We need a cleanup, but we don't need to remember the temporary. - Cleanup.setExprNeedsCleanups(true); + ExprNeedsCleanups = true; } // Possibly strip off the top CXXBindTemporaryExpr. diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp index 598ae2098aa4cd02bdffc11473db854ea5f57e9a..56161c7a4d2522f64c4d4a12460ec063ddaa2bbf 100644 --- a/lib/Sema/SemaExprObjC.cpp +++ b/lib/Sema/SemaExprObjC.cpp @@ -4067,7 +4067,7 @@ Sema::CheckObjCARCConversion(SourceRange castRange, QualType castType, castExpr = ImplicitCastExpr::Create(Context, castExpr->getType(), CK_ARCConsumeObject, castExpr, nullptr, VK_RValue); - Cleanup.setExprNeedsCleanups(true); + ExprNeedsCleanups = true; return ACR_okay; } @@ -4310,7 +4310,7 @@ ExprResult Sema::BuildObjCBridgedCast(SourceLocation LParenLoc, TSInfo, SubExpr); if (MustConsume) { - Cleanup.setExprNeedsCleanups(true); + ExprNeedsCleanups = true; Result = ImplicitCastExpr::Create(Context, T, CK_ARCConsumeObject, Result, nullptr, VK_RValue); } diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index 2c4cfab0548ebe49c009c5174fd40cec9a2ee3a2..c162007349ca21f24ae51eb7d093d6da3cae8d77 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -4807,8 +4807,8 @@ static void checkIndirectCopyRestoreSource(Sema &S, Expr *src) { // If isWeakAccess to true, there will be an implicit // load which requires a cleanup. if (S.getLangOpts().ObjCAutoRefCount && isWeakAccess) - S.Cleanup.setExprNeedsCleanups(true); - + S.ExprNeedsCleanups = true; + if (iik == IIK_okay) return; S.Diag(src->getExprLoc(), diag::err_arc_nonlocal_writeback) @@ -6182,22 +6182,6 @@ static void CheckForNullPointerDereference(Sema &S, const Expr *E) { } } -MaterializeTemporaryExpr * -Sema::CreateMaterializeTemporaryExpr(QualType T, Expr *Temporary, - bool BoundToLvalueReference) { - auto MTE = new (Context) - MaterializeTemporaryExpr(T, Temporary, BoundToLvalueReference); - - // Order an ExprWithCleanups for lifetime marks. - // - // TODO: It'll be good to have a single place to check the access of the - // destructor and generate ExprWithCleanups for various uses. Currently these - // are done in both CreateMaterializeTemporaryExpr and MaybeBindToTemporary, - // but there may be a chance to merge them. - Cleanup.setExprNeedsCleanups(false); - return MTE; -} - ExprResult InitializationSequence::Perform(Sema &S, const InitializedEntity &Entity, @@ -6462,7 +6446,7 @@ InitializationSequence::Perform(Sema &S, return ExprError(); // Materialize the temporary into memory. - MaterializeTemporaryExpr *MTE = S.CreateMaterializeTemporaryExpr( + MaterializeTemporaryExpr *MTE = new (S.Context) MaterializeTemporaryExpr( Entity.getType().getNonReferenceType(), CurInit.get(), Entity.getType()->isLValueReferenceType()); @@ -6482,7 +6466,7 @@ InitializationSequence::Perform(Sema &S, MTE->getType()->isObjCLifetimeType()) || (MTE->getStorageDuration() == SD_Automatic && MTE->getType().isDestructedType())) - S.Cleanup.setExprNeedsCleanups(true); + S.ExprNeedsCleanups = true; CurInit = MTE; break; @@ -6874,9 +6858,9 @@ InitializationSequence::Perform(Sema &S, << CurInit.get()->getSourceRange(); // Materialize the temporary into memory. - MaterializeTemporaryExpr *MTE = S.CreateMaterializeTemporaryExpr( - CurInit.get()->getType(), CurInit.get(), - /*BoundToLvalueReference=*/false); + MaterializeTemporaryExpr *MTE = new (S.Context) + MaterializeTemporaryExpr(CurInit.get()->getType(), CurInit.get(), + /*BoundToLvalueReference=*/false); // Maybe lifetime-extend the array temporary's subobjects to match the // entity's lifetime. diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp index ae768b62677120be9f398ebd1f2a7b0d281d0fbe..d1d002b5d41e9838b356d54fd255a4f17e0d60b8 100644 --- a/lib/Sema/SemaLambda.cpp +++ b/lib/Sema/SemaLambda.cpp @@ -1500,7 +1500,7 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc, SourceRange IntroducerRange; bool ExplicitParams; bool ExplicitResultType; - CleanupInfo LambdaCleanup; + bool LambdaExprNeedsCleanups; bool ContainsUnexpandedParameterPack; SmallVector<VarDecl *, 4> ArrayIndexVars; SmallVector<unsigned, 4> ArrayIndexStarts; @@ -1510,7 +1510,7 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc, IntroducerRange = LSI->IntroducerRange; ExplicitParams = LSI->ExplicitParams; ExplicitResultType = !LSI->HasImplicitReturnType; - LambdaCleanup = LSI->Cleanup; + LambdaExprNeedsCleanups = LSI->ExprNeedsCleanups; ContainsUnexpandedParameterPack = LSI->ContainsUnexpandedParameterPack; CallOperator->setLexicalDeclContext(Class); @@ -1591,8 +1591,9 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc, CheckCompletedCXXClass(Class); } - Cleanup.mergeFrom(LambdaCleanup); - + if (LambdaExprNeedsCleanups) + ExprNeedsCleanups = true; + LambdaExpr *Lambda = LambdaExpr::Create(Context, Class, IntroducerRange, CaptureDefault, CaptureDefaultLoc, Captures, @@ -1713,7 +1714,7 @@ ExprResult Sema::BuildBlockForLambdaConversion(SourceLocation CurrentLocation, // Create the block literal expression. Expr *BuildBlock = new (Context) BlockExpr(Block, Conv->getConversionType()); ExprCleanupObjects.push_back(Block); - Cleanup.setExprNeedsCleanups(true); + ExprNeedsCleanups = true; return BuildBlock; } diff --git a/lib/Sema/SemaOpenMP.cpp b/lib/Sema/SemaOpenMP.cpp index b8160e0b60ebd3a96b348f36486d2a2c5d5ee3d4..36ad9e80e379b41cacac4e5dec8c8bd8bf5200b1 100644 --- a/lib/Sema/SemaOpenMP.cpp +++ b/lib/Sema/SemaOpenMP.cpp @@ -3801,10 +3801,6 @@ bool OpenMPIterationSpaceChecker::CheckInit(Stmt *S, bool EmitDiags) { } return true; } - if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(S)) - if (!ExprTemp->cleanupsHaveSideEffects()) - S = ExprTemp->getSubExpr(); - InitSrcRange = S->getSourceRange(); if (Expr *E = dyn_cast<Expr>(S)) S = E->IgnoreParens(); @@ -3992,10 +3988,6 @@ bool OpenMPIterationSpaceChecker::CheckInc(Expr *S) { SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_incr) << LCDecl; return true; } - if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(S)) - if (!ExprTemp->cleanupsHaveSideEffects()) - S = ExprTemp->getSubExpr(); - IncrementSrcRange = S->getSourceRange(); S = S->IgnoreParens(); if (auto UO = dyn_cast<UnaryOperator>(S)) { diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index 7156cd2a9adb53290eace2d5be494003a1aaf403..d2d4098d17709e2ed235f9bf498422213c0d71c1 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -1518,10 +1518,6 @@ namespace { // variables Increment and DRE. bool ProcessIterationStmt(Sema &S, Stmt* Statement, bool &Increment, DeclRefExpr *&DRE) { - if (auto Cleanups = dyn_cast<ExprWithCleanups>(Statement)) - if (!Cleanups->cleanupsHaveSideEffects()) - Statement = Cleanups->getSubExpr(); - if (UnaryOperator *UO = dyn_cast<UnaryOperator>(Statement)) { switch (UO->getOpcode()) { default: return false; @@ -2476,10 +2472,6 @@ static void DiagnoseForRangeReferenceVariableCopies(Sema &SemaRef, QualType VariableType = VD->getType(); - if (auto Cleanups = dyn_cast<ExprWithCleanups>(InitExpr)) - if (!Cleanups->cleanupsHaveSideEffects()) - InitExpr = Cleanups->getSubExpr(); - const MaterializeTemporaryExpr *MTE = dyn_cast<MaterializeTemporaryExpr>(InitExpr); diff --git a/lib/Serialization/ASTReaderStmt.cpp b/lib/Serialization/ASTReaderStmt.cpp index abb885e81b2b3629006b6bd3c1fbacc1ef5a31eb..15e289f6f8e2e1de0c788f3725c3ee97a1a488ef 100644 --- a/lib/Serialization/ASTReaderStmt.cpp +++ b/lib/Serialization/ASTReaderStmt.cpp @@ -1448,7 +1448,6 @@ void ASTStmtReader::VisitExprWithCleanups(ExprWithCleanups *E) { E->getTrailingObjects<BlockDecl *>()[i] = ReadDeclAs<BlockDecl>(Record, Idx); - E->ExprWithCleanupsBits.CleanupsHaveSideEffects = Record[Idx++]; E->SubExpr = Reader.ReadSubExpr(); } diff --git a/lib/Serialization/ASTWriterStmt.cpp b/lib/Serialization/ASTWriterStmt.cpp index 911ac478b8182c553dbd40931c95b13b2f4804f9..5382b4af9228476cab867ea7c74ee0301cfe1806 100644 --- a/lib/Serialization/ASTWriterStmt.cpp +++ b/lib/Serialization/ASTWriterStmt.cpp @@ -1430,8 +1430,7 @@ void ASTStmtWriter::VisitExprWithCleanups(ExprWithCleanups *E) { Record.push_back(E->getNumObjects()); for (unsigned i = 0, e = E->getNumObjects(); i != e; ++i) Record.AddDeclRef(E->getObject(i)); - - Record.push_back(E->cleanupsHaveSideEffects()); + Record.AddStmt(E->getSubExpr()); Code = serialization::EXPR_EXPR_WITH_CLEANUPS; } diff --git a/unittests/ASTMatchers/ASTMatchersNodeTest.cpp b/unittests/ASTMatchers/ASTMatchersNodeTest.cpp index c659c6a002667882dd50092ed4319752255ea219..4bbc0a48019e77a7615dd3155a469b30f51c685d 100644 --- a/unittests/ASTMatchers/ASTMatchersNodeTest.cpp +++ b/unittests/ASTMatchers/ASTMatchersNodeTest.cpp @@ -999,8 +999,8 @@ TEST(ExprWithCleanups, MatchesExprWithCleanups) { EXPECT_TRUE(matches("struct Foo { ~Foo(); };" "const Foo f = Foo();", varDecl(hasInitializer(exprWithCleanups())))); - EXPECT_FALSE(matches("struct Foo { }; Foo a;" - "const Foo f = a;", + EXPECT_FALSE(matches("struct Foo { };" + "const Foo f = Foo();", varDecl(hasInitializer(exprWithCleanups())))); }