void updated this revision to Diff 173445.
void added a comment.
Herald added a subscriber: jfb.

Adding ConstantExpr visitor.


Repository:
  rC Clang

https://reviews.llvm.org/D54355

Files:
  include/clang/AST/Expr.h
  lib/AST/ASTImporter.cpp
  lib/AST/Expr.cpp
  lib/AST/ExprConstant.cpp
  lib/CodeGen/CGBuiltin.cpp
  lib/Sema/SemaDeclCXX.cpp
  lib/Sema/SemaExpr.cpp
  lib/Sema/SemaOverload.cpp
  lib/Sema/SemaTemplateDeduction.cpp
  lib/Sema/SemaType.cpp
  lib/StaticAnalyzer/Core/ExprEngine.cpp
  test/Analysis/builtin-functions.cpp
  test/SemaCXX/compound-literal.cpp

Index: test/SemaCXX/compound-literal.cpp
===================================================================
--- test/SemaCXX/compound-literal.cpp
+++ test/SemaCXX/compound-literal.cpp
@@ -36,8 +36,8 @@
 
   POD p = (POD){1, 2};
   // CHECK-NOT: CXXBindTemporaryExpr {{.*}} 'brace_initializers::POD'
-  // CHECK: ConstantExpr {{.*}} 'brace_initializers::POD'
-  // CHECK-NEXT: CompoundLiteralExpr {{.*}} 'brace_initializers::POD'
+  // CHECK: CompoundLiteralExpr {{.*}} 'brace_initializers::POD'
+  // CHECK-NEXT: ConstantExpr {{.*}} 'brace_initializers::POD'
   // CHECK-NEXT: InitListExpr {{.*}} 'brace_initializers::POD'
   // CHECK-NEXT: IntegerLiteral {{.*}} 1{{$}}
   // CHECK-NEXT: IntegerLiteral {{.*}} 2{{$}}
Index: test/Analysis/builtin-functions.cpp
===================================================================
--- test/Analysis/builtin-functions.cpp
+++ test/Analysis/builtin-functions.cpp
@@ -70,14 +70,14 @@
   const int j = 2;
   constexpr int k = 3;
   clang_analyzer_eval(__builtin_constant_p(42) == 1); // expected-warning {{TRUE}}
-  clang_analyzer_eval(__builtin_constant_p(i) == 0); // expected-warning {{TRUE}}
+  clang_analyzer_eval(__builtin_constant_p(i) == 0); // expected-warning {{UNKNOWN}}
   clang_analyzer_eval(__builtin_constant_p(j) == 1); // expected-warning {{TRUE}}
   clang_analyzer_eval(__builtin_constant_p(k) == 1); // expected-warning {{TRUE}}
-  clang_analyzer_eval(__builtin_constant_p(i + 42) == 0); // expected-warning {{TRUE}}
+  clang_analyzer_eval(__builtin_constant_p(i + 42) == 0); // expected-warning {{UNKNOWN}}
   clang_analyzer_eval(__builtin_constant_p(j + 42) == 1); // expected-warning {{TRUE}}
   clang_analyzer_eval(__builtin_constant_p(k + 42) == 1); // expected-warning {{TRUE}}
   clang_analyzer_eval(__builtin_constant_p(" ") == 1); // expected-warning {{TRUE}}
-  clang_analyzer_eval(__builtin_constant_p(test_constant_p) == 0); // expected-warning {{TRUE}}
+  clang_analyzer_eval(__builtin_constant_p(test_constant_p) == 0); // expected-warning {{UNKNOWN}}
   clang_analyzer_eval(__builtin_constant_p(k - 3) == 0); // expected-warning {{FALSE}}
   clang_analyzer_eval(__builtin_constant_p(k - 3) == 1); // expected-warning {{TRUE}}
 }
Index: lib/StaticAnalyzer/Core/ExprEngine.cpp
===================================================================
--- lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -1283,9 +1283,6 @@
       break;
 
     case Expr::ConstantExprClass:
-      // Handled due to it being a wrapper class.
-      break;
-
     case Stmt::ExprWithCleanupsClass:
       // Handled due to fully linearised CFG.
       break;
Index: lib/Sema/SemaType.cpp
===================================================================
--- lib/Sema/SemaType.cpp
+++ lib/Sema/SemaType.cpp
@@ -2233,10 +2233,6 @@
     T = Context.getConstantArrayType(T, ConstVal, ASM, Quals);
   }
 
-  if (ArraySize && !CurContext->isFunctionOrMethod())
-    // A file-scoped array must have a constant array size.
-    ArraySize = new (Context) ConstantExpr(ArraySize);
-
   // OpenCL v1.2 s6.9.d: variable length arrays are not supported.
   if (getLangOpts().OpenCL && T->isVariableArrayType()) {
     Diag(Loc, diag::err_opencl_vla);
Index: lib/Sema/SemaTemplateDeduction.cpp
===================================================================
--- lib/Sema/SemaTemplateDeduction.cpp
+++ lib/Sema/SemaTemplateDeduction.cpp
@@ -178,6 +178,8 @@
   while (true) {
     if (ImplicitCastExpr *IC = dyn_cast<ImplicitCastExpr>(E))
       E = IC->getSubExpr();
+    else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(E))
+      E = CE->getSubExpr();
     else if (SubstNonTypeTemplateParmExpr *Subst =
                dyn_cast<SubstNonTypeTemplateParmExpr>(E))
       E = Subst->getReplacement();
@@ -5225,6 +5227,8 @@
   while (true) {
     if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E))
       E = ICE->getSubExpr();
+    else if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(E))
+      E = CE->getSubExpr();
     else if (const SubstNonTypeTemplateParmExpr *Subst =
                dyn_cast<SubstNonTypeTemplateParmExpr>(E))
       E = Subst->getReplacement();
Index: lib/Sema/SemaOverload.cpp
===================================================================
--- lib/Sema/SemaOverload.cpp
+++ lib/Sema/SemaOverload.cpp
@@ -5444,7 +5444,7 @@
 
     if (Notes.empty()) {
       // It's a constant expression.
-      return new (S.Context) ConstantExpr(Result.get());
+      return ConstantExpr::Create(S.Context, Result.get());
     }
   }
 
Index: lib/Sema/SemaExpr.cpp
===================================================================
--- lib/Sema/SemaExpr.cpp
+++ lib/Sema/SemaExpr.cpp
@@ -4899,6 +4899,14 @@
   unsigned NumParams = Proto->getNumParams();
   bool Invalid = false;
   size_t ArgIx = 0;
