[cfe-commits] r146289 - in /cfe/trunk: include/clang/AST/Expr.h include/clang/Basic/DiagnosticCommonKinds.td lib/AST/ExprConstant.cpp lib/Sema/SemaExpr.cpp test/Sema/i-c-e.c test/Sema/switch.c test/SemaCXX/constant-expression-cxx11.cpp

Richard Smith richard-llvm at metafoo.co.uk
Fri Dec 9 14:58:01 PST 2011


Author: rsmith
Date: Fri Dec  9 16:58:01 2011
New Revision: 146289

URL: http://llvm.org/viewvc/llvm-project?rev=146289&view=rev
Log:
C++11 constant expressions: Don't use CheckICE in C++11; instead, determine
whether an expression is a (core) constant expression as a side-effect of
evaluation. This takes us from accepting far too few expressions as ICEs to
accepting slightly too many -- fixes for the remaining cases are coming next.

The diagnostics produced when an expression is found to be non-constant are
currently quite poor (with generic wording but reasonable source locations),
and will be improved in subsequent commits.

Modified:
    cfe/trunk/include/clang/AST/Expr.h
    cfe/trunk/include/clang/Basic/DiagnosticCommonKinds.td
    cfe/trunk/lib/AST/ExprConstant.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/test/Sema/i-c-e.c
    cfe/trunk/test/Sema/switch.c
    cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp

Modified: cfe/trunk/include/clang/AST/Expr.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Expr.h?rev=146289&r1=146288&r2=146289&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Expr.h (original)
+++ cfe/trunk/include/clang/AST/Expr.h Fri Dec  9 16:58:01 2011
@@ -417,10 +417,7 @@
   bool isIntegerConstantExpr(llvm::APSInt &Result, ASTContext &Ctx,
                              SourceLocation *Loc = 0,
                              bool isEvaluated = true) const;
-  bool isIntegerConstantExpr(ASTContext &Ctx, SourceLocation *Loc = 0) const {
-    llvm::APSInt X;
-    return isIntegerConstantExpr(X, Ctx, Loc);
-  }
+  bool isIntegerConstantExpr(ASTContext &Ctx, SourceLocation *Loc = 0) const;
 
   /// isConstantInitializer - Returns true if this expression can be emitted to
   /// IR as a constant, and thus can be used as a constant initializer in C.
@@ -432,14 +429,14 @@
     /// For example, (f() && 0) can be folded, but it still has side effects.
     bool HasSideEffects;
 
-    /// Diag - If the expression is unfoldable, then Diag contains a note
+    /// Diag - If the expression is unfoldable, then Diag may contain a note
     /// diagnostic indicating why it's not foldable. DiagLoc indicates a caret
     /// position for the error, and DiagExpr is the expression that caused
     /// the error.
-    /// If the expression is foldable, but not an integer constant expression,
-    /// Diag contains a note diagnostic that describes why it isn't an integer
-    /// constant expression. If the expression *is* an integer constant
-    /// expression, then Diag will be zero.
+    /// If the expression is foldable, but not a constant expression, Diag
+    /// may contain a note diagnostic that describes why it isn't a constant
+    /// expression. If the expression *is* a constant expression, then Diag
+    /// will be zero.
     unsigned Diag;
     const Expr *DiagExpr;
     SourceLocation DiagLoc;

Modified: cfe/trunk/include/clang/Basic/DiagnosticCommonKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticCommonKinds.td?rev=146289&r1=146288&r2=146289&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticCommonKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticCommonKinds.td Fri Dec  9 16:58:01 2011
@@ -83,8 +83,8 @@
   "integer constant is so large that it is unsigned">;
 
 // Sema && AST
-def note_invalid_subexpr_in_ice : Note<
-  "subexpression not valid in an integer constant expression">;
+def note_invalid_subexpr_in_const_expr : Note<
+  "subexpression not valid in a constant expression">;
 
 // Targets
 

Modified: cfe/trunk/lib/AST/ExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=146289&r1=146288&r2=146289&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprConstant.cpp (original)
+++ cfe/trunk/lib/AST/ExprConstant.cpp Fri Dec  9 16:58:01 2011
@@ -298,6 +298,27 @@
     bool atCallLimit() const {
       return CallStackDepth > getLangOpts().ConstexprCallDepth;
     }
