diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp | 472 |
1 files changed, 303 insertions, 169 deletions
diff --git a/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp b/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp index 4cac4fa..7d7ca99 100644 --- a/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp @@ -320,7 +320,7 @@ namespace { APValue *getTemporary(const void *Key) { MapTy::iterator I = Temporaries.find(Key); - return I == Temporaries.end() ? 0 : &I->second; + return I == Temporaries.end() ? nullptr : &I->second; } APValue &createTemporary(const void *Key, bool IsLifetimeExtended); }; @@ -347,7 +347,8 @@ namespace { PartialDiagnostic *Diag; public: - explicit OptionalDiagnostic(PartialDiagnostic *Diag = 0) : Diag(Diag) {} + explicit OptionalDiagnostic(PartialDiagnostic *Diag = nullptr) + : Diag(Diag) {} template<typename T> OptionalDiagnostic &operator<<(const T &v) { @@ -474,13 +475,30 @@ namespace { /// Evaluate in any way we know how. Don't worry about side-effects that /// can't be modeled. - EM_IgnoreSideEffects + EM_IgnoreSideEffects, + + /// Evaluate as a constant expression. Stop if we find that the expression + /// is not a constant expression. Some expressions can be retried in the + /// optimizer if we don't constant fold them here, but in an unevaluated + /// context we try to fold them immediately since the optimizer never + /// gets a chance to look at it. + EM_ConstantExpressionUnevaluated, + + /// Evaluate as a potential constant expression. Keep going if we hit a + /// construct that we can't evaluate yet (because we don't yet know the + /// value of something) but stop if we hit something that could never be + /// a constant expression. Some expressions can be retried in the + /// optimizer if we don't constant fold them here, but in an unevaluated + /// context we try to fold them immediately since the optimizer never + /// gets a chance to look at it. + EM_PotentialConstantExpressionUnevaluated } EvalMode; /// Are we checking whether the expression is a potential constant /// expression? bool checkingPotentialConstantExpression() const { - return EvalMode == EM_PotentialConstantExpression; + return EvalMode == EM_PotentialConstantExpression || + EvalMode == EM_PotentialConstantExpressionUnevaluated; } /// Are we checking an expression for overflow? @@ -489,12 +507,13 @@ namespace { bool checkingForOverflow() { return EvalMode == EM_EvaluateForOverflow; } EvalInfo(const ASTContext &C, Expr::EvalStatus &S, EvaluationMode Mode) - : Ctx(const_cast<ASTContext&>(C)), EvalStatus(S), CurrentCall(0), + : Ctx(const_cast<ASTContext &>(C)), EvalStatus(S), CurrentCall(nullptr), CallStackDepth(0), NextCallIndex(1), StepsLeft(getLangOpts().ConstexprStepLimit), - BottomFrame(*this, SourceLocation(), 0, 0, 0), - EvaluatingDecl((const ValueDecl*)0), EvaluatingDeclValue(0), - HasActiveDiagnostic(false), EvalMode(Mode) {} + BottomFrame(*this, SourceLocation(), nullptr, nullptr, nullptr), + EvaluatingDecl((const ValueDecl *)nullptr), + EvaluatingDeclValue(nullptr), HasActiveDiagnostic(false), + EvalMode(Mode) {} void setEvaluatingDecl(APValue::LValueBase Base, APValue &Value) { EvaluatingDecl = Base; @@ -527,7 +546,7 @@ namespace { CallStackFrame *Frame = CurrentCall; while (Frame->Index > CallIndex) Frame = Frame->Caller; - return (Frame->Index == CallIndex) ? Frame : 0; + return (Frame->Index == CallIndex) ? Frame : nullptr; } bool nextStep(const Stmt *S) { @@ -573,6 +592,8 @@ namespace { // some later problem. case EM_ConstantExpression: case EM_PotentialConstantExpression: + case EM_ConstantExpressionUnevaluated: + case EM_PotentialConstantExpressionUnevaluated: HasActiveDiagnostic = false; return OptionalDiagnostic(); } @@ -644,11 +665,13 @@ namespace { bool keepEvaluatingAfterSideEffect() { switch (EvalMode) { case EM_PotentialConstantExpression: + case EM_PotentialConstantExpressionUnevaluated: case EM_EvaluateForOverflow: case EM_IgnoreSideEffects: return true; case EM_ConstantExpression: + case EM_ConstantExpressionUnevaluated: case EM_ConstantFold: return false; } @@ -670,10 +693,12 @@ namespace { switch (EvalMode) { case EM_PotentialConstantExpression: + case EM_PotentialConstantExpressionUnevaluated: case EM_EvaluateForOverflow: return true; case EM_ConstantExpression: + case EM_ConstantExpressionUnevaluated: case EM_ConstantFold: case EM_IgnoreSideEffects: return false; @@ -696,7 +721,9 @@ namespace { Info.EvalStatus.Diag->empty() && !Info.EvalStatus.HasSideEffects), OldMode(Info.EvalMode) { - if (Enabled && Info.EvalMode == EvalInfo::EM_ConstantExpression) + if (Enabled && + (Info.EvalMode == EvalInfo::EM_ConstantExpression || + Info.EvalMode == EvalInfo::EM_ConstantExpressionUnevaluated)) Info.EvalMode = EvalInfo::EM_ConstantFold; } void keepDiagnostics() { Enabled = false; } @@ -716,7 +743,7 @@ namespace { public: SpeculativeEvaluationRAII(EvalInfo &Info, - SmallVectorImpl<PartialDiagnosticAt> *NewDiag = 0) + SmallVectorImpl<PartialDiagnosticAt> *NewDiag = nullptr) : Info(Info), Old(Info.EvalStatus) { Info.EvalStatus.Diag = NewDiag; // If we're speculatively evaluating, we may have skipped over some @@ -943,7 +970,7 @@ namespace { // any object: we won't use such a designator for anything. if (!Info.getLangOpts().CPlusPlus11) Designator.setInvalid(); - return checkNullPointer(Info, E, CSK) && + return (CSK == CSK_ArrayToPointer || checkNullPointer(Info, E, CSK)) && Designator.checkSubobject(Info, E, CSK); } @@ -961,7 +988,7 @@ namespace { Designator.addComplexUnchecked(EltTy, Imag); } void adjustIndex(EvalInfo &Info, const Expr *E, uint64_t N) { - if (checkNullPointer(Info, E, CSK_ArrayIndex)) + if (N && checkNullPointer(Info, E, CSK_ArrayIndex)) Designator.adjustIndex(Info, E, N); } }; @@ -1141,7 +1168,7 @@ static int64_t getExtValue(const APSInt &Value) { /// Should this call expression be treated as a string literal? static bool IsStringLiteralCall(const CallExpr *E) { - unsigned Builtin = E->isBuiltinCall(); + unsigned Builtin = E->getBuiltinCallee(); return (Builtin == Builtin::BI__builtin___CFStringMakeConstantString || Builtin == Builtin::BI__builtin___NSStringMakeConstantString); } @@ -1242,11 +1269,29 @@ static bool CheckLValueConstantExpression(EvalInfo &Info, SourceLocation Loc, LVal.getLValueCallIndex() == 0) && "have call index for global lvalue"); - // Check if this is a thread-local variable. if (const ValueDecl *VD = Base.dyn_cast<const ValueDecl*>()) { if (const VarDecl *Var = dyn_cast<const VarDecl>(VD)) { + // Check if this is a thread-local variable. if (Var->getTLSKind()) return false; + + // A dllimport variable never acts like a constant. + if (Var->hasAttr<DLLImportAttr>()) + return false; + } + if (const auto *FD = dyn_cast<const FunctionDecl>(VD)) { + // __declspec(dllimport) must be handled very carefully: + // We must never initialize an expression with the thunk in C++. + // Doing otherwise would allow the same id-expression to yield + // different addresses for the same function in different translation + // units. However, this means that we must dynamically initialize the + // expression with the contents of the import address table at runtime. + // + // The C language has no notion of ODR; furthermore, it has no notion of + // dynamic initialization. This means that we are permitted to + // perform initialization with the address of the thunk. + if (Info.getLangOpts().CPlusPlus && FD->hasAttr<DLLImportAttr>()) + return false; } } @@ -1276,7 +1321,7 @@ static bool CheckLValueConstantExpression(EvalInfo &Info, SourceLocation Loc, /// Check that this core constant expression is of literal type, and if not, /// produce an appropriate diagnostic. static bool CheckLiteralType(EvalInfo &Info, const Expr *E, - const LValue *This = 0) { + const LValue *This = nullptr) { if (!E->isRValue() || E->getType()->isLiteralType(Info.Ctx)) return true; @@ -1307,6 +1352,11 @@ static bool CheckConstantExpression(EvalInfo &Info, SourceLocation DiagLoc, return false; } + // We allow _Atomic(T) to be initialized from anything that T can be + // initialized from. + if (const AtomicType *AT = Type->getAs<AtomicType>()) + Type = AT->getValueType(); + // Core issue 1454: For a literal constant expression of array or class type, // each subobject of its value shall have been initialized by a constant // expression. @@ -1338,8 +1388,7 @@ static bool CheckConstantExpression(EvalInfo &Info, SourceLocation DiagLoc, return false; } } - for (RecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end(); - I != E; ++I) { + for (const auto *I : RD->fields()) { if (!CheckConstantExpression(Info, DiagLoc, I->getType(), Value.getStructField(I->getFieldIndex()))) return false; @@ -1738,7 +1787,7 @@ static bool CastToDerivedClass(EvalInfo &Info, const Expr *E, LValue &Result, static bool HandleLValueDirectBase(EvalInfo &Info, const Expr *E, LValue &Obj, const CXXRecordDecl *Derived, const CXXRecordDecl *Base, - const ASTRecordLayout *RL = 0) { + const ASTRecordLayout *RL = nullptr) { if (!RL) { if (Derived->isInvalidDecl()) return false; RL = &Info.Ctx.getASTRecordLayout(Derived); @@ -1791,7 +1840,7 @@ static bool HandleLValueBasePath(EvalInfo &Info, const CastExpr *E, /// currently described by LVal. static bool HandleLValueMember(EvalInfo &Info, const Expr *E, LValue &LVal, const FieldDecl *FD, - const ASTRecordLayout *RL = 0) { + const ASTRecordLayout *RL = nullptr) { if (!RL) { if (FD->getParent()->isInvalidDecl()) return false; RL = &Info.Ctx.getASTRecordLayout(FD->getParent()); @@ -1807,9 +1856,8 @@ static bool HandleLValueMember(EvalInfo &Info, const Expr *E, LValue &LVal, static bool HandleLValueIndirectMember(EvalInfo &Info, const Expr *E, LValue &LVal, const IndirectFieldDecl *IFD) { - for (IndirectFieldDecl::chain_iterator C = IFD->chain_begin(), - CE = IFD->chain_end(); C != CE; ++C) - if (!HandleLValueMember(Info, E, LVal, cast<FieldDecl>(*C))) + for (const auto *C : IFD->chain()) + if (!HandleLValueMember(Info, E, LVal, cast<FieldDecl>(C))) return false; return true; } @@ -2047,7 +2095,7 @@ struct CompleteObject { /// The type of the complete object. QualType Type; - CompleteObject() : Value(0) {} + CompleteObject() : Value(nullptr) {} CompleteObject(APValue *Value, QualType Type) : Value(Value), Type(Type) { assert(Value && "missing value for complete object"); @@ -2075,7 +2123,7 @@ findSubobject(EvalInfo &Info, const Expr *E, const CompleteObject &Obj, APValue *O = Obj.Value; QualType ObjType = Obj.Type; - const FieldDecl *LastField = 0; + const FieldDecl *LastField = nullptr; // Walk the designator's path to find the subobject. for (unsigned I = 0, N = Sub.Entries.size(); /**/; ++I) { @@ -2098,7 +2146,7 @@ findSubobject(EvalInfo &Info, const Expr *E, const CompleteObject &Obj, return true; } - LastField = 0; + LastField = nullptr; if (ObjType->isArrayType()) { // Next subobject is an array element. const ConstantArrayType *CAT = Info.Ctx.getAsConstantArrayType(ObjType); @@ -2381,7 +2429,7 @@ CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E, AccessKinds AK, return CompleteObject(); } - CallStackFrame *Frame = 0; + CallStackFrame *Frame = nullptr; if (LVal.CallIndex) { Frame = Info.getCallFrame(LVal.CallIndex); if (!Frame) { @@ -2406,7 +2454,7 @@ CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E, AccessKinds AK, } // Compute value storage location and type of base object. - APValue *BaseVal = 0; + APValue *BaseVal = nullptr; QualType BaseType = getType(LVal.Base); if (const ValueDecl *D = LVal.Base.dyn_cast<const ValueDecl*>()) { @@ -2776,7 +2824,7 @@ struct IncDecSubobjectHandler { // if we're post-incrementing a complex. if (Old) { *Old = Subobj; - Old = 0; + Old = nullptr; } switch (Subobj.getKind()) { @@ -2913,6 +2961,7 @@ static bool EvaluateObjectArgument(EvalInfo &Info, const Expr *Object, if (Object->getType()->isLiteralType(Info.Ctx)) return EvaluateTemporary(Object, This, Info); + Info.Diag(Object, diag::note_constexpr_nonliteral) << Object->getType(); return false; } @@ -2934,14 +2983,14 @@ static const ValueDecl *HandleMemberPointerAccess(EvalInfo &Info, bool IncludeMember = true) { MemberPtr MemPtr; if (!EvaluateMemberPointer(RHS, MemPtr, Info)) - return 0; + return nullptr; // C++11 [expr.mptr.oper]p6: If the second operand is the null pointer to // member value, the behavior is undefined. if (!MemPtr.getDecl()) { // FIXME: Specific diagnostic. Info.Diag(RHS); - return 0; + return nullptr; } if (MemPtr.isDerivedMember()) { @@ -2951,7 +3000,7 @@ static const ValueDecl *HandleMemberPointerAccess(EvalInfo &Info, if (LV.Designator.MostDerivedPathLength + MemPtr.Path.size() > LV.Designator.Entries.size()) { Info.Diag(RHS); - return 0; + return nullptr; } unsigned PathLengthToMember = LV.Designator.Entries.size() - MemPtr.Path.size(); @@ -2961,14 +3010,14 @@ static const ValueDecl *HandleMemberPointerAccess(EvalInfo &Info, const CXXRecordDecl *MPDecl = MemPtr.Path[I]; if (LVDecl->getCanonicalDecl() != MPDecl->getCanonicalDecl()) { Info.Diag(RHS); - return 0; + return nullptr; } } // Truncate the lvalue to the appropriate derived class. if (!CastToDerivedClass(Info, RHS, LV, MemPtr.getContainingRecord(), PathLengthToMember)) - return 0; + return nullptr; } else if (!MemPtr.Path.empty()) { // Extend the LValue path with the member pointer's path. LV.Designator.Entries.reserve(LV.Designator.Entries.size() + @@ -2983,24 +3032,24 @@ static const ValueDecl *HandleMemberPointerAccess(EvalInfo &Info, for (unsigned I = 1, N = MemPtr.Path.size(); I != N; ++I) { const CXXRecordDecl *Base = MemPtr.Path[N - I - 1]; if (!HandleLValueDirectBase(Info, RHS, LV, RD, Base)) - return 0; + return nullptr; RD = Base; } // Finally cast to the class containing the member. if (!HandleLValueDirectBase(Info, RHS, LV, RD, MemPtr.getContainingRecord())) - return 0; + return nullptr; } // Add the member. Note that we cannot build bound member functions here. if (IncludeMember) { if (const FieldDecl *FD = dyn_cast<FieldDecl>(MemPtr.getDecl())) { if (!HandleLValueMember(Info, RHS, LV, FD)) - return 0; + return nullptr; } else if (const IndirectFieldDecl *IFD = dyn_cast<IndirectFieldDecl>(MemPtr.getDecl())) { if (!HandleLValueIndirectMember(Info, RHS, LV, IFD)) - return 0; + return nullptr; } else { llvm_unreachable("can't construct reference to bound member function"); } @@ -3020,7 +3069,7 @@ static const ValueDecl *HandleMemberPointerAccess(EvalInfo &Info, MemberPtr MemPtr; EvaluateMemberPointer(BO->getRHS(), MemPtr, Info); } - return 0; + return nullptr; } return HandleMemberPointerAccess(Info, BO->getLHS()->getType(), LV, @@ -3092,14 +3141,18 @@ static bool EvaluateDecl(EvalInfo &Info, const Decl *D) { Result.set(VD, Info.CurrentCall->Index); APValue &Val = Info.CurrentCall->createTemporary(VD, true); - if (!VD->getInit()) { + const Expr *InitE = VD->getInit(); + if (!InitE) { Info.Diag(D->getLocStart(), diag::note_constexpr_uninitialized) << false << VD->getType(); Val = APValue(); return false; } - if (!EvaluateInPlace(Val, Info, Result, VD->getInit())) { + if (InitE->isValueDependent()) + return false; + + if (!EvaluateInPlace(Val, Info, Result, InitE)) { // Wipe out any partially-computed value, to allow tracking that this // evaluation failed. Val = APValue(); @@ -3120,12 +3173,13 @@ static bool EvaluateCond(EvalInfo &Info, const VarDecl *CondDecl, } static EvalStmtResult EvaluateStmt(APValue &Result, EvalInfo &Info, - const Stmt *S, const SwitchCase *SC = 0); + const Stmt *S, + const SwitchCase *SC = nullptr); /// Evaluate the body of a loop, and translate the result as appropriate. static EvalStmtResult EvaluateLoopBody(APValue &Result, EvalInfo &Info, const Stmt *Body, - const SwitchCase *Case = 0) { + const SwitchCase *Case = nullptr) { BlockScopeRAII Scope(Info); switch (EvalStmtResult ESR = EvaluateStmt(Result, Info, Body, Case)) { case ESR_Break: @@ -3159,7 +3213,7 @@ static EvalStmtResult EvaluateSwitch(APValue &Result, EvalInfo &Info, // Find the switch case corresponding to the value of the condition. // FIXME: Cache this lookup. - const SwitchCase *Found = 0; + const SwitchCase *Found = nullptr; for (const SwitchCase *SC = SS->getSwitchCaseList(); SC; SC = SC->getNextSwitchCase()) { if (isa<DefaultStmt>(SC)) { @@ -3224,7 +3278,7 @@ static EvalStmtResult EvaluateStmt(APValue &Result, EvalInfo &Info, case Stmt::CaseStmtClass: case Stmt::DefaultStmtClass: if (Case == S) - Case = 0; + Case = nullptr; break; case Stmt::IfStmtClass: { @@ -3291,13 +3345,12 @@ static EvalStmtResult EvaluateStmt(APValue &Result, EvalInfo &Info, case Stmt::DeclStmtClass: { const DeclStmt *DS = cast<DeclStmt>(S); - for (DeclStmt::const_decl_iterator DclIt = DS->decl_begin(), - DclEnd = DS->decl_end(); DclIt != DclEnd; ++DclIt) { + for (const auto *DclIt : DS->decls()) { // Each declaration initialization is its own full-expression. // FIXME: This isn't quite right; if we're performing aggregate // initialization, each braced subexpression is its own full-expression. FullExpressionRAII Scope(Info); - if (!EvaluateDecl(Info, *DclIt) && !Info.keepEvaluatingAfterFailure()) + if (!EvaluateDecl(Info, DclIt) && !Info.keepEvaluatingAfterFailure()) return ESR_Failed; } return ESR_Succeeded; @@ -3315,11 +3368,10 @@ static EvalStmtResult EvaluateStmt(APValue &Result, EvalInfo &Info, BlockScopeRAII Scope(Info); const CompoundStmt *CS = cast<CompoundStmt>(S); - for (CompoundStmt::const_body_iterator BI = CS->body_begin(), - BE = CS->body_end(); BI != BE; ++BI) { - EvalStmtResult ESR = EvaluateStmt(Result, Info, *BI, Case); + for (const auto *BI : CS->body()) { + EvalStmtResult ESR = EvaluateStmt(Result, Info, BI, Case); if (ESR == ESR_Succeeded) - Case = 0; + Case = nullptr; else if (ESR != ESR_CaseNotFound) return ESR; } @@ -3368,7 +3420,7 @@ static EvalStmtResult EvaluateStmt(APValue &Result, EvalInfo &Info, EvalStmtResult ESR = EvaluateLoopBody(Result, Info, DS->getBody(), Case); if (ESR != ESR_Continue) return ESR; - Case = 0; + Case = nullptr; FullExpressionRAII CondScope(Info); if (!EvaluateAsBooleanCondition(DS->getCond(), Continue, Info)) @@ -3593,7 +3645,7 @@ static bool HandleFunctionCall(SourceLocation CallLoc, EvalStmtResult ESR = EvaluateStmt(Result, Info, Body); if (ESR == ESR_Succeeded) { - if (Callee->getResultType()->isVoidType()) + if (Callee->getReturnType()->isVoidType()) return true; Info.Diag(Callee->getLocEnd(), diag::note_constexpr_no_return); } @@ -3659,15 +3711,14 @@ static bool HandleConstructorCall(SourceLocation CallLoc, const LValue &This, #ifndef NDEBUG CXXRecordDecl::base_class_const_iterator BaseIt = RD->bases_begin(); #endif - for (CXXConstructorDecl::init_const_iterator I = Definition->init_begin(), - E = Definition->init_end(); I != E; ++I) { + for (const auto *I : Definition->inits()) { LValue Subobject = This; APValue *Value = &Result; // Determine the subobject to initialize. - FieldDecl *FD = 0; - if ((*I)->isBaseInitializer()) { - QualType BaseType((*I)->getBaseClass(), 0); + FieldDecl *FD = nullptr; + if (I->isBaseInitializer()) { + QualType BaseType(I->getBaseClass(), 0); #ifndef NDEBUG // Non-virtual base classes are initialized in the order in the class // definition. We have already checked for virtual base classes. @@ -3676,12 +3727,12 @@ static bool HandleConstructorCall(SourceLocation CallLoc, const LValue &This, "base class initializers not in expected order"); ++BaseIt; #endif - if (!HandleLValueDirectBase(Info, (*I)->getInit(), Subobject, RD, + if (!HandleLValueDirectBase(Info, I->getInit(), Subobject, RD, BaseType->getAsCXXRecordDecl(), &Layout)) return false; Value = &Result.getStructBase(BasesSeen++); - } else if ((FD = (*I)->getMember())) { - if (!HandleLValueMember(Info, (*I)->getInit(), Subobject, FD, &Layout)) + } else if ((FD = I->getMember())) { + if (!HandleLValueMember(Info, I->getInit(), Subobject, FD, &Layout)) return false; if (RD->isUnion()) { Result = APValue(FD); @@ -3689,13 +3740,11 @@ static bool HandleConstructorCall(SourceLocation CallLoc, const LValue &This, } else { Value = &Result.getStructField(FD->getFieldIndex()); } - } else if (IndirectFieldDecl *IFD = (*I)->getIndirectMember()) { + } else if (IndirectFieldDecl *IFD = I->getIndirectMember()) { // Walk the indirect field decl's chain to find the object to initialize, // and make sure we've initialized every step along it. - for (IndirectFieldDecl::chain_iterator C = IFD->chain_begin(), - CE = IFD->chain_end(); - C != CE; ++C) { - FD = cast<FieldDecl>(*C); + for (auto *C : IFD->chain()) { + FD = cast<FieldDecl>(C); CXXRecordDecl *CD = cast<CXXRecordDecl>(FD->getParent()); // Switch the union field if it differs. This happens if we had // preceding zero-initialization, and we're now initializing a union @@ -3710,7 +3759,7 @@ static bool HandleConstructorCall(SourceLocation CallLoc, const LValue &This, *Value = APValue(APValue::UninitStruct(), CD->getNumBases(), std::distance(CD->field_begin(), CD->field_end())); } - if (!HandleLValueMember(Info, (*I)->getInit(), Subobject, FD)) + if (!HandleLValueMember(Info, I->getInit(), Subobject, FD)) return false; if (CD->isUnion()) Value = &Value->getUnionValue(); @@ -3722,8 +3771,8 @@ static bool HandleConstructorCall(SourceLocation CallLoc, const LValue &This, } FullExpressionRAII InitScope(Info); - if (!EvaluateInPlace(*Value, Info, Subobject, (*I)->getInit()) || - (FD && FD->isBitField() && !truncateBitfieldValue(Info, (*I)->getInit(), + if (!EvaluateInPlace(*Value, Info, Subobject, I->getInit()) || + (FD && FD->isBitField() && !truncateBitfieldValue(Info, I->getInit(), *Value, FD))) { // If we're checking for a potential constant expression, evaluate all // initializers even if some of them fail. @@ -3742,15 +3791,14 @@ static bool HandleConstructorCall(SourceLocation CallLoc, const LValue &This, //===----------------------------------------------------------------------===// namespace { -// FIXME: RetTy is always bool. Remove it. -template <class Derived, typename RetTy=bool> +template <class Derived> class ExprEvaluatorBase - : public ConstStmtVisitor<Derived, RetTy> { + : public ConstStmtVisitor<Derived, bool> { private: - RetTy DerivedSuccess(const APValue &V, const Expr *E) { + bool DerivedSuccess(const APValue &V, const Expr *E) { return static_cast<Derived*>(this)->Success(V, E); } - RetTy DerivedZeroInitialization(const Expr *E) { + bool DerivedZeroInitialization(const Expr *E) { return static_cast<Derived*>(this)->ZeroInitialization(E); } @@ -3795,14 +3843,14 @@ private: protected: EvalInfo &Info; - typedef ConstStmtVisitor<Derived, RetTy> StmtVisitorTy; + typedef ConstStmtVisitor<Derived, bool> StmtVisitorTy; typedef ExprEvaluatorBase ExprEvaluatorBaseTy; OptionalDiagnostic CCEDiag(const Expr *E, diag::kind D) { return Info.CCEDiag(E, D); } - RetTy ZeroInitialization(const Expr *E) { return Error(E); } + bool ZeroInitialization(const Expr *E) { return Error(E); } public: ExprEvaluatorBase(EvalInfo &Info) : Info(Info) {} @@ -3819,28 +3867,28 @@ public: return Error(E, diag::note_invalid_subexpr_in_const_expr); } - RetTy VisitStmt(const Stmt *) { + bool VisitStmt(const Stmt *) { llvm_unreachable("Expression evaluator should not be called on stmts"); } - RetTy VisitExpr(const Expr *E) { + bool VisitExpr(const Expr *E) { return Error(E); } - RetTy VisitParenExpr(const ParenExpr *E) + bool VisitParenExpr(const ParenExpr *E) { return StmtVisitorTy::Visit(E->getSubExpr()); } - RetTy VisitUnaryExtension(const UnaryOperator *E) + bool VisitUnaryExtension(const UnaryOperator *E) { return StmtVisitorTy::Visit(E->getSubExpr()); } - RetTy VisitUnaryPlus(const UnaryOperator *E) + bool VisitUnaryPlus(const UnaryOperator *E) { return StmtVisitorTy::Visit(E->getSubExpr()); } - RetTy VisitChooseExpr(const ChooseExpr *E) + bool VisitChooseExpr(const ChooseExpr *E) { return StmtVisitorTy::Visit(E->getChosenSubExpr()); } - RetTy VisitGenericSelectionExpr(const GenericSelectionExpr *E) + bool VisitGenericSelectionExpr(const GenericSelectionExpr *E) { return StmtVisitorTy::Visit(E->getResultExpr()); } - RetTy VisitSubstNonTypeTemplateParmExpr(const SubstNonTypeTemplateParmExpr *E) + bool VisitSubstNonTypeTemplateParmExpr(const SubstNonTypeTemplateParmExpr *E) { return StmtVisitorTy::Visit(E->getReplacement()); } - RetTy VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *E) + bool VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *E) { return StmtVisitorTy::Visit(E->getExpr()); } - RetTy VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *E) { + bool VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *E) { // The initializer may not have been parsed yet, or might be erroneous. if (!E->getExpr()) return Error(E); @@ -3848,19 +3896,19 @@ public: } // We cannot create any objects for which cleanups are required, so there is // nothing to do here; all cleanups must come from unevaluated subexpressions. - RetTy VisitExprWithCleanups(const ExprWithCleanups *E) + bool VisitExprWithCleanups(const ExprWithCleanups *E) { return StmtVisitorTy::Visit(E->getSubExpr()); } - RetTy VisitCXXReinterpretCastExpr(const CXXReinterpretCastExpr *E) { + bool VisitCXXReinterpretCastExpr(const CXXReinterpretCastExpr *E) { CCEDiag(E, diag::note_constexpr_invalid_cast) << 0; return static_cast<Derived*>(this)->VisitCastExpr(E); } - RetTy VisitCXXDynamicCastExpr(const CXXDynamicCastExpr *E) { + bool VisitCXXDynamicCastExpr(const CXXDynamicCastExpr *E) { CCEDiag(E, diag::note_constexpr_invalid_cast) << 1; return static_cast<Derived*>(this)->VisitCastExpr(E); } - RetTy VisitBinaryOperator(const BinaryOperator *E) { + bool VisitBinaryOperator(const BinaryOperator *E) { switch (E->getOpcode()) { default: return Error(E); @@ -3882,7 +3930,7 @@ public: } } - RetTy VisitBinaryConditionalOperator(const BinaryConditionalOperator *E) { + bool VisitBinaryConditionalOperator(const BinaryConditionalOperator *E) { // Evaluate and cache the common expression. We treat it as a temporary, // even though it's not quite the same thing. if (!Evaluate(Info.CurrentCall->createTemporary(E->getOpaqueValue(), false), @@ -3892,7 +3940,7 @@ public: return HandleConditionalOperator(E); } - RetTy VisitConditionalOperator(const ConditionalOperator *E) { + bool VisitConditionalOperator(const ConditionalOperator *E) { bool IsBcpCall = false; // If the condition (ignoring parens) is a __builtin_constant_p call, // the result is a constant expression if it can be folded without @@ -3900,7 +3948,7 @@ public: // for discussion. if (const CallExpr *CallCE = dyn_cast<CallExpr>(E->getCond()->IgnoreParenCasts())) - if (CallCE->isBuiltinCall() == Builtin::BI__builtin_constant_p) + if (CallCE->getBuiltinCallee() == Builtin::BI__builtin_constant_p) IsBcpCall = true; // Always assume __builtin_constant_p(...) ? ... : ... is a potential @@ -3917,7 +3965,7 @@ public: return true; } - RetTy VisitOpaqueValueExpr(const OpaqueValueExpr *E) { + bool VisitOpaqueValueExpr(const OpaqueValueExpr *E) { if (APValue *Value = Info.CurrentCall->getTemporary(E)) return DerivedSuccess(*Value, E); @@ -3931,18 +3979,18 @@ public: return StmtVisitorTy::Visit(Source); } - RetTy VisitCallExpr(const CallExpr *E) { + bool VisitCallExpr(const CallExpr *E) { const Expr *Callee = E->getCallee()->IgnoreParens(); QualType CalleeType = Callee->getType(); - const FunctionDecl *FD = 0; - LValue *This = 0, ThisVal; + const FunctionDecl *FD = nullptr; + LValue *This = nullptr, ThisVal; ArrayRef<const Expr *> Args(E->getArgs(), E->getNumArgs()); bool HasQualifier = false; // Extract function decl and 'this' pointer from the callee. if (CalleeType->isSpecificBuiltinType(BuiltinType::BoundMember)) { - const ValueDecl *Member = 0; + const ValueDecl *Member = nullptr; 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)) @@ -4004,7 +4052,7 @@ public: isa<CXXMethodDecl>(FD) && cast<CXXMethodDecl>(FD)->isVirtual()) return Error(E, diag::note_constexpr_virtual_call); - const FunctionDecl *Definition = 0; + const FunctionDecl *Definition = nullptr; Stmt *Body = FD->getBody(Definition); APValue Result; @@ -4016,28 +4064,28 @@ public: return DerivedSuccess(Result, E); } - RetTy VisitCompoundLiteralExpr(const CompoundLiteralExpr *E) { + bool VisitCompoundLiteralExpr(const CompoundLiteralExpr *E) { return StmtVisitorTy::Visit(E->getInitializer()); } - RetTy VisitInitListExpr(const InitListExpr *E) { + bool VisitInitListExpr(const InitListExpr *E) { if (E->getNumInits() == 0) return DerivedZeroInitialization(E); if (E->getNumInits() == 1) return StmtVisitorTy::Visit(E->getInit(0)); return Error(E); } - RetTy VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E) { + bool VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E) { return DerivedZeroInitialization(E); } - RetTy VisitCXXScalarValueInitExpr(const CXXScalarValueInitExpr *E) { + bool VisitCXXScalarValueInitExpr(const CXXScalarValueInitExpr *E) { return DerivedZeroInitialization(E); } - RetTy VisitCXXNullPtrLiteralExpr(const CXXNullPtrLiteralExpr *E) { + bool VisitCXXNullPtrLiteralExpr(const CXXNullPtrLiteralExpr *E) { return DerivedZeroInitialization(E); } /// A member expression where the object is a prvalue is itself a prvalue. - RetTy VisitMemberExpr(const MemberExpr *E) { + bool VisitMemberExpr(const MemberExpr *E) { assert(!E->isArrow() && "missing call to bound member function?"); APValue Val; @@ -4061,7 +4109,7 @@ public: DerivedSuccess(Result, E); } - RetTy VisitCastExpr(const CastExpr *E) { + bool VisitCastExpr(const CastExpr *E) { switch (E->getCastKind()) { default: break; @@ -4093,13 +4141,13 @@ public: return Error(E); } - RetTy VisitUnaryPostInc(const UnaryOperator *UO) { + bool VisitUnaryPostInc(const UnaryOperator *UO) { return VisitUnaryPostIncDec(UO); } - RetTy VisitUnaryPostDec(const UnaryOperator *UO) { + bool VisitUnaryPostDec(const UnaryOperator *UO) { return VisitUnaryPostIncDec(UO); } - RetTy VisitUnaryPostIncDec(const UnaryOperator *UO) { + bool VisitUnaryPostIncDec(const UnaryOperator *UO) { if (!Info.getLangOpts().CPlusPlus1y && !Info.keepEvaluatingAfterFailure()) return Error(UO); @@ -4113,7 +4161,7 @@ public: return DerivedSuccess(RVal, UO); } - RetTy VisitStmtExpr(const StmtExpr *E) { + bool VisitStmtExpr(const StmtExpr *E) { // We will have checked the full-expressions inside the statement expression // when they were completed, and don't need to check them again now. if (Info.checkingForOverflow()) @@ -4162,11 +4210,11 @@ public: namespace { template<class Derived> class LValueExprEvaluatorBase - : public ExprEvaluatorBase<Derived, bool> { + : public ExprEvaluatorBase<Derived> { protected: LValue &Result; typedef LValueExprEvaluatorBase LValueExprEvaluatorBaseTy; - typedef ExprEvaluatorBase<Derived, bool> ExprEvaluatorBaseTy; + typedef ExprEvaluatorBase<Derived> ExprEvaluatorBaseTy; bool Success(APValue::LValueBase B) { Result.set(B); @@ -4356,7 +4404,7 @@ bool LValueExprEvaluator::VisitDeclRefExpr(const DeclRefExpr *E) { } bool LValueExprEvaluator::VisitVarDecl(const Expr *E, const VarDecl *VD) { - CallStackFrame *Frame = 0; + CallStackFrame *Frame = nullptr; if (VD->hasLocalStorage() && Info.CurrentCall->Index > 1) Frame = Info.CurrentCall; @@ -4533,7 +4581,7 @@ bool LValueExprEvaluator::VisitUnaryPreIncDec(const UnaryOperator *UO) { return handleIncDec( this->Info, UO, Result, UO->getSubExpr()->getType(), - UO->isIncrementOp(), 0); + UO->isIncrementOp(), nullptr); } bool LValueExprEvaluator::VisitCompoundAssignOperator( @@ -4584,7 +4632,7 @@ bool LValueExprEvaluator::VisitBinAssign(const BinaryOperator *E) { namespace { class PointerExprEvaluator - : public ExprEvaluatorBase<PointerExprEvaluator, bool> { + : public ExprEvaluatorBase<PointerExprEvaluator> { LValue &Result; bool Success(const Expr *E) { @@ -4601,7 +4649,7 @@ public: return true; } bool ZeroInitialization(const Expr *E) { - return Success((Expr*)0); + return Success((Expr*)nullptr); } bool VisitBinaryOperator(const BinaryOperator *E); @@ -4623,8 +4671,13 @@ public: // Can't look at 'this' when checking a potential constant expression. if (Info.checkingPotentialConstantExpression()) return false; - if (!Info.CurrentCall->This) - return Error(E); + if (!Info.CurrentCall->This) { + if (Info.getLangOpts().CPlusPlus11) + Info.Diag(E, diag::note_constexpr_this) << E->isImplicit(); + else + Info.Diag(E); + return false; + } Result = *Info.CurrentCall->This; return true; } @@ -4729,7 +4782,7 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr* E) { if (Value.isInt()) { unsigned Size = Info.Ctx.getTypeSize(E->getType()); uint64_t N = Value.getInt().extOrTrunc(Size).getZExtValue(); - Result.Base = (Expr*)0; + Result.Base = (Expr*)nullptr; Result.Offset = CharUnits::fromQuantity(N); Result.CallIndex = 0; Result.Designator.setInvalid(); @@ -4769,7 +4822,7 @@ bool PointerExprEvaluator::VisitCallExpr(const CallExpr *E) { if (IsStringLiteralCall(E)) return Success(E); - switch (E->isBuiltinCall()) { + switch (E->getBuiltinCallee()) { case Builtin::BI__builtin_addressof: return EvaluateLValue(E->getArg(0), Result, Info); @@ -4784,7 +4837,7 @@ bool PointerExprEvaluator::VisitCallExpr(const CallExpr *E) { namespace { class MemberPointerExprEvaluator - : public ExprEvaluatorBase<MemberPointerExprEvaluator, bool> { + : public ExprEvaluatorBase<MemberPointerExprEvaluator> { MemberPtr &Result; bool Success(const ValueDecl *D) { @@ -4801,7 +4854,7 @@ public: return true; } bool ZeroInitialization(const Expr *E) { - return Success((const ValueDecl*)0); + return Success((const ValueDecl*)nullptr); } bool VisitCastExpr(const CastExpr *E); @@ -4872,7 +4925,7 @@ bool MemberPointerExprEvaluator::VisitUnaryAddrOf(const UnaryOperator *E) { namespace { class RecordExprEvaluator - : public ExprEvaluatorBase<RecordExprEvaluator, bool> { + : public ExprEvaluatorBase<RecordExprEvaluator> { const LValue &This; APValue &Result; public: @@ -4925,14 +4978,13 @@ static bool HandleClassZeroInitialization(EvalInfo &Info, const Expr *E, } } - for (RecordDecl::field_iterator I = RD->field_begin(), End = RD->field_end(); - I != End; ++I) { + for (const auto *I : RD->fields()) { // -- if T is a reference type, no initialization is performed. if (I->getType()->isReferenceType()) continue; LValue Subobject = This; - if (!HandleLValueMember(Info, E, Subobject, *I, &Layout)) + if (!HandleLValueMember(Info, E, Subobject, I, &Layout)) return false; ImplicitValueInitExpr VIE(I->getType()); @@ -4952,7 +5004,7 @@ bool RecordExprEvaluator::ZeroInitialization(const Expr *E) { // object's first non-static named data member is zero-initialized RecordDecl::field_iterator I = RD->field_begin(); if (I == RD->field_end()) { - Result = APValue((const FieldDecl*)0); + Result = APValue((const FieldDecl*)nullptr); return true; } @@ -5040,8 +5092,7 @@ bool RecordExprEvaluator::VisitInitListExpr(const InitListExpr *E) { std::distance(RD->field_begin(), RD->field_end())); unsigned ElementNo = 0; bool Success = true; - for (RecordDecl::field_iterator Field = RD->field_begin(), - FieldEnd = RD->field_end(); Field != FieldEnd; ++Field) { + for (const auto *Field : RD->fields()) { // Anonymous bit-fields are not considered members of the class for // purposes of aggregate initialization. if (Field->isUnnamedBitfield()) @@ -5054,7 +5105,7 @@ bool RecordExprEvaluator::VisitInitListExpr(const InitListExpr *E) { // FIXME: Diagnostics here should point to the end of the initializer // list, not the start. if (!HandleLValueMember(Info, HaveInit ? E->getInit(ElementNo) : E, - Subobject, *Field, &Layout)) + Subobject, Field, &Layout)) return false; // Perform an implicit value-initialization for members beyond the end of @@ -5069,7 +5120,7 @@ bool RecordExprEvaluator::VisitInitListExpr(const InitListExpr *E) { APValue &FieldVal = Result.getStructField(Field->getFieldIndex()); if (!EvaluateInPlace(FieldVal, Info, Subobject, Init) || (Field->isBitField() && !truncateBitfieldValue(Info, Init, - FieldVal, *Field))) { + FieldVal, Field))) { if (!Info.keepEvaluatingAfterFailure()) return false; Success = false; @@ -5100,7 +5151,7 @@ bool RecordExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E) { return ZeroInitialization(E); } - const FunctionDecl *Definition = 0; + const FunctionDecl *Definition = nullptr; FD->getBody(Definition); if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition)) @@ -5234,7 +5285,7 @@ static bool EvaluateTemporary(const Expr *E, LValue &Result, EvalInfo &Info) { namespace { class VectorExprEvaluator - : public ExprEvaluatorBase<VectorExprEvaluator, bool> { + : public ExprEvaluatorBase<VectorExprEvaluator> { APValue &Result; public: @@ -5415,7 +5466,7 @@ bool VectorExprEvaluator::VisitUnaryImag(const UnaryOperator *E) { namespace { class ArrayExprEvaluator - : public ExprEvaluatorBase<ArrayExprEvaluator, bool> { + : public ExprEvaluatorBase<ArrayExprEvaluator> { const LValue &This; APValue &Result; public: @@ -5487,7 +5538,7 @@ bool ArrayExprEvaluator::VisitInitListExpr(const InitListExpr *E) { unsigned NumEltsToInit = E->getNumInits(); unsigned NumElts = CAT->getSize().getZExtValue(); - const Expr *FillerExpr = E->hasArrayFiller() ? E->getArrayFiller() : 0; + const Expr *FillerExpr = E->hasArrayFiller() ? E->getArrayFiller() : nullptr; // If the initializer might depend on the array index, run it for each // array element. For now, just whitelist non-class value-initialization. @@ -5582,7 +5633,7 @@ bool ArrayExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E, return EvaluateInPlace(*Value, Info, Subobject, &VIE); } - const FunctionDecl *Definition = 0; + const FunctionDecl *Definition = nullptr; FD->getBody(Definition); if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition)) @@ -5610,7 +5661,7 @@ bool ArrayExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E, namespace { class IntExprEvaluator - : public ExprEvaluatorBase<IntExprEvaluator, bool> { + : public ExprEvaluatorBase<IntExprEvaluator> { APValue &Result; public: IntExprEvaluator(EvalInfo &info, APValue &result) @@ -5716,14 +5767,6 @@ public: return ZeroInitialization(E); } - bool VisitUnaryTypeTraitExpr(const UnaryTypeTraitExpr *E) { - return Success(E->getValue(), E); - } - - bool VisitBinaryTypeTraitExpr(const BinaryTypeTraitExpr *E) { - return Success(E->getValue(), E); - } - bool VisitTypeTraitExpr(const TypeTraitExpr *E) { return Success(E->getValue(), E); } @@ -5964,7 +6007,7 @@ bool IntExprEvaluator::TryEvaluateBuiltinObjectSize(const CallExpr *E) { } bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) { - switch (unsigned BuiltinOp = E->isBuiltinCall()) { + switch (unsigned BuiltinOp = E->getBuiltinCallee()) { default: return ExprEvaluatorBaseTy::VisitCallExpr(E); @@ -5983,7 +6026,17 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) { // Expression had no side effects, but we couldn't statically determine the // size of the referenced object. - return Error(E); + switch (Info.EvalMode) { + case EvalInfo::EM_ConstantExpression: + case EvalInfo::EM_PotentialConstantExpression: + case EvalInfo::EM_ConstantFold: + case EvalInfo::EM_EvaluateForOverflow: + case EvalInfo::EM_IgnoreSideEffects: + return Error(E); + case EvalInfo::EM_ConstantExpressionUnevaluated: + case EvalInfo::EM_PotentialConstantExpressionUnevaluated: + return Success(-1ULL, E); + } } case Builtin::BI__builtin_bswap16: @@ -6005,7 +6058,8 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) { case Builtin::BI__builtin_clz: case Builtin::BI__builtin_clzl: - case Builtin::BI__builtin_clzll: { + case Builtin::BI__builtin_clzll: + case Builtin::BI__builtin_clzs: { APSInt Val; if (!EvaluateInteger(E->getArg(0), Val, Info)) return false; @@ -6020,7 +6074,8 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) { case Builtin::BI__builtin_ctz: case Builtin::BI__builtin_ctzl: - case Builtin::BI__builtin_ctzll: { + case Builtin::BI__builtin_ctzll: + case Builtin::BI__builtin_ctzs: { APSInt Val; if (!EvaluateInteger(E->getArg(0), Val, Info)) return false; @@ -6256,11 +6311,11 @@ class DataRecursiveIntBinOpEvaluator { const Expr *E; EvalResult LHSResult; // meaningful only for binary operator expression. enum { AnyExprKind, BinOpKind, BinOpVisitedLHSKind } Kind; - - Job() : StoredInfo(0) { } + + Job() : StoredInfo(nullptr) {} void startSpeculativeEval(EvalInfo &Info) { OldEvalStatus = Info.EvalStatus; - Info.EvalStatus.Diag = 0; + Info.EvalStatus.Diag = nullptr; StoredInfo = &Info; } ~Job() { @@ -6886,8 +6941,9 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { } CharUnits IntExprEvaluator::GetAlignOfType(QualType T) { - // C++ [expr.alignof]p3: "When alignof is applied to a reference type, the - // result shall be the alignment of the referenced type." + // C++ [expr.alignof]p3: + // When alignof is applied to a reference type, the result is the + // alignment of the referenced type. if (const ReferenceType *Ref = T->getAs<ReferenceType>()) T = Ref->getPointeeType(); @@ -6906,7 +6962,7 @@ CharUnits IntExprEvaluator::GetAlignOfExpr(const Expr *E) { // alignof decl is always accepted, even if it doesn't make sense: we default // to 1 in those cases. if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) - return Info.Ctx.getDeclAlign(DRE->getDecl(), + return Info.Ctx.getDeclAlign(DRE->getDecl(), /*RefAsPointee*/true); if (const MemberExpr *ME = dyn_cast<MemberExpr>(E)) @@ -7109,6 +7165,7 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) { case CK_BuiltinFnToFnPtr: case CK_ZeroToOCLEvent: case CK_NonAtomicToAtomic: + case CK_AddressSpaceConversion: llvm_unreachable("invalid cast kind for integral value"); case CK_BitCast: @@ -7247,7 +7304,7 @@ bool IntExprEvaluator::VisitCXXNoexceptExpr(const CXXNoexceptExpr *E) { namespace { class FloatExprEvaluator - : public ExprEvaluatorBase<FloatExprEvaluator, bool> { + : public ExprEvaluatorBase<FloatExprEvaluator> { APFloat &Result; public: FloatExprEvaluator(EvalInfo &info, APFloat &result) @@ -7308,7 +7365,7 @@ static bool TryEvaluateBuiltinNaN(const ASTContext &Context, } bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) { - switch (E->isBuiltinCall()) { + switch (E->getBuiltinCallee()) { default: return ExprEvaluatorBaseTy::VisitCallExpr(E); @@ -7463,7 +7520,7 @@ bool FloatExprEvaluator::VisitCastExpr(const CastExpr *E) { namespace { class ComplexExprEvaluator - : public ExprEvaluatorBase<ComplexExprEvaluator, bool> { + : public ExprEvaluatorBase<ComplexExprEvaluator> { ComplexValue &Result; public: @@ -7581,6 +7638,7 @@ bool ComplexExprEvaluator::VisitCastExpr(const CastExpr *E) { case CK_BuiltinFnToFnPtr: case CK_ZeroToOCLEvent: case CK_NonAtomicToAtomic: + case CK_AddressSpaceConversion: llvm_unreachable("invalid cast kind for complex value"); case CK_LValueToRValue: @@ -7847,7 +7905,7 @@ bool ComplexExprEvaluator::VisitInitListExpr(const InitListExpr *E) { namespace { class AtomicExprEvaluator : - public ExprEvaluatorBase<AtomicExprEvaluator, bool> { + public ExprEvaluatorBase<AtomicExprEvaluator> { APValue &Result; public: AtomicExprEvaluator(EvalInfo &Info, APValue &Result) @@ -7887,7 +7945,7 @@ static bool EvaluateAtomic(const Expr *E, APValue &Result, EvalInfo &Info) { namespace { class VoidExprEvaluator - : public ExprEvaluatorBase<VoidExprEvaluator, bool> { + : public ExprEvaluatorBase<VoidExprEvaluator> { public: VoidExprEvaluator(EvalInfo &Info) : ExprEvaluatorBaseTy(Info) {} @@ -7902,6 +7960,16 @@ public: return true; } } + + bool VisitCallExpr(const CallExpr *E) { + switch (E->getBuiltinCallee()) { + default: + return ExprEvaluatorBaseTy::VisitCallExpr(E); + case Builtin::BI__assume: + // The argument is not evaluated! + return true; + } + } }; } // end anonymous namespace @@ -7989,6 +8057,8 @@ static bool Evaluate(APValue &Result, EvalInfo &Info, const Expr *E) { /// an object can indirectly refer to subobjects which were initialized earlier. static bool EvaluateInPlace(APValue &Result, EvalInfo &Info, const LValue &This, const Expr *E, bool AllowNonLiteralTypes) { + assert(!E->isValueDependent()); + if (!AllowNonLiteralTypes && !CheckLiteralType(Info, E, &This)) return false; @@ -8008,6 +8078,9 @@ static bool EvaluateInPlace(APValue &Result, EvalInfo &Info, const LValue &This, /// 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) { + if (E->getType().isNull()) + return false; + if (!CheckLiteralType(Info, E)) return false; @@ -8035,6 +8108,13 @@ static bool FastEvaluateAsRValue(const Expr *Exp, Expr::EvalResult &Result, IsConst = true; return true; } + + // This case should be rare, but we need to check it before we check on + // the type below. + if (Exp->getType().isNull()) { + IsConst = false; + return true; + } // FIXME: Evaluating values of large array and record types can cause // performance problems. Only do so in C++11 for now. @@ -8292,10 +8372,20 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) { case Expr::MaterializeTemporaryExprClass: case Expr::PseudoObjectExprClass: case Expr::AtomicExprClass: - case Expr::InitListExprClass: case Expr::LambdaExprClass: return ICEDiag(IK_NotICE, E->getLocStart()); + case Expr::InitListExprClass: { + // C++03 [dcl.init]p13: If T is a scalar type, then a declaration of the + // form "T x = { a };" is equivalent to "T x = a;". + // Unless we're initializing a reference, T is a scalar as it is known to be + // of integral or enumeration type. + if (E->isRValue()) + if (cast<InitListExpr>(E)->getNumInits() == 1) + return CheckICE(cast<InitListExpr>(E)->getInit(0), Ctx); + return ICEDiag(IK_NotICE, E->getLocStart()); + } + case Expr::SizeOfPackExprClass: case Expr::GNUNullExprClass: // GCC considers the GNU __null value to be an integral constant expression. @@ -8314,8 +8404,6 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) { case Expr::ObjCBoolLiteralExprClass: case Expr::CXXBoolLiteralExprClass: case Expr::CXXScalarValueInitExprClass: - case Expr::UnaryTypeTraitExprClass: - case Expr::BinaryTypeTraitExprClass: case Expr::TypeTraitExprClass: case Expr::ArrayTypeTraitExprClass: case Expr::ExpressionTraitExprClass: @@ -8327,7 +8415,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) { // constant expressions, but they can never be ICEs because an ICE cannot // contain an operand of (pointer to) function type. const CallExpr *CE = cast<CallExpr>(E); - if (CE->isBuiltinCall()) + if (CE->getBuiltinCallee()) return CheckEvalInICE(E, Ctx); return ICEDiag(IK_NotICE, E->getLocStart()); } @@ -8544,7 +8632,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) { // extension. See GCC PR38377 for discussion. if (const CallExpr *CallCE = dyn_cast<CallExpr>(Exp->getCond()->IgnoreParenCasts())) - if (CallCE->isBuiltinCall() == Builtin::BI__builtin_constant_p) + if (CallCE->getBuiltinCallee() == Builtin::BI__builtin_constant_p) return CheckEvalInICE(E, Ctx); ICEDiag CondResult = CheckICE(Exp->getCond(), Ctx); if (CondResult.Kind == IK_NotICE) @@ -8602,7 +8690,7 @@ static bool EvaluateCPlusPlus11IntegralConstantExpr(const ASTContext &Ctx, bool Expr::isIntegerConstantExpr(const ASTContext &Ctx, SourceLocation *Loc) const { if (Ctx.getLangOpts().CPlusPlus11) - return EvaluateCPlusPlus11IntegralConstantExpr(Ctx, this, 0, Loc); + return EvaluateCPlusPlus11IntegralConstantExpr(Ctx, this, nullptr, Loc); ICEDiag D = CheckICE(this, Ctx); if (D.Kind != IK_ICE) { @@ -8654,6 +8742,28 @@ bool Expr::isCXX11ConstantExpr(const ASTContext &Ctx, APValue *Result, return IsConstExpr; } +bool Expr::EvaluateWithSubstitution(APValue &Value, ASTContext &Ctx, + const FunctionDecl *Callee, + ArrayRef<const Expr*> Args) const { + Expr::EvalStatus Status; + EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantExpressionUnevaluated); + + ArgVector ArgValues(Args.size()); + for (ArrayRef<const Expr*>::iterator I = Args.begin(), E = Args.end(); + I != E; ++I) { + if (!Evaluate(ArgValues[I - Args.begin()], Info, *I)) + // If evaluation fails, throw away the argument entirely. + ArgValues[I - Args.begin()] = APValue(); + if (Info.EvalStatus.HasSideEffects) + return false; + } + + // Build fake call to Callee. + CallStackFrame Frame(Info, Callee->getLocation(), Callee, /*This*/nullptr, + ArgValues.data()); + return Evaluate(Value, Info, this) && !Info.EvalStatus.HasSideEffects; +} + bool Expr::isPotentialConstantExpr(const FunctionDecl *FD, SmallVectorImpl< PartialDiagnosticAt> &Diags) { @@ -8670,7 +8780,7 @@ bool Expr::isPotentialConstantExpr(const FunctionDecl *FD, EvalInfo::EM_PotentialConstantExpression); const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD); - const CXXRecordDecl *RD = MD ? MD->getParent()->getCanonicalDecl() : 0; + const CXXRecordDecl *RD = MD ? MD->getParent()->getCanonicalDecl() : nullptr; // Fabricate an arbitrary expression on the stack and pretend that it // is a temporary being used as the 'this' pointer. @@ -8689,8 +8799,32 @@ bool Expr::isPotentialConstantExpr(const FunctionDecl *FD, Info.setEvaluatingDecl(This.getLValueBase(), Scratch); HandleConstructorCall(Loc, This, Args, CD, Info, Scratch); } else - HandleFunctionCall(Loc, FD, (MD && MD->isInstance()) ? &This : 0, + HandleFunctionCall(Loc, FD, (MD && MD->isInstance()) ? &This : nullptr, Args, FD->getBody(), Info, Scratch); return Diags.empty(); } + +bool Expr::isPotentialConstantExprUnevaluated(Expr *E, + const FunctionDecl *FD, + SmallVectorImpl< + PartialDiagnosticAt> &Diags) { + Expr::EvalStatus Status; + Status.Diag = &Diags; + + EvalInfo Info(FD->getASTContext(), Status, + EvalInfo::EM_PotentialConstantExpressionUnevaluated); + + // Fabricate a call stack frame to give the arguments a plausible cover story. + ArrayRef<const Expr*> Args; + ArgVector ArgValues(0); + bool Success = EvaluateArgs(Args, ArgValues, Info); + (void)Success; + assert(Success && + "Failed to set up arguments for potential constant evaluation"); + CallStackFrame Frame(Info, SourceLocation(), FD, nullptr, ArgValues.data()); + + APValue ResultScratch; + Evaluate(ResultScratch, Info, E); + return Diags.empty(); +} |