+
+  unsigned ICEArguments = 0;
+  if (FDecl)
+    if (auto BuiltinID = FDecl->getBuiltinID()) {
+      ASTContext::GetBuiltinTypeError Error;
+      Context.GetBuiltinType(BuiltinID, Error, &ICEArguments);
+    }
+
   // Continue to check argument types (even if we have too few/many args).
   for (unsigned i = FirstParam; i < NumParams; i++) {
     QualType ProtoArgType = Proto->getParamType(i);
@@ -4962,6 +4970,9 @@
     // Check for violations of C99 static array rules (C99 6.7.5.3p7).
     CheckStaticArrayArgument(CallLoc, Param, Arg);
 
+    if ((ICEArguments & (1 << (ArgIx - 1))) != 0)
+      Arg = ConstantExpr::Create(Context, Arg);
+
     AllArgs.push_back(Arg);
   }
 
@@ -5769,15 +5780,16 @@
           ? VK_RValue
           : VK_LValue;
 
+  if (isFileScope)
+    LiteralExpr = ConstantExpr::Create(Context, LiteralExpr);
   Expr *E = new (Context) CompoundLiteralExpr(LParenLoc, TInfo, literalType,
                                               VK, LiteralExpr, isFileScope);
   if (isFileScope) {
     if (!LiteralExpr->isTypeDependent() &&
         !LiteralExpr->isValueDependent() &&
         !literalType->isDependentType()) // C99 6.5.2.5p3
       if (CheckForConstantInitializer(LiteralExpr, literalType))
         return ExprError();
-    E = new (Context) ConstantExpr(E);
   } else if (literalType.getAddressSpace() != LangAS::opencl_private &&
              literalType.getAddressSpace() != LangAS::Default) {
     // Embedded-C extensions to C99 6.5.2.5:
@@ -14141,12 +14153,15 @@
     return ExprError();
   }
 
+  if (!CurContext->isFunctionOrMethod())
+    E = ConstantExpr::Create(Context, E);
+
   // Circumvent ICE checking in C++11 to avoid evaluating the expression twice
   // in the non-ICE case.
   if (!getLangOpts().CPlusPlus11 && E->isIntegerConstantExpr(Context)) {
     if (Result)
       *Result = E->EvaluateKnownConstIntCheckOverflow(Context);
-    return new (Context) ConstantExpr(E);
+    return E;
   }
 
   Expr::EvalResult EvalResult;
@@ -14164,7 +14179,7 @@
   if (Folded && getLangOpts().CPlusPlus11 && Notes.empty()) {
     if (Result)
       *Result = EvalResult.Val.getInt();
-    return new (Context) ConstantExpr(E);
+    return E;
   }
 
   // If our only note is the usual "invalid subexpression" note, just point
@@ -14192,7 +14207,7 @@
 
   if (Result)
     *Result = EvalResult.Val.getInt();
