summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorBill Wendling <isanbard@gmail.com>2018-10-31 03:48:47 +0000
committerBill Wendling <isanbard@gmail.com>2018-10-31 03:48:47 +0000
commit0680f97fc4904c486a8b6a66928b329d3d7cd65c (patch)
tree2bd642a2abfaa066932a214bd1176e4f56afb6aa /lib
parent3b778bc3cec73f904457d70d6f956e1aafe1b550 (diff)
Create ConstantExpr class
A ConstantExpr class represents a full expression that's in a context where a constant expression is required. This class reflects the path the evaluator took to reach the expression rather than the syntactic context in which the expression occurs. In the future, the class will be expanded to cache the result of the evaluated expression so that it's not needlessly re-evaluated Reviewed By: rsmith Differential Revision: https://reviews.llvm.org/D53475 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@345692 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r--lib/ARCMigrate/TransAutoreleasePool.cpp4
-rw-r--r--lib/ARCMigrate/TransRetainReleaseDealloc.cpp6
-rw-r--r--lib/ARCMigrate/TransUnbridgedCasts.cpp2
-rw-r--r--lib/ARCMigrate/Transforms.cpp4
-rw-r--r--lib/AST/Decl.cpp2
-rw-r--r--lib/AST/Expr.cpp5
-rw-r--r--lib/AST/ExprCXX.cpp9
-rw-r--r--lib/AST/ExprClassification.cpp3
-rw-r--r--lib/AST/ExprConstant.cpp7
-rw-r--r--lib/AST/ItaniumMangle.cpp4
-rw-r--r--lib/AST/ParentMap.cpp2
-rw-r--r--lib/AST/Stmt.cpp4
-rw-r--r--lib/AST/StmtPrinter.cpp4
-rw-r--r--lib/AST/StmtProfile.cpp4
-rw-r--r--lib/Analysis/LiveVariables.cpp4
-rw-r--r--lib/Analysis/ThreadSafety.cpp4
-rw-r--r--lib/Analysis/ThreadSafetyCommon.cpp2
-rw-r--r--lib/CodeGen/CGBlocks.cpp10
-rw-r--r--lib/CodeGen/CGDecl.cpp6
-rw-r--r--lib/CodeGen/CGStmt.cpp7
-rw-r--r--lib/CodeGen/CGStmtOpenMP.cpp8
-rw-r--r--lib/CodeGen/CodeGenFunction.h8
-rw-r--r--lib/Sema/SemaExceptionSpec.cpp3
-rw-r--r--lib/Sema/SemaInit.cpp8
-rw-r--r--lib/Sema/SemaOpenMP.cpp4
-rw-r--r--lib/Sema/SemaStmt.cpp6
-rw-r--r--lib/Sema/TreeTransform.h10
-rw-r--r--lib/Serialization/ASTReaderStmt.cpp9
-rw-r--r--lib/Serialization/ASTWriterStmt.cpp6
-rw-r--r--lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp5
-rw-r--r--lib/StaticAnalyzer/Core/BugReporter.cpp2
-rw-r--r--lib/StaticAnalyzer/Core/BugReporterVisitors.cpp8
-rw-r--r--lib/StaticAnalyzer/Core/Environment.cpp3
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngine.cpp3
34 files changed, 114 insertions, 62 deletions
diff --git a/lib/ARCMigrate/TransAutoreleasePool.cpp b/lib/ARCMigrate/TransAutoreleasePool.cpp
index 1acf63cc2b..9d20774a89 100644
--- a/lib/ARCMigrate/TransAutoreleasePool.cpp
+++ b/lib/ARCMigrate/TransAutoreleasePool.cpp
@@ -403,8 +403,8 @@ private:
return cast<Expr>(getEssential((Stmt*)E));
}
static Stmt *getEssential(Stmt *S) {
- if (ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(S))
- S = EWC->getSubExpr();
+ if (FullExpr *FE = dyn_cast<FullExpr>(S))
+ S = FE->getSubExpr();
if (Expr *E = dyn_cast<Expr>(S))
S = E->IgnoreParenCasts();
return S;
diff --git a/lib/ARCMigrate/TransRetainReleaseDealloc.cpp b/lib/ARCMigrate/TransRetainReleaseDealloc.cpp
index f2aceaa795..f0987786d4 100644
--- a/lib/ARCMigrate/TransRetainReleaseDealloc.cpp
+++ b/lib/ARCMigrate/TransRetainReleaseDealloc.cpp
@@ -253,7 +253,7 @@ private:
}
while (OuterS && (isa<ParenExpr>(OuterS) ||
isa<CastExpr>(OuterS) ||
- isa<ExprWithCleanups>(OuterS)));
+ isa<FullExpr>(OuterS)));
if (!OuterS)
return std::make_pair(prevStmt, nextStmt);
@@ -376,8 +376,8 @@ private:
RecContainer = StmtE;
Rec = Init->IgnoreParenImpCasts();
- if (ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(Rec))
- Rec = EWC->getSubExpr()->IgnoreParenImpCasts();
+ if (FullExpr *FE = dyn_cast<FullExpr>(Rec))
+ Rec = FE->getSubExpr()->IgnoreParenImpCasts();
RecRange = Rec->getSourceRange();
if (SM.isMacroArgExpansion(RecRange.getBegin()))
RecRange.setBegin(SM.getImmediateSpellingLoc(RecRange.getBegin()));
diff --git a/lib/ARCMigrate/TransUnbridgedCasts.cpp b/lib/ARCMigrate/TransUnbridgedCasts.cpp
index 631eceb03f..9d46d8c5fc 100644
--- a/lib/ARCMigrate/TransUnbridgedCasts.cpp
+++ b/lib/ARCMigrate/TransUnbridgedCasts.cpp
@@ -372,7 +372,7 @@ private:
Stmt *parent = E;
do {
parent = StmtMap->getParentIgnoreParenImpCasts(parent);
- } while (parent && isa<ExprWithCleanups>(parent));
+ } while (parent && isa<FullExpr>(parent));
if (ReturnStmt *retS = dyn_cast_or_null<ReturnStmt>(parent)) {
std::string note = "remove the cast and change return type of function "
diff --git a/lib/ARCMigrate/Transforms.cpp b/lib/ARCMigrate/Transforms.cpp
index a403744de7..8bd2b407ae 100644
--- a/lib/ARCMigrate/Transforms.cpp
+++ b/lib/ARCMigrate/Transforms.cpp
@@ -74,8 +74,8 @@ bool trans::isPlusOneAssign(const BinaryOperator *E) {
bool trans::isPlusOne(const Expr *E) {
if (!E)
return false;
- if (const ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(E))
- E = EWC->getSubExpr();
+ if (const FullExpr *FE = dyn_cast<FullExpr>(E))
+ E = FE->getSubExpr();
if (const ObjCMessageExpr *
ME = dyn_cast<ObjCMessageExpr>(E->IgnoreParenCasts()))
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 5f82d13a0d..5477dc4404 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -2576,7 +2576,7 @@ Expr *ParmVarDecl::getDefaultArg() {
"Default argument is not yet instantiated!");
Expr *Arg = getInit();
- if (auto *E = dyn_cast_or_null<ExprWithCleanups>(Arg))
+ if (auto *E = dyn_cast_or_null<FullExpr>(Arg))
return E->getSubExpr();
return Arg;
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index c9422233d9..4f7f807a84 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -3126,6 +3126,11 @@ bool Expr::HasSideEffects(const ASTContext &Ctx,
// These never have a side-effect.
return false;
+ case ConstantExprClass:
+ // FIXME: Move this into the "return false;" block above.
+ return cast<ConstantExpr>(this)->getSubExpr()->HasSideEffects(
+ Ctx, IncludePossibleEffects);
+
case CallExprClass:
case CXXOperatorCallExprClass:
case CXXMemberCallExprClass:
diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp
index f14f5a361b..00a460758e 100644
--- a/lib/AST/ExprCXX.cpp
+++ b/lib/AST/ExprCXX.cpp
@@ -1044,12 +1044,7 @@ bool LambdaExpr::isMutable() const {
ExprWithCleanups::ExprWithCleanups(Expr *subexpr,
bool CleanupsHaveSideEffects,
ArrayRef<CleanupObject> objects)
- : Expr(ExprWithCleanupsClass, subexpr->getType(),
- subexpr->getValueKind(), subexpr->getObjectKind(),
- subexpr->isTypeDependent(), subexpr->isValueDependent(),
- subexpr->isInstantiationDependent(),
- subexpr->containsUnexpandedParameterPack()),
- SubExpr(subexpr) {
+ : FullExpr(ExprWithCleanupsClass, subexpr) {
ExprWithCleanupsBits.CleanupsHaveSideEffects = CleanupsHaveSideEffects;
ExprWithCleanupsBits.NumObjects = objects.size();
for (unsigned i = 0, e = objects.size(); i != e; ++i)
@@ -1066,7 +1061,7 @@ ExprWithCleanups *ExprWithCleanups::Create(const ASTContext &C, Expr *subexpr,
}
ExprWithCleanups::ExprWithCleanups(EmptyShell empty, unsigned numObjects)
- : Expr(ExprWithCleanupsClass, empty) {
+ : FullExpr(ExprWithCleanupsClass, empty) {
ExprWithCleanupsBits.NumObjects = numObjects;
}
diff --git a/lib/AST/ExprClassification.cpp b/lib/AST/ExprClassification.cpp
index e50dd9c79d..e1d6a1c9ed 100644
--- a/lib/AST/ExprClassification.cpp
+++ b/lib/AST/ExprClassification.cpp
@@ -194,6 +194,9 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
case Expr::DesignatedInitUpdateExprClass:
return Cl::CL_PRValue;
+ case Expr::ConstantExprClass:
+ return ClassifyInternal(Ctx, cast<ConstantExpr>(E)->getSubExpr());
+
// Next come the complicated cases.
case Expr::SubstNonTypeTemplateParmExprClass:
return ClassifyInternal(Ctx,
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp
index d5bbbd2b57..bf08d6bb65 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/lib/AST/ExprConstant.cpp
@@ -143,8 +143,8 @@ namespace {
// If we're doing a variable assignment from e.g. malloc(N), there will
// probably be a cast of some kind. In exotic cases, we might also see a
// top-level ExprWithCleanups. Ignore them either way.
- if (const auto *EC = dyn_cast<ExprWithCleanups>(E))
- E = EC->getSubExpr()->IgnoreParens();
+ if (const auto *FE = dyn_cast<FullExpr>(E))
+ E = FE->getSubExpr()->IgnoreParens();
if (const auto *Cast = dyn_cast<CastExpr>(E))
E = Cast->getSubExpr()->IgnoreParens();
@@ -11062,6 +11062,9 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) {
return
CheckICE(cast<SubstNonTypeTemplateParmExpr>(E)->getReplacement(), Ctx);
+ case Expr::ConstantExprClass:
+ return CheckICE(cast<ConstantExpr>(E)->getSubExpr(), Ctx);
+
case Expr::ParenExprClass:
return CheckICE(cast<ParenExpr>(E)->getSubExpr(), Ctx);
case Expr::GenericSelectionExprClass:
diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp
index d276ccce3c..99a9e87afb 100644
--- a/lib/AST/ItaniumMangle.cpp
+++ b/lib/AST/ItaniumMangle.cpp
@@ -3507,6 +3507,10 @@ recurse:
case Expr::CXXInheritedCtorInitExprClass:
llvm_unreachable("unexpected statement kind");
+ case Expr::ConstantExprClass:
+ E = cast<ConstantExpr>(E)->getSubExpr();
+ goto recurse;
+
// FIXME: invent manglings for all these.
case Expr::BlockExprClass:
case Expr::ChooseExprClass:
diff --git a/lib/AST/ParentMap.cpp b/lib/AST/ParentMap.cpp
index af2a480dc2..88c178aa37 100644
--- a/lib/AST/ParentMap.cpp
+++ b/lib/AST/ParentMap.cpp
@@ -163,7 +163,7 @@ bool ParentMap::isConsumedExpr(Expr* E) const {
// Ignore parents that don't guarantee consumption.
while (P && (isa<ParenExpr>(P) || isa<CastExpr>(P) ||
- isa<ExprWithCleanups>(P))) {
+ isa<FullExpr>(P))) {
DirectChild = P;
P = getParent(P);
}
diff --git a/lib/AST/Stmt.cpp b/lib/AST/Stmt.cpp
index bb8e424c6e..901df9ca75 100644
--- a/lib/AST/Stmt.cpp
+++ b/lib/AST/Stmt.cpp
@@ -118,8 +118,8 @@ Stmt *Stmt::IgnoreImplicit() {
while (s != lasts) {
lasts = s;
- if (auto *ewc = dyn_cast<ExprWithCleanups>(s))
- s = ewc->getSubExpr();
+ if (auto *fe = dyn_cast<FullExpr>(s))
+ s = fe->getSubExpr();
if (auto *mte = dyn_cast<MaterializeTemporaryExpr>(s))
s = mte->GetTemporaryExpr();
diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp
index fa33e667c6..ae726e3871 100644
--- a/lib/AST/StmtPrinter.cpp
+++ b/lib/AST/StmtPrinter.cpp
@@ -906,6 +906,10 @@ void StmtPrinter::VisitOMPTargetTeamsDistributeSimdDirective(
// Expr printing methods.
//===----------------------------------------------------------------------===//
+void StmtPrinter::VisitConstantExpr(ConstantExpr *Node) {
+ PrintExpr(Node->getSubExpr());
+}
+
void StmtPrinter::VisitDeclRefExpr(DeclRefExpr *Node) {
if (const auto *OCED = dyn_cast<OMPCapturedExprDecl>(Node->getDecl())) {
OCED->getInit()->IgnoreImpCasts()->printPretty(OS, nullptr, Policy);
diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp
index ad29a0594d..987ee43f2c 100644
--- a/lib/AST/StmtProfile.cpp
+++ b/lib/AST/StmtProfile.cpp
@@ -996,6 +996,10 @@ void StmtProfiler::VisitExpr(const Expr *S) {
VisitStmt(S);
}
+void StmtProfiler::VisitConstantExpr(const ConstantExpr *S) {
+ VisitExpr(S);
+}
+
void StmtProfiler::VisitDeclRefExpr(const DeclRefExpr *S) {
VisitExpr(S);
if (!Canonical)
diff --git a/lib/Analysis/LiveVariables.cpp b/lib/Analysis/LiveVariables.cpp
index f7bfcadf59..4f22ccc55a 100644
--- a/lib/Analysis/LiveVariables.cpp
+++ b/lib/Analysis/LiveVariables.cpp
@@ -237,8 +237,8 @@ static const Stmt *LookThroughStmt(const Stmt *S) {
while (S) {
if (const Expr *Ex = dyn_cast<Expr>(S))
S = Ex->IgnoreParens();
- if (const ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(S)) {
- S = EWC->getSubExpr();
+ if (const FullExpr *FE = dyn_cast<FullExpr>(S)) {
+ S = FE->getSubExpr();
continue;
}
if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(S)) {
diff --git a/lib/Analysis/ThreadSafety.cpp b/lib/Analysis/ThreadSafety.cpp
index dad2417d8e..f83b0e0cab 100644
--- a/lib/Analysis/ThreadSafety.cpp
+++ b/lib/Analysis/ThreadSafety.cpp
@@ -1398,8 +1398,8 @@ const CallExpr* ThreadSafetyAnalyzer::getTrylockCallExpr(const Stmt *Cond,
return getTrylockCallExpr(PE->getSubExpr(), C, Negate);
else if (const auto *CE = dyn_cast<ImplicitCastExpr>(Cond))
return getTrylockCallExpr(CE->getSubExpr(), C, Negate);
- else if (const auto *EWC = dyn_cast<ExprWithCleanups>(Cond))
- return getTrylockCallExpr(EWC->getSubExpr(), C, Negate);
+ else if (const auto *FE = dyn_cast<FullExpr>(Cond))
+ return getTrylockCallExpr(FE->getSubExpr(), C, Negate);
else if (const auto *DRE = dyn_cast<DeclRefExpr>(Cond)) {
const Expr *E = LocalVarMap.lookupExpr(DRE->getDecl(), C);
return getTrylockCallExpr(E, C, Negate);
diff --git a/lib/Analysis/ThreadSafetyCommon.cpp b/lib/Analysis/ThreadSafetyCommon.cpp
index 115c012a05..0c09974cf4 100644
--- a/lib/Analysis/ThreadSafetyCommon.cpp
+++ b/lib/Analysis/ThreadSafetyCommon.cpp
@@ -235,6 +235,8 @@ til::SExpr *SExprBuilder::translate(const Stmt *S, CallingContext *Ctx) {
cast<BinaryConditionalOperator>(S), Ctx);
// We treat these as no-ops
+ case Stmt::ConstantExprClass:
+ return translate(cast<ConstantExpr>(S)->getSubExpr(), Ctx);
case Stmt::ParenExprClass:
return translate(cast<ParenExpr>(S)->getSubExpr(), Ctx);
case Stmt::ExprWithCleanupsClass:
diff --git a/lib/CodeGen/CGBlocks.cpp b/lib/CodeGen/CGBlocks.cpp
index ad0b7abdd2..bbd103ad43 100644
--- a/lib/CodeGen/CGBlocks.cpp
+++ b/lib/CodeGen/CGBlocks.cpp
@@ -859,10 +859,12 @@ static void enterBlockScope(CodeGenFunction &CGF, BlockDecl *block) {
/// Enter a full-expression with a non-trivial number of objects to
/// clean up. This is in this file because, at the moment, the only
/// kind of cleanup object is a BlockDecl*.
-void CodeGenFunction::enterNonTrivialFullExpression(const ExprWithCleanups *E) {
- assert(E->getNumObjects() != 0);
- for (const ExprWithCleanups::CleanupObject &C : E->getObjects())
- enterBlockScope(*this, C);
+void CodeGenFunction::enterNonTrivialFullExpression(const FullExpr *E) {
+ if (const auto EWC = dyn_cast<ExprWithCleanups>(E)) {
+ assert(EWC->getNumObjects() != 0);
+ for (const ExprWithCleanups::CleanupObject &C : EWC->getObjects())
+ enterBlockScope(*this, C);
+ }
}
/// Find the layout for the given block in a linked list and remove it.
diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp
index e4f5d430f2..b52ea9da30 100644
--- a/lib/CodeGen/CGDecl.cpp
+++ b/lib/CodeGen/CGDecl.cpp
@@ -754,9 +754,9 @@ void CodeGenFunction::EmitScalarInit(const Expr *init, const ValueDecl *D,
// If we're emitting a value with lifetime, we have to do the
// initialization *before* we leave the cleanup scopes.
- if (const ExprWithCleanups *ewc = dyn_cast<ExprWithCleanups>(init)) {
- enterFullExpression(ewc);
- init = ewc->getSubExpr();
+ if (const FullExpr *fe = dyn_cast<FullExpr>(init)) {
+ enterFullExpression(fe);
+ init = fe->getSubExpr();
}
CodeGenFunction::RunCleanupsScope Scope(*this);
diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp
index 39a2cc145f..10700bcf79 100644
--- a/lib/CodeGen/CGStmt.cpp
+++ b/lib/CodeGen/CGStmt.cpp
@@ -1047,10 +1047,9 @@ void CodeGenFunction::EmitReturnStmt(const ReturnStmt &S) {
// exception to our over-conservative rules about not jumping to
// statements following block literals with non-trivial cleanups.
RunCleanupsScope cleanupScope(*this);
- if (const ExprWithCleanups *cleanups =
- dyn_cast_or_null<ExprWithCleanups>(RV)) {
- enterFullExpression(cleanups);
- RV = cleanups->getSubExpr();
+ if (const FullExpr *fe = dyn_cast_or_null<FullExpr>(RV)) {
+ enterFullExpression(fe);
+ RV = fe->getSubExpr();
}
// FIXME: Clean this up by using an LValue for ReturnTemp,
diff --git a/lib/CodeGen/CGStmtOpenMP.cpp b/lib/CodeGen/CGStmtOpenMP.cpp
index 7b6d835623..b3972b6220 100644
--- a/lib/CodeGen/CGStmtOpenMP.cpp
+++ b/lib/CodeGen/CGStmtOpenMP.cpp
@@ -3986,13 +3986,13 @@ void CodeGenFunction::EmitOMPAtomicDirective(const OMPAtomicDirective &S) {
}
const Stmt *CS = S.getInnermostCapturedStmt()->IgnoreContainers();
- if (const auto *EWC = dyn_cast<ExprWithCleanups>(CS))
- enterFullExpression(EWC);
+ if (const auto *FE = dyn_cast<FullExpr>(CS))
+ enterFullExpression(FE);
// Processing for statements under 'atomic capture'.
if (const auto *Compound = dyn_cast<CompoundStmt>(CS)) {
for (const Stmt *C : Compound->body()) {
- if (const auto *EWC = dyn_cast<ExprWithCleanups>(C))
- enterFullExpression(EWC);
+ if (const auto *FE = dyn_cast<FullExpr>(C))
+ enterFullExpression(FE);
}
}
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h
index 262b8dc70b..c73cef5d35 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -3947,11 +3947,13 @@ public:
void EmitSynthesizedCXXCopyCtor(Address Dest, Address Src, const Expr *Exp);
- void enterFullExpression(const ExprWithCleanups *E) {
- if (E->getNumObjects() == 0) return;
+ void enterFullExpression(const FullExpr *E) {
+ if (const auto *EWC = dyn_cast<ExprWithCleanups>(E))
+ if (EWC->getNumObjects() == 0)
+ return;
enterNonTrivialFullExpression(E);
}
- void enterNonTrivialFullExpression(const ExprWithCleanups *E);
+ void enterNonTrivialFullExpression(const FullExpr *E);
void EmitCXXThrowExpr(const CXXThrowExpr *E, bool KeepInsertionPoint = true);
diff --git a/lib/Sema/SemaExceptionSpec.cpp b/lib/Sema/SemaExceptionSpec.cpp
index 4de205c504..e0850feaff 100644
--- a/lib/Sema/SemaExceptionSpec.cpp
+++ b/lib/Sema/SemaExceptionSpec.cpp
@@ -1051,6 +1051,9 @@ CanThrowResult Sema::canThrow(const Expr *E) {
// [Can throw] if in a potentially-evaluated context the expression would
// contain:
switch (E->getStmtClass()) {
+ case Expr::ConstantExprClass:
+ return canThrow(cast<ConstantExpr>(E)->getSubExpr());
+
case Expr::CXXThrowExprClass:
// - a potentially evaluated throw-expression
return CT_Can;
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp
index f4687fe818..0cfac99719 100644
--- a/lib/Sema/SemaInit.cpp
+++ b/lib/Sema/SemaInit.cpp
@@ -6510,8 +6510,8 @@ static void visitLocalsRetainedByReferenceBinding(IndirectLocalPath &Path,
do {
Old = Init;
- if (auto *EWC = dyn_cast<ExprWithCleanups>(Init))
- Init = EWC->getSubExpr();
+ if (auto *FE = dyn_cast<FullExpr>(Init))
+ Init = FE->getSubExpr();
if (InitListExpr *ILE = dyn_cast<InitListExpr>(Init)) {
// If this is just redundant braces around an initializer, step over it.
@@ -6634,8 +6634,8 @@ static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path,
Init = DIE->getExpr();
}
- if (auto *EWC = dyn_cast<ExprWithCleanups>(Init))
- Init = EWC->getSubExpr();
+ if (auto *FE = dyn_cast<FullExpr>(Init))
+ Init = FE->getSubExpr();
// Dig out the expression which constructs the extended temporary.
Init = const_cast<Expr *>(Init->skipRValueSubobjectAdjustments());
diff --git a/lib/Sema/SemaOpenMP.cpp b/lib/Sema/SemaOpenMP.cpp
index ac8f740d0d..4e96614441 100644
--- a/lib/Sema/SemaOpenMP.cpp
+++ b/lib/Sema/SemaOpenMP.cpp
@@ -669,8 +669,8 @@ bool isParallelOrTaskRegion(OpenMPDirectiveKind DKind) {
} // namespace
static const Expr *getExprAsWritten(const Expr *E) {
- if (const auto *ExprTemp = dyn_cast<ExprWithCleanups>(E))
- E = ExprTemp->getSubExpr();
+ if (const auto *FE = dyn_cast<FullExpr>(E))
+ E = FE->getSubExpr();
if (const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E))
E = MTE->GetTemporaryExpr();
diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp
index 26019d4aae..91357de91b 100644
--- a/lib/Sema/SemaStmt.cpp
+++ b/lib/Sema/SemaStmt.cpp
@@ -246,7 +246,7 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) {
// we might want to make a more specific diagnostic. Check for one of these
// cases now.
unsigned DiagID = diag::warn_unused_expr;
- if (const ExprWithCleanups *Temps = dyn_cast<ExprWithCleanups>(E))
+ if (const FullExpr *Temps = dyn_cast<FullExpr>(E))
E = Temps->getSubExpr();
if (const CXXBindTemporaryExpr *TempExpr = dyn_cast<CXXBindTemporaryExpr>(E))
E = TempExpr->getSubExpr();
@@ -631,8 +631,8 @@ static bool EqEnumVals(const std::pair<llvm::APSInt, EnumConstantDecl*>& lhs,
/// GetTypeBeforeIntegralPromotion - Returns the pre-promotion type of
/// potentially integral-promoted expression @p expr.
static QualType GetTypeBeforeIntegralPromotion(const Expr *&E) {
- if (const auto *CleanUps = dyn_cast<ExprWithCleanups>(E))
- E = CleanUps->getSubExpr();
+ if (const auto *FE = dyn_cast<FullExpr>(E))
+ E = FE->getSubExpr();
while (const auto *ImpCast = dyn_cast<ImplicitCastExpr>(E)) {
if (ImpCast->getCastKind() != CK_IntegralCast) break;
E = ImpCast->getSubExpr();
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index 50434645f5..6138882569 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -3344,8 +3344,8 @@ ExprResult TreeTransform<Derived>::TransformInitializer(Expr *Init,
if (!Init)
return Init;
- if (ExprWithCleanups *ExprTemp = dyn_cast<ExprWithCleanups>(Init))
- Init = ExprTemp->getSubExpr();
+ if (auto *FE = dyn_cast<FullExpr>(Init))
+ Init = FE->getSubExpr();
if (auto *AIL = dyn_cast<ArrayInitLoopExpr>(Init))
Init = AIL->getCommonExpr();
@@ -8916,6 +8916,12 @@ TreeTransform<Derived>::TransformOMPIsDevicePtrClause(OMPIsDevicePtrClause *C) {
//===----------------------------------------------------------------------===//
template<typename Derived>
ExprResult
+TreeTransform<Derived>::TransformConstantExpr(ConstantExpr *E) {
+ return TransformExpr(E->getSubExpr());
+}
+
+template<typename Derived>
+ExprResult
TreeTransform<Derived>::TransformPredefinedExpr(PredefinedExpr *E) {
if (!E->isTypeDependent())
return E;
diff --git a/lib/Serialization/ASTReaderStmt.cpp b/lib/Serialization/ASTReaderStmt.cpp
index 6f7dff3893..ef370260c5 100644
--- a/lib/Serialization/ASTReaderStmt.cpp
+++ b/lib/Serialization/ASTReaderStmt.cpp
@@ -524,6 +524,11 @@ void ASTStmtReader::VisitExpr(Expr *E) {
"Incorrect expression field count");
}
+void ASTStmtReader::VisitConstantExpr(ConstantExpr *E) {
+ VisitExpr(E);
+ E->setSubExpr(Record.readSubExpr());
+}
+
void ASTStmtReader::VisitPredefinedExpr(PredefinedExpr *E) {
VisitExpr(E);
bool HasFunctionName = Record.readInt();
@@ -2385,6 +2390,10 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
Context, Record[ASTStmtReader::NumStmtFields]);
break;
+ case EXPR_CONSTANT:
+ S = new (Context) ConstantExpr(Empty);
+ break;
+
case EXPR_PREDEFINED:
S = PredefinedExpr::CreateEmpty(
Context,
diff --git a/lib/Serialization/ASTWriterStmt.cpp b/lib/Serialization/ASTWriterStmt.cpp
index 2b0c95229d..4f579dc346 100644
--- a/lib/Serialization/ASTWriterStmt.cpp
+++ b/lib/Serialization/ASTWriterStmt.cpp
@@ -426,6 +426,12 @@ void ASTStmtWriter::VisitExpr(Expr *E) {
Record.push_back(E->getObjectKind());
}
+void ASTStmtWriter::VisitConstantExpr(ConstantExpr *E) {
+ VisitExpr(E);
+ Record.AddStmt(E->getSubExpr());
+ Code = serialization::EXPR_CONSTANT;
+}
+
void ASTStmtWriter::VisitPredefinedExpr(PredefinedExpr *E) {
VisitExpr(E);
diff --git a/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp b/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp
index 76a9a7c567..7446eadf34 100644
--- a/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp
@@ -329,9 +329,8 @@ public:
return;
if (const Expr *E = V->getInit()) {
- while (const ExprWithCleanups *exprClean =
- dyn_cast<ExprWithCleanups>(E))
- E = exprClean->getSubExpr();
+ while (const FullExpr *FE = dyn_cast<FullExpr>(E))
+ E = FE->getSubExpr();
// Look through transitive assignments, e.g.:
// int x = y = 0;
diff --git a/lib/StaticAnalyzer/Core/BugReporter.cpp b/lib/StaticAnalyzer/Core/BugReporter.cpp
index 8899fa67a3..8ace876815 100644
--- a/lib/StaticAnalyzer/Core/BugReporter.cpp
+++ b/lib/StaticAnalyzer/Core/BugReporter.cpp
@@ -1265,7 +1265,7 @@ static const Stmt *getStmtParent(const Stmt *S, const ParentMap &PM) {
if (!S)
break;
- if (isa<ExprWithCleanups>(S) ||
+ if (isa<FullExpr>(S) ||
isa<CXXBindTemporaryExpr>(S) ||
isa<SubstNonTypeTemplateParmExpr>(S))
continue;
diff --git a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
index 344c88099c..99069d8be0 100644
--- a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
+++ b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
@@ -136,8 +136,8 @@ const Expr *bugreporter::getDerefExpr(const Stmt *S) {
E = AE->getBase();
} else if (const auto *PE = dyn_cast<ParenExpr>(E)) {
E = PE->getSubExpr();
- } else if (const auto *EWC = dyn_cast<ExprWithCleanups>(E)) {
- E = EWC->getSubExpr();
+ } else if (const auto *FE = dyn_cast<FullExpr>(E)) {
+ E = FE->getSubExpr();
} else {
// Other arbitrary stuff.
break;
@@ -1494,8 +1494,8 @@ static const MemRegion *getLocationRegionIfReference(const Expr *E,
static const Expr *peelOffOuterExpr(const Expr *Ex,
const ExplodedNode *N) {
Ex = Ex->IgnoreParenCasts();
- if (const auto *EWC = dyn_cast<ExprWithCleanups>(Ex))
- return peelOffOuterExpr(EWC->getSubExpr(), N);
+ if (const auto *FE = dyn_cast<FullExpr>(Ex))
+ return peelOffOuterExpr(FE->getSubExpr(), N);
if (const auto *OVE = dyn_cast<OpaqueValueExpr>(Ex))
return peelOffOuterExpr(OVE->getSourceExpr(), N);
if (const auto *POE = dyn_cast<PseudoObjectExpr>(Ex)) {
diff --git a/lib/StaticAnalyzer/Core/Environment.cpp b/lib/StaticAnalyzer/Core/Environment.cpp
index 96b5931036..da99dbc7ac 100644
--- a/lib/StaticAnalyzer/Core/Environment.cpp
+++ b/lib/StaticAnalyzer/Core/Environment.cpp
@@ -44,6 +44,9 @@ static const Expr *ignoreTransparentExprs(const Expr *E) {
case Stmt::ExprWithCleanupsClass:
E = cast<ExprWithCleanups>(E)->getSubExpr();
break;
+ case Stmt::ConstantExprClass:
+ E = cast<ConstantExpr>(E)->getSubExpr();
+ break;
case Stmt::CXXBindTemporaryExprClass:
E = cast<CXXBindTemporaryExpr>(E)->getSubExpr();
break;
diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp
index f30cf5a216..2b48cd0f72 100644
--- a/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -1267,6 +1267,9 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
case Stmt::ObjCPropertyRefExprClass:
llvm_unreachable("These are handled by PseudoObjectExpr");
+ case Expr::ConstantExprClass:
+ return Visit(cast<ConstantExpr>(S)->getSubExpr(), Pred, DstTop);
+
case Stmt::GNUNullExprClass: {
// GNU __null is a pointer-width integer, not an actual pointer.
ProgramStateRef state = Pred->getState();