diff options
Diffstat (limited to 'lib/AST/ExprConstant.cpp')
-rw-r--r-- | lib/AST/ExprConstant.cpp | 306 |
1 files changed, 177 insertions, 129 deletions
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index 6e0b5fc..ae86150 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -35,15 +35,16 @@ #include "clang/AST/APValue.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/ASTDiagnostic.h" #include "clang/AST/CharUnits.h" +#include "clang/AST/Expr.h" #include "clang/AST/RecordLayout.h" #include "clang/AST/StmtVisitor.h" #include "clang/AST/TypeLoc.h" -#include "clang/AST/ASTDiagnostic.h" -#include "clang/AST/Expr.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/TargetInfo.h" #include "llvm/ADT/SmallString.h" +#include "llvm/Support/raw_ostream.h" #include <cstring> #include <functional> @@ -317,7 +318,7 @@ namespace { OptionalDiagnostic &operator<<(const APSInt &I) { if (Diag) { - llvm::SmallVector<char, 32> Buffer; + SmallVector<char, 32> Buffer; I.toString(Buffer); *Diag << StringRef(Buffer.data(), Buffer.size()); } @@ -326,7 +327,7 @@ namespace { OptionalDiagnostic &operator<<(const APFloat &F) { if (Diag) { - llvm::SmallVector<char, 32> Buffer; + SmallVector<char, 32> Buffer; F.toString(Buffer); *Diag << StringRef(Buffer.data(), Buffer.size()); } @@ -383,13 +384,17 @@ namespace { /// expression is a potential constant expression? If so, some diagnostics /// are suppressed. bool CheckingPotentialConstantExpression; + + bool IntOverflowCheckMode; - EvalInfo(const ASTContext &C, Expr::EvalStatus &S) + EvalInfo(const ASTContext &C, Expr::EvalStatus &S, + bool OverflowCheckMode=false) : Ctx(const_cast<ASTContext&>(C)), EvalStatus(S), CurrentCall(0), CallStackDepth(0), NextCallIndex(1), BottomFrame(*this, SourceLocation(), 0, 0, 0), EvaluatingDecl(0), EvaluatingDeclValue(0), HasActiveDiagnostic(false), - CheckingPotentialConstantExpression(false) {} + CheckingPotentialConstantExpression(false), + IntOverflowCheckMode(OverflowCheckMode) {} void setEvaluatingDecl(const VarDecl *VD, APValue &Value) { EvaluatingDecl = VD; @@ -473,6 +478,8 @@ namespace { return OptionalDiagnostic(); } + bool getIntOverflowCheckMode() { return IntOverflowCheckMode; } + /// Diagnose that the evaluation does not produce a C++11 core constant /// expression. template<typename LocArg> @@ -505,8 +512,11 @@ namespace { /// Should we continue evaluation as much as possible after encountering a /// construct which can't be folded? bool keepEvaluatingAfterFailure() { - return CheckingPotentialConstantExpression && - EvalStatus.Diag && EvalStatus.Diag->empty(); + // Should return true in IntOverflowCheckMode, so that we check for + // overflow even if some subexpressions can't be evaluated as constants. + return IntOverflowCheckMode || + (CheckingPotentialConstantExpression && + EvalStatus.Diag && EvalStatus.Diag->empty()); } }; @@ -534,8 +544,7 @@ namespace { public: SpeculativeEvaluationRAII(EvalInfo &Info, - llvm::SmallVectorImpl<PartialDiagnosticAt> - *NewDiag = 0) + SmallVectorImpl<PartialDiagnosticAt> *NewDiag = 0) : Info(Info), Old(Info.EvalStatus) { Info.EvalStatus.Diag = NewDiag; } @@ -586,7 +595,7 @@ CallStackFrame::~CallStackFrame() { } /// Produce a string describing the given constexpr call. -static void describeCall(CallStackFrame *Frame, llvm::raw_ostream &Out) { +static void describeCall(CallStackFrame *Frame, raw_ostream &Out) { unsigned ArgIndex = 0; bool IsMemberCall = isa<CXXMethodDecl>(Frame->Callee) && !isa<CXXConstructorDecl>(Frame->Callee) && @@ -634,7 +643,7 @@ void EvalInfo::addCallStack(unsigned Limit) { continue; } - llvm::SmallVector<char, 128> Buffer; + SmallVector<char, 128> Buffer; llvm::raw_svector_ostream Out(Buffer); describeCall(Frame, Out); addDiag(Frame->CallLoc, diag::note_constexpr_call_here) << Out.str(); @@ -737,7 +746,7 @@ namespace { bool checkSubobject(EvalInfo &Info, const Expr *E, CheckSubobjectKind CSK) { // Outside C++11, do not build a designator referring to a subobject of // any object: we won't use such a designator for anything. - if (!Info.getLangOpts().CPlusPlus0x) + if (!Info.getLangOpts().CPlusPlus11) Designator.setInvalid(); return checkNullPointer(Info, E, CSK) && Designator.checkSubobject(Info, E, CSK); @@ -971,7 +980,7 @@ static bool CheckLValueConstantExpression(EvalInfo &Info, SourceLocation Loc, // manufacture when checking potential constant expressions is conservatively // assumed to be global here. if (!IsGlobalLValue(Base)) { - if (Info.getLangOpts().CPlusPlus0x) { + if (Info.getLangOpts().CPlusPlus11) { const ValueDecl *VD = Base.dyn_cast<const ValueDecl*>(); Info.Diag(Loc, diag::note_constexpr_non_global, 1) << IsReferenceType << !Designator.Entries.empty() @@ -1025,7 +1034,7 @@ static bool CheckLiteralType(EvalInfo &Info, const Expr *E) { return true; // Prvalue constant expressions must be of literal types. - if (Info.getLangOpts().CPlusPlus0x) + if (Info.getLangOpts().CPlusPlus11) Info.Diag(E, diag::note_constexpr_nonliteral) << E->getType(); else @@ -1462,7 +1471,7 @@ static bool EvaluateVarDeclInit(EvalInfo &Info, const Expr *E, // Check that we can fold the initializer. In C++, we will have already done // this in the cases where it matters for conformance. - llvm::SmallVector<PartialDiagnosticAt, 8> Notes; + SmallVector<PartialDiagnosticAt, 8> Notes; if (!VD->evaluateValue(Notes)) { Info.Diag(E, diag::note_constexpr_var_init_non_constant, Notes.size() + 1) << VD; @@ -1526,7 +1535,7 @@ static bool ExtractSubobject(EvalInfo &Info, const Expr *E, // A diagnostic will have already been produced. return false; if (Sub.isOnePastTheEnd()) { - Info.Diag(E, Info.getLangOpts().CPlusPlus0x ? + Info.Diag(E, Info.getLangOpts().CPlusPlus11 ? (unsigned)diag::note_constexpr_read_past_end : (unsigned)diag::note_invalid_subexpr_in_const_expr); return false; @@ -1548,7 +1557,7 @@ static bool ExtractSubobject(EvalInfo &Info, const Expr *E, if (CAT->getSize().ule(Index)) { // Note, it should not be possible to form a pointer with a valid // designator which points more than one past the end of the array. - Info.Diag(E, Info.getLangOpts().CPlusPlus0x ? + Info.Diag(E, Info.getLangOpts().CPlusPlus11 ? (unsigned)diag::note_constexpr_read_past_end : (unsigned)diag::note_invalid_subexpr_in_const_expr); return false; @@ -1570,7 +1579,7 @@ static bool ExtractSubobject(EvalInfo &Info, const Expr *E, // Next subobject is a complex number. uint64_t Index = Sub.Entries[I].ArrayIndex; if (Index > 1) { - Info.Diag(E, Info.getLangOpts().CPlusPlus0x ? + Info.Diag(E, Info.getLangOpts().CPlusPlus11 ? (unsigned)diag::note_constexpr_read_past_end : (unsigned)diag::note_invalid_subexpr_in_const_expr); return false; @@ -1795,7 +1804,7 @@ static bool HandleLValueToRValueConversion(EvalInfo &Info, const Expr *Conv, // We support folding of const floating-point types, in order to make // static const data members of such types (supported as an extension) // more useful. - if (Info.getLangOpts().CPlusPlus0x) { + if (Info.getLangOpts().CPlusPlus11) { Info.CCEDiag(Conv, diag::note_constexpr_ltor_non_constexpr, 1) << VD; Info.Note(VD->getLocation(), diag::note_declared_at); } else { @@ -1803,7 +1812,7 @@ static bool HandleLValueToRValueConversion(EvalInfo &Info, const Expr *Conv, } } else { // FIXME: Allow folding of values of any literal type in all languages. - if (Info.getLangOpts().CPlusPlus0x) { + if (Info.getLangOpts().CPlusPlus11) { Info.Diag(Conv, diag::note_constexpr_ltor_non_constexpr, 1) << VD; Info.Note(VD->getLocation(), diag::note_declared_at); } else { @@ -2080,7 +2089,7 @@ static bool CheckTrivialDefaultConstructor(EvalInfo &Info, SourceLocation Loc, // call is a core constant expression whether or not the constructor is // constexpr. if (!CD->isConstexpr() && !IsValueInitialization) { - if (Info.getLangOpts().CPlusPlus0x) { + if (Info.getLangOpts().CPlusPlus11) { // FIXME: If DiagDecl is an implicitly-declared special member function, // we should be much more explicit about why it's not constexpr. Info.CCEDiag(Loc, diag::note_constexpr_invalid_function, 1) @@ -2108,7 +2117,7 @@ static bool CheckConstexprFunction(EvalInfo &Info, SourceLocation CallLoc, if (Definition && Definition->isConstexpr() && !Definition->isInvalidDecl()) return true; - if (Info.getLangOpts().CPlusPlus0x) { + if (Info.getLangOpts().CPlusPlus11) { const FunctionDecl *DiagDecl = Definition ? Definition : Declaration; // FIXME: If DiagDecl is an implicitly-declared special member function, we // should be much more explicit about why it's not constexpr. @@ -2311,7 +2320,7 @@ private: // Speculatively evaluate both arms. { - llvm::SmallVector<PartialDiagnosticAt, 8> Diag; + SmallVector<PartialDiagnosticAt, 8> Diag; SpeculativeEvaluationRAII Speculate(Info, &Diag); StmtVisitorTy::Visit(E->getFalseExpr()); @@ -2482,7 +2491,7 @@ public: const FunctionDecl *FD = 0; LValue *This = 0, ThisVal; - llvm::ArrayRef<const Expr*> Args(E->getArgs(), E->getNumArgs()); + ArrayRef<const Expr *> Args(E->getArgs(), E->getNumArgs()); bool HasQualifier = false; // Extract function decl and 'this' pointer from the callee. @@ -3487,7 +3496,7 @@ bool RecordExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E) { if (ZeroInit && !ZeroInitialization(E)) return false; - llvm::ArrayRef<const Expr*> Args(E->getArgs(), E->getNumArgs()); + ArrayRef<const Expr *> Args(E->getArgs(), E->getNumArgs()); return HandleConstructorCall(E->getExprLoc(), This, Args, cast<CXXConstructorDecl>(Definition), Info, Result); @@ -3629,7 +3638,6 @@ bool VectorExprEvaluator::VisitCastExpr(const CastExpr* E) { SmallVector<APValue, 4> Elts; if (EltTy->isRealFloatingType()) { const llvm::fltSemantics &Sem = Info.Ctx.getFloatTypeSemantics(EltTy); - bool isIEESem = &Sem != &APFloat::PPCDoubleDouble; unsigned FloatEltSize = EltSize; if (&Sem == &APFloat::x87DoubleExtended) FloatEltSize = 80; @@ -3639,7 +3647,7 @@ bool VectorExprEvaluator::VisitCastExpr(const CastExpr* E) { Elt = SValInt.rotl(i*EltSize+FloatEltSize).trunc(FloatEltSize); else Elt = SValInt.rotr(i*EltSize).trunc(FloatEltSize); - Elts.push_back(APValue(APFloat(Elt, isIEESem))); + Elts.push_back(APValue(APFloat(Sem, Elt))); } } else if (EltTy->isIntegerType()) { for (unsigned i = 0; i < NElts; i++) { @@ -3898,7 +3906,7 @@ bool ArrayExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E) { return false; } - llvm::ArrayRef<const Expr*> Args(E->getArgs(), E->getNumArgs()); + ArrayRef<const Expr *> Args(E->getArgs(), E->getNumArgs()); return HandleConstructorCall(E->getExprLoc(), Subobject, Args, cast<CXXConstructorDecl>(Definition), Info, *Value); @@ -4317,7 +4325,7 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) { case Builtin::BIstrlen: // A call to strlen is not a constant expression. - if (Info.getLangOpts().CPlusPlus0x) + if (Info.getLangOpts().CPlusPlus11) Info.CCEDiag(E, diag::note_constexpr_invalid_function) << /*isConstexpr*/0 << /*isConstructor*/0 << "'strlen'"; else @@ -4419,8 +4427,14 @@ static APSInt CheckedIntArithmetic(EvalInfo &Info, const Expr *E, APSInt Value(Op(LHS.extend(BitWidth), RHS.extend(BitWidth)), false); APSInt Result = Value.trunc(LHS.getBitWidth()); - if (Result.extend(BitWidth) != Value) - HandleOverflow(Info, E, Value, E->getType()); + if (Result.extend(BitWidth) != Value) { + if (Info.getIntOverflowCheckMode()) + Info.Ctx.getDiagnostics().Report(E->getExprLoc(), + diag::warn_integer_constant_overflow) + << Result.toString(10) << E->getType(); + else + HandleOverflow(Info, E, Value, E->getType()); + } return Result; } @@ -4707,9 +4721,14 @@ bool DataRecursiveIntBinOpEvaluator:: return Success(E->getOpcode() == BO_Rem ? LHS % RHS : LHS / RHS, E, Result); case BO_Shl: { - // During constant-folding, a negative shift is an opposite shift. Such - // a shift is not a constant expression. - if (RHS.isSigned() && RHS.isNegative()) { + if (Info.getLangOpts().OpenCL) + // OpenCL 6.3j: shift values are effectively % word size of LHS. + RHS &= APSInt(llvm::APInt(RHS.getBitWidth(), + static_cast<uint64_t>(LHS.getBitWidth() - 1)), + RHS.isUnsigned()); + else if (RHS.isSigned() && RHS.isNegative()) { + // During constant-folding, a negative shift is an opposite shift. Such + // a shift is not a constant expression. CCEDiag(E, diag::note_constexpr_negative_shift) << RHS; RHS = -RHS; goto shift_right; @@ -4734,9 +4753,14 @@ bool DataRecursiveIntBinOpEvaluator:: return Success(LHS << SA, E, Result); } case BO_Shr: { - // During constant-folding, a negative shift is an opposite shift. Such a - // shift is not a constant expression. - if (RHS.isSigned() && RHS.isNegative()) { + if (Info.getLangOpts().OpenCL) + // OpenCL 6.3j: shift values are effectively % word size of LHS. + RHS &= APSInt(llvm::APInt(RHS.getBitWidth(), + static_cast<uint64_t>(LHS.getBitWidth() - 1)), + RHS.isUnsigned()); + else if (RHS.isSigned() && RHS.isNegative()) { + // During constant-folding, a negative shift is an opposite shift. Such a + // shift is not a constant expression. CCEDiag(E, diag::note_constexpr_negative_shift) << RHS; RHS = -RHS; goto shift_left; @@ -5362,6 +5386,7 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) { case CK_IntegralComplexCast: case CK_IntegralComplexToFloatingComplex: case CK_BuiltinFnToFnPtr: + case CK_ZeroToOCLEvent: llvm_unreachable("invalid cast kind for integral value"); case CK_BitCast: @@ -5849,6 +5874,7 @@ bool ComplexExprEvaluator::VisitCastExpr(const CastExpr *E) { case CK_ARCExtendBlockObject: case CK_CopyAndAutoreleaseBlockObject: case CK_BuiltinFnToFnPtr: + case CK_ZeroToOCLEvent: llvm_unreachable("invalid cast kind for complex value"); case CK_LValueToRValue: @@ -6191,12 +6217,12 @@ static bool Evaluate(APValue &Result, EvalInfo &Info, const Expr *E) { return false; Result = Info.CurrentCall->Temporaries[E]; } else if (E->getType()->isVoidType()) { - if (!Info.getLangOpts().CPlusPlus0x) + if (!Info.getLangOpts().CPlusPlus11) Info.CCEDiag(E, diag::note_constexpr_nonliteral) << E->getType(); if (!EvaluateVoid(E, Info)) return false; - } else if (Info.getLangOpts().CPlusPlus0x) { + } else if (Info.getLangOpts().CPlusPlus11) { Info.Diag(E, diag::note_constexpr_nonliteral) << E->getType(); return false; } else { @@ -6249,26 +6275,39 @@ static bool EvaluateAsRValue(EvalInfo &Info, const Expr *E, APValue &Result) { return CheckConstantExpression(Info, E->getExprLoc(), E->getType(), 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 -/// we want to. If this function returns true, it returns the folded constant -/// in Result. If this expression is a glvalue, an lvalue-to-rvalue conversion -/// will be applied to the result. -bool Expr::EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx) const { +static bool FastEvaluateAsRValue(const Expr *Exp, Expr::EvalResult &Result, + const ASTContext &Ctx, bool &IsConst) { // Fast-path evaluations of integer literals, since we sometimes see files // containing vast quantities of these. - if (const IntegerLiteral *L = dyn_cast<IntegerLiteral>(this)) { + if (const IntegerLiteral *L = dyn_cast<IntegerLiteral>(Exp)) { Result.Val = APValue(APSInt(L->getValue(), L->getType()->isUnsignedIntegerType())); + IsConst = true; return true; } - + // FIXME: Evaluating values of large array and record types can cause // performance problems. Only do so in C++11 for now. - if (isRValue() && (getType()->isArrayType() || getType()->isRecordType()) && - !Ctx.getLangOpts().CPlusPlus0x) - return false; + if (Exp->isRValue() && (Exp->getType()->isArrayType() || + Exp->getType()->isRecordType()) && + !Ctx.getLangOpts().CPlusPlus11) { + IsConst = false; + return true; + } + return false; +} + +/// 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 +/// we want to. If this function returns true, it returns the folded constant +/// in Result. If this expression is a glvalue, an lvalue-to-rvalue conversion +/// will be applied to the result. +bool Expr::EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx) const { + bool IsConst; + if (FastEvaluateAsRValue(this, Result, Ctx, IsConst)) + return IsConst; + EvalInfo Info(Ctx, Result); return ::EvaluateAsRValue(Info, this, Result.Val); } @@ -6309,11 +6348,11 @@ bool Expr::EvaluateAsLValue(EvalResult &Result, const ASTContext &Ctx) const { bool Expr::EvaluateAsInitializer(APValue &Value, const ASTContext &Ctx, const VarDecl *VD, - llvm::SmallVectorImpl<PartialDiagnosticAt> &Notes) const { + SmallVectorImpl<PartialDiagnosticAt> &Notes) const { // FIXME: Evaluating initializers for large array and record types can cause // performance problems. Only do so in C++11 for now. if (isRValue() && (getType()->isArrayType() || getType()->isRecordType()) && - !Ctx.getLangOpts().CPlusPlus0x) + !Ctx.getLangOpts().CPlusPlus11) return false; Expr::EvalStatus EStatus; @@ -6353,8 +6392,10 @@ bool Expr::isEvaluatable(const ASTContext &Ctx) const { return EvaluateAsRValue(Result, Ctx) && !Result.HasSideEffects; } -APSInt Expr::EvaluateKnownConstInt(const ASTContext &Ctx) const { +APSInt Expr::EvaluateKnownConstInt(const ASTContext &Ctx, + SmallVectorImpl<PartialDiagnosticAt> *Diag) const { EvalResult EvalResult; + EvalResult.Diag = Diag; bool Result = EvaluateAsRValue(EvalResult, Ctx); (void)Result; assert(Result && "Could not evaluate expression"); @@ -6363,6 +6404,17 @@ APSInt Expr::EvaluateKnownConstInt(const ASTContext &Ctx) const { return EvalResult.Val.getInt(); } +void Expr::EvaluateForOverflow(const ASTContext &Ctx, + SmallVectorImpl<PartialDiagnosticAt> *Diags) const { + bool IsConst; + EvalResult EvalResult; + EvalResult.Diag = Diags; + if (!FastEvaluateAsRValue(this, EvalResult, Ctx, IsConst)) { + EvalInfo Info(Ctx, EvalResult, true); + (void)::EvaluateAsRValue(Info, this, EvalResult.Val); + } +} + bool Expr::EvalResult::isGlobalLValue() const { assert(Val.isLValue()); return IsGlobalLValue(Val.getLValueBase()); @@ -6374,54 +6426,55 @@ APSInt Expr::EvaluateKnownConstInt(const ASTContext &Ctx) const { /// FIXME: Pass up a reason why! Invalid operation in i-c-e, division by zero, /// comma, etc -/// -/// FIXME: Handle offsetof. Two things to do: Handle GCC's __builtin_offsetof -/// to support gcc 4.0+ and handle the idiom GCC recognizes with a null pointer -/// cast+dereference. // CheckICE - This function does the fundamental ICE checking: the returned -// ICEDiag contains a Val of 0, 1, or 2, and a possibly null SourceLocation. +// ICEDiag contains an ICEKind indicating whether the expression is an ICE, +// and a (possibly null) SourceLocation indicating the location of the problem. +// // Note that to reduce code duplication, this helper does no evaluation // itself; the caller checks whether the expression is evaluatable, and // in the rare cases where CheckICE actually cares about the evaluated // value, it calls into Evalute. -// -// Meanings of Val: -// 0: This expression is an ICE. -// 1: This expression is not an ICE, but if it isn't evaluated, it's -// a legal subexpression for an ICE. This return value is used to handle -// the comma operator in C99 mode. -// 2: This expression is not an ICE, and is not a legal subexpression for one. namespace { +enum ICEKind { + /// This expression is an ICE. + IK_ICE, + /// This expression is not an ICE, but if it isn't evaluated, it's + /// a legal subexpression for an ICE. This return value is used to handle + /// the comma operator in C99 mode, and non-constant subexpressions. + IK_ICEIfUnevaluated, + /// This expression is not an ICE, and is not a legal subexpression for one. + IK_NotICE +}; + struct ICEDiag { - unsigned Val; + ICEKind Kind; SourceLocation Loc; - public: - ICEDiag(unsigned v, SourceLocation l) : Val(v), Loc(l) {} - ICEDiag() : Val(0) {} + ICEDiag(ICEKind IK, SourceLocation l) : Kind(IK), Loc(l) {} }; } -static ICEDiag NoDiag() { return ICEDiag(); } +static ICEDiag NoDiag() { return ICEDiag(IK_ICE, SourceLocation()); } + +static ICEDiag Worst(ICEDiag A, ICEDiag B) { return A.Kind >= B.Kind ? A : B; } static ICEDiag CheckEvalInICE(const Expr* E, ASTContext &Ctx) { Expr::EvalResult EVResult; if (!E->EvaluateAsRValue(EVResult, Ctx) || EVResult.HasSideEffects || - !EVResult.Val.isInt()) { - return ICEDiag(2, E->getLocStart()); - } + !EVResult.Val.isInt()) + return ICEDiag(IK_NotICE, E->getLocStart()); + return NoDiag(); } static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { assert(!E->isValueDependent() && "Should not see value dependent exprs!"); - if (!E->getType()->isIntegralOrEnumerationType()) { - return ICEDiag(2, E->getLocStart()); - } + if (!E->getType()->isIntegralOrEnumerationType()) + return ICEDiag(IK_NotICE, E->getLocStart()); switch (E->getStmtClass()) { #define ABSTRACT_STMT(Node) @@ -6490,7 +6543,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { case Expr::AtomicExprClass: case Expr::InitListExprClass: case Expr::LambdaExprClass: - return ICEDiag(2, E->getLocStart()); + return ICEDiag(IK_NotICE, E->getLocStart()); case Expr::SizeOfPackExprClass: case Expr::GNUNullExprClass: @@ -6525,7 +6578,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { const CallExpr *CE = cast<CallExpr>(E); if (CE->isBuiltinCall()) return CheckEvalInICE(E, Ctx); - return ICEDiag(2, E->getLocStart()); + return ICEDiag(IK_NotICE, E->getLocStart()); } case Expr::DeclRefExprClass: { if (isa<EnumConstantDecl>(cast<DeclRefExpr>(E)->getDecl())) @@ -6537,14 +6590,14 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { // getAnyInitializer() can find a default argument, which leads // to chaos. if (isa<ParmVarDecl>(D)) - return ICEDiag(2, cast<DeclRefExpr>(E)->getLocation()); + 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(2, cast<DeclRefExpr>(E)->getLocation()); + return ICEDiag(IK_NotICE, cast<DeclRefExpr>(E)->getLocation()); const VarDecl *VD; // Look for a declaration of this variable that has an initializer, and @@ -6552,10 +6605,10 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { if (Dcl->getAnyInitializer(VD) && VD->checkInitIsICE()) return NoDiag(); else - return ICEDiag(2, cast<DeclRefExpr>(E)->getLocation()); + return ICEDiag(IK_NotICE, cast<DeclRefExpr>(E)->getLocation()); } } - return ICEDiag(2, E->getLocStart()); + return ICEDiag(IK_NotICE, E->getLocStart()); } case Expr::UnaryOperatorClass: { const UnaryOperator *Exp = cast<UnaryOperator>(E); @@ -6569,7 +6622,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { // 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(2, E->getLocStart()); + return ICEDiag(IK_NotICE, E->getLocStart()); case UO_Extension: case UO_LNot: case UO_Plus: @@ -6579,23 +6632,23 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { case UO_Imag: return CheckICE(Exp->getSubExpr(), Ctx); } - + // OffsetOf falls through here. } 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); + // 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(2, E->getLocStart()); + return ICEDiag(IK_NotICE, E->getLocStart()); return NoDiag(); } case Expr::BinaryOperatorClass: { @@ -6617,7 +6670,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { // 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(2, E->getLocStart()); + return ICEDiag(IK_NotICE, E->getLocStart()); case BO_Mul: case BO_Div: @@ -6642,14 +6695,14 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { Exp->getOpcode() == BO_Rem) { // EvaluateAsRValue gives an error for undefined Div/Rem, so make sure // we don't evaluate one. - if (LHSResult.Val == 0 && RHSResult.Val == 0) { + if (LHSResult.Kind == IK_ICE && RHSResult.Kind == IK_ICE) { llvm::APSInt REval = Exp->getRHS()->EvaluateKnownConstInt(Ctx); if (REval == 0) - return ICEDiag(1, E->getLocStart()); + return ICEDiag(IK_ICEIfUnevaluated, E->getLocStart()); if (REval.isSigned() && REval.isAllOnesValue()) { llvm::APSInt LEval = Exp->getLHS()->EvaluateKnownConstInt(Ctx); if (LEval.isMinSignedValue()) - return ICEDiag(1, E->getLocStart()); + return ICEDiag(IK_ICEIfUnevaluated, E->getLocStart()); } } } @@ -6657,22 +6710,20 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { 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.Val == 0 && RHSResult.Val == 0) - return ICEDiag(1, E->getLocStart()); + if (LHSResult.Kind == IK_ICE && RHSResult.Kind == IK_ICE) + return ICEDiag(IK_ICEIfUnevaluated, E->getLocStart()); } else { // In both C89 and C++, commas in ICEs are illegal. - return ICEDiag(2, E->getLocStart()); + return ICEDiag(IK_NotICE, E->getLocStart()); } } - if (LHSResult.Val >= RHSResult.Val) - return LHSResult; - return RHSResult; + return Worst(LHSResult, RHSResult); } case BO_LAnd: case BO_LOr: { ICEDiag LHSResult = CheckICE(Exp->getLHS(), Ctx); ICEDiag RHSResult = CheckICE(Exp->getRHS(), Ctx); - if (LHSResult.Val == 0 && RHSResult.Val == 1) { + 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. @@ -6682,9 +6733,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { return NoDiag(); } - if (LHSResult.Val >= RHSResult.Val) - return LHSResult; - return RHSResult; + return Worst(LHSResult, RHSResult); } } } @@ -6709,7 +6758,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { if (FL->getValue().convertToInteger(IgnoredVal, llvm::APFloat::rmTowardZero, &Ignored) & APFloat::opInvalidOp) - return ICEDiag(2, E->getLocStart()); + return ICEDiag(IK_NotICE, E->getLocStart()); return NoDiag(); } } @@ -6722,18 +6771,18 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { case CK_IntegralCast: return CheckICE(SubExpr, Ctx); default: - return ICEDiag(2, E->getLocStart()); + return ICEDiag(IK_NotICE, E->getLocStart()); } } case Expr::BinaryConditionalOperatorClass: { const BinaryConditionalOperator *Exp = cast<BinaryConditionalOperator>(E); ICEDiag CommonResult = CheckICE(Exp->getCommon(), Ctx); - if (CommonResult.Val == 2) return CommonResult; + if (CommonResult.Kind == IK_NotICE) return CommonResult; ICEDiag FalseResult = CheckICE(Exp->getFalseExpr(), Ctx); - if (FalseResult.Val == 2) return FalseResult; - if (CommonResult.Val == 1) return CommonResult; - if (FalseResult.Val == 1 && - Exp->getCommon()->EvaluateKnownConstInt(Ctx) == 0) return NoDiag(); + 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: { @@ -6747,26 +6796,25 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { if (CallCE->isBuiltinCall() == Builtin::BI__builtin_constant_p) return CheckEvalInICE(E, Ctx); ICEDiag CondResult = CheckICE(Exp->getCond(), Ctx); - if (CondResult.Val == 2) + if (CondResult.Kind == IK_NotICE) return CondResult; ICEDiag TrueResult = CheckICE(Exp->getTrueExpr(), Ctx); ICEDiag FalseResult = CheckICE(Exp->getFalseExpr(), Ctx); - if (TrueResult.Val == 2) + if (TrueResult.Kind == IK_NotICE) return TrueResult; - if (FalseResult.Val == 2) + if (FalseResult.Kind == IK_NotICE) return FalseResult; - if (CondResult.Val == 1) + if (CondResult.Kind == IK_ICEIfUnevaluated) return CondResult; - if (TrueResult.Val == 0 && FalseResult.Val == 0) + 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) { + if (Exp->getCond()->EvaluateKnownConstInt(Ctx) == 0) return FalseResult; - } return TrueResult; } case Expr::CXXDefaultArgExprClass: @@ -6799,12 +6847,12 @@ static bool EvaluateCPlusPlus11IntegralConstantExpr(ASTContext &Ctx, } bool Expr::isIntegerConstantExpr(ASTContext &Ctx, SourceLocation *Loc) const { - if (Ctx.getLangOpts().CPlusPlus0x) + if (Ctx.getLangOpts().CPlusPlus11) return EvaluateCPlusPlus11IntegralConstantExpr(Ctx, this, 0, Loc); - ICEDiag d = CheckICE(this, Ctx); - if (d.Val != 0) { - if (Loc) *Loc = d.Loc; + ICEDiag D = CheckICE(this, Ctx); + if (D.Kind != IK_ICE) { + if (Loc) *Loc = D.Loc; return false; } return true; @@ -6812,7 +6860,7 @@ bool Expr::isIntegerConstantExpr(ASTContext &Ctx, SourceLocation *Loc) const { bool Expr::isIntegerConstantExpr(llvm::APSInt &Value, ASTContext &Ctx, SourceLocation *Loc, bool isEvaluated) const { - if (Ctx.getLangOpts().CPlusPlus0x) + if (Ctx.getLangOpts().CPlusPlus11) return EvaluateCPlusPlus11IntegralConstantExpr(Ctx, this, &Value, Loc); if (!isIntegerConstantExpr(Ctx, Loc)) @@ -6823,7 +6871,7 @@ bool Expr::isIntegerConstantExpr(llvm::APSInt &Value, ASTContext &Ctx, } bool Expr::isCXX98IntegralConstantExpr(ASTContext &Ctx) const { - return CheckICE(this, Ctx).Val == 0; + return CheckICE(this, Ctx).Kind == IK_ICE; } bool Expr::isCXX11ConstantExpr(ASTContext &Ctx, APValue *Result, @@ -6834,7 +6882,7 @@ bool Expr::isCXX11ConstantExpr(ASTContext &Ctx, APValue *Result, // Build evaluation settings. Expr::EvalStatus Status; - llvm::SmallVector<PartialDiagnosticAt, 8> Diags; + SmallVector<PartialDiagnosticAt, 8> Diags; Status.Diag = &Diags; EvalInfo Info(Ctx, Status); @@ -6853,7 +6901,7 @@ bool Expr::isCXX11ConstantExpr(ASTContext &Ctx, APValue *Result, } bool Expr::isPotentialConstantExpr(const FunctionDecl *FD, - llvm::SmallVectorImpl< + SmallVectorImpl< PartialDiagnosticAt> &Diags) { // FIXME: It would be useful to check constexpr function templates, but at the // moment the constant expression evaluator cannot cope with the non-rigorous |