Browse Source

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
Bill Wendling 6 years ago
parent
commit
0680f97fc4
40 changed files with 187 additions and 73 deletions
  1. 58 0
      include/clang/AST/Expr.h
  2. 1 10
      include/clang/AST/ExprCXX.h
  3. 2 0
      include/clang/AST/RecursiveASTVisitor.h
  4. 5 1
      include/clang/Basic/StmtNodes.td
  5. 3 0
      include/clang/Serialization/ASTBitCodes.h
  6. 2 2
      lib/ARCMigrate/TransAutoreleasePool.cpp
  7. 3 3
      lib/ARCMigrate/TransRetainReleaseDealloc.cpp
  8. 1 1
      lib/ARCMigrate/TransUnbridgedCasts.cpp
  9. 2 2
      lib/ARCMigrate/Transforms.cpp
  10. 1 1
      lib/AST/Decl.cpp
  11. 5 0
      lib/AST/Expr.cpp
  12. 2 7
      lib/AST/ExprCXX.cpp
  13. 3 0
      lib/AST/ExprClassification.cpp
  14. 5 2
      lib/AST/ExprConstant.cpp
  15. 4 0
      lib/AST/ItaniumMangle.cpp
  16. 1 1
      lib/AST/ParentMap.cpp
  17. 2 2
      lib/AST/Stmt.cpp
  18. 4 0
      lib/AST/StmtPrinter.cpp
  19. 4 0
      lib/AST/StmtProfile.cpp
  20. 2 2
      lib/Analysis/LiveVariables.cpp
  21. 2 2
      lib/Analysis/ThreadSafety.cpp
  22. 2 0
      lib/Analysis/ThreadSafetyCommon.cpp
  23. 6 4
      lib/CodeGen/CGBlocks.cpp
  24. 3 3
      lib/CodeGen/CGDecl.cpp
  25. 3 4
      lib/CodeGen/CGStmt.cpp
  26. 4 4
      lib/CodeGen/CGStmtOpenMP.cpp
  27. 5 3
      lib/CodeGen/CodeGenFunction.h
  28. 3 0
      lib/Sema/SemaExceptionSpec.cpp
  29. 4 4
      lib/Sema/SemaInit.cpp
  30. 2 2
      lib/Sema/SemaOpenMP.cpp
  31. 3 3
      lib/Sema/SemaStmt.cpp
  32. 8 2
      lib/Sema/TreeTransform.h
  33. 9 0
      lib/Serialization/ASTReaderStmt.cpp
  34. 6 0
      lib/Serialization/ASTWriterStmt.cpp
  35. 2 3
      lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp
  36. 1 1
      lib/StaticAnalyzer/Core/BugReporter.cpp
  37. 4 4
      lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
  38. 3 0
      lib/StaticAnalyzer/Core/Environment.cpp
  39. 3 0
      lib/StaticAnalyzer/Core/ExprEngine.cpp
  40. 4 0
      tools/libclang/CXCursor.cpp

+ 58 - 0
include/clang/AST/Expr.h

@@ -868,6 +868,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.
 // Primary Expressions.
 //===----------------------------------------------------------------------===//
 //===----------------------------------------------------------------------===//

+ 1 - 10
include/clang/AST/ExprCXX.h

@@ -3031,7 +3031,7 @@ public:
 /// potentially-evaluated block literal.  The lifetime of a block
 /// potentially-evaluated block literal.  The lifetime of a block
 /// literal is the extent of the enclosing scope.
 /// literal is the extent of the enclosing scope.
 class ExprWithCleanups final
 class ExprWithCleanups final
-    : public Expr,
+    : public FullExpr,
       private llvm::TrailingObjects<ExprWithCleanups, BlockDecl *> {
       private llvm::TrailingObjects<ExprWithCleanups, BlockDecl *> {
 public:
 public:
   /// The type of objects that are kept in the cleanup.
   /// The type of objects that are kept in the cleanup.
@@ -3044,8 +3044,6 @@ private:
   friend class ASTStmtReader;
   friend class ASTStmtReader;
   friend TrailingObjects;
   friend TrailingObjects;
 
 
-  Stmt *SubExpr;
-
   ExprWithCleanups(EmptyShell, unsigned NumObjects);
   ExprWithCleanups(EmptyShell, unsigned NumObjects);
   ExprWithCleanups(Expr *SubExpr, bool CleanupsHaveSideEffects,
   ExprWithCleanups(Expr *SubExpr, bool CleanupsHaveSideEffects,
                    ArrayRef<CleanupObject> Objects);
                    ArrayRef<CleanupObject> Objects);
@@ -3070,17 +3068,10 @@ public:
     return getObjects()[i];
     return getObjects()[i];
   }
   }
 
 
