Skip to content
This repository was archived by the owner on Nov 1, 2021. It is now read-only.

Commit e1fab5f

Browse files
committed
[Temporary] Add an ExprWithCleanups for each C++ MaterializeTemporaryExpr.
These ExprWithCleanups are added for holding a RunCleanupsScope not for destructor calls; rather, they are for lifetime marks. This requires ExprWithCleanups to keep a bit to indicate whether it have cleanups with side effects (e.g. dtor calls). Differential Revision: http://reviews.llvm.org/D20498 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@272296 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 8617be2 commit e1fab5f

23 files changed

+181
-63
lines changed

Diff for: include/clang/AST/ExprCXX.h

+6-1
Original file line numberDiff line numberDiff line change
@@ -2877,7 +2877,8 @@ class ExprWithCleanups final
28772877
Stmt *SubExpr;
28782878

28792879
ExprWithCleanups(EmptyShell, unsigned NumObjects);
2880-
ExprWithCleanups(Expr *SubExpr, ArrayRef<CleanupObject> Objects);
2880+
ExprWithCleanups(Expr *SubExpr, bool CleanupsHaveSideEffects,
2881+
ArrayRef<CleanupObject> Objects);
28812882

28822883
friend TrailingObjects;
28832884
friend class ASTStmtReader;
@@ -2887,6 +2888,7 @@ class ExprWithCleanups final
28872888
unsigned numObjects);
28882889

28892890
static ExprWithCleanups *Create(const ASTContext &C, Expr *subexpr,
2891+
bool CleanupsHaveSideEffects,
28902892
ArrayRef<CleanupObject> objects);
28912893

