diff options
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; |