Index: include/clang/AST/Expr.h =================================================================== --- include/clang/AST/Expr.h +++ include/clang/AST/Expr.h @@ -868,6 +868,64 @@ } }; +//===----------------------------------------------------------------------===// +// Wrapper Expressions. +//===----------------------------------------------------------------------===// + +/// FullExpr - Represents a "full-expression" node. +class FullExpr : public Expr { +protected: + FullExpr(StmtClass SC, Expr *val) + : Expr(SC, val->getType(), + val->getValueKind(), val->getObjectKind(), + val->isTypeDependent(), val->isValueDependent(), + val->isInstantiationDependent(), + val->containsUnexpandedParameterPack()) {} + FullExpr(StmtClass SC, EmptyShell Empty) + : Expr(SC, Empty) {} +public: + const Expr *getSubExpr() const; + Expr *getSubExpr(); + + static bool classof(const Stmt *T) { + return T->getStmtClass() >= firstFullExprConstant && + T->getStmtClass() <= lastFullExprConstant; + } +}; + +/// ConstantExpr - An expression that occurs in a constant context. +class ConstantExpr : public FullExpr { + Stmt *Val; +public: + ConstantExpr(Expr *val) + : FullExpr(ConstantExprClass, val), Val(val) {} + + /// Build an empty constant expression wrapper. + explicit ConstantExpr(EmptyShell Empty) + : FullExpr(ConstantExprClass, Empty) {} + + const Expr *getSubExpr() const { return cast(Val); } + Expr *getSubExpr() { return cast(Val); } + void setSubExpr(Expr *E) { Val = E; } + + SourceLocation getBeginLoc() const LLVM_READONLY { + return Val->getBeginLoc(); + } + SourceLocation getEndLoc() const LLVM_READONLY { + return Val->getEndLoc(); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ConstantExprClass; + } + + // Iterators + child_range children() { return child_range(&Val, &Val+1); } + const_child_range children() const { + return const_child_range(&Val, &Val + 1); + } +}; + //===----------------------------------------------------------------------===// // Primary Expressions. //===----------------------------------------------------------------------===// Index: include/clang/AST/ExprCXX.h =================================================================== --- include/clang/AST/ExprCXX.h +++ include/clang/AST/ExprCXX.h @@ -3031,7 +3031,7 @@ /// 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 { public: /// The type of objects that are kept in the cleanup. Index: include/clang/AST/RecursiveASTVisitor.h =================================================================== --- include/clang/AST/RecursiveASTVisitor.h +++ include/clang/AST/RecursiveASTVisitor.h @@ -2199,6 +2199,8 @@ 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())); Index: include/clang/AST/StmtDataCollectors.td =================================================================== --- include/clang/AST/StmtDataCollectors.td +++ include/clang/AST/StmtDataCollectors.td @@ -14,6 +14,13 @@ }]; } +//--- Wrappers -----------------------------------------------------------// +class ConstantExpr { + code Code = [{ + addData(S->getType()); + }]; +} + //--- Builtin functionality ----------------------------------------------// class ArrayTypeTraitExpr { code Code = [{ Index: include/clang/Basic/StmtNodes.td =================================================================== --- include/clang/Basic/StmtNodes.td +++ include/clang/Basic/StmtNodes.td @@ -93,6 +93,10 @@ def GenericSelectionExpr : DStmt; def PseudoObjectExpr : DStmt; +// Wrapper expressions +def FullExpr : DStmt; +def ConstantExpr : DStmt; + // Atomic expressions def AtomicExpr : DStmt; @@ -131,7 +135,7 @@ def CXXConstructExpr : DStmt; def CXXInheritedCtorInitExpr : DStmt; def CXXBindTemporaryExpr : DStmt; -def ExprWithCleanups : DStmt; +def ExprWithCleanups : DStmt; def CXXTemporaryObjectExpr : DStmt; def CXXUnresolvedConstructExpr : DStmt; def CXXDependentScopeMemberExpr : DStmt; Index: include/clang/Serialization/ASTBitCodes.h =================================================================== --- include/clang/Serialization/ASTBitCodes.h +++ include/clang/Serialization/ASTBitCodes.h @@ -1618,6 +1618,9 @@ /// A MS-style AsmStmt record. STMT_MSASM, + /// A constant expression context. + EXPR_CONSTANT, + /// A PredefinedExpr record. EXPR_PREDEFINED, Index: lib/ARCMigrate/TransAutoreleasePool.cpp =================================================================== --- lib/ARCMigrate/TransAutoreleasePool.cpp +++ lib/ARCMigrate/TransAutoreleasePool.cpp @@ -403,8 +403,8 @@ return cast(getEssential((Stmt*)E)); } static Stmt *getEssential(Stmt *S) { - if (ExprWithCleanups *EWC = dyn_cast(S)) - S = EWC->getSubExpr(); + if (FullExpr *FE = dyn_cast(S)) + S = FE->getSubExpr(); if (Expr *E = dyn_cast(S)) S = E->IgnoreParenCasts(); return S; Index: lib/ARCMigrate/TransRetainReleaseDealloc.cpp =================================================================== --- lib/ARCMigrate/TransRetainReleaseDealloc.cpp +++ lib/ARCMigrate/TransRetainReleaseDealloc.cpp @@ -253,7 +253,7 @@ } while (OuterS && (isa(OuterS) || isa(OuterS) || - isa(OuterS))); + isa(OuterS))); if (!OuterS) return std::make_pair(prevStmt, nextStmt); @@ -376,8 +376,8 @@ RecContainer = StmtE; Rec = Init->IgnoreParenImpCasts(); - if (ExprWithCleanups *EWC = dyn_cast(Rec)) - Rec = EWC->getSubExpr()->IgnoreParenImpCasts(); + if (FullExpr *FE = dyn_cast(Rec)) + Rec = FE->getSubExpr()->IgnoreParenImpCasts(); RecRange = Rec->getSourceRange(); if (SM.isMacroArgExpansion(RecRange.getBegin())) RecRange.setBegin(SM.getImmediateSpellingLoc(RecRange.getBegin())); Index: lib/ARCMigrate/TransUnbridgedCasts.cpp =================================================================== --- lib/ARCMigrate/TransUnbridgedCasts.cpp +++ lib/ARCMigrate/TransUnbridgedCasts.cpp @@ -372,7 +372,7 @@ Stmt *parent = E; do { parent = StmtMap->getParentIgnoreParenImpCasts(parent); - } while (parent && isa(parent)); + } while (parent && isa(parent)); if (ReturnStmt *retS = dyn_cast_or_null(parent)) { std::string note = "remove the cast and change return type of function " Index: lib/ARCMigrate/Transforms.cpp =================================================================== --- lib/ARCMigrate/Transforms.cpp +++ lib/ARCMigrate/Transforms.cpp @@ -74,8 +74,8 @@ bool trans::isPlusOne(const Expr *E) { if (!E) return false; - if (const ExprWithCleanups *EWC = dyn_cast(E)) - E = EWC->getSubExpr(); + if (const FullExpr *FE = dyn_cast(E)) + E = FE->getSubExpr(); if (const ObjCMessageExpr * ME = dyn_cast(E->IgnoreParenCasts())) Index: lib/AST/Decl.cpp =================================================================== --- lib/AST/Decl.cpp +++ lib/AST/Decl.cpp @@ -2576,7 +2576,7 @@ "Default argument is not yet instantiated!"); Expr *Arg = getInit(); - if (auto *E = dyn_cast_or_null(Arg)) + if (auto *E = dyn_cast_or_null(Arg)) return E->getSubExpr(); return Arg; Index: lib/AST/Expr.cpp =================================================================== --- lib/AST/Expr.cpp +++ lib/AST/Expr.cpp @@ -226,6 +226,26 @@ llvm_unreachable("unknown expression kind"); } +//===----------------------------------------------------------------------===// +// Wrapper Expressions. +//===----------------------------------------------------------------------===// + +const Expr *FullExpr::getSubExpr() const { + if (const auto *EWC = dyn_cast(this)) + return EWC->getSubExpr(); + if (const auto *CE = dyn_cast(this)) + return CE->getSubExpr(); + return nullptr; +} + +Expr *FullExpr::getSubExpr() { + if (auto *EWC = dyn_cast(this)) + return EWC->getSubExpr(); + if (auto *CE = dyn_cast(this)) + return CE->getSubExpr(); + return nullptr; +} + //===----------------------------------------------------------------------===// // Primary Expressions. //===----------------------------------------------------------------------===// @@ -3121,6 +3141,11 @@ // These never have a side-effect. return false; + case ConstantExprClass: + // FIXME: Move this into the "return false;" block above. + return cast(this)->getSubExpr()->HasSideEffects( + Ctx, IncludePossibleEffects); + case CallExprClass: case CXXOperatorCallExprClass: case CXXMemberCallExprClass: Index: lib/AST/ExprCXX.cpp =================================================================== --- lib/AST/ExprCXX.cpp +++ lib/AST/ExprCXX.cpp @@ -1044,12 +1044,7 @@ ExprWithCleanups::ExprWithCleanups(Expr *subexpr, bool CleanupsHaveSideEffects, ArrayRef objects) - : Expr(ExprWithCleanupsClass, subexpr->getType(), - subexpr->getValueKind(), subexpr->getObjectKind(), - subexpr->isTypeDependent(), subexpr->isValueDependent(), - subexpr->isInstantiationDependent(), - subexpr->containsUnexpandedParameterPack()), - SubExpr(subexpr) { + : FullExpr(ExprWithCleanupsClass, subexpr), SubExpr(subexpr) { ExprWithCleanupsBits.CleanupsHaveSideEffects = CleanupsHaveSideEffects; ExprWithCleanupsBits.NumObjects = objects.size(); for (unsigned i = 0, e = objects.size(); i != e; ++i) @@ -1066,7 +1061,7 @@ } ExprWithCleanups::ExprWithCleanups(EmptyShell empty, unsigned numObjects) - : Expr(ExprWithCleanupsClass, empty) { + : FullExpr(ExprWithCleanupsClass, empty) { ExprWithCleanupsBits.NumObjects = numObjects; } Index: lib/AST/ExprClassification.cpp =================================================================== --- lib/AST/ExprClassification.cpp +++ lib/AST/ExprClassification.cpp @@ -194,6 +194,9 @@ case Expr::DesignatedInitUpdateExprClass: return Cl::CL_PRValue; + case Expr::ConstantExprClass: + return ClassifyInternal(Ctx, cast(E)->getSubExpr()); + // Next come the complicated cases. case Expr::SubstNonTypeTemplateParmExprClass: return ClassifyInternal(Ctx, Index: lib/AST/ExprConstant.cpp =================================================================== --- lib/AST/ExprConstant.cpp +++ lib/AST/ExprConstant.cpp @@ -143,8 +143,8 @@ // 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(E)) - E = EC->getSubExpr()->IgnoreParens(); + if (const auto *FE = dyn_cast(E)) + E = FE->getSubExpr()->IgnoreParens(); if (const auto *Cast = dyn_cast(E)) E = Cast->getSubExpr()->IgnoreParens(); @@ -11062,6 +11062,9 @@ return CheckICE(cast(E)->getReplacement(), Ctx); + case Expr::ConstantExprClass: + return CheckICE(cast(E)->getSubExpr(), Ctx); + case Expr::ParenExprClass: return CheckICE(cast(E)->getSubExpr(), Ctx); case Expr::GenericSelectionExprClass: Index: lib/AST/ItaniumMangle.cpp =================================================================== --- lib/AST/ItaniumMangle.cpp +++ lib/AST/ItaniumMangle.cpp @@ -3507,6 +3507,10 @@ case Expr::CXXInheritedCtorInitExprClass: llvm_unreachable("unexpected statement kind"); + case Expr::ConstantExprClass: + E = cast(E)->getSubExpr(); + goto recurse; + // FIXME: invent manglings for all these. case Expr::BlockExprClass: case Expr::ChooseExprClass: Index: lib/AST/ParentMap.cpp =================================================================== --- lib/AST/ParentMap.cpp +++ lib/AST/ParentMap.cpp @@ -163,7 +163,7 @@ // Ignore parents that don't guarantee consumption. while (P && (isa(P) || isa(P) || - isa(P))) { + isa(P))) { DirectChild = P; P = getParent(P); } Index: lib/AST/Stmt.cpp =================================================================== --- lib/AST/Stmt.cpp +++ lib/AST/Stmt.cpp @@ -118,8 +118,8 @@ while (s != lasts) { lasts = s; - if (auto *ewc = dyn_cast(s)) - s = ewc->getSubExpr(); + if (auto *fe = dyn_cast(s)) + s = fe->getSubExpr(); if (auto *mte = dyn_cast(s)) s = mte->GetTemporaryExpr(); Index: lib/AST/StmtPrinter.cpp =================================================================== --- lib/AST/StmtPrinter.cpp +++ lib/AST/StmtPrinter.cpp @@ -906,6 +906,10 @@ // Expr printing methods. //===----------------------------------------------------------------------===// +void StmtPrinter::VisitConstantExpr(ConstantExpr *Node) { + VisitExpr(Node->getSubExpr()); +} + void StmtPrinter::VisitDeclRefExpr(DeclRefExpr *Node) { if (const auto *OCED = dyn_cast(Node->getDecl())) { OCED->getInit()->IgnoreImpCasts()->printPretty(OS, nullptr, Policy); Index: lib/AST/StmtProfile.cpp =================================================================== --- lib/AST/StmtProfile.cpp +++ lib/AST/StmtProfile.cpp @@ -996,6 +996,10 @@ VisitStmt(S); } +void StmtProfiler::VisitConstantExpr(const ConstantExpr *S) { + VisitExpr(S); +} + void StmtProfiler::VisitDeclRefExpr(const DeclRefExpr *S) { VisitExpr(S); if (!Canonical) Index: lib/Analysis/LiveVariables.cpp =================================================================== --- lib/Analysis/LiveVariables.cpp +++ lib/Analysis/LiveVariables.cpp @@ -237,8 +237,8 @@ while (S) { if (const Expr *Ex = dyn_cast(S)) S = Ex->IgnoreParens(); - if (const ExprWithCleanups *EWC = dyn_cast(S)) { - S = EWC->getSubExpr(); + if (const FullExpr *FE = dyn_cast(S)) { + S = FE->getSubExpr(); continue; } if (const OpaqueValueExpr *OVE = dyn_cast(S)) { Index: lib/Analysis/ThreadSafety.cpp =================================================================== --- lib/Analysis/ThreadSafety.cpp +++ lib/Analysis/ThreadSafety.cpp @@ -1398,8 +1398,8 @@ return getTrylockCallExpr(PE->getSubExpr(), C, Negate); else if (const auto *CE = dyn_cast(Cond)) return getTrylockCallExpr(CE->getSubExpr(), C, Negate); - else if (const auto *EWC = dyn_cast(Cond)) - return getTrylockCallExpr(EWC->getSubExpr(), C, Negate); + else if (const auto *FE = dyn_cast(Cond)) + return getTrylockCallExpr(FE->getSubExpr(), C, Negate); else if (const auto *DRE = dyn_cast(Cond)) { const Expr *E = LocalVarMap.lookupExpr(DRE->getDecl(), C); return getTrylockCallExpr(E, C, Negate); Index: lib/Analysis/ThreadSafetyCommon.cpp =================================================================== --- lib/Analysis/ThreadSafetyCommon.cpp +++ lib/Analysis/ThreadSafetyCommon.cpp @@ -235,6 +235,8 @@ cast(S), Ctx); // We treat these as no-ops + case Stmt::ConstantExprClass: + return translate(cast(S)->getSubExpr(), Ctx); case Stmt::ParenExprClass: return translate(cast(S)->getSubExpr(), Ctx); case Stmt::ExprWithCleanupsClass: Index: lib/CodeGen/CGBlocks.cpp =================================================================== --- lib/CodeGen/CGBlocks.cpp +++ lib/CodeGen/CGBlocks.cpp @@ -859,10 +859,11 @@ /// 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) { +void CodeGenFunction::enterNonTrivialFullExpression(const FullExpr *E) { assert(E->getNumObjects() != 0); - for (const ExprWithCleanups::CleanupObject &C : E->getObjects()) - enterBlockScope(*this, C); + if (const auto EWC = dyn_cast(E)) + for (const ExprWithCleanups::CleanupObject &C : EWC->getObjects()) + enterBlockScope(*this, C); } /// Find the layout for the given block in a linked list and remove it. Index: lib/CodeGen/CGDecl.cpp =================================================================== --- lib/CodeGen/CGDecl.cpp +++ lib/CodeGen/CGDecl.cpp @@ -754,9 +754,9 @@ // 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(init)) { - enterFullExpression(ewc); - init = ewc->getSubExpr(); + if (const FullExpr *fe = dyn_cast(init)) { + enterFullExpression(fe); + init = fe->getSubExpr(); } CodeGenFunction::RunCleanupsScope Scope(*this); Index: lib/CodeGen/CGStmt.cpp =================================================================== --- lib/CodeGen/CGStmt.cpp +++ lib/CodeGen/CGStmt.cpp @@ -1047,10 +1047,9 @@ // 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(RV)) { - enterFullExpression(cleanups); - RV = cleanups->getSubExpr(); + if (const FullExpr *fe = dyn_cast_or_null(RV)) { + enterFullExpression(fe); + RV = fe->getSubExpr(); } // FIXME: Clean this up by using an LValue for ReturnTemp, Index: lib/CodeGen/CGStmtOpenMP.cpp =================================================================== --- lib/CodeGen/CGStmtOpenMP.cpp +++ lib/CodeGen/CGStmtOpenMP.cpp @@ -3918,13 +3918,13 @@ } const Stmt *CS = S.getInnermostCapturedStmt()->IgnoreContainers(); - if (const auto *EWC = dyn_cast(CS)) - enterFullExpression(EWC); + if (const auto *FE = dyn_cast(CS)) + enterFullExpression(FE); // Processing for statements under 'atomic capture'. if (const auto *Compound = dyn_cast(CS)) { for (const Stmt *C : Compound->body()) { - if (const auto *EWC = dyn_cast(C)) - enterFullExpression(EWC); + if (const auto *FE = dyn_cast(C)) + enterFullExpression(FE); } } Index: lib/CodeGen/CodeGenFunction.h =================================================================== --- lib/CodeGen/CodeGenFunction.h +++ lib/CodeGen/CodeGenFunction.h @@ -3947,11 +3947,13 @@ 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(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); Index: lib/Sema/SemaExceptionSpec.cpp =================================================================== --- lib/Sema/SemaExceptionSpec.cpp +++ lib/Sema/SemaExceptionSpec.cpp @@ -1051,6 +1051,9 @@ // [Can throw] if in a potentially-evaluated context the expression would // contain: switch (E->getStmtClass()) { + case Expr::ConstantExprClass: + return canThrow(cast(E)->getSubExpr()); + case Expr::CXXThrowExprClass: // - a potentially evaluated throw-expression return CT_Can; Index: lib/Sema/SemaInit.cpp =================================================================== --- lib/Sema/SemaInit.cpp +++ lib/Sema/SemaInit.cpp @@ -6510,8 +6510,8 @@ do { Old = Init; - if (auto *EWC = dyn_cast(Init)) - Init = EWC->getSubExpr(); + if (auto *FE = dyn_cast(Init)) + Init = FE->getSubExpr(); if (InitListExpr *ILE = dyn_cast(Init)) { // If this is just redundant braces around an initializer, step over it. @@ -6634,8 +6634,8 @@ Init = DIE->getExpr(); } - if (auto *EWC = dyn_cast(Init)) - Init = EWC->getSubExpr(); + if (auto *FE = dyn_cast(Init)) + Init = FE->getSubExpr(); // Dig out the expression which constructs the extended temporary. Init = const_cast(Init->skipRValueSubobjectAdjustments()); Index: lib/Sema/SemaOpenMP.cpp =================================================================== --- lib/Sema/SemaOpenMP.cpp +++ lib/Sema/SemaOpenMP.cpp @@ -630,8 +630,8 @@ } // namespace static const Expr *getExprAsWritten(const Expr *E) { - if (const auto *ExprTemp = dyn_cast(E)) - E = ExprTemp->getSubExpr(); + if (const auto *FE = dyn_cast(E)) + E = FE->getSubExpr(); if (const auto *MTE = dyn_cast(E)) E = MTE->GetTemporaryExpr(); Index: lib/Sema/SemaStmt.cpp =================================================================== --- lib/Sema/SemaStmt.cpp +++ lib/Sema/SemaStmt.cpp @@ -246,7 +246,7 @@ // 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(E)) + if (const FullExpr *Temps = dyn_cast(E)) E = Temps->getSubExpr(); if (const CXXBindTemporaryExpr *TempExpr = dyn_cast(E)) E = TempExpr->getSubExpr(); @@ -631,8 +631,8 @@ /// 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(E)) - E = CleanUps->getSubExpr(); + if (const auto *FE = dyn_cast(E)) + E = FE->getSubExpr(); while (const auto *ImpCast = dyn_cast(E)) { if (ImpCast->getCastKind() != CK_IntegralCast) break; E = ImpCast->getSubExpr(); Index: lib/Sema/TreeTransform.h =================================================================== --- lib/Sema/TreeTransform.h +++ lib/Sema/TreeTransform.h @@ -3344,8 +3344,8 @@ if (!Init) return Init; - if (ExprWithCleanups *ExprTemp = dyn_cast(Init)) - Init = ExprTemp->getSubExpr(); + if (auto *FE = dyn_cast(Init)) + Init = FE->getSubExpr(); if (auto *AIL = dyn_cast(Init)) Init = AIL->getCommonExpr(); @@ -8914,6 +8914,12 @@ //===----------------------------------------------------------------------===// // Expression transformation //===----------------------------------------------------------------------===// +template +ExprResult +TreeTransform::TransformConstantExpr(ConstantExpr *E) { + return TransformExpr(E->getSubExpr()); +} + template ExprResult TreeTransform::TransformPredefinedExpr(PredefinedExpr *E) { Index: lib/Serialization/ASTReaderStmt.cpp =================================================================== --- lib/Serialization/ASTReaderStmt.cpp +++ lib/Serialization/ASTReaderStmt.cpp @@ -504,6 +504,11 @@ "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(); @@ -2355,6 +2360,10 @@ Context, Record[ASTStmtReader::NumStmtFields]); break; + case EXPR_CONSTANT: + S = new (Context) ConstantExpr(Empty); + break; + case EXPR_PREDEFINED: S = PredefinedExpr::CreateEmpty( Context, Index: lib/Serialization/ASTWriterStmt.cpp =================================================================== --- lib/Serialization/ASTWriterStmt.cpp +++ lib/Serialization/ASTWriterStmt.cpp @@ -401,6 +401,12 @@ 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); Index: lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp =================================================================== --- lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp +++ lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp @@ -329,9 +329,8 @@ return; if (const Expr *E = V->getInit()) { - while (const ExprWithCleanups *exprClean = - dyn_cast(E)) - E = exprClean->getSubExpr(); + while (const FullExpr *FE = dyn_cast(E)) + E = FE->getSubExpr(); // Look through transitive assignments, e.g.: // int x = y = 0; Index: lib/StaticAnalyzer/Core/BugReporter.cpp =================================================================== --- lib/StaticAnalyzer/Core/BugReporter.cpp +++ lib/StaticAnalyzer/Core/BugReporter.cpp @@ -1265,7 +1265,7 @@ if (!S) break; - if (isa(S) || + if (isa(S) || isa(S) || isa(S)) continue; Index: lib/StaticAnalyzer/Core/BugReporterVisitors.cpp =================================================================== --- lib/StaticAnalyzer/Core/BugReporterVisitors.cpp +++ lib/StaticAnalyzer/Core/BugReporterVisitors.cpp @@ -136,8 +136,8 @@ E = AE->getBase(); } else if (const auto *PE = dyn_cast(E)) { E = PE->getSubExpr(); - } else if (const auto *EWC = dyn_cast(E)) { - E = EWC->getSubExpr(); + } else if (const auto *FE = dyn_cast(E)) { + E = FE->getSubExpr(); } else { // Other arbitrary stuff. break; @@ -1494,8 +1494,8 @@ static const Expr *peelOffOuterExpr(const Expr *Ex, const ExplodedNode *N) { Ex = Ex->IgnoreParenCasts(); - if (const auto *EWC = dyn_cast(Ex)) - return peelOffOuterExpr(EWC->getSubExpr(), N); + if (const auto *FE = dyn_cast(Ex)) + return peelOffOuterExpr(FE->getSubExpr(), N); if (const auto *OVE = dyn_cast(Ex)) return peelOffOuterExpr(OVE->getSourceExpr(), N); if (const auto *POE = dyn_cast(Ex)) { Index: lib/StaticAnalyzer/Core/Environment.cpp =================================================================== --- lib/StaticAnalyzer/Core/Environment.cpp +++ lib/StaticAnalyzer/Core/Environment.cpp @@ -44,6 +44,9 @@ case Stmt::ExprWithCleanupsClass: E = cast(E)->getSubExpr(); break; + case Stmt::ConstantExprClass: + E = cast(E)->getSubExpr(); + break; case Stmt::CXXBindTemporaryExprClass: E = cast(E)->getSubExpr(); break; Index: lib/StaticAnalyzer/Core/ExprEngine.cpp =================================================================== --- lib/StaticAnalyzer/Core/ExprEngine.cpp +++ lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -1267,6 +1267,9 @@ case Stmt::ObjCPropertyRefExprClass: llvm_unreachable("These are handled by PseudoObjectExpr"); + case Expr::ConstantExprClass: + return Visit(cast(S)->getSubExpr(), Pred, DstTop); + case Stmt::GNUNullExprClass: { // GNU __null is a pointer-width integer, not an actual pointer. ProgramStateRef state = Pred->getState(); Index: tools/libclang/CXCursor.cpp =================================================================== --- tools/libclang/CXCursor.cpp +++ tools/libclang/CXCursor.cpp @@ -343,6 +343,10 @@ K = CXCursor_CharacterLiteral; break; + case Stmt::ConstantExprClass: + return MakeCXCursor(cast(S)->getSubExpr(), + Parent, TU, RegionOfInterest); + case Stmt::ParenExprClass: K = CXCursor_ParenExpr; break;