-  return new (Context) ConstantExpr(E);
+  return E;
 }
 
 namespace {
Index: lib/Sema/SemaDeclCXX.cpp
===================================================================
--- lib/Sema/SemaDeclCXX.cpp
+++ lib/Sema/SemaDeclCXX.cpp
@@ -13861,6 +13861,8 @@
     ExprResult Converted = PerformContextuallyConvertToBool(AssertExpr);
     if (Converted.isInvalid())
       Failed = true;
+    else
+      Converted = ConstantExpr::Create(Context, Converted.get());
 
     llvm::APSInt Cond;
     if (!Failed && VerifyIntegerConstantExpression(Converted.get(), &Cond,
Index: lib/CodeGen/CGBuiltin.cpp
===================================================================
--- lib/CodeGen/CGBuiltin.cpp
+++ lib/CodeGen/CGBuiltin.cpp
@@ -1918,6 +1918,19 @@
   case Builtin::BI__builtin_rotateright64:
     return emitRotate(E, true);
 
+  case Builtin::BI__builtin_constant_p: {
+    if (CGM.getCodeGenOpts().OptimizationLevel == 0)
+      // At -O0, we don't perform inlining, so we don't need to delay the
+      // processing.
+      return RValue::get(ConstantInt::get(Int32Ty, 0));
+    if (auto *DRE = dyn_cast<DeclRefExpr>(E->getArg(0)->IgnoreImplicit()))
+      if (DRE->getType()->isAggregateType())
+        return RValue::get(ConstantInt::get(Int32Ty, 0));
+    Value *Arg = EmitScalarExpr(E->getArg(0));
+    Value *F = CGM.getIntrinsic(Intrinsic::is_constant, Arg->getType());
+    Value *Call = Builder.CreateCall(F, Arg);
+    return RValue::get(Builder.CreateZExtOrBitCast(Call, Int32Ty));
+  }
   case Builtin::BI__builtin_object_size: {
     unsigned Type =
         E->getArg(1)->EvaluateKnownConstInt(getContext()).getZExtValue();
Index: lib/AST/ExprConstant.cpp
===================================================================
--- lib/AST/ExprConstant.cpp
+++ lib/AST/ExprConstant.cpp
@@ -45,6 +45,7 @@
 #include "clang/AST/TypeLoc.h"
 #include "clang/Basic/Builtins.h"
 #include "clang/Basic/TargetInfo.h"
+#include "llvm/Support/SaveAndRestore.h"
 #include "llvm/Support/raw_ostream.h"
 #include <cstring>
 #include <functional>
@@ -721,6 +722,10 @@
     /// Whether or not we're currently speculatively evaluating.
     bool IsSpeculativelyEvaluating;
 
+    /// Whether or not we're in a context where the front end requires a
+    /// constant value.
+    bool InConstantContext;
+
     enum EvaluationMode {
       /// Evaluate as a constant expression. Stop if we find that the expression
       /// is not a constant expression.
@@ -782,7 +787,7 @@
         EvaluatingDecl((const ValueDecl *)nullptr),
         EvaluatingDeclValue(nullptr), HasActiveDiagnostic(false),
         HasFoldFailureDiagnostic(false), IsSpeculativelyEvaluating(false),
-        EvalMode(Mode) {}
+        InConstantContext(false), EvalMode(Mode) {}
 
     void setEvaluatingDecl(APValue::LValueBase Base, APValue &Value) {
       EvaluatingDecl = Base;
@@ -7347,6 +7352,8 @@
   //                            Visitor Methods
   //===--------------------------------------------------------------------===//
 
+  bool VisitConstantExpr(const ConstantExpr *E);
+
   bool VisitIntegerLiteral(const IntegerLiteral *E) {
     return Success(E->getValue(), E);
   }
@@ -8087,6 +8094,11 @@
   return true;
 }
 
+bool IntExprEvaluator::VisitConstantExpr(const ConstantExpr *E) {
+  llvm::SaveAndRestore<bool> InConstantContext(Info.InConstantContext, true);
+  return ExprEvaluatorBaseTy::VisitConstantExpr(E);
+}
+
 bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) {
   if (unsigned BuiltinOp = E->getBuiltinCallee())
     return VisitBuiltinCallExpr(E, BuiltinOp);
@@ -8174,8 +8186,20 @@
     return Success(Val.countLeadingZeros(), E);
   }
 
-  case Builtin::BI__builtin_constant_p:
-    return Success(EvaluateBuiltinConstantP(Info.Ctx, E->getArg(0)), E);
+  case Builtin::BI__builtin_constant_p: {
+    auto Arg = E->getArg(0);
+    if (EvaluateBuiltinConstantP(Info.Ctx, Arg))
+      return Success(true, E);
+    auto ArgTy = Arg->IgnoreImplicit()->getType();
+    if (!Info.InConstantContext && !Arg->HasSideEffects(Info.Ctx) &&
+        !ArgTy->isAggregateType() && !ArgTy->isPointerType()) {
+      // We can delay calculation of __builtin_constant_p until after
+      // inlining. Note: This diagnostic won't be shown to the user.
+      Info.FFDiag(E, diag::note_invalid_subexpr_in_const_expr);
+      return false;
+    }
+    return Success(false, E);
+  }
 
   case Builtin::BI__builtin_ctz:
   case Builtin::BI__builtin_ctzl:
@@ -10956,401 +10980,378 @@
 
 static ICEDiag Worst(ICEDiag A, ICEDiag B) { return A.Kind >= B.Kind ? A : B; }
 
-static ICEDiag CheckEvalInICE(const Expr* E, const ASTContext &Ctx) {
+static ICEDiag CheckEvalInICE(const Expr *E, const ASTContext &Ctx,
+                              EvalInfo &Info) {
   Expr::EvalResult EVResult;
-  if (!E->EvaluateAsRValue(EVResult, Ctx) || EVResult.HasSideEffects ||
+  if (!::EvaluateAsRValue(Info, E, EVResult.Val) || EVResult.HasSideEffects ||
       !EVResult.Val.isInt())
     return ICEDiag(IK_NotICE, E->getBeginLoc());
 
   return NoDiag();
 }
 
+class ICEChecker
+  : public ConstStmtVisitor<ICEChecker, ICEDiag> {
+  const ASTContext &Ctx;
+  EvalInfo &Info;
+
+  typedef ConstStmtVisitor<ICEChecker, ICEDiag> StmtVisitorTy;
+
+public:
+  ICEChecker(const ASTContext &Ctx, EvalInfo &Info)
+      : Ctx(Ctx), Info(Info) {}
+
+  ICEDiag VisitStmt(const Stmt *S) {
+    return ICEDiag(IK_NotICE, S->getBeginLoc());
+  }
+
+  ICEDiag VisitExpr(const Expr *E);
+  ICEDiag VisitConstantExpr(const ConstantExpr *E);
+  ICEDiag VisitInitListExpr(const InitListExpr *E);
+  ICEDiag VisitSubstNonTypeTemplateParmExpr(
+      const SubstNonTypeTemplateParmExpr *E);
+  ICEDiag VisitParenExpr(const ParenExpr *E);
+  ICEDiag VisitGenericSelectionExpr(const GenericSelectionExpr *E);
+  ICEDiag VisitCallExpr(const CallExpr *E);
+  ICEDiag VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *E);
+  ICEDiag VisitDeclRefExpr(const DeclRefExpr *E);
+  ICEDiag VisitBinaryOperator(const BinaryOperator *E);
+  ICEDiag VisitUnaryOperator(const UnaryOperator *E);
+  ICEDiag VisitOffsetOfExpr(const OffsetOfExpr *E);
+  ICEDiag VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *E);
+  ICEDiag VisitCastExpr(const CastExpr *E);
+  ICEDiag VisitBinaryConditionalOperator(const BinaryConditionalOperator *E);
+  ICEDiag VisitConditionalOperator(const ConditionalOperator *E);
+  ICEDiag VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *E);
+  ICEDiag VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *E);
+  ICEDiag VisitChooseExpr(const ChooseExpr *E);
+};
+
+ICEDiag ICEChecker::VisitExpr(const Expr *E) {
+  switch (E->getStmtClass()) {
+  default:
+    return ICEDiag(IK_NotICE, E->getBeginLoc());
+  case Expr::ArrayTypeTraitExprClass:
+  case Expr::CharacterLiteralClass:
+  case Expr::CXXBoolLiteralExprClass:
+  case Expr::CXXNoexceptExprClass:
+  case Expr::CXXScalarValueInitExprClass:
+  case Expr::ExpressionTraitExprClass:
+  case Expr::FixedPointLiteralClass:
+  case Expr::GNUNullExprClass:
+    // GCC considers the GNU __null value to be an integral constant expression.
+  case Expr::IntegerLiteralClass:
+  case Expr::ObjCBoolLiteralExprClass:
+  case Expr::SizeOfPackExprClass:
+  case Expr::TypeTraitExprClass:
+    return NoDiag();
+  }
+}
+
+ICEDiag ICEChecker::VisitConstantExpr(const ConstantExpr *E) {
+  llvm::SaveAndRestore<bool> InConstantContext(Info.InConstantContext, true);
+  return StmtVisitorTy::Visit(E->getSubExpr());
+}
+
+ICEDiag ICEChecker::VisitInitListExpr(const InitListExpr *E) {
+  // C++03 [dcl.init]p13: If T is a scalar type, then a declaration of the form
+  // "T x = { a };" is equivalent to "T x = a;".
+  // Unless we're initializing a reference, T is a scalar as it is known to be
+  // of integral or enumeration type.
+  if (E->isRValue())
+    if (E->getNumInits() == 1)
+      return StmtVisitorTy::Visit(E->getInit(0));
+  return ICEDiag(IK_NotICE, E->getBeginLoc());
+}
+
+ICEDiag ICEChecker::VisitSubstNonTypeTemplateParmExpr(
+    const SubstNonTypeTemplateParmExpr *E) {
+  return StmtVisitorTy::Visit(E->getReplacement());
+}
+
+ICEDiag ICEChecker::VisitParenExpr(const ParenExpr *E) {
+  return StmtVisitorTy::Visit(E->getSubExpr());
+}
+
+ICEDiag ICEChecker::VisitGenericSelectionExpr(const GenericSelectionExpr *E) {
+  return StmtVisitorTy::Visit(E->getResultExpr());
+}
+
+ICEDiag ICEChecker::VisitCallExpr(const CallExpr *E) {
+  // C99 6.6/3 allows function calls within unevaluated subexpressions of
+  // constant expressions, but they can never be ICEs because an ICE cannot
+  // contain an operand of (pointer to) function type.
+  if (E->getBuiltinCallee())
+    return CheckEvalInICE(E, Ctx, Info);
+  return ICEDiag(IK_NotICE, E->getBeginLoc());
+}
+
+ICEDiag ICEChecker::VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *E) {
+  return VisitCallExpr(E);
+}
+
+ICEDiag ICEChecker::VisitDeclRefExpr(const DeclRefExpr *E) {
+  if (isa<EnumConstantDecl>(E->getDecl()))
+    return NoDiag();
+
+  const ValueDecl *D = E->getDecl();
+  if (Ctx.getLangOpts().CPlusPlus &&
+      D && IsConstNonVolatile(D->getType())) {
+    // Parameter variables are never constants.  Without this check,
+    // getAnyInitializer() can find a default argument, which leads
+    // to chaos.
+    if (isa<ParmVarDecl>(D))
+      return ICEDiag(IK_NotICE, E->getLocation());
+
+    // C++ 7.1.5.1p2
+    //   A variable of non-volatile const-qualified integral or enumeration
+    //   type initialized by an ICE can be used in ICEs.
+    if (const VarDecl *Dcl = dyn_cast<VarDecl>(D)) {
+      if (!Dcl->getType()->isIntegralOrEnumerationType())
+        return ICEDiag(IK_NotICE, E->getLocation());
+
+      const VarDecl *VD;
+      // Look for a declaration of this variable that has an initializer, and
+      // check whether it is an ICE.
+      if (Dcl->getAnyInitializer(VD) && VD->checkInitIsICE())
+        return NoDiag();
+      else
+        return ICEDiag(IK_NotICE, E->getLocation());
+    }
+  }
+  return ICEDiag(IK_NotICE, E->getBeginLoc());
+}
+
+ICEDiag ICEChecker::VisitUnaryOperator(const UnaryOperator *E) {
+  switch (E->getOpcode()) {
+  case UO_PostInc:
+  case UO_PostDec:
+  case UO_PreInc:
+  case UO_PreDec:
+  case UO_AddrOf:
+  case UO_Deref:
+  case UO_Coawait:
+    // C99 6.6/3 allows increment and decrement within unevaluated
+    // subexpressions of constant expressions, but they can never be ICEs
+    // because an ICE cannot contain an lvalue operand.
+    return ICEDiag(IK_NotICE, E->getBeginLoc());
+
+  case UO_Extension:
+  case UO_LNot:
+  case UO_Plus:
+  case UO_Minus:
+  case UO_Not:
+  case UO_Real:
+  case UO_Imag:
+    return StmtVisitorTy::Visit(E->getSubExpr());
+  }
+  llvm_unreachable("invalid unary operator class");
+}
+
+ICEDiag ICEChecker::VisitBinaryOperator(const BinaryOperator *E) {
+  switch (E->getOpcode()) {
+  case BO_PtrMemD:
+  case BO_PtrMemI:
+  case BO_Assign:
+  case BO_MulAssign:
+  case BO_DivAssign:
+  case BO_RemAssign:
+  case BO_AddAssign:
+  case BO_SubAssign:
+  case BO_ShlAssign:
+  case BO_ShrAssign:
+  case BO_AndAssign:
+  case BO_XorAssign:
+  case BO_OrAssign:
+    // C99 6.6/3 allows assignments within unevaluated subexpressions of
+    // constant expressions, but they can never be ICEs because an ICE cannot
+    // contain an lvalue operand.
+    return ICEDiag(IK_NotICE, E->getBeginLoc());
+
+  case BO_Mul:
+  case BO_Div:
+  case BO_Rem:
+  case BO_Add:
+  case BO_Sub:
+  case BO_Shl:
+  case BO_Shr:
+  case BO_LT:
+  case BO_GT:
+  case BO_LE:
+  case BO_GE:
+  case BO_EQ:
+  case BO_NE:
+  case BO_And:
+  case BO_Xor:
+  case BO_Or:
+  case BO_Comma:
+  case BO_Cmp: {
+    ICEDiag LHSResult = StmtVisitorTy::Visit(E->getLHS());
+    ICEDiag RHSResult = StmtVisitorTy::Visit(E->getRHS());
+    if (E->getOpcode() == BO_Div ||
+        E->getOpcode() == BO_Rem) {
+      // EvaluateAsRValue gives an error for undefined Div/Rem, so make sure
+      // we don't evaluate one.
+      if (LHSResult.Kind == IK_ICE && RHSResult.Kind == IK_ICE) {
+        llvm::APSInt REval = E->getRHS()->EvaluateKnownConstInt(Ctx);
+        if (REval == 0)
+          return ICEDiag(IK_ICEIfUnevaluated, E->getBeginLoc());
+        if (REval.isSigned() && REval.isAllOnesValue()) {
+          llvm::APSInt LEval = E->getLHS()->EvaluateKnownConstInt(Ctx);
+          if (LEval.isMinSignedValue())
+            return ICEDiag(IK_ICEIfUnevaluated, E->getBeginLoc());
+        }
+      }
+    }
+    if (E->getOpcode() == BO_Comma) {
+      if (Ctx.getLangOpts().C99) {
+        // C99 6.6p3 introduces a strange edge case: comma can be in an ICE
+        // if it isn't evaluated.
+        if (LHSResult.Kind == IK_ICE && RHSResult.Kind == IK_ICE)
+          return ICEDiag(IK_ICEIfUnevaluated, E->getBeginLoc());
+      } else {
+        // In both C89 and C++, commas in ICEs are illegal.
+        return ICEDiag(IK_NotICE, E->getBeginLoc());
+      }
+    }
+    return Worst(LHSResult, RHSResult);
+  }
+  case BO_LAnd:
+  case BO_LOr: {
+    ICEDiag LHSResult = StmtVisitorTy::Visit(E->getLHS());
+    ICEDiag RHSResult = StmtVisitorTy::Visit(E->getRHS());
+    if (LHSResult.Kind == IK_ICE && RHSResult.Kind == IK_ICEIfUnevaluated) {
+      // Rare case where the RHS has a comma "side-effect"; we need
+      // to actually check the condition to see whether the side
+      // with the comma is evaluated.
+      if ((E->getOpcode() == BO_LAnd) !=
+          (E->getLHS()->EvaluateKnownConstInt(Ctx) == 0))
+        return RHSResult;
+      return NoDiag();
+    }
+
+    return Worst(LHSResult, RHSResult);
+  }
+  }
+  llvm_unreachable("invalid binary operator kind");
+}
+
+ICEDiag ICEChecker::VisitOffsetOfExpr(const OffsetOfExpr *E) {
+  // Note that per C99, offsetof must be an ICE. And AFAIK, using
+  // EvaluateAsRValue matches the proposed gcc behavior for cases like
+  // "offsetof(struct s{int x[4];}, x[1.0])".  This doesn't affect compliance:
+  // we should warn earlier for offsetof expressions with array subscripts that
+  // aren't ICEs, and if the array subscripts are ICEs, the value of the
+  // offsetof must be an integer constant.
+  return CheckEvalInICE(E, Ctx, Info);
+}
+
+ICEDiag ICEChecker::VisitUnaryExprOrTypeTraitExpr(
+    const UnaryExprOrTypeTraitExpr *E) {
+  if (E->getKind() ==  UETT_SizeOf &&
+      E->getTypeOfArgument()->isVariableArrayType())
+    return ICEDiag(IK_NotICE, E->getBeginLoc());
+  return NoDiag();
+}
+
+ICEDiag ICEChecker::VisitCastExpr(const CastExpr *E) {
+  const Expr *SubExpr = E->getSubExpr();
+  if (isa<ExplicitCastExpr>(E)) {
+    if (const FloatingLiteral *FL
+          = dyn_cast<FloatingLiteral>(SubExpr->IgnoreParenImpCasts())) {
+      unsigned DestWidth = Ctx.getIntWidth(E->getType());
+      bool DestSigned = E->getType()->isSignedIntegerOrEnumerationType();
+      APSInt IgnoredVal(DestWidth, !DestSigned);
+      bool Ignored;
+      // If the value does not fit in the destination type, the behavior is
+      // undefined, so we are not required to treat it as a constant
+      // expression.
+      if (FL->getValue().convertToInteger(IgnoredVal,
+                                          llvm::APFloat::rmTowardZero,
+                                          &Ignored) & APFloat::opInvalidOp)
+        return ICEDiag(IK_NotICE, E->getBeginLoc());
+      return NoDiag();
+    }
+  }
+  switch (E->getCastKind()) {
+  default:
+    return ICEDiag(IK_NotICE, E->getBeginLoc());
+  case CK_LValueToRValue:
+  case CK_AtomicToNonAtomic:
+  case CK_NonAtomicToAtomic:
+  case CK_NoOp:
+  case CK_IntegralToBoolean:
+  case CK_IntegralCast:
+    return StmtVisitorTy::Visit(SubExpr);
+  }
+}
+
+ICEDiag ICEChecker::VisitBinaryConditionalOperator(
+    const BinaryConditionalOperator *E) {
+  ICEDiag CommonResult = StmtVisitorTy::Visit(E->getCommon());
+  if (CommonResult.Kind == IK_NotICE) return CommonResult;
+  ICEDiag FalseResult = StmtVisitorTy::Visit(E->getFalseExpr());
+  if (FalseResult.Kind == IK_NotICE) return FalseResult;
+  if (CommonResult.Kind == IK_ICEIfUnevaluated) return CommonResult;
+  if (FalseResult.Kind == IK_ICEIfUnevaluated &&
+      E->getCommon()->EvaluateKnownConstInt(Ctx) != 0) return NoDiag();
+  return FalseResult;
+}
+
+ICEDiag ICEChecker::VisitConditionalOperator(const ConditionalOperator *E) {
+  // If the condition (ignoring parens) is a __builtin_constant_p call,
+  // then only the true side is actually considered in an integer constant
+  // expression, and it is fully evaluated.  This is an important GNU
+  // extension.  See GCC PR38377 for discussion.
+  if (const CallExpr *CallCE
+      = dyn_cast<CallExpr>(E->getCond()->IgnoreParenCasts()))
+    if (CallCE->getBuiltinCallee() == Builtin::BI__builtin_constant_p)
+      return CheckEvalInICE(E, Ctx, Info);
+  ICEDiag CondResult = StmtVisitorTy::Visit(E->getCond());
+  if (CondResult.Kind == IK_NotICE)
+    return CondResult;
+
+  ICEDiag TrueResult = StmtVisitorTy::Visit(E->getTrueExpr());
+  ICEDiag FalseResult = StmtVisitorTy::Visit(E->getFalseExpr());
+
+  if (TrueResult.Kind == IK_NotICE)
+    return TrueResult;
+  if (FalseResult.Kind == IK_NotICE)
+    return FalseResult;
+  if (CondResult.Kind == IK_ICEIfUnevaluated)
+    return CondResult;
+  if (TrueResult.Kind == IK_ICE && FalseResult.Kind == IK_ICE)
+    return NoDiag();
+  // Rare case where the diagnostics depend on which side is evaluated
+  // Note that if we get here, CondResult is 0, and at least one of
+  // TrueResult and FalseResult is non-zero.
+  if (E->getCond()->EvaluateKnownConstInt(Ctx) == 0)
+    return FalseResult;
+  return TrueResult;
+}
+
+ICEDiag ICEChecker::VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *E) {
+  return StmtVisitorTy::Visit(E->getExpr());
+}
+
+ICEDiag ICEChecker::VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *E) {
+  return StmtVisitorTy::Visit(E->getExpr());
+}
+
+ICEDiag ICEChecker::VisitChooseExpr(const ChooseExpr *E) {
+  return StmtVisitorTy::Visit(E->getChosenSubExpr());
+}
+
 static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) {
   assert(!E->isValueDependent() && "Should not see value dependent exprs!");
   if (!E->getType()->isIntegralOrEnumerationType())
     return ICEDiag(IK_NotICE, E->getBeginLoc());
 
-  switch (E->getStmtClass()) {
-#define ABSTRACT_STMT(Node)
-#define STMT(Node, Base) case Expr::Node##Class:
-#define EXPR(Node, Base)
-#include "clang/AST/StmtNodes.inc"
-  case Expr::PredefinedExprClass:
-  case Expr::FloatingLiteralClass:
-  case Expr::ImaginaryLiteralClass:
-  case Expr::StringLiteralClass:
-  case Expr::ArraySubscriptExprClass:
-  case Expr::OMPArraySectionExprClass:
-  case Expr::MemberExprClass:
-  case Expr::CompoundAssignOperatorClass:
-  case Expr::CompoundLiteralExprClass:
-  case Expr::ExtVectorElementExprClass:
-  case Expr::DesignatedInitExprClass:
-  case Expr::ArrayInitLoopExprClass:
-  case Expr::ArrayInitIndexExprClass:
-  case Expr::NoInitExprClass:
-  case Expr::DesignatedInitUpdateExprClass:
-  case Expr::ImplicitValueInitExprClass:
-  case Expr::ParenListExprClass:
-  case Expr::VAArgExprClass:
-  case Expr::AddrLabelExprClass:
-  case Expr::StmtExprClass:
-  case Expr::CXXMemberCallExprClass:
-  case Expr::CUDAKernelCallExprClass:
-  case Expr::CXXDynamicCastExprClass:
-  case Expr::CXXTypeidExprClass:
-  case Expr::CXXUuidofExprClass:
-  case Expr::MSPropertyRefExprClass:
-  case Expr::MSPropertySubscriptExprClass:
-  case Expr::CXXNullPtrLiteralExprClass:
-  case Expr::UserDefinedLiteralClass:
-  case Expr::CXXThisExprClass:
-  case Expr::CXXThrowExprClass:
-  case Expr::CXXNewExprClass:
-  case Expr::CXXDeleteExprClass:
-  case Expr::CXXPseudoDestructorExprClass:
-  case Expr::UnresolvedLookupExprClass:
-  case Expr::TypoExprClass:
-  case Expr::DependentScopeDeclRefExprClass:
-  case Expr::CXXConstructExprClass:
-  case Expr::CXXInheritedCtorInitExprClass:
-  case Expr::CXXStdInitializerListExprClass:
-  case Expr::CXXBindTemporaryExprClass:
-  case Expr::ExprWithCleanupsClass:
-  case Expr::CXXTemporaryObjectExprClass:
-  case Expr::CXXUnresolvedConstructExprClass:
-  case Expr::CXXDependentScopeMemberExprClass:
-  case Expr::UnresolvedMemberExprClass:
-  case Expr::ObjCStringLiteralClass:
-  case Expr::ObjCBoxedExprClass:
-  case Expr::ObjCArrayLiteralClass:
-  case Expr::ObjCDictionaryLiteralClass:
-  case Expr::ObjCEncodeExprClass:
-  case Expr::ObjCMessageExprClass:
-  case Expr::ObjCSelectorExprClass:
-  case Expr::ObjCProtocolExprClass:
-  case Expr::ObjCIvarRefExprClass:
-  case Expr::ObjCPropertyRefExprClass:
-  case Expr::ObjCSubscriptRefExprClass:
-  case Expr::ObjCIsaExprClass:
-  case Expr::ObjCAvailabilityCheckExprClass:
-  case Expr::ShuffleVectorExprClass:
-  case Expr::ConvertVectorExprClass:
-  case Expr::BlockExprClass:
-  case Expr::NoStmtClass:
-  case Expr::OpaqueValueExprClass:
-  case Expr::PackExpansionExprClass:
-  case Expr::SubstNonTypeTemplateParmPackExprClass:
-  case Expr::FunctionParmPackExprClass:
-  case Expr::AsTypeExprClass:
-  case Expr::ObjCIndirectCopyRestoreExprClass:
-  case Expr::MaterializeTemporaryExprClass:
-  case Expr::PseudoObjectExprClass:
-  case Expr::AtomicExprClass:
-  case Expr::LambdaExprClass:
-  case Expr::CXXFoldExprClass:
-  case Expr::CoawaitExprClass:
-  case Expr::DependentCoawaitExprClass:
-  case Expr::CoyieldExprClass:
-    return ICEDiag(IK_NotICE, E->getBeginLoc());
-
-  case Expr::InitListExprClass: {
-    // C++03 [dcl.init]p13: If T is a scalar type, then a declaration of the
-    // form "T x = { a };" is equivalent to "T x = a;".
-    // Unless we're initializing a reference, T is a scalar as it is known to be
-    // of integral or enumeration type.
-    if (E->isRValue())
-      if (cast<InitListExpr>(E)->getNumInits() == 1)
-        return CheckICE(cast<InitListExpr>(E)->getInit(0), Ctx);
-    return ICEDiag(IK_NotICE, E->getBeginLoc());
-  }
-
-  case Expr::SizeOfPackExprClass:
-  case Expr::GNUNullExprClass:
-    // GCC considers the GNU __null value to be an integral constant expression.
-    return NoDiag();
-
-  case Expr::SubstNonTypeTemplateParmExprClass:
-    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:
-    return CheckICE(cast<GenericSelectionExpr>(E)->getResultExpr(), Ctx);
-  case Expr::IntegerLiteralClass:
-  case Expr::FixedPointLiteralClass:
-  case Expr::CharacterLiteralClass:
-  case Expr::ObjCBoolLiteralExprClass:
-  case Expr::CXXBoolLiteralExprClass:
-  case Expr::CXXScalarValueInitExprClass:
-  case Expr::TypeTraitExprClass:
-  case Expr::ArrayTypeTraitExprClass:
-  case Expr::ExpressionTraitExprClass:
-  case Expr::CXXNoexceptExprClass:
-    return NoDiag();
-  case Expr::CallExprClass:
-  case Expr::CXXOperatorCallExprClass: {
-    // C99 6.6/3 allows function calls within unevaluated subexpressions of
-    // constant expressions, but they can never be ICEs because an ICE cannot
-    // contain an operand of (pointer to) function type.
-    const CallExpr *CE = cast<CallExpr>(E);
-    if (CE->getBuiltinCallee())
-      return CheckEvalInICE(E, Ctx);
-    return ICEDiag(IK_NotICE, E->getBeginLoc());
-  }
-  case Expr::DeclRefExprClass: {
-    if (isa<EnumConstantDecl>(cast<DeclRefExpr>(E)->getDecl()))
-      return NoDiag();
-    const ValueDecl *D = cast<DeclRefExpr>(E)->getDecl();
-    if (Ctx.getLangOpts().CPlusPlus &&
-        D && IsConstNonVolatile(D->getType())) {
-      // Parameter variables are never constants.  Without this check,
-      // getAnyInitializer() can find a default argument, which leads
-      // to chaos.
-      if (isa<ParmVarDecl>(D))
-        return ICEDiag(IK_NotICE, cast<DeclRefExpr>(E)->getLocation());
-
-      // C++ 7.1.5.1p2
-      //   A variable of non-volatile const-qualified integral or enumeration
-      //   type initialized by an ICE can be used in ICEs.
-      if (const VarDecl *Dcl = dyn_cast<VarDecl>(D)) {
-        if (!Dcl->getType()->isIntegralOrEnumerationType())
-          return ICEDiag(IK_NotICE, cast<DeclRefExpr>(E)->getLocation());
-
-        const VarDecl *VD;
-        // Look for a declaration of this variable that has an initializer, and
-        // check whether it is an ICE.
-        if (Dcl->getAnyInitializer(VD) && VD->checkInitIsICE())
-          return NoDiag();
-        else
-          return ICEDiag(IK_NotICE, cast<DeclRefExpr>(E)->getLocation());
-      }
-    }
-    return ICEDiag(IK_NotICE, E->getBeginLoc());
-  }
-  case Expr::UnaryOperatorClass: {
-    const UnaryOperator *Exp = cast<UnaryOperator>(E);
-    switch (Exp->getOpcode()) {
-    case UO_PostInc:
-    case UO_PostDec:
-    case UO_PreInc:
-    case UO_PreDec:
-    case UO_AddrOf:
-    case UO_Deref:
-    case UO_Coawait:
-      // C99 6.6/3 allows increment and decrement within unevaluated
-      // subexpressions of constant expressions, but they can never be ICEs
-      // because an ICE cannot contain an lvalue operand.
-      return ICEDiag(IK_NotICE, E->getBeginLoc());
-    case UO_Extension:
-    case UO_LNot:
-    case UO_Plus:
-    case UO_Minus:
-    case UO_Not:
-    case UO_Real:
-    case UO_Imag:
-      return CheckICE(Exp->getSubExpr(), Ctx);
-    }
-    llvm_unreachable("invalid unary operator class");
-  }
-  case Expr::OffsetOfExprClass: {
-    // Note that per C99, offsetof must be an ICE. And AFAIK, using
-    // EvaluateAsRValue matches the proposed gcc behavior for cases like
-    // "offsetof(struct s{int x[4];}, x[1.0])".  This doesn't affect
-    // compliance: we should warn earlier for offsetof expressions with
-    // array subscripts that aren't ICEs, and if the array subscripts
-    // are ICEs, the value of the offsetof must be an integer constant.
-    return CheckEvalInICE(E, Ctx);
-  }
-  case Expr::UnaryExprOrTypeTraitExprClass: {
-    const UnaryExprOrTypeTraitExpr *Exp = cast<UnaryExprOrTypeTraitExpr>(E);
-    if ((Exp->getKind() ==  UETT_SizeOf) &&
-        Exp->getTypeOfArgument()->isVariableArrayType())
-      return ICEDiag(IK_NotICE, E->getBeginLoc());
-    return NoDiag();
-  }
-  case Expr::BinaryOperatorClass: {
-    const BinaryOperator *Exp = cast<BinaryOperator>(E);
-    switch (Exp->getOpcode()) {
-    case BO_PtrMemD:
-    case BO_PtrMemI:
-    case BO_Assign:
-    case BO_MulAssign:
-    case BO_DivAssign:
-    case BO_RemAssign:
-    case BO_AddAssign:
-    case BO_SubAssign:
-    case BO_ShlAssign:
-    case BO_ShrAssign:
-    case BO_AndAssign:
-    case BO_XorAssign:
-    case BO_OrAssign:
-      // C99 6.6/3 allows assignments within unevaluated subexpressions of
-      // constant expressions, but they can never be ICEs because an ICE cannot
-      // contain an lvalue operand.
-      return ICEDiag(IK_NotICE, E->getBeginLoc());
-
-    case BO_Mul:
-    case BO_Div:
-    case BO_Rem:
-    case BO_Add:
-    case BO_Sub:
-    case BO_Shl:
-    case BO_Shr:
-    case BO_LT:
-    case BO_GT:
-    case BO_LE:
-    case BO_GE:
-    case BO_EQ:
-    case BO_NE:
-    case BO_And:
-    case BO_Xor:
-    case BO_Or:
-    case BO_Comma:
-    case BO_Cmp: {
-      ICEDiag LHSResult = CheckICE(Exp->getLHS(), Ctx);
-      ICEDiag RHSResult = CheckICE(Exp->getRHS(), Ctx);
-      if (Exp->getOpcode() == BO_Div ||
-          Exp->getOpcode() == BO_Rem) {
-        // EvaluateAsRValue gives an error for undefined Div/Rem, so make sure
-        // we don't evaluate one.
-        if (LHSResult.Kind == IK_ICE && RHSResult.Kind == IK_ICE) {
-          llvm::APSInt REval = Exp->getRHS()->EvaluateKnownConstInt(Ctx);
-          if (REval == 0)
-            return ICEDiag(IK_ICEIfUnevaluated, E->getBeginLoc());
-          if (REval.isSigned() && REval.isAllOnesValue()) {
-            llvm::APSInt LEval = Exp->getLHS()->EvaluateKnownConstInt(Ctx);
-            if (LEval.isMinSignedValue())
-              return ICEDiag(IK_ICEIfUnevaluated, E->getBeginLoc());
-          }
-        }
-      }
-      if (Exp->getOpcode() == BO_Comma) {
-        if (Ctx.getLangOpts().C99) {
-          // C99 6.6p3 introduces a strange edge case: comma can be in an ICE
-          // if it isn't evaluated.
-          if (LHSResult.Kind == IK_ICE && RHSResult.Kind == IK_ICE)
-            return ICEDiag(IK_ICEIfUnevaluated, E->getBeginLoc());
-        } else {
-          // In both C89 and C++, commas in ICEs are illegal.
-          return ICEDiag(IK_NotICE, E->getBeginLoc());
-        }
-      }
-      return Worst(LHSResult, RHSResult);
-    }
-    case BO_LAnd:
-    case BO_LOr: {
-      ICEDiag LHSResult = CheckICE(Exp->getLHS(), Ctx);
-      ICEDiag RHSResult = CheckICE(Exp->getRHS(), Ctx);
-      if (LHSResult.Kind == IK_ICE && RHSResult.Kind == IK_ICEIfUnevaluated) {
-        // Rare case where the RHS has a comma "side-effect"; we need
-        // to actually check the condition to see whether the side
-        // with the comma is evaluated.
-        if ((Exp->getOpcode() == BO_LAnd) !=
-            (Exp->getLHS()->EvaluateKnownConstInt(Ctx) == 0))
-          return RHSResult;
-        return NoDiag();
-      }
-
-      return Worst(LHSResult, RHSResult);
-    }
-    }
-    llvm_unreachable("invalid binary operator kind");
-  }
-  case Expr::ImplicitCastExprClass:
-  case Expr::CStyleCastExprClass:
-  case Expr::CXXFunctionalCastExprClass:
-  case Expr::CXXStaticCastExprClass:
-  case Expr::CXXReinterpretCastExprClass:
-  case Expr::CXXConstCastExprClass:
-  case Expr::ObjCBridgedCastExprClass: {
-    const Expr *SubExpr = cast<CastExpr>(E)->getSubExpr();
-    if (isa<ExplicitCastExpr>(E)) {
-      if (const FloatingLiteral *FL
-            = dyn_cast<FloatingLiteral>(SubExpr->IgnoreParenImpCasts())) {
-        unsigned DestWidth = Ctx.getIntWidth(E->getType());
-        bool DestSigned = E->getType()->isSignedIntegerOrEnumerationType();
-        APSInt IgnoredVal(DestWidth, !DestSigned);
-        bool Ignored;
-        // If the value does not fit in the destination type, the behavior is
-        // undefined, so we are not required to treat it as a constant
-        // expression.
-        if (FL->getValue().convertToInteger(IgnoredVal,
-                                            llvm::APFloat::rmTowardZero,
-                                            &Ignored) & APFloat::opInvalidOp)
-          return ICEDiag(IK_NotICE, E->getBeginLoc());
-        return NoDiag();
-      }
-    }
-    switch (cast<CastExpr>(E)->getCastKind()) {
-    case CK_LValueToRValue:
-    case CK_AtomicToNonAtomic:
-    case CK_NonAtomicToAtomic:
-    case CK_NoOp:
-    case CK_IntegralToBoolean:
-    case CK_IntegralCast:
-      return CheckICE(SubExpr, Ctx);
-    default:
-      return ICEDiag(IK_NotICE, E->getBeginLoc());
-    }
-  }
-  case Expr::BinaryConditionalOperatorClass: {
-    const BinaryConditionalOperator *Exp = cast<BinaryConditionalOperator>(E);
-    ICEDiag CommonResult = CheckICE(Exp->getCommon(), Ctx);
-    if (CommonResult.Kind == IK_NotICE) return CommonResult;
-    ICEDiag FalseResult = CheckICE(Exp->getFalseExpr(), Ctx);
-    if (FalseResult.Kind == IK_NotICE) return FalseResult;
-    if (CommonResult.Kind == IK_ICEIfUnevaluated) return CommonResult;
-    if (FalseResult.Kind == IK_ICEIfUnevaluated &&
-        Exp->getCommon()->EvaluateKnownConstInt(Ctx) != 0) return NoDiag();
-    return FalseResult;
-  }
-  case Expr::ConditionalOperatorClass: {
-    const ConditionalOperator *Exp = cast<ConditionalOperator>(E);
-    // If the condition (ignoring parens) is a __builtin_constant_p call,
-    // then only the true side is actually considered in an integer constant
-    // expression, and it is fully evaluated.  This is an important GNU
-    // extension.  See GCC PR38377 for discussion.
-    if (const CallExpr *CallCE
-        = dyn_cast<CallExpr>(Exp->getCond()->IgnoreParenCasts()))
-      if (CallCE->getBuiltinCallee() == Builtin::BI__builtin_constant_p)
-        return CheckEvalInICE(E, Ctx);
-    ICEDiag CondResult = CheckICE(Exp->getCond(), Ctx);
-    if (CondResult.Kind == IK_NotICE)
-      return CondResult;
-
-    ICEDiag TrueResult = CheckICE(Exp->getTrueExpr(), Ctx);
-    ICEDiag FalseResult = CheckICE(Exp->getFalseExpr(), Ctx);
-
-    if (TrueResult.Kind == IK_NotICE)
-      return TrueResult;
-    if (FalseResult.Kind == IK_NotICE)
-      return FalseResult;
-    if (CondResult.Kind == IK_ICEIfUnevaluated)
-      return CondResult;
-    if (TrueResult.Kind == IK_ICE && FalseResult.Kind == IK_ICE)
-      return NoDiag();
-    // Rare case where the diagnostics depend on which side is evaluated
-    // Note that if we get here, CondResult is 0, and at least one of
-    // TrueResult and FalseResult is non-zero.
-    if (Exp->getCond()->EvaluateKnownConstInt(Ctx) == 0)
-      return FalseResult;
-    return TrueResult;
-  }
-  case Expr::CXXDefaultArgExprClass:
-    return CheckICE(cast<CXXDefaultArgExpr>(E)->getExpr(), Ctx);
-  case Expr::CXXDefaultInitExprClass:
-    return CheckICE(cast<CXXDefaultInitExpr>(E)->getExpr(), Ctx);
-  case Expr::ChooseExprClass: {
-    return CheckICE(cast<ChooseExpr>(E)->getChosenSubExpr(), Ctx);
-  }
-  }
-
-  llvm_unreachable("Invalid StmtClass!");
+  Expr::EvalStatus Status;
+  SmallVector<PartialDiagnosticAt, 8> Diags;
+  Status.Diag = &Diags;
+  EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantExpression);
+  return ICEChecker(Ctx, Info).Visit(E);
 }
 
 /// Evaluate an expression as a C++11 integral constant expression.