28922894
ArrayRef<CleanupObject> getObjects() const {
@@ -2903,6 +2905,9 @@ class ExprWithCleanups final
29032905

29042906
Expr *getSubExpr() { return cast<Expr>(SubExpr); }
29052907
const Expr *getSubExpr() const { return cast<Expr>(SubExpr); }
2908+
bool cleanupsHaveSideEffects() const {
2909+
return ExprWithCleanupsBits.CleanupsHaveSideEffects;
2910+
}
29062911

29072912
/// As with any mutator of the AST, be very careful
29082913
/// when modifying an existing AST to preserve its invariants.

Diff for: include/clang/AST/Stmt.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,10 @@ class LLVM_ALIGNAS(LLVM_PTR_SIZE) Stmt {
192192

193193
unsigned : NumExprBits;
194194

195-
unsigned NumObjects : 32 - NumExprBits;
195+
// When false, it must not have side effects.
196+
bool CleanupsHaveSideEffects : 1;
197+
198+
unsigned NumObjects : 32 - 1 - NumExprBits;
196199
};
197200

198201
class PseudoObjectExprBitfields {

Diff for: include/clang/Sema/CleanupInfo.h

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
//===--- CleanupInfo.cpp - Cleanup Control in Sema ------------------------===//
2+
//
3+
// The LLVM Compiler Infrastructure
4+
//
5+
// This file is distributed under the University of Illinois Open Source
6+
// License. See LICENSE.TXT for details.
7+
//
8+
//===----------------------------------------------------------------------===//
9+
//
10+
// This file implements a set of operations on whether generating an
11+
// ExprWithCleanups in a full expression.
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
#ifndef LLVM_CLANG_SEMA_CLEANUP_INFO_H
16+
#define LLVM_CLANG_SEMA_CLEANUP_INFO_H
17+
18+
namespace clang {
19+
20+
class CleanupInfo {
21+
bool ExprNeedsCleanups = false;
22+
bool CleanupsHaveSideEffects = false;
23+
24+
public:
25+
bool exprNeedsCleanups() const { return ExprNeedsCleanups; }
26+
27+
bool cleanupsHaveSideEffects() const { return CleanupsHaveSideEffects; }
28+
29+
void setExprNeedsCleanups(bool SideEffects) {
30+
ExprNeedsCleanups = true;
31+
CleanupsHaveSideEffects |= SideEffects;
32+
}
33+
34+
void reset() {
35+
ExprNeedsCleanups = false;
36+
CleanupsHaveSideEffects = false;
37+
}
38+
39+
void mergeFrom(CleanupInfo Rhs) {
40+
ExprNeedsCleanups |= Rhs.ExprNeedsCleanups;
41+
CleanupsHaveSideEffects |= Rhs.CleanupsHaveSideEffects;
42+
}
43+
};
44+
45+
} // end namespace clang
46+
47+
#endif

Diff for: include/clang/Sema/ScopeInfo.h

+3-2
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "clang/AST/Type.h"
2020
#include "clang/Basic/CapturedStmt.h"
2121
#include "clang/Basic/PartialDiagnostic.h"
22+
#include "clang/Sema/CleanupInfo.h"
2223
#include "clang/Sema/Ownership.h"
2324
#include "llvm/ADT/DenseMap.h"
2425
#include "llvm/ADT/SmallSet.h"
@@ -682,7 +683,7 @@ class LambdaScopeInfo final : public CapturingScopeInfo {
682683
bool ExplicitParams;
683684

684685
/// \brief Whether any of the capture expressions requires cleanups.
685-
bool ExprNeedsCleanups;
686+
CleanupInfo Cleanup;
686687

687688
/// \brief Whether the lambda contains an unexpanded parameter pack.
688689
bool ContainsUnexpandedParameterPack;
@@ -730,7 +731,7 @@ class LambdaScopeInfo final : public CapturingScopeInfo {
730731
LambdaScopeInfo(DiagnosticsEngine &Diag)
731732
: CapturingScopeInfo(Diag, ImpCap_None), Lambda(nullptr),
732733
CallOperator(nullptr), NumExplicitCaptures(0), Mutable(false),
733-
ExplicitParams(false), ExprNeedsCleanups(false),
734+
ExplicitParams(false), Cleanup{},
734735
ContainsUnexpandedParameterPack(false), AutoTemplateParameterDepth(0),
735736
GLTemplateParameterList(nullptr) {
736737
Kind = SK_Lambda;

Diff for: include/clang/Sema/Sema.h

+10-6
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include "clang/Basic/TemplateKinds.h"
3535
#include "clang/Basic/TypeTraits.h"
3636
#include "clang/Sema/AnalysisBasedWarnings.h"
37+
#include "clang/Sema/CleanupInfo.h"
3738
#include "clang/Sema/DeclSpec.h"
3839
#include "clang/Sema/ExternalSemaSource.h"
3940
#include "clang/Sema/IdentifierResolver.h"
@@ -440,9 +441,8 @@ class Sema {
440441
/// if Sema is already doing so, which would cause infinite recursions.
441442
bool IsBuildingRecoveryCallExpr;
442443

443-
/// ExprNeedsCleanups - True if the current evaluation context
444-
/// requires cleanups to be run at its conclusion.
445-
bool ExprNeedsCleanups;
444+
/// Used to control the generation of ExprWithCleanups.
445+
CleanupInfo Cleanup;
446446

447447
/// ExprCleanupObjects - This is the stack of objects requiring
448448
/// cleanup that are created by the current full expression. The
@@ -830,7 +830,7 @@ class Sema {
830830
ExpressionEvaluationContext Context;
831831

832832
/// \brief Whether the enclosing context needed a cleanup.
833-
bool ParentNeedsCleanups;
833+
CleanupInfo ParentCleanup;
834834

835835
/// \brief Whether we are in a decltype expression.
836836
bool IsDecltype;
@@ -871,10 +871,10 @@ class Sema {
871871

872872
ExpressionEvaluationContextRecord(ExpressionEvaluationContext Context,
873873
unsigned NumCleanupObjects,
874-
bool ParentNeedsCleanups,
874+
CleanupInfo ParentCleanup,
875875
Decl *ManglingContextDecl,
876876
bool IsDecltype)
877-
: Context(Context), ParentNeedsCleanups(ParentNeedsCleanups),
877+
: Context(Context), ParentCleanup(ParentCleanup),
878878
IsDecltype(IsDecltype), NumCleanupObjects(NumCleanupObjects),
879879
NumTypos(0),
880880
ManglingContextDecl(ManglingContextDecl), MangleNumbering() { }
@@ -4872,6 +4872,10 @@ class Sema {
48724872
Stmt *MaybeCreateStmtWithCleanups(Stmt *SubStmt);
48734873
ExprResult MaybeCreateExprWithCleanups(ExprResult SubExpr);
48744874

4875+
MaterializeTemporaryExpr *
4876+
CreateMaterializeTemporaryExpr(QualType T, Expr *Temporary,
4877+
bool BoundToLvalueReference);
4878+
48754879
ExprResult ActOnFinishFullExpr(Expr *Expr) {
48764880
return ActOnFinishFullExpr(Expr, Expr ? Expr->getExprLoc()
48774881
: SourceLocation());

Diff for: lib/AST/Expr.cpp

+6-1
Original file line numberDiff line numberDiff line change
@@ -2890,7 +2890,6 @@ bool Expr::HasSideEffects(const ASTContext &Ctx,
28902890
case CXXThrowExprClass:
28912891
case CXXNewExprClass:
28922892
case CXXDeleteExprClass:
2893-
case ExprWithCleanupsClass:
28942893
case CoawaitExprClass:
28952894
case CoyieldExprClass:
28962895
// These always have a side-effect.
@@ -2903,6 +2902,12 @@ bool Expr::HasSideEffects(const ASTContext &Ctx,
29032902
return Finder.hasSideEffects();
29042903
}
29052904

2905+
case ExprWithCleanupsClass:
2906+
if (IncludePossibleEffects)
2907+
if (cast<ExprWithCleanups>(this)->cleanupsHaveSideEffects())
2908+
return true;
2909+
break;
2910+
29062911
case ParenExprClass:
29072912
case ArraySubscriptExprClass:
29082913
case OMPArraySectionExprClass:

Diff for: lib/AST/ExprCXX.cpp

+5-1
Original file line numberDiff line numberDiff line change
@@ -1039,23 +1039,27 @@ bool LambdaExpr::isMutable() const {
10391039
}
10401040

10411041
ExprWithCleanups::ExprWithCleanups(Expr *subexpr,
1042+
bool CleanupsHaveSideEffects,
10421043
ArrayRef<CleanupObject> objects)
10431044
: Expr(ExprWithCleanupsClass, subexpr->getType(),
10441045
subexpr->getValueKind(), subexpr->getObjectKind(),
10451046
subexpr->isTypeDependent(), subexpr->isValueDependent(),
10461047
subexpr->isInstantiationDependent(),
10471048
subexpr->containsUnexpandedParameterPack()),
10481049
SubExpr(subexpr) {
1050+
ExprWithCleanupsBits.CleanupsHaveSideEffects = CleanupsHaveSideEffects;
10491051
ExprWithCleanupsBits.NumObjects = objects.size();
10501052
for (unsigned i = 0, e = objects.size(); i != e; ++i)
10511053
getTrailingObjects<CleanupObject>()[i] = objects[i];
10521054
}
10531055

10541056
ExprWithCleanups *ExprWithCleanups::Create(const ASTContext &C, Expr *subexpr,
1057+
bool CleanupsHaveSideEffects,
10551058
ArrayRef<CleanupObject> objects) {
10561059
void *buffer = C.Allocate(totalSizeToAlloc<CleanupObject>(objects.size()),
10571060
llvm::alignOf<ExprWithCleanups>());
1058-
return new (buffer) ExprWithCleanups(subexpr, objects);
1061+
return new (buffer)
1062+
ExprWithCleanups(subexpr, CleanupsHaveSideEffects, objects);
10591063
}
10601064

10611065
ExprWithCleanups::ExprWithCleanups(EmptyShell empty, unsigned numObjects)

Diff for: lib/Analysis/Consumed.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -466,9 +466,15 @@ class ConsumedStmtVisitor : public ConstStmtVisitor<ConsumedStmtVisitor> {
466466
MapType PropagationMap;
467467

468468
InfoEntry findInfo(const Expr *E) {
469+
if (auto Cleanups = dyn_cast<ExprWithCleanups>(E))
470+
if (!Cleanups->cleanupsHaveSideEffects())
471+
E = Cleanups->getSubExpr();
469472
return PropagationMap.find(E->IgnoreParens());
470473
}
471474
ConstInfoEntry findInfo(const Expr *E) const {
475+
if (auto Cleanups = dyn_cast<ExprWithCleanups>(E))
476+
if (!Cleanups->cleanupsHaveSideEffects())
477+
E = Cleanups->getSubExpr();
472478
return PropagationMap.find(E->IgnoreParens());
473479
}
474480
void insertInfo(const Expr *E, const PropagationInfo &PI) {

Diff for: lib/CodeGen/CGExprConstant.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -764,6 +764,12 @@ class ConstExprEmitter :
764764
return Visit(DIE->getExpr());
765765
}
766766

767+
llvm::Constant *VisitExprWithCleanups(ExprWithCleanups *E) {
768+
if (!E->cleanupsHaveSideEffects())
769+
return Visit(E->getSubExpr());
770+
return nullptr;
771+
}
772+
767773
llvm::Constant *VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E) {
768774
return Visit(E->GetTemporaryExpr());
769775
}

Diff for: lib/Sema/Sema.cpp

+3-2
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
8888
ConstSegStack(nullptr), CodeSegStack(nullptr), CurInitSeg(nullptr),
8989
VisContext(nullptr),
9090
IsBuildingRecoveryCallExpr(false),
91-
ExprNeedsCleanups(false), LateTemplateParser(nullptr),
91+
Cleanup{}, LateTemplateParser(nullptr),
9292
LateTemplateParserCleanup(nullptr),
9393
OpaqueParser(nullptr), IdResolver(pp), StdInitializerList(nullptr),
9494
CXXTypeInfoDecl(nullptr), MSVCGuidDecl(nullptr),
@@ -124,7 +124,8 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
124124
// Tell diagnostics how to render things from the AST library.
125125
Diags.SetArgToStringFn(&FormatASTNodeDiagnosticArgument, &Context);
126126

127-
ExprEvalContexts.emplace_back(PotentiallyEvaluated, 0, false, nullptr, false);
127+
ExprEvalContexts.emplace_back(PotentiallyEvaluated, 0, CleanupInfo{}, nullptr,
128+
false);
128129

129130
FunctionScopes.push_back(new FunctionScopeInfo(Diags));
130131

Diff for: lib/Sema/SemaCast.cpp

+4-4
Original file line numberDiff line numberDiff line change
@@ -641,8 +641,8 @@ void CastOperation::CheckDynamicCast() {
641641
// If we're dynamic_casting from a prvalue to an rvalue reference, we need
642642
// to materialize the prvalue before we bind the reference to it.
643643
if (SrcExpr.get()->isRValue())
644-
SrcExpr = new (Self.Context) MaterializeTemporaryExpr(
645-
SrcType, SrcExpr.get(), /*IsLValueReference*/false);
644+
SrcExpr = Self.CreateMaterializeTemporaryExpr(
645+
SrcType, SrcExpr.get(), /*IsLValueReference*/ false);
646646
SrcPointee = SrcType;
647647
}
648648

@@ -1649,8 +1649,8 @@ static TryCastResult TryConstCast(Sema &Self, ExprResult &SrcExpr,
16491649
if (NeedToMaterializeTemporary)
16501650
// This is a const_cast from a class prvalue to an rvalue reference type.
16511651
// Materialize a temporary to store the result of the conversion.
1652-
SrcExpr = new (Self.Context) MaterializeTemporaryExpr(
1653-
SrcType, SrcExpr.get(), /*IsLValueReference*/ false);
1652+
SrcExpr = Self.CreateMaterializeTemporaryExpr(SrcType, SrcExpr.get(),
1653+
/*IsLValueReference*/ false);
16541654

16551655
return TC_Success;
16561656
}

Diff for: lib/Sema/SemaCoroutine.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ ExprResult Sema::BuildCoawaitExpr(SourceLocation Loc, Expr *E) {
244244
// If the expression is a temporary, materialize it as an lvalue so that we
245245
// can use it multiple times.
246246
if (E->getValueKind() == VK_RValue)
247-
E = new (Context) MaterializeTemporaryExpr(E->getType(), E, true);
247+
E = CreateMaterializeTemporaryExpr(E->getType(), E, true);
248248

249249
// Build the await_ready, await_suspend, await_resume calls.
250250
ReadySuspendResumeResult RSS = buildCoawaitCalls(*this, Loc, E);
@@ -311,7 +311,7 @@ ExprResult Sema::BuildCoyieldExpr(SourceLocation Loc, Expr *E) {
311311
// If the expression is a temporary, materialize it as an lvalue so that we
312312
// can use it multiple times.
313313
if (E->getValueKind() == VK_RValue)
314-
E = new (Context) MaterializeTemporaryExpr(E->getType(), E, true);
314+
E = CreateMaterializeTemporaryExpr(E->getType(), E, true);
315315

316316
// Build the await_ready, await_suspend, await_resume calls.
317317
ReadySuspendResumeResult RSS = buildCoawaitCalls(*this, Loc, E);

Diff for: lib/Sema/SemaDecl.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -11648,7 +11648,7 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
1164811648
assert(ExprCleanupObjects.size() ==
1164911649
ExprEvalContexts.back().NumCleanupObjects &&
1165011650
"Leftover temporaries in function");
11651-
assert(!ExprNeedsCleanups && "Unaccounted cleanups in function");
11651+
assert(!Cleanup.exprNeedsCleanups() && "Unaccounted cleanups in function");
1165211652
assert(MaybeODRUseExprs.empty() &&
1165311653
"Leftover expressions for odr-use checking");
1165411654
}

0 commit comments

Comments
 (0)