-  Expr *getSubExpr() { return cast<Expr>(SubExpr); }
-  const Expr *getSubExpr() const { return cast<Expr>(SubExpr); }
-
   bool cleanupsHaveSideEffects() const {
   bool cleanupsHaveSideEffects() const {
     return ExprWithCleanupsBits.CleanupsHaveSideEffects;
     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 {
   SourceLocation getBeginLoc() const LLVM_READONLY {
     return SubExpr->getBeginLoc();
     return SubExpr->getBeginLoc();
   }
   }

+ 2 - 0
include/clang/AST/RecursiveASTVisitor.h

@@ -2199,6 +2199,8 @@ DEF_TRAVERSE_STMT(ReturnStmt, {})
 DEF_TRAVERSE_STMT(SwitchStmt, {})
 DEF_TRAVERSE_STMT(SwitchStmt, {})
 DEF_TRAVERSE_STMT(WhileStmt, {})
 DEF_TRAVERSE_STMT(WhileStmt, {})
 
 
+DEF_TRAVERSE_STMT(ConstantExpr, {})
+
 DEF_TRAVERSE_STMT(CXXDependentScopeMemberExpr, {
 DEF_TRAVERSE_STMT(CXXDependentScopeMemberExpr, {
   TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
   TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
   TRY_TO(TraverseDeclarationNameInfo(S->getMemberNameInfo()));
   TRY_TO(TraverseDeclarationNameInfo(S->getMemberNameInfo()));

+ 5 - 1
include/clang/Basic/StmtNodes.td

@@ -93,6 +93,10 @@ def VAArgExpr : DStmt<Expr>;
 def GenericSelectionExpr : DStmt<Expr>;
 def GenericSelectionExpr : DStmt<Expr>;
 def PseudoObjectExpr : DStmt<Expr>;
 def PseudoObjectExpr : DStmt<Expr>;
 
 
+// Wrapper expressions
+def FullExpr : DStmt<Expr, 1>;
+def ConstantExpr : DStmt<FullExpr>;
+
 // Atomic expressions
 // Atomic expressions
 def AtomicExpr : DStmt<Expr>;
 def AtomicExpr : DStmt<Expr>;
 
 
@@ -131,7 +135,7 @@ def DependentScopeDeclRefExpr : DStmt<Expr>;
 def CXXConstructExpr : DStmt<Expr>;
 def CXXConstructExpr : DStmt<Expr>;
 def CXXInheritedCtorInitExpr : DStmt<Expr>;
 def CXXInheritedCtorInitExpr : DStmt<Expr>;
 def CXXBindTemporaryExpr : DStmt<Expr>;
 def CXXBindTemporaryExpr : DStmt<Expr>;
-def ExprWithCleanups : DStmt<Expr>;
+def ExprWithCleanups : DStmt<FullExpr>;
 def CXXTemporaryObjectExpr : DStmt<CXXConstructExpr>;
 def CXXTemporaryObjectExpr : DStmt<CXXConstructExpr>;
 def CXXUnresolvedConstructExpr : DStmt<Expr>;
 def CXXUnresolvedConstructExpr : DStmt<Expr>;
 def CXXDependentScopeMemberExpr : DStmt<Expr>;
 def CXXDependentScopeMemberExpr : DStmt<Expr>;

+ 3 - 0
include/clang/Serialization/ASTBitCodes.h

@@ -1618,6 +1618,9 @@ namespace serialization {
       /// A MS-style AsmStmt record.
       /// A MS-style AsmStmt record.
       STMT_MSASM,
       STMT_MSASM,
 
 
+      /// A constant expression context.
+      EXPR_CONSTANT,
+
       /// A PredefinedExpr record.
       /// A PredefinedExpr record.
       EXPR_PREDEFINED,
       EXPR_PREDEFINED,
 
 

+ 2 - 2
lib/ARCMigrate/TransAutoreleasePool.cpp

@@ -403,8 +403,8 @@ private:
     return cast<Expr>(getEssential((Stmt*)E));
     return cast<Expr>(getEssential((Stmt*)E));
   }
   }
   static Stmt *getEssential(Stmt *S) {
   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))
     if (Expr *E = dyn_cast<Expr>(S))
       S = E->IgnoreParenCasts();
       S = E->IgnoreParenCasts();
     return S;
     return S;

+ 3 - 3
lib/ARCMigrate/TransRetainReleaseDealloc.cpp

@@ -253,7 +253,7 @@ private:
     }
     }
     while (OuterS && (isa<ParenExpr>(OuterS) ||
     while (OuterS && (isa<ParenExpr>(OuterS) ||
                       isa<CastExpr>(OuterS) ||
                       isa<CastExpr>(OuterS) ||
-                      isa<ExprWithCleanups>(OuterS)));
+                      isa<FullExpr>(OuterS)));
 
 
     if (!OuterS)
     if (!OuterS)
       return std::make_pair(prevStmt, nextStmt);
       return std::make_pair(prevStmt, nextStmt);
@@ -376,8 +376,8 @@ private:
 
 
     RecContainer = StmtE;
     RecContainer = StmtE;
     Rec = Init->IgnoreParenImpCasts();
     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();
     RecRange = Rec->getSourceRange();
     if (SM.isMacroArgExpansion(RecRange.getBegin()))
     if (SM.isMacroArgExpansion(RecRange.getBegin()))
       RecRange.setBegin(SM.getImmediateSpellingLoc(RecRange.getBegin()));
       RecRange.setBegin(SM.getImmediateSpellingLoc(RecRange.getBegin()));

+ 1 - 1
lib/ARCMigrate/TransUnbridgedCasts.cpp

@@ -372,7 +372,7 @@ private:
       Stmt *parent = E;
       Stmt *parent = E;
       do {
       do {
         parent = StmtMap->getParentIgnoreParenImpCasts(parent);
         parent = StmtMap->getParentIgnoreParenImpCasts(parent);
-      } while (parent && isa<ExprWithCleanups>(parent));
+      } while (parent && isa<FullExpr>(parent));
 
 
       if (ReturnStmt *retS = dyn_cast_or_null<ReturnStmt>(parent)) {
       if (ReturnStmt *retS = dyn_cast_or_null<ReturnStmt>(parent)) {
         std::string note = "remove the cast and change return type of function "
         std::string note = "remove the cast and change return type of function "

+ 2 - 2
lib/ARCMigrate/Transforms.cpp

@@ -74,8 +74,8 @@ bool trans::isPlusOneAssign(const BinaryOperator *E) {
 bool trans::isPlusOne(const Expr *E) {
 bool trans::isPlusOne(const Expr *E) {
   if (!E)
   if (!E)
     return false;
     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 *
   if (const ObjCMessageExpr *
         ME = dyn_cast<ObjCMessageExpr>(E->IgnoreParenCasts()))
         ME = dyn_cast<ObjCMessageExpr>(E->IgnoreParenCasts()))

+ 1 - 1
lib/AST/Decl.cpp

@@ -2576,7 +2576,7 @@ Expr *ParmVarDecl::getDefaultArg() {
          "Default argument is not yet instantiated!");
          "Default argument is not yet instantiated!");
 
 
   Expr *Arg = getInit();
   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 E->getSubExpr();
 
 
   return Arg;
   return Arg;

+ 5 - 0
lib/AST/Expr.cpp

@@ -3126,6 +3126,11 @@ bool Expr::HasSideEffects(const ASTContext &Ctx,
     // These never have a side-effect.
     // These never have a side-effect.
     return false;
     return false;
 
 
+  case ConstantExprClass:
+    // FIXME: Move this into the "return false;" block above.
+    return cast<ConstantExpr>(this)->getSubExpr()->HasSideEffects(
+        Ctx, IncludePossibleEffects);
+
   case CallExprClass:
   case CallExprClass:
   case CXXOperatorCallExprClass:
   case CXXOperatorCallExprClass:
   case CXXMemberCallExprClass:
   case CXXMemberCallExprClass:

+ 2 - 7
lib/AST/ExprCXX.cpp

@@ -1044,12 +1044,7 @@ bool LambdaExpr::isMutable() const {
 ExprWithCleanups::ExprWithCleanups(Expr *subexpr,
 ExprWithCleanups::ExprWithCleanups(Expr *subexpr,
                                    bool CleanupsHaveSideEffects,
                                    bool CleanupsHaveSideEffects,
                                    ArrayRef<CleanupObject> objects)
                                    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.CleanupsHaveSideEffects = CleanupsHaveSideEffects;
   ExprWithCleanupsBits.NumObjects = objects.size();
   ExprWithCleanupsBits.NumObjects = objects.size();
   for (unsigned i = 0, e = objects.size(); i != e; ++i)
   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)
 ExprWithCleanups::ExprWithCleanups(EmptyShell empty, unsigned numObjects)
-    : Expr(ExprWithCleanupsClass, empty) {
+    : FullExpr(ExprWithCleanupsClass, empty) {
   ExprWithCleanupsBits.NumObjects = numObjects;
   ExprWithCleanupsBits.NumObjects = numObjects;
 }
 }
 
 

+ 3 - 0
lib/AST/ExprClassification.cpp

@@ -194,6 +194,9 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
   case Expr::DesignatedInitUpdateExprClass:
   case Expr::DesignatedInitUpdateExprClass:
     return Cl::CL_PRValue;
     return Cl::CL_PRValue;
 
 
+  case Expr::ConstantExprClass:
+    return ClassifyInternal(Ctx, cast<ConstantExpr>(E)->getSubExpr());
+
     // Next come the complicated cases.
     // Next come the complicated cases.
   case Expr::SubstNonTypeTemplateParmExprClass:
   case Expr::SubstNonTypeTemplateParmExprClass:
     return ClassifyInternal(Ctx,
     return ClassifyInternal(Ctx,

+ 5 - 2
lib/AST/ExprConstant.cpp

@@ -143,8 +143,8 @@ namespace {
     // If we're doing a variable assignment from e.g. malloc(N), there will
     // 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
     // probably be a cast of some kind. In exotic cases, we might also see a
     // top-level ExprWithCleanups. Ignore them either way.
     // 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))
     if (const auto *Cast = dyn_cast<CastExpr>(E))
       E = Cast->getSubExpr()->IgnoreParens();
       E = Cast->getSubExpr()->IgnoreParens();
@@ -11062,6 +11062,9 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) {
     return
     return
       CheckICE(cast<SubstNonTypeTemplateParmExpr>(E)->getReplacement(), Ctx);
       CheckICE(cast<SubstNonTypeTemplateParmExpr>(E)->getReplacement(), Ctx);
 
 
+  case Expr::ConstantExprClass:
+    return CheckICE(cast<ConstantExpr>(E)->getSubExpr(), Ctx);
+
   case Expr::ParenExprClass:
   case Expr::ParenExprClass:
     return CheckICE(cast<ParenExpr>(E)->getSubExpr(), Ctx);
     return CheckICE(cast<ParenExpr>(E)->getSubExpr(), Ctx);
   case Expr::GenericSelectionExprClass:
   case Expr::GenericSelectionExprClass:

+ 4 - 0
lib/AST/ItaniumMangle.cpp

@@ -3507,6 +3507,10 @@ recurse:
   case Expr::CXXInheritedCtorInitExprClass:
   case Expr::CXXInheritedCtorInitExprClass:
     llvm_unreachable("unexpected statement kind");
     llvm_unreachable("unexpected statement kind");
 
 
+  case Expr::ConstantExprClass:
+    E = cast<ConstantExpr>(E)->getSubExpr();
+    goto recurse;
+
   // FIXME: invent manglings for all these.
   // FIXME: invent manglings for all these.
   case Expr::BlockExprClass:
   case Expr::BlockExprClass:
   case Expr::ChooseExprClass:
   case Expr::ChooseExprClass:

+ 1 - 1
lib/AST/ParentMap.cpp

@@ -163,7 +163,7 @@ bool ParentMap::isConsumedExpr(Expr* E) const {
 
 
   // Ignore parents that don't guarantee consumption.
   // Ignore parents that don't guarantee consumption.
   while (P && (isa<ParenExpr>(P) || isa<CastExpr>(P) ||
   while (P && (isa<ParenExpr>(P) || isa<CastExpr>(P) ||
-               isa<ExprWithCleanups>(P))) {
+               isa<FullExpr>(P))) {
     DirectChild = P;
     DirectChild = P;
     P = getParent(P);
     P = getParent(P);
   }
   }

+ 2 - 2
lib/AST/Stmt.cpp

@@ -118,8 +118,8 @@ Stmt *Stmt::IgnoreImplicit() {
   while (s != lasts) {
   while (s != lasts) {
     lasts = s;
     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))
     if (auto *mte = dyn_cast<MaterializeTemporaryExpr>(s))
       s = mte->GetTemporaryExpr();
       s = mte->GetTemporaryExpr();

+ 4 - 0
lib/AST/StmtPrinter.cpp

@@ -906,6 +906,10 @@ void StmtPrinter::VisitOMPTargetTeamsDistributeSimdDirective(
 //  Expr printing methods.
 //  Expr printing methods.
 //===----------------------------------------------------------------------===//
 //===----------------------------------------------------------------------===//
 
 
+void StmtPrinter::VisitConstantExpr(ConstantExpr *Node) {
+  PrintExpr(Node->getSubExpr());
+}
+
 void StmtPrinter::VisitDeclRefExpr(DeclRefExpr *Node) {
 void StmtPrinter::VisitDeclRefExpr(DeclRefExpr *Node) {
   if (const auto *OCED = dyn_cast<OMPCapturedExprDecl>(Node->getDecl())) {
   if (const auto *OCED = dyn_cast<OMPCapturedExprDecl>(Node->getDecl())) {
     OCED->getInit()->IgnoreImpCasts()->printPretty(OS, nullptr, Policy);
     OCED->getInit()->IgnoreImpCasts()->printPretty(OS, nullptr, Policy);

+ 4 - 0
lib/AST/StmtProfile.cpp

@@ -996,6 +996,10 @@ void StmtProfiler::VisitExpr(const Expr *S) {
   VisitStmt(S);
   VisitStmt(S);
 }
 }
 
 
+void StmtProfiler::VisitConstantExpr(const ConstantExpr *S) {
+  VisitExpr(S);
+}
+
 void StmtProfiler::VisitDeclRefExpr(const DeclRefExpr *S) {
 void StmtProfiler::VisitDeclRefExpr(const DeclRefExpr *S) {
   VisitExpr(S);
   VisitExpr(S);
   if (!Canonical)
   if (!Canonical)

+ 2 - 2
lib/Analysis/LiveVariables.cpp

@@ -237,8 +237,8 @@ static const Stmt *LookThroughStmt(const Stmt *S) {
   while (S) {
   while (S) {
     if (const Expr *Ex = dyn_cast<Expr>(S))
     if (const Expr *Ex = dyn_cast<Expr>(S))
       S = Ex->IgnoreParens();
       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;
       continue;
     }
     }
     if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(S)) {
     if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(S)) {

+ 2 - 2
lib/Analysis/ThreadSafety.cpp

@@ -1398,8 +1398,8 @@ const CallExpr* ThreadSafetyAnalyzer::getTrylockCallExpr(const Stmt *Cond,
     return getTrylockCallExpr(PE->getSubExpr(), C, Negate);
     return getTrylockCallExpr(PE->getSubExpr(), C, Negate);
   else if (const auto *CE = dyn_cast<ImplicitCastExpr>(Cond))
   else if (const auto *CE = dyn_cast<ImplicitCastExpr>(Cond))
     return getTrylockCallExpr(CE->getSubExpr(), C, Negate);
     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)) {
   else if (const auto *DRE = dyn_cast<DeclRefExpr>(Cond)) {
     const Expr *E = LocalVarMap.lookupExpr(DRE->getDecl(), C);
     const Expr *E = LocalVarMap.lookupExpr(DRE->getDecl(), C);
     return getTrylockCallExpr(E, C, Negate);
     return getTrylockCallExpr(E, C, Negate);

+ 2 - 0
lib/Analysis/ThreadSafetyCommon.cpp

@@ -235,6 +235,8 @@ til::SExpr *SExprBuilder::translate(const Stmt *S, CallingContext *Ctx) {
              cast<BinaryConditionalOperator>(S), Ctx);
              cast<BinaryConditionalOperator>(S), Ctx);
 
 
   // We treat these as no-ops
   // We treat these as no-ops
+  case Stmt::ConstantExprClass:
+    return translate(cast<ConstantExpr>(S)->getSubExpr(), Ctx);
   case Stmt::ParenExprClass:
   case Stmt::ParenExprClass:
     return translate(cast<ParenExpr>(S)->getSubExpr(), Ctx);
     return translate(cast<ParenExpr>(S)->getSubExpr(), Ctx);
   case Stmt::ExprWithCleanupsClass:
   case Stmt::ExprWithCleanupsClass:

+ 6 - 4
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
 /// 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
 /// clean up.  This is in this file because, at the moment, the only
 /// kind of cleanup object is a BlockDecl*.
 /// 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.
 /// Find the layout for the given block in a linked list and remove it.

+ 3 - 3
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
   // If we're emitting a value with lifetime, we have to do the
   // initialization *before* we leave the cleanup scopes.
   // 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);
   CodeGenFunction::RunCleanupsScope Scope(*this);
 
 

+ 3 - 4
lib/CodeGen/CGStmt.cpp

@@ -1047,10 +1047,9 @@ void CodeGenFunction::EmitReturnStmt(const ReturnStmt &S) {
   // exception to our over-conservative rules about not jumping to
   // exception to our over-conservative rules about not jumping to
   // statements following block literals with non-trivial cleanups.
   // statements following block literals with non-trivial cleanups.
   RunCleanupsScope cleanupScope(*this);
   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,
   // FIXME: Clean this up by using an LValue for ReturnTemp,

+ 4 - 4
lib/CodeGen/CGStmtOpenMP.cpp

@@ -3986,13 +3986,13 @@ void CodeGenFunction::EmitOMPAtomicDirective(const OMPAtomicDirective &S) {
   }
   }
 
 
   const Stmt *CS = S.getInnermostCapturedStmt()->IgnoreContainers();
   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'.
   // Processing for statements under 'atomic capture'.
   if (const auto *Compound = dyn_cast<CompoundStmt>(CS)) {
   if (const auto *Compound = dyn_cast<CompoundStmt>(CS)) {
     for (const Stmt *C : Compound->body()) {
     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);
     }
     }
   }
   }
 
 

+ 5 - 3
lib/CodeGen/CodeGenFunction.h

@@ -3947,11 +3947,13 @@ public:
 
 
   void EmitSynthesizedCXXCopyCtor(Address Dest, Address Src, const Expr *Exp);
   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);
     enterNonTrivialFullExpression(E);
   }
   }
-  void enterNonTrivialFullExpression(const ExprWithCleanups *E);
+  void enterNonTrivialFullExpression(const FullExpr *E);
 
 
   void EmitCXXThrowExpr(const CXXThrowExpr *E, bool KeepInsertionPoint = true);
   void EmitCXXThrowExpr(const CXXThrowExpr *E, bool KeepInsertionPoint = true);
 
 

+ 3 - 0
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
   //   [Can throw] if in a potentially-evaluated context the expression would
   //   contain:
   //   contain:
   switch (E->getStmtClass()) {
   switch (E->getStmtClass()) {
+  case Expr::ConstantExprClass:
+    return canThrow(cast<ConstantExpr>(E)->getSubExpr());
+
   case Expr::CXXThrowExprClass:
   case Expr::CXXThrowExprClass:
     //   - a potentially evaluated throw-expression
     //   - a potentially evaluated throw-expression
     return CT_Can;
     return CT_Can;

+ 4 - 4
lib/Sema/SemaInit.cpp

@@ -6510,8 +6510,8 @@ static void visitLocalsRetainedByReferenceBinding(IndirectLocalPath &Path,
   do {
   do {
     Old = Init;
     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 (InitListExpr *ILE = dyn_cast<InitListExpr>(Init)) {
       // If this is just redundant braces around an initializer, step over it.
       // If this is just redundant braces around an initializer, step over it.
@@ -6634,8 +6634,8 @@ static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path,
       Init = DIE->getExpr();
       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.
     // Dig out the expression which constructs the extended temporary.
     Init = const_cast<Expr *>(Init->skipRValueSubobjectAdjustments());
     Init = const_cast<Expr *>(Init->skipRValueSubobjectAdjustments());

+ 2 - 2
lib/Sema/SemaOpenMP.cpp

@@ -669,8 +669,8 @@ bool isParallelOrTaskRegion(OpenMPDirectiveKind DKind) {
 } // namespace
 } // namespace
 
 
 static const Expr *getExprAsWritten(const Expr *E) {
 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))
   if (const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E))
     E = MTE->GetTemporaryExpr();
     E = MTE->GetTemporaryExpr();

+ 3 - 3
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
   // we might want to make a more specific diagnostic.  Check for one of these
   // cases now.
   // cases now.
   unsigned DiagID = diag::warn_unused_expr;
   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();
     E = Temps->getSubExpr();
   if (const CXXBindTemporaryExpr *TempExpr = dyn_cast<CXXBindTemporaryExpr>(E))
   if (const CXXBindTemporaryExpr *TempExpr = dyn_cast<CXXBindTemporaryExpr>(E))
     E = TempExpr->getSubExpr();
     E = TempExpr->getSubExpr();
@@ -631,8 +631,8 @@ static bool EqEnumVals(const std::pair<llvm::APSInt, EnumConstantDecl*>& lhs,
 /// GetTypeBeforeIntegralPromotion - Returns the pre-promotion type of
 /// GetTypeBeforeIntegralPromotion - Returns the pre-promotion type of
 /// potentially integral-promoted expression @p expr.
 /// potentially integral-promoted expression @p expr.
 static QualType GetTypeBeforeIntegralPromotion(const Expr *&E) {
 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)) {
   while (const auto *ImpCast = dyn_cast<ImplicitCastExpr>(E)) {
     if (ImpCast->getCastKind() != CK_IntegralCast) break;
     if (ImpCast->getCastKind() != CK_IntegralCast) break;
     E = ImpCast->getSubExpr();
     E = ImpCast->getSubExpr();

+ 8 - 2
lib/Sema/TreeTransform.h

@@ -3344,8 +3344,8 @@ ExprResult TreeTransform<Derived>::TransformInitializer(Expr *Init,
   if (!Init)
   if (!Init)
     return 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))
   if (auto *AIL = dyn_cast<ArrayInitLoopExpr>(Init))
     Init = AIL->getCommonExpr();
     Init = AIL->getCommonExpr();
@@ -8914,6 +8914,12 @@ TreeTransform<Derived>::TransformOMPIsDevicePtrClause(OMPIsDevicePtrClause *C) {
 //===----------------------------------------------------------------------===//
 //===----------------------------------------------------------------------===//
 // Expression transformation
 // Expression transformation
 //===----------------------------------------------------------------------===//
 //===----------------------------------------------------------------------===//
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformConstantExpr(ConstantExpr *E) {
+  return TransformExpr(E->getSubExpr());
+}
+
 template<typename Derived>
 template<typename Derived>
 ExprResult
 ExprResult
 TreeTransform<Derived>::TransformPredefinedExpr(PredefinedExpr *E) {
 TreeTransform<Derived>::TransformPredefinedExpr(PredefinedExpr *E) {

+ 9 - 0
lib/Serialization/ASTReaderStmt.cpp

@@ -524,6 +524,11 @@ void ASTStmtReader::VisitExpr(Expr *E) {
          "Incorrect expression field count");
          "Incorrect expression field count");
 }
 }
 
 
+void ASTStmtReader::VisitConstantExpr(ConstantExpr *E) {
+  VisitExpr(E);
+  E->setSubExpr(Record.readSubExpr());
+}
+
 void ASTStmtReader::VisitPredefinedExpr(PredefinedExpr *E) {
 void ASTStmtReader::VisitPredefinedExpr(PredefinedExpr *E) {
   VisitExpr(E);
   VisitExpr(E);
   bool HasFunctionName = Record.readInt();
   bool HasFunctionName = Record.readInt();
@@ -2385,6 +2390,10 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
           Context, Record[ASTStmtReader::NumStmtFields]);
           Context, Record[ASTStmtReader::NumStmtFields]);
       break;
       break;
 
 
+    case EXPR_CONSTANT:
+      S = new (Context) ConstantExpr(Empty);
+      break;
+
     case EXPR_PREDEFINED:
     case EXPR_PREDEFINED:
       S = PredefinedExpr::CreateEmpty(
       S = PredefinedExpr::CreateEmpty(
           Context,
           Context,

+ 6 - 0
lib/Serialization/ASTWriterStmt.cpp

@@ -426,6 +426,12 @@ void ASTStmtWriter::VisitExpr(Expr *E) {
   Record.push_back(E->getObjectKind());
   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) {
 void ASTStmtWriter::VisitPredefinedExpr(PredefinedExpr *E) {
   VisitExpr(E);
   VisitExpr(E);
 
 

+ 2 - 3
lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp

@@ -329,9 +329,8 @@ public:
             return;
             return;
 
 
           if (const Expr *E = V->getInit()) {
           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.:
             // Look through transitive assignments, e.g.:
             // int x = y = 0;
             // int x = y = 0;

+ 1 - 1
lib/StaticAnalyzer/Core/BugReporter.cpp

@@ -1265,7 +1265,7 @@ static const Stmt *getStmtParent(const Stmt *S, const ParentMap &PM) {
     if (!S)
     if (!S)
       break;
       break;
 
 
-    if (isa<ExprWithCleanups>(S) ||
+    if (isa<FullExpr>(S) ||
         isa<CXXBindTemporaryExpr>(S) ||
         isa<CXXBindTemporaryExpr>(S) ||
         isa<SubstNonTypeTemplateParmExpr>(S))
         isa<SubstNonTypeTemplateParmExpr>(S))
       continue;
       continue;

+ 4 - 4
lib/StaticAnalyzer/Core/BugReporterVisitors.cpp

@@ -136,8 +136,8 @@ const Expr *bugreporter::getDerefExpr(const Stmt *S) {
       E = AE->getBase();
       E = AE->getBase();
     } else if (const auto *PE = dyn_cast<ParenExpr>(E)) {
     } else if (const auto *PE = dyn_cast<ParenExpr>(E)) {
       E = PE->getSubExpr();
       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 {
     } else {
       // Other arbitrary stuff.
       // Other arbitrary stuff.
       break;
       break;
@@ -1494,8 +1494,8 @@ static const MemRegion *getLocationRegionIfReference(const Expr *E,
 static const Expr *peelOffOuterExpr(const Expr *Ex,
 static const Expr *peelOffOuterExpr(const Expr *Ex,
                                     const ExplodedNode *N) {
                                     const ExplodedNode *N) {
   Ex = Ex->IgnoreParenCasts();
   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))
   if (const auto *OVE = dyn_cast<OpaqueValueExpr>(Ex))
     return peelOffOuterExpr(OVE->getSourceExpr(), N);
     return peelOffOuterExpr(OVE->getSourceExpr(), N);
   if (const auto *POE = dyn_cast<PseudoObjectExpr>(Ex)) {
   if (const auto *POE = dyn_cast<PseudoObjectExpr>(Ex)) {

+ 3 - 0
lib/StaticAnalyzer/Core/Environment.cpp

@@ -44,6 +44,9 @@ static const Expr *ignoreTransparentExprs(const Expr *E) {
   case Stmt::ExprWithCleanupsClass:
   case Stmt::ExprWithCleanupsClass:
     E = cast<ExprWithCleanups>(E)->getSubExpr();
     E = cast<ExprWithCleanups>(E)->getSubExpr();
     break;
     break;
+  case Stmt::ConstantExprClass:
+    E = cast<ConstantExpr>(E)->getSubExpr();
+    break;
   case Stmt::CXXBindTemporaryExprClass:
   case Stmt::CXXBindTemporaryExprClass:
     E = cast<CXXBindTemporaryExpr>(E)->getSubExpr();
     E = cast<CXXBindTemporaryExpr>(E)->getSubExpr();
     break;
     break;

+ 3 - 0
lib/StaticAnalyzer/Core/ExprEngine.cpp

@@ -1267,6 +1267,9 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
     case Stmt::ObjCPropertyRefExprClass:
     case Stmt::ObjCPropertyRefExprClass:
       llvm_unreachable("These are handled by PseudoObjectExpr");
       llvm_unreachable("These are handled by PseudoObjectExpr");
 
 
+    case Expr::ConstantExprClass:
+      return Visit(cast<ConstantExpr>(S)->getSubExpr(), Pred, DstTop);
+
     case Stmt::GNUNullExprClass: {
     case Stmt::GNUNullExprClass: {
       // GNU __null is a pointer-width integer, not an actual pointer.
       // GNU __null is a pointer-width integer, not an actual pointer.
       ProgramStateRef state = Pred->getState();
       ProgramStateRef state = Pred->getState();

+ 4 - 0
tools/libclang/CXCursor.cpp

@@ -343,6 +343,10 @@ CXCursor cxcursor::MakeCXCursor(const Stmt *S, const Decl *Parent,
     K = CXCursor_CharacterLiteral;
     K = CXCursor_CharacterLiteral;
     break;
     break;
 
 
+  case Stmt::ConstantExprClass:
+    return MakeCXCursor(cast<ConstantExpr>(S)->getSubExpr(),
+                        Parent, TU, RegionOfInterest);
+
   case Stmt::ParenExprClass:
   case Stmt::ParenExprClass:
     K = CXCursor_ParenExpr;
     K = CXCursor_ParenExpr;
     break;
     break;