Index: lib/AST/Expr.cpp
===================================================================
--- lib/AST/Expr.cpp
+++ lib/AST/Expr.cpp
@@ -2585,8 +2585,8 @@
       E = NTTP->getReplacement();
       continue;
     }
-    if (ConstantExpr *CE = dyn_cast<ConstantExpr>(E)) {
-      E = CE->getSubExpr();
+    if (FullExpr *FE = dyn_cast<FullExpr>(E)) {
+      E = FE->getSubExpr();
       continue;
     }
     return E;
@@ -2610,8 +2610,8 @@
       E = NTTP->getReplacement();
       continue;
     }
-    if (ConstantExpr *CE = dyn_cast<ConstantExpr>(E)) {
-      E = CE->getSubExpr();
+    if (FullExpr *FE = dyn_cast<FullExpr>(E)) {
+      E = FE->getSubExpr();
       continue;
     }
     return E;
@@ -2639,8 +2639,8 @@
                                   = dyn_cast<SubstNonTypeTemplateParmExpr>(E)) {
       E = NTTP->getReplacement();
       continue;
-    } else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(E)) {
-      E = CE->getSubExpr();
+    } else if (FullExpr *FE = dyn_cast<FullExpr>(E)) {
+      E = FE->getSubExpr();
       continue;
     }
     break;
