summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/clang/AST/Expr.h58
-rw-r--r--include/clang/AST/ExprCXX.h11
-rw-r--r--include/clang/AST/RecursiveASTVisitor.h2
-rw-r--r--include/clang/Basic/StmtNodes.td6
-rw-r--r--include/clang/Serialization/ASTBitCodes.h3
-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
-rw-r--r--tools/libclang/CXCursor.cpp4
40 files changed, 187 insertions, 73 deletions
diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h
index a835c01623..8b94be3be7 100644
--- a/include/clang/AST/Expr.h
+++ b/include/clang/AST/Expr.h
@@ -869,6 +869,64 @@ public:
};
//===----------------------------------------------------------------------===//
+// Wrapper Expressions.
+//===----------------------------------------------------------------------===//
+
+/// FullExpr - Represents a "full-expression" node.
+class FullExpr : public Expr {
+protected:
+ Stmt *SubExpr;
+
+ FullExpr(StmtClass SC, Expr *subexpr)
+ : Expr(SC, subexpr->getType(),
+ subexpr->getValueKind(), subexpr->getObjectKind(),
+ subexpr->isTypeDependent(), subexpr->isValueDependent(),
+ subexpr->isInstantiationDependent(),
+ subexpr->containsUnexpandedParameterPack()), SubExpr(subexpr) {}
+ FullExpr(StmtClass SC, EmptyShell Empty)
+ : Expr(SC, Empty) {}
+public:
+ const Expr *getSubExpr() const { return cast<Expr>(SubExpr); }
+ Expr *getSubExpr() { return cast<Expr>(SubExpr); }
+
+ /// As with any mutator of the AST, be very careful when modifying an
+ /// existing AST to preserve its invariants.
+ void setSubExpr(Expr *E) { SubExpr = E; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() >= firstFullExprConstant &&
+ T->getStmtClass() <= lastFullExprConstant;
+ }
+};
+
+/// ConstantExpr - An expression that occurs in a constant context.
+struct ConstantExpr : public FullExpr {
+ ConstantExpr(Expr *subexpr)
+ : FullExpr(ConstantExprClass, subexpr) {}
+
+ /// Build an empty constant expression wrapper.
+ explicit ConstantExpr(EmptyShell Empty)
+ : FullExpr(ConstantExprClass, Empty) {}
+
+ SourceLocation getBeginLoc() const LLVM_READONLY {
+ return SubExpr->getBeginLoc();
+ }
+ SourceLocation getEndLoc() const LLVM_READONLY {
+ return SubExpr->getEndLoc();
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ConstantExprClass;
+ }
+
+ // Iterators
+ child_range children() { return child_range(&SubExpr, &SubExpr+1); }
+ const_child_range children() const {
+ return const_child_range(&SubExpr, &SubExpr + 1);
+ }
+};
+
+//===----------------------------------------------------------------------===//
// Primary Expressions.
//===----------------------------------------------------------------------===//
diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h
index 8fbd53798a..13ece0d6d3 100644
--- a/include/clang/AST/ExprCXX.h
+++ b/include/clang/AST/ExprCXX.h
@@ -3031,7 +3031,7 @@ public:
/// potentially-evaluated block literal. The lifetime of a block
/// literal is the extent of the enclosing scope.
class ExprWithCleanups final
- : public Expr,
+ : public FullExpr,
private llvm::TrailingObjects<ExprWithCleanups, BlockDecl *> {
public:
/// The type of objects that are kept in the cleanup.
@@ -3044,8 +3044,6 @@ private:
friend class ASTStmtReader;
friend TrailingObjects;
- Stmt *SubExpr;
-
ExprWithCleanups(EmptyShell, unsigned NumObjects);
ExprWithCleanups(Expr *SubExpr, bool CleanupsHaveSideEffects,
ArrayRef<CleanupObject> Objects);
@@ -3070,17 +3068,10 @@ public:
return getObjects()[i];
}
- 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.
- void setSubExpr(Expr *E) { SubExpr = E; }
-
SourceLocation getBeginLoc() const LLVM_READONLY {
return SubExpr->getBeginLoc();
}
diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h
index 87f324e42d..a19ea31433 100644
--- a/include/clang/AST/RecursiveASTVisitor.h
+++ b/include/clang/AST/RecursiveASTVisitor.h
@@ -2199,6 +2199,8 @@ DEF_TRAVERSE_STMT(ReturnStmt, {})
DEF_TRAVERSE_STMT(SwitchStmt, {})
DEF_TRAVERSE_STMT(WhileStmt, {})
+DEF_TRAVERSE_STMT(ConstantExpr, {})
+
DEF_TRAVERSE_STMT(CXXDependentScopeMemberExpr, {
TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
TRY_TO(TraverseDeclarationNameInfo(S->getMemberNameInfo()));
diff --git a/include/clang/Basic/StmtNodes.td b/include/clang/Basic/StmtNodes.td
index 1517d741cb..9054fb11a6 100644
--- a/include/clang/Basic/StmtNodes.td
+++ b/include/clang/Basic/StmtNodes.td
@@ -93,6 +93,10 @@ def VAArgExpr : DStmt<Expr>;
def GenericSelectionExpr : DStmt<Expr>;
def PseudoObjectExpr : DStmt<Expr>;
+// Wrapper expressions
+def FullExpr : DStmt<Expr, 1>;
+def ConstantExpr : DStmt<FullExpr>;
+
// Atomic expressions
def AtomicExpr : DStmt<Expr>;
@@ -131,7 +135,7 @@ def DependentScopeDeclRefExpr : DStmt<Expr>;
def CXXConstructExpr : DStmt<Expr>;
def CXXInheritedCtorInitExpr : DStmt<Expr>;
def CXXBindTemporaryExpr : DStmt<Expr>;
-def ExprWithCleanups : DStmt<Expr>;
+def ExprWithCleanups : DStmt<FullExpr>;
def CXXTemporaryObjectExpr : DStmt<CXXConstructExpr>;
def CXXUnresolvedConstructExpr : DStmt<Expr>;
def CXXDependentScopeMemberExpr : DStmt<Expr>;
diff --git a/include/clang/Serialization/ASTBitCodes.h b/include/clang/Serialization/ASTBitCodes.h
index 478217ccf5..a49295b962 100644
--- a/include/clang/Serialization/ASTBitCodes.h
+++ b/include/clang/Serialization/ASTBitCodes.h
@@ -1618,6 +1618,9 @@ namespace serialization {
/// A MS-style AsmStmt record.
STMT_MSASM,
+ /// A constant expression context.
+ EXPR_CONSTANT,
+
/// A PredefinedExpr record.
EXPR_PREDEFINED,
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();
diff --git a/tools/libclang/CXCursor.cpp b/tools/libclang/CXCursor.cpp
index 890bec7b82..0fee9e20ef 100644
--- a/tools/libclang/CXCursor.cpp
+++ b/tools/libclang/CXCursor.cpp
@@ -343,6 +343,10 @@ CXCursor cxcursor::MakeCXCursor(const Stmt *S, const Decl *Parent,
K = CXCursor_CharacterLiteral;
break;
+ case Stmt::ConstantExprClass:
+ return MakeCXCursor(cast<ConstantExpr>(S)->getSubExpr(),
+ Parent, TU, RegionOfInterest);
+
case Stmt::ParenExprClass:
K = CXCursor_ParenExpr;
break;