+
+    /// Diagnose that the evaluation does not produce a C++11 core constant
+    /// expression.
+    void CCEDiag(const Expr *E, SourceLocation Loc, diag::kind Diag) {
+      // Don't override a previous diagnostic.
+      if (EvalStatus.Diag == 0) {
+        EvalStatus.DiagLoc = Loc;
+        EvalStatus.Diag = Diag;
+        EvalStatus.DiagExpr = E;
+      }
+    }
+
+    /// Diagnose that the evaluation cannot be folded.
+    void Diag(const Expr *E, SourceLocation Loc, diag::kind Diag) {
+      // If we have a prior diagnostic, it will be noting that the expression
+      // isn't a constant expression. This diagnostic is more important.
+      // FIXME: We might want to show both diagnostics to the user.
+      EvalStatus.DiagLoc = Loc;
+      EvalStatus.Diag = Diag;
+      EvalStatus.DiagExpr = E;
+    }
   };
 
   CallStackFrame::CallStackFrame(EvalInfo &Info, const LValue *This,
@@ -543,9 +564,12 @@
 /// Check that this reference or pointer core constant expression is a valid
 /// value for a constant expression. Type T should be either LValue or CCValue.
 template<typename T>
-static bool CheckLValueConstantExpression(const T &LVal, APValue &Value) {
-  if (!IsGlobalLValue(LVal.getLValueBase()))
+static bool CheckLValueConstantExpression(EvalInfo &Info, const Expr *E,
+                                          const T &LVal, APValue &Value) {
+  if (!IsGlobalLValue(LVal.getLValueBase())) {
+    Info.Diag(E, E->getExprLoc(), diag::note_invalid_subexpr_in_const_expr);
     return false;
+  }
 
   const SubobjectDesignator &Designator = LVal.getLValueDesignator();
   // A constant expression must refer to an object or be a null pointer.
@@ -564,12 +588,14 @@
 
 /// Check that this core constant expression value is a valid value for a
 /// constant expression, and if it is, produce the corresponding constant value.
-static bool CheckConstantExpression(const CCValue &CCValue, APValue &Value) {
+/// If not, report an appropriate diagnostic.
+static bool CheckConstantExpression(EvalInfo &Info, const Expr *E,
+                                    const CCValue &CCValue, APValue &Value) {
   if (!CCValue.isLValue()) {
     Value = CCValue;
     return true;
   }
-  return CheckLValueConstantExpression(CCValue, Value);
+  return CheckLValueConstantExpression(Info, E, CCValue, Value);
 }
 
 const ValueDecl *GetLValueBaseDecl(const LValue &LVal) {
@@ -840,13 +866,16 @@
 }
 
 /// Try to evaluate the initializer for a variable declaration.
-static bool EvaluateVarDeclInit(EvalInfo &Info, const VarDecl *VD,
+static bool EvaluateVarDeclInit(EvalInfo &Info, const Expr *E,
+                                const VarDecl *VD,
                                 CallStackFrame *Frame, CCValue &Result) {
   // If this is a parameter to an active constexpr function call, perform
   // argument substitution.
   if (const ParmVarDecl *PVD = dyn_cast<ParmVarDecl>(VD)) {
-    if (!Frame || !Frame->Arguments)
+    if (!Frame || !Frame->Arguments) {
+      Info.Diag(E, E->getExprLoc(), diag::note_invalid_subexpr_in_const_expr);
       return false;
+    }
     Result = Frame->Arguments[PVD->getFunctionScopeIndex()];
     return true;
   }
@@ -860,20 +889,26 @@
 
   // Never evaluate the initializer of a weak variable. We can't be sure that
   // this is the definition which will be used.
-  if (VD->isWeak())
+  if (VD->isWeak()) {
+    Info.Diag(E, E->getExprLoc(), diag::note_invalid_subexpr_in_const_expr);
     return false;
+  }
 
   const Expr *Init = VD->getAnyInitializer();
-  if (!Init || Init->isValueDependent())
+  if (!Init || Init->isValueDependent()) {
+    Info.Diag(E, E->getExprLoc(), diag::note_invalid_subexpr_in_const_expr);
     return false;
+  }
 
   if (APValue *V = VD->getEvaluatedValue()) {
     Result = CCValue(*V, CCValue::GlobalValue());
     return !Result.isUninit();
   }
 
-  if (VD->isEvaluatingValue())
+  if (VD->isEvaluatingValue()) {
+    Info.Diag(E, E->getExprLoc(), diag::note_invalid_subexpr_in_const_expr);
     return false;
+  }
 
   VD->setEvaluatingValue();
 
@@ -894,6 +929,7 @@
     // or a failed evaluation of the initializer should be reattempted each time
     // it is used.
     VD->setEvaluatedValue(APValue());
+    Info.Diag(E, E->getExprLoc(), diag::note_invalid_subexpr_in_const_expr);
     return false;
   }
 
@@ -923,10 +959,13 @@
 }
 
 /// Extract the designated sub-object of an rvalue.
-static bool ExtractSubobject(EvalInfo &Info, CCValue &Obj, QualType ObjType,
+static bool ExtractSubobject(EvalInfo &Info, const Expr *E,
+                             CCValue &Obj, QualType ObjType,
                              const SubobjectDesignator &Sub, QualType SubType) {
-  if (Sub.Invalid || Sub.OnePastTheEnd)
+  if (Sub.Invalid || Sub.OnePastTheEnd) {
+    Info.Diag(E, E->getExprLoc(), diag::note_invalid_subexpr_in_const_expr);
     return false;
+  }
   if (Sub.Entries.empty())
     return true;
 
@@ -937,11 +976,12 @@
     if (ObjType->isArrayType()) {
       // Next subobject is an array element.
       const ConstantArrayType *CAT = Info.Ctx.getAsConstantArrayType(ObjType);
-      if (!CAT)
-        return false;
+      assert(CAT && "vla in literal type?");
       uint64_t Index = Sub.Entries[I].ArrayIndex;
-      if (CAT->getSize().ule(Index))
+      if (CAT->getSize().ule(Index)) {
+        Info.Diag(E, E->getExprLoc(), diag::note_invalid_subexpr_in_const_expr);
         return false;
+      }
       if (O->getArrayInitializedElts() > Index)
         O = &O->getArrayInitializedElt(Index);
       else
@@ -953,8 +993,11 @@
       if (RD->isUnion()) {
         const FieldDecl *UnionField = O->getUnionField();
         if (!UnionField ||
-            UnionField->getCanonicalDecl() != Field->getCanonicalDecl())
+            UnionField->getCanonicalDecl() != Field->getCanonicalDecl()) {
+          Info.Diag(E, E->getExprLoc(),
+                    diag::note_invalid_subexpr_in_const_expr);
           return false;
+        }
         O = &O->getUnionValue();
       } else
         O = &O->getStructField(Field->getFieldIndex());
@@ -967,8 +1010,10 @@
       ObjType = Info.Ctx.getRecordType(Base);
     }
 
-    if (O->isUninit())
+    if (O->isUninit()) {
+      Info.Diag(E, E->getExprLoc(), diag::note_invalid_subexpr_in_const_expr);
       return false;
+    }
   }
 
   Obj = CCValue(*O, CCValue::GlobalValue());
@@ -980,17 +1025,23 @@
 /// for looking up the glvalue referred to by an entity of reference type.
 ///
 /// \param Info - Information about the ongoing evaluation.
+/// \param Conv - The expression for which we are performing the conversion.
+///               Used for diagnostics.
 /// \param Type - The type we expect this conversion to produce.
 /// \param LVal - The glvalue on which we are attempting to perform this action.
 /// \param RVal - The produced value will be placed here.
-static bool HandleLValueToRValueConversion(EvalInfo &Info, QualType Type,
+static bool HandleLValueToRValueConversion(EvalInfo &Info, const Expr *Conv,
+                                           QualType Type,
                                            const LValue &LVal, CCValue &RVal) {
   const Expr *Base = LVal.Base.dyn_cast<const Expr*>();
   CallStackFrame *Frame = LVal.Frame;
 
-  // FIXME: Indirection through a null pointer deserves a diagnostic.
-  if (!LVal.Base)
+  if (!LVal.Base) {
+    // FIXME: Indirection through a null pointer deserves a specific diagnostic.
+    Info.Diag(Conv, Conv->getExprLoc(),
+              diag::note_invalid_subexpr_in_const_expr);
     return false;
+  }
 
   if (const ValueDecl *D = LVal.Base.dyn_cast<const ValueDecl*>()) {
     // In C++98, const, non-volatile integers initialized with ICEs are ICEs.
@@ -1005,22 +1056,32 @@
     // objects in constant expressions), but lvalue-to-rvalue conversions on
     // them are not permitted.
     const VarDecl *VD = dyn_cast<VarDecl>(D);
-    if (!VD || VD->isInvalidDecl())
+    if (!VD || VD->isInvalidDecl()) {
+      Info.Diag(Conv, Conv->getExprLoc(),
+                diag::note_invalid_subexpr_in_const_expr);
       return false;
+    }
+
     QualType VT = VD->getType();
     if (!isa<ParmVarDecl>(VD)) {
-      if (!IsConstNonVolatile(VT))
+      if (!IsConstNonVolatile(VT)) {
+        Info.Diag(Conv, Conv->getExprLoc(),
+                  diag::note_invalid_subexpr_in_const_expr);
         return false;
+      }
       // FIXME: Allow folding of values of any literal type in all languages.
       if (!VT->isIntegralOrEnumerationType() && !VT->isRealFloatingType() &&
-          !VD->isConstexpr())
+          !VD->isConstexpr()) {
+        Info.Diag(Conv, Conv->getExprLoc(),
+                  diag::note_invalid_subexpr_in_const_expr);
         return false;
+      }
     }
-    if (!EvaluateVarDeclInit(Info, VD, Frame, RVal))
+    if (!EvaluateVarDeclInit(Info, Conv, VD, Frame, RVal))
       return false;
 
     if (isa<ParmVarDecl>(VD) || !VD->getAnyInitializer()->isLValue())
-      return ExtractSubobject(Info, RVal, VT, LVal.Designator, Type);
+      return ExtractSubobject(Info, Conv, RVal, VT, LVal.Designator, Type);
 
     // The declaration was initialized by an lvalue, with no lvalue-to-rvalue
     // conversion. This happens when the declaration and the lvalue should be
@@ -1036,13 +1097,19 @@
   // FIXME: Support PredefinedExpr, ObjCEncodeExpr, MakeStringConstant
   if (const StringLiteral *S = dyn_cast<StringLiteral>(Base)) {
     const SubobjectDesignator &Designator = LVal.Designator;
-    if (Designator.Invalid || Designator.Entries.size() != 1)
+    if (Designator.Invalid || Designator.Entries.size() != 1) {
+      Info.Diag(Conv, Conv->getExprLoc(),
+                diag::note_invalid_subexpr_in_const_expr);
       return false;
+    }
 
     assert(Type->isIntegerType() && "string element not integer type");
     uint64_t Index = Designator.Entries[0].ArrayIndex;
-    if (Index > S->getLength())
+    if (Index > S->getLength()) {
+      Info.Diag(Conv, Conv->getExprLoc(),
+                diag::note_invalid_subexpr_in_const_expr);
       return false;
+    }
     APSInt Value(S->getCharByteWidth() * Info.Ctx.getCharWidth(),
                  Type->isUnsignedIntegerType());
     if (Index < S->getLength())
@@ -1063,10 +1130,14 @@
     assert(!Info.getLangOpts().CPlusPlus && "lvalue compound literal in c++?");
     if (!Evaluate(RVal, Info, CLE->getInitializer()))
       return false;
-  } else
+  } else {
+    Info.Diag(Conv, Conv->getExprLoc(),
+              diag::note_invalid_subexpr_in_const_expr);
     return false;
+  }
 
-  return ExtractSubobject(Info, RVal, Base->getType(), LVal.Designator, Type);
+  return ExtractSubobject(Info, Conv, RVal, Base->getType(), LVal.Designator,
+                          Type);
 }
 
 /// Build an lvalue for the object argument of a member function call.
@@ -1270,11 +1341,15 @@
 }
 
 /// Evaluate a function call.
-static bool HandleFunctionCall(const LValue *This, ArrayRef<const Expr*> Args,
-                               const Stmt *Body, EvalInfo &Info,
-                               CCValue &Result) {
-  if (Info.atCallLimit())
+static bool HandleFunctionCall(const Expr *CallExpr, const LValue *This,
+                               ArrayRef<const Expr*> Args, const Stmt *Body,
+                               EvalInfo &Info, CCValue &Result) {
+  if (Info.atCallLimit()) {
+    // FIXME: Add a specific proper diagnostic for this.
+    Info.Diag(CallExpr, CallExpr->getExprLoc(),
+              diag::note_invalid_subexpr_in_const_expr);
     return false;
+  }
 
   ArgVector ArgValues(Args.size());
   if (!EvaluateArgs(Args, ArgValues, Info))
@@ -1285,13 +1360,17 @@
 }
 
 /// Evaluate a constructor call.
-static bool HandleConstructorCall(const LValue &This,
+static bool HandleConstructorCall(const Expr *CallExpr, const LValue &This,
                                   ArrayRef<const Expr*> Args,
                                   const CXXConstructorDecl *Definition,
                                   EvalInfo &Info,
                                   APValue &Result) {
-  if (Info.atCallLimit())
+  if (Info.atCallLimit()) {
+    // FIXME: Add a specific diagnostic for this.
+    Info.Diag(CallExpr, CallExpr->getExprLoc(),
+              diag::note_invalid_subexpr_in_const_expr);
     return false;
+  }
 
   ArgVector ArgValues(Args.size());
   if (!EvaluateArgs(Args, ArgValues, Info))
@@ -1349,6 +1428,8 @@
         return false;
     } else {
       // FIXME: handle indirect field initializers
+      Info.Diag((*I)->getInit(), (*I)->getInit()->getExprLoc(),
+                diag::note_invalid_subexpr_in_const_expr);
       return false;
     }
   }
@@ -1466,16 +1547,14 @@
 //===----------------------------------------------------------------------===//
 namespace {
 
-template <class Derived, typename RetTy=void>
+// FIXME: RetTy is always bool. Remove it.
+template <class Derived, typename RetTy=bool>
 class ExprEvaluatorBase
   : public ConstStmtVisitor<Derived, RetTy> {
 private:
   RetTy DerivedSuccess(const CCValue &V, const Expr *E) {
     return static_cast<Derived*>(this)->Success(V, E);
   }
-  RetTy DerivedError(const Expr *E) {
-    return static_cast<Derived*>(this)->Error(E);
-  }
   RetTy DerivedValueInitialization(const Expr *E) {
     return static_cast<Derived*>(this)->ValueInitialization(E);
   }
@@ -1485,7 +1564,21 @@
   typedef ConstStmtVisitor<Derived, RetTy> StmtVisitorTy;
   typedef ExprEvaluatorBase ExprEvaluatorBaseTy;
 
-  RetTy ValueInitialization(const Expr *E) { return DerivedError(E); }
+  void CCEDiag(const Expr *E, diag::kind D) {
+    Info.CCEDiag(E, E->getExprLoc(), D);
+  }
+
+  /// Report an evaluation error. This should only be called when an error is
+  /// first discovered. When propagating an error, just return false.
+  bool Error(const Expr *E, diag::kind D) {
+    Info.Diag(E, E->getExprLoc(), D);
+    return false;
+  }
+  bool Error(const Expr *E) {
+    return Error(E, diag::note_invalid_subexpr_in_const_expr);
+  }
+
+  RetTy ValueInitialization(const Expr *E) { return Error(E); }
 
 public:
   ExprEvaluatorBase(EvalInfo &Info) : Info(Info) {}
@@ -1494,7 +1587,7 @@
     llvm_unreachable("Expression evaluator should not be called on stmts");
   }
   RetTy VisitExpr(const Expr *E) {
-    return DerivedError(E);
+    return Error(E);
   }
 
   RetTy VisitParenExpr(const ParenExpr *E)
@@ -1515,7 +1608,7 @@
   RetTy VisitBinaryOperator(const BinaryOperator *E) {
     switch (E->getOpcode()) {
     default:
-      return DerivedError(E);
+      return Error(E);
 
     case BO_Comma:
       VisitIgnoredValue(E->getLHS());
@@ -1527,7 +1620,7 @@
       if (!HandleMemberPointerAccess(Info, E, Obj))
         return false;
       CCValue Result;
-      if (!HandleLValueToRValueConversion(Info, E->getType(), Obj, Result))
+      if (!HandleLValueToRValueConversion(Info, E, E->getType(), Obj, Result))
         return false;
       return DerivedSuccess(Result, E);
     }
@@ -1537,11 +1630,11 @@
   RetTy VisitBinaryConditionalOperator(const BinaryConditionalOperator *E) {
     OpaqueValueEvaluation opaque(Info, E->getOpaqueValue(), E->getCommon());
     if (opaque.hasError())
-      return DerivedError(E);
+      return false;
 
     bool cond;
     if (!EvaluateAsBooleanCondition(E->getCond(), cond, Info))
-      return DerivedError(E);
+      return false;
 
     return StmtVisitorTy::Visit(cond ? E->getTrueExpr() : E->getFalseExpr());
   }
@@ -1549,7 +1642,7 @@
   RetTy VisitConditionalOperator(const ConditionalOperator *E) {
     bool BoolResult;
     if (!EvaluateAsBooleanCondition(E->getCond(), BoolResult, Info))
-      return DerivedError(E);
+      return false;
 
     Expr *EvalExpr = BoolResult ? E->getTrueExpr() : E->getFalseExpr();
     return StmtVisitorTy::Visit(EvalExpr);
@@ -1560,10 +1653,10 @@
     if (!Value) {
       const Expr *Source = E->getSourceExpr();
       if (!Source)
-        return DerivedError(E);
+        return Error(E);
       if (Source == E) { // sanity checking.
         assert(0 && "OpaqueValueExpr recursively refers to itself");
-        return DerivedError(E);
+        return Error(E);
       }
       return StmtVisitorTy::Visit(Source);
     }
@@ -1580,39 +1673,46 @@
 
     // Extract function decl and 'this' pointer from the callee.
     if (CalleeType->isSpecificBuiltinType(BuiltinType::BoundMember)) {
+      const ValueDecl *Member = 0;
       if (const MemberExpr *ME = dyn_cast<MemberExpr>(Callee)) {
         // Explicit bound member calls, such as x.f() or p->g();
         if (!EvaluateObjectArgument(Info, ME->getBase(), ThisVal))
-          return DerivedError(ME->getBase());
+          return false;
+        Member = ME->getMemberDecl();
         This = &ThisVal;
-        FD = dyn_cast<FunctionDecl>(ME->getMemberDecl());
-        if (!FD)
-          return DerivedError(ME);
       } else if (const BinaryOperator *BE = dyn_cast<BinaryOperator>(Callee)) {
         // Indirect bound member calls ('.*' or '->*').
-        const ValueDecl *Member = HandleMemberPointerAccess(Info, BE, ThisVal,
-                                                            false);
+        Member = HandleMemberPointerAccess(Info, BE, ThisVal, false);
+        if (!Member) return false;
         This = &ThisVal;
-        FD = dyn_cast_or_null<FunctionDecl>(Member);
-        if (!FD)
-          return DerivedError(Callee);
       } else
-        return DerivedError(Callee);
+        return Error(Callee);
+
+      FD = dyn_cast<FunctionDecl>(Member);
+      if (!FD)
+        return Error(Callee);
     } else if (CalleeType->isFunctionPointerType()) {
       CCValue Call;
-      if (!Evaluate(Call, Info, Callee) || !Call.isLValue() ||
-          !Call.getLValueOffset().isZero())
-        return DerivedError(Callee);
+      if (!Evaluate(Call, Info, Callee))
+        return false;
 
+      if (!Call.isLValue() || !Call.getLValueOffset().isZero())
+        return Error(Callee);
       FD = dyn_cast_or_null<FunctionDecl>(
                              Call.getLValueBase().dyn_cast<const ValueDecl*>());
       if (!FD)
-        return DerivedError(Callee);
+        return Error(Callee);
 
       // Overloaded operator calls to member functions are represented as normal
       // calls with '*this' as the first argument.
       const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD);
       if (MD && !MD->isStatic()) {
+        // FIXME: When selecting an implicit conversion for an overloaded
+        // operator delete, we sometimes try to evaluate calls to conversion
+        // operators without a 'this' parameter!
+        if (Args.empty())
+          return Error(E);
+
         if (!EvaluateObjectArgument(Info, Args[0], ThisVal))
           return false;
         This = &ThisVal;
@@ -1621,21 +1721,23 @@
 
       // Don't call function pointers which have been cast to some other type.
       if (!Info.Ctx.hasSameType(CalleeType->getPointeeType(), FD->getType()))
-        return DerivedError(E);
+        return Error(E);
     } else
-      return DerivedError(E);
+      return Error(E);
 
     const FunctionDecl *Definition;
     Stmt *Body = FD->getBody(Definition);
     CCValue CCResult;
     APValue Result;
 
-    if (Body && Definition->isConstexpr() && !Definition->isInvalidDecl() &&
-        HandleFunctionCall(This, Args, Body, Info, CCResult) &&
-        CheckConstantExpression(CCResult, Result))
-      return DerivedSuccess(CCValue(Result, CCValue::GlobalValue()), E);
+    if (!Body || !Definition->isConstexpr() || Definition->isInvalidDecl())
+      return Error(E);
+
+    if (!HandleFunctionCall(E, This, Args, Body, Info, CCResult) ||
+        !CheckConstantExpression(Info, E, CCResult, Result))
+      return false;
 
-    return DerivedError(E);
+    return DerivedSuccess(CCValue(Result, CCValue::GlobalValue()), E);
   }
 
   RetTy VisitCompoundLiteralExpr(const CompoundLiteralExpr *E) {
@@ -1648,7 +1750,7 @@
       if (E->getNumInits() == 1)
         return StmtVisitorTy::Visit(E->getInit(0));
     }
-    return DerivedError(E);
+    return Error(E);
   }
   RetTy VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E) {
     return DerivedValueInitialization(E);
@@ -1671,7 +1773,7 @@
     QualType BaseTy = E->getBase()->getType();
 
     const FieldDecl *FD = dyn_cast<FieldDecl>(E->getMemberDecl());
-    if (!FD) return false;
+    if (!FD) return Error(E);
     assert(!FD->getType()->isReferenceType() && "prvalue reference?");
     assert(BaseTy->getAs<RecordType>()->getDecl()->getCanonicalDecl() ==
            FD->getParent()->getCanonicalDecl() && "record / field mismatch");
@@ -1679,7 +1781,7 @@
     SubobjectDesignator Designator;
     Designator.addDecl(FD);
 
-    return ExtractSubobject(Info, Val, BaseTy, Designator, E->getType()) &&
+    return ExtractSubobject(Info, E, Val, BaseTy, Designator, E->getType()) &&
            DerivedSuccess(Val, E);
   }
 
@@ -1693,16 +1795,16 @@
 
     case CK_LValueToRValue: {
       LValue LVal;
-      if (EvaluateLValue(E->getSubExpr(), LVal, Info)) {
-        CCValue RVal;
-        if (HandleLValueToRValueConversion(Info, E->getType(), LVal, RVal))
-          return DerivedSuccess(RVal, E);
-      }
-      break;
+      if (!EvaluateLValue(E->getSubExpr(), LVal, Info))
+        return false;
+      CCValue RVal;
+      if (!HandleLValueToRValueConversion(Info, E, E->getType(), LVal, RVal))
+        return false;
+      return DerivedSuccess(RVal, E);
     }
     }
 
-    return DerivedError(E);
+    return Error(E);
   }
 
   /// Visit a value which is evaluated, but whose value is ignored.
@@ -1740,9 +1842,6 @@
     Result.setFrom(V);
     return true;
   }
-  bool Error(const Expr *E) {
-    return false;
-  }
 
   bool CheckValidLValue() {
     // C++11 [basic.lval]p1: An lvalue designates a function or an object. Hence
@@ -1768,7 +1867,7 @@
 
     const FieldDecl *FD = dyn_cast<FieldDecl>(E->getMemberDecl());
     // FIXME: Handle IndirectFieldDecls
-    if (!FD) return false;
+    if (!FD) return this->Error(E);
     assert(BaseTy->getAs<RecordType>()->getDecl()->getCanonicalDecl() ==
            FD->getParent()->getCanonicalDecl() && "record / field mismatch");
     (void)BaseTy;
@@ -1777,7 +1876,7 @@
 
     if (FD->getType()->isReferenceType()) {
       CCValue RefValue;
-      if (!HandleLValueToRValueConversion(this->Info, FD->getType(), Result,
+      if (!HandleLValueToRValueConversion(this->Info, E, FD->getType(), Result,
                                           RefValue))
         return false;
       return Success(RefValue, E);
@@ -1927,10 +2026,9 @@
   }
 
   CCValue V;
-  if (EvaluateVarDeclInit(Info, VD, Info.CurrentCall, V))
-    return Success(V, E);
-
-  return Error(E);
+  if (!EvaluateVarDeclInit(Info, E, VD, Info.CurrentCall, V))
+    return false;
+  return Success(V, E);
 }
 
 bool LValueExprEvaluator::VisitMaterializeTemporaryExpr(
@@ -1949,7 +2047,7 @@
   // FIXME: The AST should contain an lvalue-to-rvalue node for such cases.
   if (!Visit(E->GetTemporaryExpr()))
     return false;
-  if (!HandleLValueToRValueConversion(Info, E->getType(), Result,
+  if (!HandleLValueToRValueConversion(Info, E, E->getType(), Result,
                                       Info.CurrentCall->Temporaries[E]))
     return false;
   Result.set(E, Info.CurrentCall);
@@ -1986,7 +2084,7 @@
 bool LValueExprEvaluator::VisitArraySubscriptExpr(const ArraySubscriptExpr *E) {
   // FIXME: Deal with vectors as array subscript bases.
   if (E->getBase()->getType()->isVectorType())
-    return false;
+    return Error(E);
 
   if (!EvaluatePointer(E->getBase(), Result, Info))
     return false;
@@ -2029,9 +2127,6 @@
     Result.setFrom(V);
     return true;
   }
-  bool Error(const Stmt *S) {
-    return false;
-  }
   bool ValueInitialization(const Expr *E) {
     return Success((Expr*)0);
   }
@@ -2047,11 +2142,11 @@
   bool VisitBlockExpr(const BlockExpr *E) {
     if (!E->getBlockDecl()->hasCaptures())
       return Success(E);
-    return false;
+    return Error(E);
   }
   bool VisitCXXThisExpr(const CXXThisExpr *E) {
     if (!Info.CurrentCall->This)
-      return false;
+      return Error(E);
     Result = *Info.CurrentCall->This;
     return true;
   }
@@ -2213,9 +2308,6 @@
     Result.setFrom(V);
     return true;
   }
-  bool Error(const Stmt *S) {
-    return false;
-  }
   bool ValueInitialization(const Expr *E) {
     return Success((const ValueDecl*)0);
   }
@@ -2253,11 +2345,11 @@
       assert(!(*PathI)->isVirtual() && "memptr cast through vbase");
       const CXXRecordDecl *Derived = (*PathI)->getType()->getAsCXXRecordDecl();
       if (!Result.castToDerived(Derived))
-        return false;
+        return Error(E);
     }
     const Type *FinalTy = E->getType()->castAs<MemberPointerType>()->getClass();
     if (!Result.castToDerived(FinalTy->getAsCXXRecordDecl()))
-      return false;
+      return Error(E);
     return true;
   }
 
@@ -2269,7 +2361,7 @@
       assert(!(*PathI)->isVirtual() && "memptr cast through vbase");
       const CXXRecordDecl *Base = (*PathI)->getType()->getAsCXXRecordDecl();
       if (!Result.castToBase(Base))
-        return false;
+        return Error(E);
     }
     return true;
   }
@@ -2296,9 +2388,8 @@
       : ExprEvaluatorBaseTy(info), This(This), Result(Result) {}
 
     bool Success(const CCValue &V, const Expr *E) {
-      return CheckConstantExpression(V, Result);
+      return CheckConstantExpression(Info, E, V, Result);
     }
-    bool Error(const Expr *E) { return false; }
 
     bool VisitCastExpr(const CastExpr *E);
     bool VisitInitListExpr(const InitListExpr *E);
@@ -2317,9 +2408,10 @@
   case CK_DerivedToBase:
   case CK_UncheckedDerivedToBase: {
     CCValue DerivedObject;
-    if (!Evaluate(DerivedObject, Info, E->getSubExpr()) ||
-        !DerivedObject.isStruct())
+    if (!Evaluate(DerivedObject, Info, E->getSubExpr()))
       return false;
+    if (!DerivedObject.isStruct())
+      return Error(E->getSubExpr());
 
     // Derived-to-base rvalue conversion: just slice off the derived part.
     APValue *Value = &DerivedObject;
@@ -2392,7 +2484,7 @@
   FD->getBody(Definition);
 
   if (!Definition || !Definition->isConstexpr() || Definition->isInvalidDecl())
-    return false;
+    return Error(E);
 
   // FIXME: Elide the copy/move construction wherever we can.
   if (E->isElidable())
@@ -2401,8 +2493,9 @@
       return Visit(ME->GetTemporaryExpr());
 
   llvm::ArrayRef<const Expr*> Args(E->getArgs(), E->getNumArgs());
-  return HandleConstructorCall(This, Args, cast<CXXConstructorDecl>(Definition),
-                               Info, Result);
+  return HandleConstructorCall(E, This, Args,
+                               cast<CXXConstructorDecl>(Definition), Info,
+                               Result);
 }
 
 static bool EvaluateRecord(const Expr *E, const LValue &This,
@@ -2486,7 +2579,6 @@
       Result = V;
       return true;
     }
-    bool Error(const Expr *E) { return false; }
     bool ValueInitialization(const Expr *E);
 
     bool VisitUnaryReal(const UnaryOperator *E)
@@ -2520,12 +2612,12 @@
     if (SETy->isIntegerType()) {
       APSInt IntResult;
       if (!EvaluateInteger(SE, IntResult, Info))
-         return Error(E);
+         return false;
       Val = APValue(IntResult);
     } else if (SETy->isRealFloatingType()) {
        APFloat F(0.0);
        if (!EvaluateFloat(SE, F, Info))
-         return Error(E);
+         return false;
        Val = APValue(F);
     } else {
       return Error(E);
@@ -2563,12 +2655,12 @@
     if (EltTy->isIntegerType()) {
       llvm::APSInt sInt(32);
       if (!EvaluateInteger(E->getInit(0), sInt, Info))
-        return Error(E);
+        return false;
       InitValue = APValue(sInt);
     } else {
       llvm::APFloat f(0.0);
       if (!EvaluateFloat(E->getInit(0), f, Info))
-        return Error(E);
+        return false;
       InitValue = APValue(f);
     }
     for (unsigned i = 0; i < NumElements; i++) {
@@ -2580,7 +2672,7 @@
         llvm::APSInt sInt(32);
         if (i < NumInits) {
           if (!EvaluateInteger(E->getInit(i), sInt, Info))
-            return Error(E);
+            return false;
         } else {
           sInt = Info.Ctx.MakeIntValue(0, EltTy);
         }
@@ -2589,7 +2681,7 @@
         llvm::APFloat f(0.0);
         if (i < NumInits) {
           if (!EvaluateFloat(E->getInit(i), f, Info))
-            return Error(E);
+            return false;
         } else {
           f = APFloat::getZero(Info.Ctx.getFloatTypeSemantics(EltTy));
         }
@@ -2639,13 +2731,12 @@
       Result = V;
       return true;
     }
-    bool Error(const Expr *E) { return false; }
 
     bool ValueInitialization(const Expr *E) {
       const ConstantArrayType *CAT =
           Info.Ctx.getAsConstantArrayType(E->getType());
       if (!CAT)
-        return false;
+        return Error(E);
 
       Result = APValue(APValue::UninitArray(), 0,
                        CAT->getSize().getZExtValue());
@@ -2674,7 +2765,7 @@
 bool ArrayExprEvaluator::VisitInitListExpr(const InitListExpr *E) {
   const ConstantArrayType *CAT = Info.Ctx.getAsConstantArrayType(E->getType());
   if (!CAT)
-    return false;
+    return Error(E);
 
   Result = APValue(APValue::UninitArray(), E->getNumInits(),
                    CAT->getSize().getZExtValue());
@@ -2703,7 +2794,7 @@
 bool ArrayExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E) {
   const ConstantArrayType *CAT = Info.Ctx.getAsConstantArrayType(E->getType());
   if (!CAT)
-    return false;
+    return Error(E);
 
   Result = APValue(APValue::UninitArray(), 0, CAT->getSize().getZExtValue());
   if (!Result.hasArrayFiller())
@@ -2714,7 +2805,7 @@
   FD->getBody(Definition);
 
   if (!Definition || !Definition->isConstexpr() || Definition->isInvalidDecl())
-    return false;
+    return Error(E);
 
   // FIXME: The Subobject here isn't necessarily right. This rarely matters,
   // but sometimes does:
@@ -2723,7 +2814,7 @@
   LValue Subobject = This;
   Subobject.Designator.addIndex(0);
   llvm::ArrayRef<const Expr*> Args(E->getArgs(), E->getNumArgs());
-  return HandleConstructorCall(Subobject, Args,
+  return HandleConstructorCall(E, Subobject, Args,
                                cast<CXXConstructorDecl>(Definition),
                                Info, Result.getArrayFiller());
 }
@@ -2777,17 +2868,6 @@
     return Success(Size.getQuantity(), E);
   }
 
-
-  bool Error(SourceLocation L, diag::kind D, const Expr *E) {
-    // Take the first error.
-    if (Info.EvalStatus.Diag == 0) {
-      Info.EvalStatus.DiagLoc = L;
-      Info.EvalStatus.Diag = D;
-      Info.EvalStatus.DiagExpr = E;
-    }
-    return false;
-  }
-
   bool Success(const CCValue &V, const Expr *E) {
     if (V.isLValue()) {
       Result = V;
@@ -2795,9 +2875,6 @@
     }
     return Success(V.getInt(), E);
   }
-  bool Error(const Expr *E) {
-    return Error(E->getLocStart(), diag::note_invalid_subexpr_in_ice, E);
-  }
 
   bool ValueInitialization(const Expr *E) { return Success(0, E); }
 
@@ -2884,20 +2961,29 @@
 /// an integer rvalue to produce a pointer (represented as an lvalue) instead.
 /// Some simple arithmetic on such values is supported (they are treated much
 /// like char*).
-static bool EvaluateIntegerOrLValue(const Expr* E, CCValue &Result,
+static bool EvaluateIntegerOrLValue(const Expr *E, CCValue &Result,
                                     EvalInfo &Info) {
   assert(E->isRValue() && E->getType()->isIntegralOrEnumerationType());
   return IntExprEvaluator(Info, Result).Visit(E);
 }
 
-static bool EvaluateInteger(const Expr* E, APSInt &Result, EvalInfo &Info) {
+static bool EvaluateInteger(const Expr *E, APSInt &Result, EvalInfo &Info) {
   CCValue Val;
-  if (!EvaluateIntegerOrLValue(E, Val, Info) || !Val.isInt())
+  if (!EvaluateIntegerOrLValue(E, Val, Info))
+    return false;
+  if (!Val.isInt()) {
+    // FIXME: It would be better to produce the diagnostic for casting
+    //        a pointer to an integer.
+    Info.Diag(E, E->getExprLoc(), diag::note_invalid_subexpr_in_const_expr);
     return false;
+  }
   Result = Val.getInt();
   return true;
 }
 
+/// Check whether the given declaration can be directly converted to an integral
+/// rvalue. If not, no diagnostic is produced; there are other things we can
+/// try.
 bool IntExprEvaluator::CheckReferencedDecl(const Expr* E, const Decl* D) {
   // Enums are integer constant exprs.
   if (const EnumConstantDecl *ECD = dyn_cast<EnumConstantDecl>(D)) {
@@ -3007,7 +3093,7 @@
       T->isFunctionType() ||
       T->isVariablyModifiedType() ||
       T->isDependentType())
-    return false;
+    return Error(E);
 
   CharUnits Size = Info.Ctx.getTypeSizeInChars(T);
   CharUnits Offset = Base.getLValueOffset();
@@ -3036,7 +3122,7 @@
       return Success(0, E);
     }
 
-    return Error(E->getLocStart(), diag::note_invalid_subexpr_in_ice, E);
+    return Error(E);
   }
 
   case Builtin::BI__builtin_classify_type:
@@ -3114,7 +3200,7 @@
       return Success(Str.size(), E);
     }
       
-    return Error(E->getLocStart(), diag::note_invalid_subexpr_in_ice, E);
+    return Error(E);
 
   case Builtin::BI__atomic_is_lock_free: {
     APSInt SizeVal;
@@ -3138,7 +3224,7 @@
       // settles.
       return Success(0, E);
 #else
-      return Error(E->getLocStart(), diag::note_invalid_subexpr_in_ice, E);
+      return Error(E);
 #endif
 
 #if 0
@@ -3157,7 +3243,7 @@
     if (Size <= Info.Ctx.toCharUnitsFromBits(InlineWidthBits))
       return Success(1, E);
 
-    return Error(E->getLocStart(), diag::note_invalid_subexpr_in_ice, E);
+    return Error(E);
   }
   }
 }
@@ -3184,7 +3270,7 @@
 
 bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
   if (E->isAssignmentOp())
-    return Error(E->getOperatorLoc(), diag::note_invalid_subexpr_in_ice, E);
+    return Error(E);
 
   if (E->getOpcode() == BO_Comma) {
     VisitIgnoredValue(E->getLHS());
@@ -3209,11 +3295,13 @@
           return Success(lhsResult && rhsResult, E);
       }
     } else {
+      // FIXME: If both evaluations fail, we should produce the diagnostic from
+      // the LHS. If the LHS is non-constant and the RHS is unevaluatable, it's
+      // less clear how to diagnose this.
       if (EvaluateAsBooleanCondition(E->getRHS(), rhsResult, Info)) {
         // We can't evaluate the LHS; however, sometimes the result
         // is determined by the RHS: X && 0 -> 0, X || 1 -> 1.
-        if (rhsResult == (E->getOpcode() == BO_LOr) ||
-            !rhsResult == (E->getOpcode() == BO_LAnd)) {
+        if (rhsResult == (E->getOpcode() == BO_LOr)) {
           // Since we weren't able to evaluate the left hand side, it
           // must have had side effects.
           Info.EvalStatus.HasSideEffects = true;
@@ -3320,24 +3408,24 @@
         // Inequalities and subtractions between unrelated pointers have
         // unspecified or undefined behavior.
         if (!E->isEqualityOp())
-          return false;
+          return Error(E);
         // A constant address may compare equal to the address of a symbol.
         // The one exception is that address of an object cannot compare equal
         // to a null pointer constant.
         if ((!LHSValue.Base && !LHSValue.Offset.isZero()) ||
             (!RHSValue.Base && !RHSValue.Offset.isZero()))
-          return false;
+          return Error(E);
         // It's implementation-defined whether distinct literals will have
         // distinct addresses. In clang, we do not guarantee the addresses are
         // distinct. However, we do know that the address of a literal will be
         // non-null.
         if ((IsLiteralLValue(LHSValue) || IsLiteralLValue(RHSValue)) &&
             LHSValue.Base && RHSValue.Base)
-          return false;
+          return Error(E);
         // We can't tell whether weak symbols will end up pointing to the same
         // object.
         if (IsWeakLValue(LHSValue) || IsWeakLValue(RHSValue))
-          return false;
+          return Error(E);
         // Pointers with different bases cannot represent the same object.
         // (Note that clang defaults to -fmerge-all-constants, which can
         // lead to inconsistent results for comparisons involving the address
@@ -3384,7 +3472,7 @@
   // The LHS of a constant expr is always evaluated and needed.
   CCValue LHSVal;
   if (!EvaluateIntegerOrLValue(E->getLHS(), LHSVal, Info))
-    return false; // error in subexpression.
+    return false;
 
   if (!Visit(E->getRHS()))
     return false;
@@ -3413,14 +3501,14 @@
 
   // All the following cases expect both operands to be an integer
   if (!LHSVal.isInt() || !RHSVal.isInt())
-    return false;
+    return Error(E);
 
   APSInt &LHS = LHSVal.getInt();
   APSInt &RHS = RHSVal.getInt();
 
   switch (E->getOpcode()) {
   default:
-    return Error(E->getOperatorLoc(), diag::note_invalid_subexpr_in_ice, E);
+    return Error(E);
   case BO_Mul: return Success(LHS * RHS, E);
   case BO_Add: return Success(LHS + RHS, E);
   case BO_Sub: return Success(LHS - RHS, E);
@@ -3429,11 +3517,11 @@
   case BO_Or:  return Success(LHS | RHS, E);
   case BO_Div:
     if (RHS == 0)
-      return Error(E->getOperatorLoc(), diag::note_expr_divide_by_zero, E);
+      return Error(E, diag::note_expr_divide_by_zero);
     return Success(LHS / RHS, E);
   case BO_Rem:
     if (RHS == 0)
-      return Error(E->getOperatorLoc(), diag::note_expr_divide_by_zero, E);
+      return Error(E, diag::note_expr_divide_by_zero);
     return Success(LHS % RHS, E);
   case BO_Shl: {
     // During constant-folding, a negative shift is an opposite shift.
@@ -3544,14 +3632,14 @@
   }
 
   llvm_unreachable("unknown expr/type trait");
-  return false;
+  return Error(E);
 }
 
 bool IntExprEvaluator::VisitOffsetOfExpr(const OffsetOfExpr *OOE) {
   CharUnits Result;
   unsigned n = OOE->getNumComponents();
   if (n == 0)
-    return false;
+    return Error(OOE);
   QualType CurrentType = OOE->getTypeSourceInfo()->getType();
   for (unsigned i = 0; i != n; ++i) {
     OffsetOfExpr::OffsetOfNode ON = OOE->getComponent(i);
@@ -3563,18 +3651,18 @@
         return false;
       const ArrayType *AT = Info.Ctx.getAsArrayType(CurrentType);
       if (!AT)
-        return false;
+        return Error(OOE);
       CurrentType = AT->getElementType();
       CharUnits ElementSize = Info.Ctx.getTypeSizeInChars(CurrentType);
       Result += IdxResult.getSExtValue() * ElementSize;
         break;
     }
-        
+
     case OffsetOfExpr::OffsetOfNode::Field: {
       FieldDecl *MemberDecl = ON.getField();
       const RecordType *RT = CurrentType->getAs<RecordType>();
-      if (!RT) 
-        return false;
+      if (!RT)
+        return Error(OOE);
       RecordDecl *RD = RT->getDecl();
       const ASTRecordLayout &RL = Info.Ctx.getASTRecordLayout(RD);
       unsigned i = MemberDecl->getFieldIndex();
@@ -3583,20 +3671,20 @@
       CurrentType = MemberDecl->getType().getNonReferenceType();
       break;
     }
-        
+
     case OffsetOfExpr::OffsetOfNode::Identifier:
       llvm_unreachable("dependent __builtin_offsetof");
-      return false;
-        
+      return Error(OOE);
+
     case OffsetOfExpr::OffsetOfNode::Base: {
       CXXBaseSpecifier *BaseSpec = ON.getBase();
       if (BaseSpec->isVirtual())
-        return false;
+        return Error(OOE);
 
       // Find the layout of the class whose base we are looking into.
       const RecordType *RT = CurrentType->getAs<RecordType>();
-      if (!RT) 
-        return false;
+      if (!RT)
+        return Error(OOE);
       RecordDecl *RD = RT->getDecl();
       const ASTRecordLayout &RL = Info.Ctx.getASTRecordLayout(RD);
 
@@ -3604,7 +3692,7 @@
       CurrentType = BaseSpec->getType();
       const RecordType *BaseRT = CurrentType->getAs<RecordType>();
       if (!BaseRT)
-        return false;
+        return Error(OOE);
       
       // Add the offset to the base.
       Result += RL.getBaseClassOffset(cast<CXXRecordDecl>(BaseRT->getDecl()));
@@ -3616,41 +3704,36 @@
 }
 
 bool IntExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) {
-  if (E->getOpcode() == UO_LNot) {
-    // LNot's operand isn't necessarily an integer, so we handle it specially.
-    bool bres;
-    if (!EvaluateAsBooleanCondition(E->getSubExpr(), bres, Info))
-      return false;
-    return Success(!bres, E);
-  }
-
-  // Only handle integral operations...
-  if (!E->getSubExpr()->getType()->isIntegralOrEnumerationType())
-    return false;
-
-  // Get the operand value.
-  CCValue Val;
-  if (!Evaluate(Val, Info, E->getSubExpr()))
-    return false;
-
   switch (E->getOpcode()) {
   default:
     // Address, indirect, pre/post inc/dec, etc are not valid constant exprs.
     // See C99 6.6p3.
-    return Error(E->getOperatorLoc(), diag::note_invalid_subexpr_in_ice, E);
+    return Error(E);
   case UO_Extension:
     // FIXME: Should extension allow i-c-e extension expressions in its scope?
     // If so, we could clear the diagnostic ID.
-    return Success(Val, E);
+    return Visit(E->getSubExpr());
   case UO_Plus:
     // The result is just the value.
-    return Success(Val, E);
-  case UO_Minus:
-    if (!Val.isInt()) return false;
-    return Success(-Val.getInt(), E);
-  case UO_Not:
-    if (!Val.isInt()) return false;
-    return Success(~Val.getInt(), E);
+    return Visit(E->getSubExpr());
+  case UO_Minus: {
+    if (!Visit(E->getSubExpr()))
+      return false;
+    if (!Result.isInt()) return Error(E);
+    return Success(-Result.getInt(), E);
+  }
+  case UO_Not: {
+    if (!Visit(E->getSubExpr()))
+      return false;
+    if (!Result.isInt()) return Error(E);
+    return Success(~Result.getInt(), E);
+  }
+  case UO_LNot: {
+    bool bres;
+    if (!EvaluateAsBooleanCondition(E->getSubExpr(), bres, Info))
+      return false;
+    return Success(!bres, E);
+  }
   }
 }
 
@@ -3700,7 +3783,7 @@
   case CK_ARCConsumeObject:
   case CK_ARCReclaimReturnedObject:
   case CK_ARCExtendBlockObject:
-    return false;
+    return Error(E);
 
   case CK_LValueToRValue:
   case CK_NoOp:
@@ -3739,7 +3822,7 @@
     if (LV.getLValueBase()) {
       // Only allow based lvalue casts if they are lossless.
       if (Info.Ctx.getTypeSize(DestType) != Info.Ctx.getTypeSize(SrcType))
-        return false;
+        return Error(E);
 
       LV.Designator.setInvalid();
       LV.moveInto(Result);
@@ -3768,14 +3851,16 @@
   }
 
   llvm_unreachable("unknown cast resulting in integral value");
-  return false;
+  return Error(E);
 }
 
 bool IntExprEvaluator::VisitUnaryReal(const UnaryOperator *E) {
   if (E->getSubExpr()->getType()->isAnyComplexType()) {
     ComplexValue LV;
-    if (!EvaluateComplex(E->getSubExpr(), LV, Info) || !LV.isComplexInt())
-      return Error(E->getExprLoc(), diag::note_invalid_subexpr_in_ice, E);
+    if (!EvaluateComplex(E->getSubExpr(), LV, Info))
+      return false;
+    if (!LV.isComplexInt())
+      return Error(E);
     return Success(LV.getComplexIntReal(), E);
   }
 
@@ -3785,8 +3870,10 @@
 bool IntExprEvaluator::VisitUnaryImag(const UnaryOperator *E) {
   if (E->getSubExpr()->getType()->isComplexIntegerType()) {
     ComplexValue LV;
-    if (!EvaluateComplex(E->getSubExpr(), LV, Info) || !LV.isComplexInt())
-      return Error(E->getExprLoc(), diag::note_invalid_subexpr_in_ice, E);
+    if (!EvaluateComplex(E->getSubExpr(), LV, Info))
+      return false;
+    if (!LV.isComplexInt())
+      return Error(E);
     return Success(LV.getComplexIntImag(), E);
   }
 
@@ -3818,9 +3905,6 @@
     Result = V.getFloat();
     return true;
   }
-  bool Error(const Stmt *S) {
-    return false;
-  }
 
   bool ValueInitialization(const Expr *E) {
     Result = APFloat::getZero(Info.Ctx.getFloatTypeSemantics(E->getType()));
@@ -3892,16 +3976,20 @@
   case Builtin::BI__builtin_nans:
   case Builtin::BI__builtin_nansf:
   case Builtin::BI__builtin_nansl:
-    return TryEvaluateBuiltinNaN(Info.Ctx, E->getType(), E->getArg(0),
-                                 true, Result);
+    if (!TryEvaluateBuiltinNaN(Info.Ctx, E->getType(), E->getArg(0),
+                               true, Result))
+      return Error(E);
+    return true;
 
   case Builtin::BI__builtin_nan:
   case Builtin::BI__builtin_nanf:
   case Builtin::BI__builtin_nanl:
     // If this is __builtin_nan() turn this into a nan, otherwise we
     // can't constant fold it.
-    return TryEvaluateBuiltinNaN(Info.Ctx, E->getType(), E->getArg(0),
-                                 false, Result);
+    if (!TryEvaluateBuiltinNaN(Info.Ctx, E->getType(), E->getArg(0),
+                               false, Result))
+      return Error(E);
+    return true;
 
   case Builtin::BI__builtin_fabs:
   case Builtin::BI__builtin_fabsf:
@@ -3955,7 +4043,7 @@
 
 bool FloatExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) {
   switch (E->getOpcode()) {
-  default: return false;
+  default: return Error(E);
   case UO_Plus:
     return EvaluateFloat(E->getSubExpr(), Result, Info);
   case UO_Minus:
@@ -3977,7 +4065,7 @@
     return false;
 
   switch (E->getOpcode()) {
-  default: return false;
+  default: return Error(E);
   case BO_Mul:
     Result.multiply(RHS, APFloat::rmNearestTiesToEven);
     return true;
@@ -4031,7 +4119,7 @@
   }
   }
 
-  return false;
+  return Error(E);
 }
 
 //===----------------------------------------------------------------------===//
@@ -4051,9 +4139,6 @@
     Result.setFrom(V);
     return true;
   }
-  bool Error(const Expr *E) {
-    return false;
-  }
 
   //===--------------------------------------------------------------------===//
   //                            Visitor Methods
@@ -4149,7 +4234,7 @@
   case CK_Dependent:
   case CK_LValueBitCast:
   case CK_UserDefinedConversion:
-    return false;
+    return Error(E);
 
   case CK_FloatingRealToComplex: {
     APFloat &Real = Result.FloatReal;
@@ -4227,7 +4312,7 @@
   }
 
   llvm_unreachable("unknown cast resulting in complex value");
-  return false;
+  return Error(E);
 }
 
 bool ComplexExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
@@ -4244,7 +4329,7 @@
   assert(Result.isComplexFloat() == RHS.isComplexFloat() &&
          "Invalid operands to binary operator.");
   switch (E->getOpcode()) {
-  default: return false;
+  default: return Error(E);
   case BO_Add:
     if (Result.isComplexFloat()) {
       Result.getComplexFloatReal().add(RHS.getComplexFloatReal(),
@@ -4328,10 +4413,9 @@
       Res_i.subtract(Tmp, APFloat::rmNearestTiesToEven);
       Res_i.divide(Den, APFloat::rmNearestTiesToEven);
     } else {
-      if (RHS.getComplexIntReal() == 0 && RHS.getComplexIntImag() == 0) {
-        // FIXME: what about diagnostics?
-        return false;
-      }
+      if (RHS.getComplexIntReal() == 0 && RHS.getComplexIntImag() == 0)
+        return Error(E, diag::note_expr_divide_by_zero);
+
       ComplexValue LHS = Result;
       APSInt Den = RHS.getComplexIntReal() * RHS.getComplexIntReal() +
         RHS.getComplexIntImag() * RHS.getComplexIntImag();
@@ -4355,8 +4439,7 @@
 
   switch (E->getOpcode()) {
   default:
-    // FIXME: what about diagnostics?
-    return false;
+    return Error(E);
   case UO_Extension:
     return true;
   case UO_Plus:
@@ -4393,7 +4476,6 @@
   VoidExprEvaluator(EvalInfo &Info) : ExprEvaluatorBaseTy(Info) {}
 
   bool Success(const CCValue &V, const Expr *e) { return true; }
-  bool Error(const Expr *E) { return false; }
 
   bool VisitCastExpr(const CastExpr *E) {
     switch (E->getCastKind()) {
@@ -4466,8 +4548,10 @@
   } else if (E->getType()->isVoidType()) {
     if (!EvaluateVoid(E, Info))
       return false;
-  } else
+  } else {
+    Info.Diag(E, E->getExprLoc(), diag::note_invalid_subexpr_in_const_expr);
     return false;
+  }
 
   return true;
 }
@@ -4490,9 +4574,27 @@
   // For any other type, in-place evaluation is unimportant.
   CCValue CoreConstResult;
   return Evaluate(CoreConstResult, Info, E) &&
-         CheckConstantExpression(CoreConstResult, Result);
+         CheckConstantExpression(Info, E, CoreConstResult, Result);
 }
 
+/// EvaluateAsRValue - Try to evaluate this expression, performing an implicit
+/// lvalue-to-rvalue cast if it is an lvalue.
+static bool EvaluateAsRValue(EvalInfo &Info, const Expr *E, APValue &Result) {
+  CCValue Value;
+  if (!::Evaluate(Value, Info, E))
+    return false;
+
+  if (E->isGLValue()) {
+    LValue LV;
+    LV.setFrom(Value);
+    if (!HandleLValueToRValueConversion(Info, E, E->getType(), LV, Value))
+      return false;
+  }
+
+  // Check this core constant expression is a constant expression, and if so,
+  // convert it to one.
+  return CheckConstantExpression(Info, E, Value, Result);
+}
 
 /// EvaluateAsRValue - Return true if this is a constant which we can fold using
 /// any crazy technique (that has nothing to do with language standards) that
@@ -4508,23 +4610,9 @@
       !Ctx.getLangOptions().CPlusPlus0x)
     return false;
 
-  EvalInfo Info(Ctx, Result);
-
   // FIXME: If this is the initializer for an lvalue, pass that in.
-  CCValue Value;
-  if (!::Evaluate(Value, Info, this))
-    return false;
-
-  if (isGLValue()) {
-    LValue LV;
-    LV.setFrom(Value);
-    if (!HandleLValueToRValueConversion(Info, getType(), LV, Value))
-      return false;
-  }
-
-  // Check this core constant expression is a constant expression, and if so,
-  // convert it to one.
-  return CheckConstantExpression(Value, Result.Val);
+  EvalInfo Info(Ctx, Result);
+  return ::EvaluateAsRValue(Info, this, Result.Val);
 }
 
 bool Expr::EvaluateAsBooleanCondition(bool &Result,
@@ -4538,9 +4626,9 @@
 bool Expr::EvaluateAsInt(APSInt &Result, const ASTContext &Ctx) const {
   EvalResult ExprResult;
   if (!EvaluateAsRValue(ExprResult, Ctx) || ExprResult.HasSideEffects ||
-      !ExprResult.Val.isInt()) {
+      !ExprResult.Val.isInt())
     return false;
-  }
+
   Result = ExprResult.Val.getInt();
   return true;
 }
@@ -4550,7 +4638,7 @@
 
   LValue LV;
   return EvaluateLValue(this, LV, Info) && !Result.HasSideEffects &&
-         CheckLValueConstantExpression(LV, Result.Val);
+         CheckLValueConstantExpression(Info, this, LV, Result.Val);
 }
 
 /// isEvaluatable - Call EvaluateAsRValue to see if this expression can be
@@ -4694,17 +4782,7 @@
   case Expr::MaterializeTemporaryExprClass:
   case Expr::PseudoObjectExprClass:
   case Expr::AtomicExprClass:
-    return ICEDiag(2, E->getLocStart());
-
   case Expr::InitListExprClass:
-    if (Ctx.getLangOptions().CPlusPlus0x) {
-      const InitListExpr *ILE = cast<InitListExpr>(E);
-      if (ILE->getNumInits() == 0)
-        return NoDiag();
-      if (ILE->getNumInits() == 1)
-        return CheckICE(ILE->getInit(0), Ctx);
-      // Fall through for more than 1 expression.
-    }
     return ICEDiag(2, E->getLocStart());
 
   case Expr::SizeOfPackExprClass:
@@ -4903,21 +4981,6 @@
     case BO_LAnd:
     case BO_LOr: {
       ICEDiag LHSResult = CheckICE(Exp->getLHS(), Ctx);
-
-      // C++0x [expr.const]p2:
-      //   [...] subexpressions of logical AND (5.14), logical OR
-      //   (5.15), and condi- tional (5.16) operations that are not
-      //   evaluated are not considered.
-      if (Ctx.getLangOptions().CPlusPlus0x && LHSResult.Val == 0) {
-        if (Exp->getOpcode() == BO_LAnd && 
-            Exp->getLHS()->EvaluateKnownConstInt(Ctx) == 0)
-          return LHSResult;
-
-        if (Exp->getOpcode() == BO_LOr &&
-            Exp->getLHS()->EvaluateKnownConstInt(Ctx) != 0)
-          return LHSResult;
-      }
-
       ICEDiag RHSResult = CheckICE(Exp->getRHS(), Ctx);
       if (LHSResult.Val == 0 && RHSResult.Val == 1) {
         // Rare case where the RHS has a comma "side-effect"; we need
@@ -4987,18 +5050,8 @@
     if (CondResult.Val == 2)
       return CondResult;
 
-    // C++0x [expr.const]p2:
-    //   subexpressions of [...] conditional (5.16) operations that
-    //   are not evaluated are not considered
-    bool TrueBranch = Ctx.getLangOptions().CPlusPlus0x
-      ? Exp->getCond()->EvaluateKnownConstInt(Ctx) != 0
-      : false;
-    ICEDiag TrueResult = NoDiag();
-    if (!Ctx.getLangOptions().CPlusPlus0x || TrueBranch)
-      TrueResult = CheckICE(Exp->getTrueExpr(), Ctx);
-    ICEDiag FalseResult = NoDiag();
-    if (!Ctx.getLangOptions().CPlusPlus0x || !TrueBranch)
-      FalseResult = CheckICE(Exp->getFalseExpr(), Ctx);
+    ICEDiag TrueResult = CheckICE(Exp->getTrueExpr(), Ctx);
+    ICEDiag FalseResult = CheckICE(Exp->getFalseExpr(), Ctx);
 
     if (TrueResult.Val == 2)
       return TrueResult;
@@ -5027,14 +5080,56 @@
   return ICEDiag(2, E->getLocStart());
 }
 
-bool Expr::isIntegerConstantExpr(llvm::APSInt &Result, ASTContext &Ctx,
-                                 SourceLocation *Loc, bool isEvaluated) const {
+/// Evaluate an expression as a C++11 constant expression.
+static bool EvaluateCPlusPlus11ConstantExpression(ASTContext &Ctx,
+                                                  const Expr *E,
+                                                  Expr::EvalResult &Result) {
+  EvalInfo Info(Ctx, Result);
+  return EvaluateAsRValue(Info, E, Result.Val) && !Result.Diag;
+}
+
+/// Evaluate an expression as a C++11 integral constant expression.
+static bool EvaluateCPlusPlus11IntegralConstantExpr(ASTContext &Ctx,
+                                                    const Expr *E,
+                                                    llvm::APSInt *Value,
+                                                    SourceLocation *Loc) {
+  if (!E->getType()->isIntegralOrEnumerationType()) {
+    if (Loc) *Loc = E->getExprLoc();
+    return false;
+  }
+
+  Expr::EvalResult Result;
+  if (EvaluateCPlusPlus11ConstantExpression(Ctx, E, Result)) {
+    assert(Result.Val.isInt() && "pointer cast to int is not an ICE");
+    if (Value) *Value = Result.Val.getInt();
+    return true;
+  } else {
+    if (Loc) *Loc = Result.DiagLoc.isValid() ? Result.DiagLoc : E->getExprLoc();
+    return false;
+  }
+}
+
+bool Expr::isIntegerConstantExpr(ASTContext &Ctx,
+                                 SourceLocation *Loc) const {
+  if (Ctx.getLangOptions().CPlusPlus0x)
+    return EvaluateCPlusPlus11IntegralConstantExpr(Ctx, this, 0, Loc);
+
   ICEDiag d = CheckICE(this, Ctx);
   if (d.Val != 0) {
     if (Loc) *Loc = d.Loc;
     return false;
   }
-  if (!EvaluateAsInt(Result, Ctx))
+  return true;
+}
+
+bool Expr::isIntegerConstantExpr(llvm::APSInt &Value, ASTContext &Ctx,
+                                 SourceLocation *Loc, bool isEvaluated) const {
+  if (Ctx.getLangOptions().CPlusPlus0x)
+    return EvaluateCPlusPlus11IntegralConstantExpr(Ctx, this, &Value, Loc);
+
+  if (!isIntegerConstantExpr(Ctx, Loc))
+    return false;
+  if (!EvaluateAsInt(Value, Ctx))
     llvm_unreachable("ICE cannot be evaluated!");
   return true;
 }

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=146289&r1=146288&r2=146289&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Fri Dec  9 16:58:01 2011
@@ -9206,7 +9206,7 @@
     if (EvalResult.Diag) {
       // We only show the note if it's not the usual "invalid subexpression"
       // or if it's actually in a subexpression.
-      if (EvalResult.Diag != diag::note_invalid_subexpr_in_ice ||
+      if (EvalResult.Diag != diag::note_invalid_subexpr_in_const_expr ||
           E->IgnoreParens() != EvalResult.DiagExpr->IgnoreParens())
         Diag(EvalResult.DiagLoc, EvalResult.Diag);
     }

Modified: cfe/trunk/test/Sema/i-c-e.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/i-c-e.c?rev=146289&r1=146288&r2=146289&view=diff
==============================================================================
--- cfe/trunk/test/Sema/i-c-e.c (original)
+++ cfe/trunk/test/Sema/i-c-e.c Fri Dec  9 16:58:01 2011
@@ -21,7 +21,7 @@
 struct c {
   int a : (  // expected-error {{expression is not an integer constant expression}}
            __builtin_constant_p((int)(1.0+2.0)) ? (int)(1.0+
-     expr  // expected-note {{subexpression not valid in an integer constant expression}}
+     expr  // expected-note {{subexpression not valid in a constant expression}}
            ) : -1);
 };
 

Modified: cfe/trunk/test/Sema/switch.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/switch.c?rev=146289&r1=146288&r2=146289&view=diff
==============================================================================
--- cfe/trunk/test/Sema/switch.c (original)
+++ cfe/trunk/test/Sema/switch.c Fri Dec  9 16:58:01 2011
@@ -50,12 +50,12 @@
   }
   
   switch (cond) {
-  case g() && 0: // expected-error {{expression is not an integer constant expression}} // expected-note {{subexpression not valid in an integer constant expression}}
+  case g() && 0: // expected-error {{expression is not an integer constant expression}} // expected-note {{subexpression not valid in a constant expression}}
     break;
   }
   
   switch (cond) {
-  case 0 ... g() || 1: // expected-error {{expression is not an integer constant expression}} // expected-note {{subexpression not valid in an integer constant expression}}
+  case 0 ... g() || 1: // expected-error {{expression is not an integer constant expression}} // expected-note {{subexpression not valid in a constant expression}}
     break;
   }
 }

Modified: cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp?rev=146289&r1=146288&r2=146289&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp (original)
+++ cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp Fri Dec  9 16:58:01 2011
@@ -1,12 +1,6 @@
 // RUN: %clang_cc1 -triple i686-linux -fsyntax-only -verify -std=c++11 %s
 
-// This version of static_assert just requires a foldable value as the
-// expression, not an ICE.
-// FIXME: Once we implement the C++11 ICE rules, most uses of this here should
-// be converted to static_assert.
-#define static_assert_fold(expr, str) \
-    static_assert(__builtin_constant_p(expr), "not an integral constant expression"); \
-    static_assert(__builtin_constant_p(expr) ? expr : true, str)
+#define static_assert_fold static_assert
 
 namespace StaticAssertFoldTest {
 





More information about the cfe-commits mailing list