@@ -2683,8 +2683,8 @@
       E = NTTP->getReplacement();
       continue;
     }
-    if (ConstantExpr *CE = dyn_cast<ConstantExpr>(E)) {
-      E = CE->getSubExpr();
+    if (FullExpr *FE = dyn_cast<FullExpr>(E)) {
+      E = FE->getSubExpr();
       continue;
     }
     return E;
@@ -2911,6 +2911,10 @@
 
     break;
   }
+  case ConstantExprClass: {
+    const Expr *Exp = cast<ConstantExpr>(this)->getSubExpr();
+    return Exp->isConstantInitializer(Ctx, false, Culprit);
+  }
   case CompoundLiteralExprClass: {
     // This handles gcc's extension that allows global initializers like
     // "struct x {int x;} x = (struct x) {};".
Index: lib/AST/ASTImporter.cpp
===================================================================
--- lib/AST/ASTImporter.cpp
+++ lib/AST/ASTImporter.cpp
@@ -6375,7 +6375,7 @@
   Expr *ToSubExpr;
   std::tie(ToSubExpr) = *Imp;
 
-  return new (Importer.getToContext()) ConstantExpr(ToSubExpr);
+  return ConstantExpr::Create(Importer.getToContext(), ToSubExpr);
 }
 
 ExpectedStmt ASTNodeImporter::VisitParenExpr(ParenExpr *E) {
Index: include/clang/AST/Expr.h
===================================================================
--- include/clang/AST/Expr.h
+++ include/clang/AST/Expr.h
@@ -901,10 +901,16 @@
 
 /// ConstantExpr - An expression that occurs in a constant context.
 class ConstantExpr : public FullExpr {
-public:
   ConstantExpr(Expr *subexpr)
     : FullExpr(ConstantExprClass, subexpr) {}
 
+public:
+  static ConstantExpr *Create(const ASTContext &Context, Expr *E) {
+    if (ConstantExpr *CE = dyn_cast<ConstantExpr>(E))
+      return CE;
+    return new (Context) ConstantExpr(E);
+  }
+
   /// Build an empty constant expression wrapper.
   explicit ConstantExpr(EmptyShell Empty)
     : FullExpr(ConstantExprClass, Empty) {}
@@ -3070,8 +3076,8 @@
   while (true)
     if (ImplicitCastExpr *ice = dyn_cast<ImplicitCastExpr>(e))
       e = ice->getSubExpr();
-    else if (ConstantExpr *ce = dyn_cast<ConstantExpr>(e))
-      e = ce->getSubExpr();
+    else if (FullExpr *fe = dyn_cast<FullExpr>(e))
+      e = fe->getSubExpr();
     else
       break;
   return e;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to