diff options
Diffstat (limited to 'lib/AST/ExprConstant.cpp')
-rw-r--r-- | lib/AST/ExprConstant.cpp | 570 |
1 files changed, 411 insertions, 159 deletions
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index 44cf75dbd25b2..da093ff22c123 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -39,11 +39,13 @@ #include "clang/AST/ASTLambda.h" #include "clang/AST/CharUnits.h" #include "clang/AST/Expr.h" +#include "clang/AST/OSLog.h" #include "clang/AST/RecordLayout.h" #include "clang/AST/StmtVisitor.h" #include "clang/AST/TypeLoc.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/TargetInfo.h" +#include "llvm/Support/SaveAndRestore.h" #include "llvm/Support/raw_ostream.h" #include <cstring> #include <functional> @@ -143,8 +145,8 @@ namespace { // If we're doing a variable assignment from e.g. malloc(N), there will // probably be a cast of some kind. In exotic cases, we might also see a // top-level ExprWithCleanups. Ignore them either way. - if (const auto *EC = dyn_cast<ExprWithCleanups>(E)) - E = EC->getSubExpr()->IgnoreParens(); + if (const auto *FE = dyn_cast<FullExpr>(E)) + E = FE->getSubExpr()->IgnoreParens(); if (const auto *Cast = dyn_cast<CastExpr>(E)) E = Cast->getSubExpr()->IgnoreParens(); @@ -350,6 +352,7 @@ namespace { /// Get the type of the designated object. QualType getType(ASTContext &Ctx) const { + assert(!Invalid && "invalid designator has no subobject type"); return MostDerivedPathLength == Entries.size() ? MostDerivedType : Ctx.getRecordType(getAsBaseClass(Entries.back())); @@ -504,7 +507,7 @@ namespace { } // FIXME: Adding this to every 'CallStackFrame' may have a nontrivial impact - // on the overall stack usage of deeply-recursing constexpr evaluataions. + // on the overall stack usage of deeply-recursing constexpr evaluations. // (We should cache this map rather than recomputing it repeatedly.) // But let's try this and see how it goes; we can look into caching the map // as a later change. @@ -719,6 +722,10 @@ namespace { /// Whether or not we're currently speculatively evaluating. bool IsSpeculativelyEvaluating; + /// Whether or not we're in a context where the front end requires a + /// constant value. + bool InConstantContext; + enum EvaluationMode { /// Evaluate as a constant expression. Stop if we find that the expression /// is not a constant expression. @@ -758,18 +765,6 @@ namespace { /// context we try to fold them immediately since the optimizer never /// gets a chance to look at it. EM_PotentialConstantExpressionUnevaluated, - - /// Evaluate as a constant expression. In certain scenarios, if: - /// - we find a MemberExpr with a base that can't be evaluated, or - /// - we find a variable initialized with a call to a function that has - /// the alloc_size attribute on it - /// then we may consider evaluation to have succeeded. - /// - /// In either case, the LValue returned shall have an invalid base; in the - /// former, the base will be the invalid MemberExpr, in the latter, the - /// base will be either the alloc_size CallExpr or a CastExpr wrapping - /// said CallExpr. - EM_OffsetFold, } EvalMode; /// Are we checking whether the expression is a potential constant @@ -792,7 +787,7 @@ namespace { EvaluatingDecl((const ValueDecl *)nullptr), EvaluatingDeclValue(nullptr), HasActiveDiagnostic(false), HasFoldFailureDiagnostic(false), IsSpeculativelyEvaluating(false), - EvalMode(Mode) {} + InConstantContext(false), EvalMode(Mode) {} void setEvaluatingDecl(APValue::LValueBase Base, APValue &Value) { EvaluatingDecl = Base; @@ -831,7 +826,7 @@ namespace { bool nextStep(const Stmt *S) { if (!StepsLeft) { - FFDiag(S->getLocStart(), diag::note_constexpr_step_limit_exceeded); + FFDiag(S->getBeginLoc(), diag::note_constexpr_step_limit_exceeded); return false; } --StepsLeft; @@ -873,7 +868,6 @@ namespace { case EM_PotentialConstantExpression: case EM_ConstantExpressionUnevaluated: case EM_PotentialConstantExpressionUnevaluated: - case EM_OffsetFold: HasActiveDiagnostic = false; return OptionalDiagnostic(); } @@ -965,7 +959,6 @@ namespace { case EM_ConstantExpression: case EM_ConstantExpressionUnevaluated: case EM_ConstantFold: - case EM_OffsetFold: return false; } llvm_unreachable("Missed EvalMode case"); @@ -984,7 +977,6 @@ namespace { case EM_EvaluateForOverflow: case EM_IgnoreSideEffects: case EM_ConstantFold: - case EM_OffsetFold: return true; case EM_PotentialConstantExpression: @@ -1020,7 +1012,6 @@ namespace { case EM_ConstantExpressionUnevaluated: case EM_ConstantFold: case EM_IgnoreSideEffects: - case EM_OffsetFold: return false; } llvm_unreachable("Missed EvalMode case"); @@ -1092,18 +1083,18 @@ namespace { } }; - /// RAII object used to treat the current evaluation as the correct pointer - /// offset fold for the current EvalMode - struct FoldOffsetRAII { + /// RAII object used to set the current evaluation mode to ignore + /// side-effects. + struct IgnoreSideEffectsRAII { EvalInfo &Info; EvalInfo::EvaluationMode OldMode; - explicit FoldOffsetRAII(EvalInfo &Info) + explicit IgnoreSideEffectsRAII(EvalInfo &Info) : Info(Info), OldMode(Info.EvalMode) { if (!Info.checkingPotentialConstantExpression()) - Info.EvalMode = EvalInfo::EM_OffsetFold; + Info.EvalMode = EvalInfo::EM_IgnoreSideEffects; } - ~FoldOffsetRAII() { Info.EvalMode = OldMode; } + ~IgnoreSideEffectsRAII() { Info.EvalMode = OldMode; } }; /// RAII object used to optionally suppress diagnostics and side-effects from @@ -1299,6 +1290,14 @@ void EvalInfo::addCallStack(unsigned Limit) { } } +/// Kinds of access we can perform on an object, for diagnostics. +enum AccessKinds { + AK_Read, + AK_Assign, + AK_Increment, + AK_Decrement +}; + namespace { struct ComplexValue { private: @@ -1404,21 +1403,36 @@ namespace { set(B, true); } + private: // Check that this LValue is not based on a null pointer. If it is, produce // a diagnostic and mark the designator as invalid. - bool checkNullPointer(EvalInfo &Info, const Expr *E, - CheckSubobjectKind CSK) { + template <typename GenDiagType> + bool checkNullPointerDiagnosingWith(const GenDiagType &GenDiag) { if (Designator.Invalid) return false; if (IsNullPtr) { - Info.CCEDiag(E, diag::note_constexpr_null_subobject) - << CSK; + GenDiag(); Designator.setInvalid(); return false; } return true; } + public: + bool checkNullPointer(EvalInfo &Info, const Expr *E, + CheckSubobjectKind CSK) { + return checkNullPointerDiagnosingWith([&Info, E, CSK] { + Info.CCEDiag(E, diag::note_constexpr_null_subobject) << CSK; + }); + } + + bool checkNullPointerForFoldAccess(EvalInfo &Info, const Expr *E, + AccessKinds AK) { + return checkNullPointerDiagnosingWith([&Info, E, AK] { + Info.FFDiag(E, diag::note_constexpr_access_null) << AK; + }); + } + // Check this LValue refers to an object. If not, set the designator to be // invalid and emit a diagnostic. bool checkSubobject(EvalInfo &Info, const Expr *E, CheckSubobjectKind CSK) { @@ -2088,11 +2102,12 @@ static APSInt HandleIntToIntCast(EvalInfo &Info, const Expr *E, QualType DestType, QualType SrcType, const APSInt &Value) { unsigned DestWidth = Info.Ctx.getIntWidth(DestType); - APSInt Result = Value; // Figure out if this is a truncate, extend or noop cast. // If the input is signed, do a sign extend, noop, or truncate. - Result = Result.extOrTrunc(DestWidth); + APSInt Result = Value.extOrTrunc(DestWidth); Result.setIsUnsigned(DestType->isUnsignedIntegerOrEnumerationType()); + if (DestType->isBooleanType()) + Result = Value.getBoolValue(); return Result; } @@ -2553,8 +2568,8 @@ static bool evaluateVarDeclInit(EvalInfo &Info, const Expr *E, if (Info.checkingPotentialConstantExpression()) return false; // FIXME: implement capture evaluation during constant expr evaluation. - Info.FFDiag(E->getLocStart(), - diag::note_unimplemented_constexpr_lambda_feature_ast) + Info.FFDiag(E->getBeginLoc(), + diag::note_unimplemented_constexpr_lambda_feature_ast) << "captures not currently allowed"; return false; } @@ -2754,14 +2769,6 @@ static bool diagnoseUnreadableFields(EvalInfo &Info, const Expr *E, return false; } -/// Kinds of access we can perform on an object, for diagnostics. -enum AccessKinds { - AK_Read, - AK_Assign, - AK_Increment, - AK_Decrement -}; - namespace { /// A handle to a complete object (an object that is not a subobject of /// another object). @@ -3432,19 +3439,31 @@ struct CompoundAssignSubobjectHandler { if (!checkConst(SubobjType)) return false; - if (!SubobjType->isIntegerType() || !RHS.isInt()) { + if (!SubobjType->isIntegerType()) { // We don't support compound assignment on integer-cast-to-pointer // values. Info.FFDiag(E); return false; } - APSInt LHS = HandleIntToIntCast(Info, E, PromotedLHSType, - SubobjType, Value); - if (!handleIntIntBinOp(Info, E, LHS, Opcode, RHS.getInt(), LHS)) - return false; - Value = HandleIntToIntCast(Info, E, SubobjType, PromotedLHSType, LHS); - return true; + if (RHS.isInt()) { + APSInt LHS = + HandleIntToIntCast(Info, E, PromotedLHSType, SubobjType, Value); + if (!handleIntIntBinOp(Info, E, LHS, Opcode, RHS.getInt(), LHS)) + return false; + Value = HandleIntToIntCast(Info, E, SubobjType, PromotedLHSType, LHS); + return true; + } else if (RHS.isFloat()) { + APFloat FValue(0.0); + return HandleIntToFloatCast(Info, E, SubobjType, Value, PromotedLHSType, + FValue) && + handleFloatFloatBinOp(Info, E, FValue, Opcode, RHS.getFloat()) && + HandleFloatToIntCast(Info, E, PromotedLHSType, FValue, SubobjType, + Value); + } + + Info.FFDiag(E); + return false; } bool found(APFloat &Value, QualType SubobjType) { return checkConst(SubobjType) && @@ -3844,8 +3863,8 @@ static bool EvaluateVarDecl(EvalInfo &Info, const VarDecl *VD) { const Expr *InitE = VD->getInit(); if (!InitE) { - Info.FFDiag(VD->getLocStart(), diag::note_constexpr_uninitialized) - << false << VD->getType(); + Info.FFDiag(VD->getBeginLoc(), diag::note_constexpr_uninitialized) + << false << VD->getType(); Val = APValue(); return false; } @@ -3990,7 +4009,8 @@ static EvalStmtResult EvaluateSwitch(StmtResult &Result, EvalInfo &Info, case ESR_CaseNotFound: // This can only happen if the switch case is nested within a statement // expression. We have no intention of supporting that. - Info.FFDiag(Found->getLocStart(), diag::note_constexpr_stmt_expr_unsupported); + Info.FFDiag(Found->getBeginLoc(), + diag::note_constexpr_stmt_expr_unsupported); return ESR_Failed; } llvm_unreachable("Invalid EvalStmtResult!"); @@ -4081,7 +4101,7 @@ static EvalStmtResult EvaluateStmt(StmtResult &Result, EvalInfo &Info, return ESR_Succeeded; } - Info.FFDiag(S->getLocStart()); + Info.FFDiag(S->getBeginLoc()); return ESR_Failed; case Stmt::NullStmtClass: @@ -4215,6 +4235,13 @@ static EvalStmtResult EvaluateStmt(StmtResult &Result, EvalInfo &Info, const CXXForRangeStmt *FS = cast<CXXForRangeStmt>(S); BlockScopeRAII Scope(Info); + // Evaluate the init-statement if present. + if (FS->getInit()) { + EvalStmtResult ESR = EvaluateStmt(Result, Info, FS->getInit()); + if (ESR != ESR_Succeeded) + return ESR; + } + // Initialize the __range variable. EvalStmtResult ESR = EvaluateStmt(Result, Info, FS->getRangeStmt()); if (ESR != ESR_Succeeded) @@ -4279,6 +4306,9 @@ static EvalStmtResult EvaluateStmt(StmtResult &Result, EvalInfo &Info, case Stmt::CaseStmtClass: case Stmt::DefaultStmtClass: return EvaluateStmt(Result, Info, cast<SwitchCase>(S)->getSubStmt(), Case); + case Stmt::CXXTryStmtClass: + // Evaluate try blocks by evaluating all sub statements. + return EvaluateStmt(Result, Info, cast<CXXTryStmt>(S)->getTryBlock(), Case); } } @@ -4321,10 +4351,13 @@ static bool CheckConstexprFunction(EvalInfo &Info, SourceLocation CallLoc, Declaration->isConstexpr()) return false; - // Bail out with no diagnostic if the function declaration itself is invalid. - // We will have produced a relevant diagnostic while parsing it. - if (Declaration->isInvalidDecl()) + // Bail out if the function declaration itself is invalid. We will + // have produced a relevant diagnostic while parsing it, so just + // note the problematic sub-expression. + if (Declaration->isInvalidDecl()) { + Info.FFDiag(CallLoc, diag::note_invalid_subexpr_in_const_expr); return false; + } // Can we evaluate this function call? if (Definition && Definition->isConstexpr() && @@ -4429,7 +4462,7 @@ static bool HandleFunctionCall(SourceLocation CallLoc, if (!handleLValueToRValueConversion(Info, Args[0], Args[0]->getType(), RHS, RHSValue)) return false; - if (!handleAssignment(Info, Args[0], *This, MD->getThisType(Info.Ctx), + if (!handleAssignment(Info, Args[0], *This, MD->getThisType(), RHSValue)) return false; This->moveInto(Result); @@ -4451,7 +4484,7 @@ static bool HandleFunctionCall(SourceLocation CallLoc, if (ESR == ESR_Succeeded) { if (Callee->getReturnType()->isVoidType()) return true; - Info.FFDiag(Callee->getLocEnd(), diag::note_constexpr_no_return); + Info.FFDiag(Callee->getEndLoc(), diag::note_constexpr_no_return); } return ESR == ESR_Returned; } @@ -4722,6 +4755,8 @@ public: return Error(E); } + bool VisitConstantExpr(const ConstantExpr *E) + { return StmtVisitorTy::Visit(E->getSubExpr()); } bool VisitParenExpr(const ParenExpr *E) { return StmtVisitorTy::Visit(E->getSubExpr()); } bool VisitUnaryExtension(const UnaryOperator *E) @@ -5076,8 +5111,8 @@ public: if (BI + 1 == BE) { const Expr *FinalExpr = dyn_cast<Expr>(*BI); if (!FinalExpr) { - Info.FFDiag((*BI)->getLocStart(), - diag::note_constexpr_stmt_expr_unsupported); + Info.FFDiag((*BI)->getBeginLoc(), + diag::note_constexpr_stmt_expr_unsupported); return false; } return this->Visit(FinalExpr); @@ -5091,8 +5126,8 @@ public: // 'break', or 'continue', it would be nice to propagate that to // the outer statement evaluation rather than bailing out. if (ESR != ESR_Failed) - Info.FFDiag((*BI)->getLocStart(), - diag::note_constexpr_stmt_expr_unsupported); + Info.FFDiag((*BI)->getBeginLoc(), + diag::note_constexpr_stmt_expr_unsupported); return false; } } @@ -5625,8 +5660,10 @@ static bool getBytesReturnedByAllocSizeCall(const ASTContext &Ctx, return false; auto EvaluateAsSizeT = [&](const Expr *E, APSInt &Into) { - if (!E->EvaluateAsInt(Into, Ctx, Expr::SE_AllowSideEffects)) + Expr::EvalResult ExprResult; + if (!E->EvaluateAsInt(ExprResult, Ctx, Expr::SE_AllowSideEffects)) return false; + Into = ExprResult.Val.getInt(); if (Into.isNegative() || !Into.isIntN(BitsInSizeT)) return false; Into = Into.zextOrSelf(BitsInSizeT); @@ -5852,11 +5889,7 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr *E) { // permitted in constant expressions in C++11. Bitcasts from cv void* are // also static_casts, but we disallow them as a resolution to DR1312. if (!E->getType()->isVoidPointerType()) { - // If we changed anything other than cvr-qualifiers, we can't use this - // value for constant folding. FIXME: Qualification conversions should - // always be CK_NoOp, but we get this wrong in C. - if (!Info.Ctx.hasCvrSimilarType(E->getType(), E->getSubExpr()->getType())) - Result.Designator.setInvalid(); + Result.Designator.setInvalid(); if (SubExpr->getType()->isVoidPointerType()) CCEDiag(E, diag::note_constexpr_invalid_cast) << 3 << SubExpr->getType(); @@ -5954,21 +5987,35 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr *E) { return ExprEvaluatorBaseTy::VisitCastExpr(E); } -static CharUnits GetAlignOfType(EvalInfo &Info, QualType T) { +static CharUnits GetAlignOfType(EvalInfo &Info, QualType T, + UnaryExprOrTypeTrait ExprKind) { // 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(); - // __alignof is defined to return the preferred alignment. if (T.getQualifiers().hasUnaligned()) return CharUnits::One(); - return Info.Ctx.toCharUnitsFromBits( - Info.Ctx.getPreferredTypeAlign(T.getTypePtr())); + + const bool AlignOfReturnsPreferred = + Info.Ctx.getLangOpts().getClangABICompat() <= LangOptions::ClangABI::Ver7; + + // __alignof is defined to return the preferred alignment. + // Before 8, clang returned the preferred alignment for alignof and _Alignof + // as well. + if (ExprKind == UETT_PreferredAlignOf || AlignOfReturnsPreferred) + return Info.Ctx.toCharUnitsFromBits( + Info.Ctx.getPreferredTypeAlign(T.getTypePtr())); + // alignof and _Alignof are defined to return the ABI alignment. + else if (ExprKind == UETT_AlignOf) + return Info.Ctx.getTypeAlignInChars(T.getTypePtr()); + else + llvm_unreachable("GetAlignOfType on a non-alignment ExprKind"); } -static CharUnits GetAlignOfExpr(EvalInfo &Info, const Expr *E) { +static CharUnits GetAlignOfExpr(EvalInfo &Info, const Expr *E, + UnaryExprOrTypeTrait ExprKind) { E = E->IgnoreParens(); // The kinds of expressions that we have special-case logic here for @@ -5985,7 +6032,7 @@ static CharUnits GetAlignOfExpr(EvalInfo &Info, const Expr *E) { return Info.Ctx.getDeclAlign(ME->getMemberDecl(), /*RefAsPointee*/true); - return GetAlignOfType(Info, E->getType()); + return GetAlignOfType(Info, E->getType(), ExprKind); } // To be clear: this happily visits unsupported builtins. Better name welcomed. @@ -6046,8 +6093,8 @@ bool PointerExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, OffsetResult.Base.dyn_cast<const ValueDecl*>()) { BaseAlignment = Info.Ctx.getDeclAlign(VD); } else { - BaseAlignment = - GetAlignOfExpr(Info, OffsetResult.Base.get<const Expr*>()); + BaseAlignment = GetAlignOfExpr( + Info, OffsetResult.Base.get<const Expr *>(), UETT_AlignOf); } if (BaseAlignment < Align) { @@ -6077,7 +6124,8 @@ bool PointerExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, return true; } - + case Builtin::BI__builtin_launder: + return evaluatePointer(E->getArg(0), Result); case Builtin::BIstrchr: case Builtin::BIwcschr: case Builtin::BImemchr: @@ -6109,9 +6157,27 @@ bool PointerExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, return false; MaxLength = N.getExtValue(); } - - QualType CharTy = E->getArg(0)->getType()->getPointeeType(); - + // We cannot find the value if there are no candidates to match against. + if (MaxLength == 0u) + return ZeroInitialization(E); + if (!Result.checkNullPointerForFoldAccess(Info, E, AK_Read) || + Result.Designator.Invalid) + return false; + QualType CharTy = Result.Designator.getType(Info.Ctx); + bool IsRawByte = BuiltinOp == Builtin::BImemchr || + BuiltinOp == Builtin::BI__builtin_memchr; + assert(IsRawByte || + Info.Ctx.hasSameUnqualifiedType( + CharTy, E->getArg(0)->getType()->getPointeeType())); + // Pointers to const void may point to objects of incomplete type. + if (IsRawByte && CharTy->isIncompleteType()) { + Info.FFDiag(E, diag::note_constexpr_ltor_incomplete_type) << CharTy; + return false; + } + // Give up on byte-oriented matching against multibyte elements. + // FIXME: We can compare the bytes in the correct order. + if (IsRawByte && Info.Ctx.getTypeSizeInChars(CharTy) != CharUnits::One()) + return false; // Figure out what value we're actually looking for (after converting to // the corresponding unsigned type if necessary). uint64_t DesiredVal; @@ -6207,6 +6273,20 @@ bool PointerExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, if (!N) return true; + // Otherwise, if either of the operands is null, we can't proceed. Don't + // try to determine the type of the copied objects, because there aren't + // any. + if (!Src.Base || !Dest.Base) { + APValue Val; + (!Src.Base ? Src : Dest).moveInto(Val); + Info.FFDiag(E, diag::note_constexpr_memcpy_null) + << Move << WChar << !!Src.Base + << Val.getAsString(Info.Ctx, E->getArg(0)->getType()); + return false; + } + if (Src.Designator.Invalid || Dest.Designator.Invalid) + return false; + // We require that Src and Dest are both pointers to arrays of // trivially-copyable type. (For the wide version, the designator will be // invalid if the designated object is not a wchar_t.) @@ -6216,6 +6296,10 @@ bool PointerExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, Info.FFDiag(E, diag::note_constexpr_memcpy_type_pun) << Move << SrcT << T; return false; } + if (T->isIncompleteType()) { + Info.FFDiag(E, diag::note_constexpr_memcpy_incomplete_type) << Move << T; + return false; + } if (!T.isTriviallyCopyableType(Info.Ctx)) { Info.FFDiag(E, diag::note_constexpr_memcpy_nontrivial) << Move << T; return false; @@ -7320,6 +7404,8 @@ public: // Visitor Methods //===--------------------------------------------------------------------===// + bool VisitConstantExpr(const ConstantExpr *E); + bool VisitIntegerLiteral(const IntegerLiteral *E) { return Success(E->getValue(), E); } @@ -7619,6 +7705,9 @@ EvaluateBuiltinClassifyType(QualType T, const LangOptions &LangOpts) { #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ case BuiltinType::Id: #include "clang/Basic/OpenCLImageTypes.def" +#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \ + case BuiltinType::Id: +#include "clang/Basic/OpenCLExtensionTypes.def" case BuiltinType::OCLSampler: case BuiltinType::OCLEvent: case BuiltinType::OCLClkEvent: @@ -8023,7 +8112,7 @@ static bool tryEvaluateBuiltinObjectSize(const Expr *E, unsigned Type, // If there are any, but we can determine the pointed-to object anyway, then // ignore the side-effects. SpeculativeEvaluationRAII SpeculativeEval(Info); - FoldOffsetRAII Fold(Info); + IgnoreSideEffectsRAII Fold(Info); if (E->isGLValue()) { // It's possible for us to be given GLValues if we're called via @@ -8057,6 +8146,11 @@ static bool tryEvaluateBuiltinObjectSize(const Expr *E, unsigned Type, return true; } +bool IntExprEvaluator::VisitConstantExpr(const ConstantExpr *E) { + llvm::SaveAndRestore<bool> InConstantContext(Info.InConstantContext, true); + return ExprEvaluatorBaseTy::VisitConstantExpr(E); +} + bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) { if (unsigned BuiltinOp = E->getBuiltinCallee()) return VisitBuiltinCallExpr(E, BuiltinOp); @@ -8091,7 +8185,6 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, case EvalInfo::EM_ConstantFold: case EvalInfo::EM_EvaluateForOverflow: case EvalInfo::EM_IgnoreSideEffects: - case EvalInfo::EM_OffsetFold: // Leave it to IR generation. return Error(E); case EvalInfo::EM_ConstantExpressionUnevaluated: @@ -8103,6 +8196,12 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, llvm_unreachable("unexpected EvalMode"); } + case Builtin::BI__builtin_os_log_format_buffer_size: { + analyze_os_log::OSLogBufferLayout Layout; + analyze_os_log::computeOSLogBufferLayout(Info.Ctx, E, Layout); + return Success(Layout.size().getQuantity(), E); + } + case Builtin::BI__builtin_bswap16: case Builtin::BI__builtin_bswap32: case Builtin::BI__builtin_bswap64: { @@ -8116,9 +8215,15 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, case Builtin::BI__builtin_classify_type: return Success((int)EvaluateBuiltinClassifyType(E, Info.getLangOpts()), E); - // FIXME: BI__builtin_clrsb - // FIXME: BI__builtin_clrsbl - // FIXME: BI__builtin_clrsbll + case Builtin::BI__builtin_clrsb: + case Builtin::BI__builtin_clrsbl: + case Builtin::BI__builtin_clrsbll: { + APSInt Val; + if (!EvaluateInteger(E->getArg(0), Val, Info)) + return false; + + return Success(Val.getBitWidth() - Val.getMinSignedBits(), E); + } case Builtin::BI__builtin_clz: case Builtin::BI__builtin_clzl: @@ -8133,8 +8238,20 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, return Success(Val.countLeadingZeros(), E); } - case Builtin::BI__builtin_constant_p: - return Success(EvaluateBuiltinConstantP(Info.Ctx, E->getArg(0)), E); + case Builtin::BI__builtin_constant_p: { + auto Arg = E->getArg(0); + if (EvaluateBuiltinConstantP(Info.Ctx, Arg)) + return Success(true, E); + auto ArgTy = Arg->IgnoreImplicit()->getType(); + if (!Info.InConstantContext && !Arg->HasSideEffects(Info.Ctx) && + !ArgTy->isAggregateType() && !ArgTy->isPointerType()) { + // We can delay calculation of __builtin_constant_p until after + // inlining. Note: This diagnostic won't be shown to the user. + Info.FFDiag(E, diag::note_invalid_subexpr_in_const_expr); + return false; + } + return Success(false, E); + } case Builtin::BI__builtin_ctz: case Builtin::BI__builtin_ctzl: @@ -8314,8 +8431,6 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, !EvaluatePointer(E->getArg(1), String2, Info)) return false; - QualType CharTy = E->getArg(0)->getType()->getPointeeType(); - uint64_t MaxLength = uint64_t(-1); if (BuiltinOp != Builtin::BIstrcmp && BuiltinOp != Builtin::BIwcscmp && @@ -8326,6 +8441,88 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, return false; MaxLength = N.getExtValue(); } + + // Empty substrings compare equal by definition. + if (MaxLength == 0u) + return Success(0, E); + + if (!String1.checkNullPointerForFoldAccess(Info, E, AK_Read) || + !String2.checkNullPointerForFoldAccess(Info, E, AK_Read) || + String1.Designator.Invalid || String2.Designator.Invalid) + return false; + + QualType CharTy1 = String1.Designator.getType(Info.Ctx); + QualType CharTy2 = String2.Designator.getType(Info.Ctx); + + bool IsRawByte = BuiltinOp == Builtin::BImemcmp || + BuiltinOp == Builtin::BI__builtin_memcmp; + + assert(IsRawByte || + (Info.Ctx.hasSameUnqualifiedType( + CharTy1, E->getArg(0)->getType()->getPointeeType()) && + Info.Ctx.hasSameUnqualifiedType(CharTy1, CharTy2))); + + const auto &ReadCurElems = [&](APValue &Char1, APValue &Char2) { + return handleLValueToRValueConversion(Info, E, CharTy1, String1, Char1) && + handleLValueToRValueConversion(Info, E, CharTy2, String2, Char2) && + Char1.isInt() && Char2.isInt(); + }; + const auto &AdvanceElems = [&] { + return HandleLValueArrayAdjustment(Info, E, String1, CharTy1, 1) && + HandleLValueArrayAdjustment(Info, E, String2, CharTy2, 1); + }; + + if (IsRawByte) { + uint64_t BytesRemaining = MaxLength; + // Pointers to const void may point to objects of incomplete type. + if (CharTy1->isIncompleteType()) { + Info.FFDiag(E, diag::note_constexpr_ltor_incomplete_type) << CharTy1; + return false; + } + if (CharTy2->isIncompleteType()) { + Info.FFDiag(E, diag::note_constexpr_ltor_incomplete_type) << CharTy2; + return false; + } + uint64_t CharTy1Width{Info.Ctx.getTypeSize(CharTy1)}; + CharUnits CharTy1Size = Info.Ctx.toCharUnitsFromBits(CharTy1Width); + // Give up on comparing between elements with disparate widths. + if (CharTy1Size != Info.Ctx.getTypeSizeInChars(CharTy2)) + return false; + uint64_t BytesPerElement = CharTy1Size.getQuantity(); + assert(BytesRemaining && "BytesRemaining should not be zero: the " + "following loop considers at least one element"); + while (true) { + APValue Char1, Char2; + if (!ReadCurElems(Char1, Char2)) + return false; + // We have compatible in-memory widths, but a possible type and + // (for `bool`) internal representation mismatch. + // Assuming two's complement representation, including 0 for `false` and + // 1 for `true`, we can check an appropriate number of elements for + // equality even if they are not byte-sized. + APSInt Char1InMem = Char1.getInt().extOrTrunc(CharTy1Width); + APSInt Char2InMem = Char2.getInt().extOrTrunc(CharTy1Width); + if (Char1InMem.ne(Char2InMem)) { + // If the elements are byte-sized, then we can produce a three-way + // comparison result in a straightforward manner. + if (BytesPerElement == 1u) { + // memcmp always compares unsigned chars. + return Success(Char1InMem.ult(Char2InMem) ? -1 : 1, E); + } + // The result is byte-order sensitive, and we have multibyte elements. + // FIXME: We can compare the remaining bytes in the correct order. + return false; + } + if (!AdvanceElems()) + return false; + if (BytesRemaining <= BytesPerElement) + break; + BytesRemaining -= BytesPerElement; + } + // Enough elements are equal to account for the memcmp limit. + return Success(0, E); + } + bool StopAtNull = (BuiltinOp != Builtin::BImemcmp && BuiltinOp != Builtin::BIwmemcmp && BuiltinOp != Builtin::BI__builtin_memcmp && @@ -8336,11 +8533,10 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, BuiltinOp == Builtin::BI__builtin_wcscmp || BuiltinOp == Builtin::BI__builtin_wcsncmp || BuiltinOp == Builtin::BI__builtin_wmemcmp; + for (; MaxLength; --MaxLength) { APValue Char1, Char2; - if (!handleLValueToRValueConversion(Info, E, CharTy, String1, Char1) || - !handleLValueToRValueConversion(Info, E, CharTy, String2, Char2) || - !Char1.isInt() || !Char2.isInt()) + if (!ReadCurElems(Char1, Char2)) return false; if (Char1.getInt() != Char2.getInt()) { if (IsWide) // wmemcmp compares with wchar_t signedness. @@ -8351,8 +8547,7 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, if (StopAtNull && !Char1.getInt()) return Success(0, E); assert(!(StopAtNull && !Char2.getInt())); - if (!HandleLValueArrayAdjustment(Info, E, String1, CharTy, 1) || - !HandleLValueArrayAdjustment(Info, E, String2, CharTy, 1)) + if (!AdvanceElems()) return false; } // We hit the strncmp / memcmp limit. @@ -9343,11 +9538,14 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { bool IntExprEvaluator::VisitUnaryExprOrTypeTraitExpr( const UnaryExprOrTypeTraitExpr *E) { switch(E->getKind()) { + case UETT_PreferredAlignOf: case UETT_AlignOf: { if (E->isArgumentType()) - return Success(GetAlignOfType(Info, E->getArgumentType()), E); + return Success(GetAlignOfType(Info, E->getArgumentType(), E->getKind()), + E); else - return Success(GetAlignOfExpr(Info, E->getArgumentExpr()), E); + return Success(GetAlignOfExpr(Info, E->getArgumentExpr(), E->getKind()), + E); } case UETT_VecStep: { @@ -9536,11 +9734,11 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) { case CK_IntegralComplexCast: case CK_IntegralComplexToFloatingComplex: case CK_BuiltinFnToFnPtr: - case CK_ZeroToOCLEvent: - case CK_ZeroToOCLQueue: + case CK_ZeroToOCLOpaqueType: case CK_NonAtomicToAtomic: case CK_AddressSpaceConversion: case CK_IntToOCLSampler: + case CK_FixedPointCast: llvm_unreachable("invalid cast kind for integral value"); case CK_BitCast: @@ -9575,6 +9773,14 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) { return Success(IntResult, E); } + case CK_FixedPointToBoolean: { + // Unsigned padding does not affect this. + APValue Val; + if (!Evaluate(Val, Info, SubExpr)) + return false; + return Success(Val.getInt().getBoolValue(), E); + } + case CK_IntegralCast: { if (!Visit(SubExpr)) return false; @@ -9697,8 +9903,7 @@ bool FixedPointExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) { if (Value.isSigned() && Value.isMinSignedValue() && E->canOverflow()) { SmallString<64> S; FixedPointValueToString(S, Value, - Info.Ctx.getTypeInfo(E->getType()).Width, - /*Radix=*/10); + Info.Ctx.getTypeInfo(E->getType()).Width); Info.CCEDiag(E, diag::note_constexpr_overflow) << S << E->getType(); if (Info.noteUndefinedBehavior()) return false; } @@ -10071,11 +10276,12 @@ bool ComplexExprEvaluator::VisitCastExpr(const CastExpr *E) { case CK_ARCExtendBlockObject: case CK_CopyAndAutoreleaseBlockObject: case CK_BuiltinFnToFnPtr: - case CK_ZeroToOCLEvent: - case CK_ZeroToOCLQueue: + case CK_ZeroToOCLOpaqueType: case CK_NonAtomicToAtomic: case CK_AddressSpaceConversion: case CK_IntToOCLSampler: + case CK_FixedPointCast: + case CK_FixedPointToBoolean: llvm_unreachable("invalid cast kind for complex value"); case CK_LValueToRValue: @@ -10236,7 +10442,7 @@ bool ComplexExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { case BO_Mul: if (Result.isComplexFloat()) { // This is an implementation of complex multiplication according to the - // constraints laid out in C11 Annex G. The implemention uses the + // constraints laid out in C11 Annex G. The implementation uses the // following naming scheme: // (a + ib) * (c + id) ComplexValue LHS = Result; @@ -10317,7 +10523,7 @@ bool ComplexExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { case BO_Div: if (Result.isComplexFloat()) { // This is an implementation of complex division according to the - // constraints laid out in C11 Annex G. The implemention uses the + // constraints laid out in C11 Annex G. The implementation uses the // following naming scheme: // (a + ib) / (c + id) ComplexValue LHS = Result; @@ -10693,19 +10899,46 @@ static bool FastEvaluateAsRValue(const Expr *Exp, Expr::EvalResult &Result, return false; } +static bool hasUnacceptableSideEffect(Expr::EvalStatus &Result, + Expr::SideEffectsKind SEK) { + return (SEK < Expr::SE_AllowSideEffects && Result.HasSideEffects) || + (SEK < Expr::SE_AllowUndefinedBehavior && Result.HasUndefinedBehavior); +} + +static bool EvaluateAsRValue(const Expr *E, Expr::EvalResult &Result, + const ASTContext &Ctx, EvalInfo &Info) { + bool IsConst; + if (FastEvaluateAsRValue(E, Result, Ctx, IsConst)) + return IsConst; + + return EvaluateAsRValue(Info, E, Result.Val); +} + +static bool EvaluateAsInt(const Expr *E, Expr::EvalResult &ExprResult, + const ASTContext &Ctx, + Expr::SideEffectsKind AllowSideEffects, + EvalInfo &Info) { + if (!E->getType()->isIntegralOrEnumerationType()) + return false; + + if (!::EvaluateAsRValue(E, ExprResult, Ctx, Info) || + !ExprResult.Val.isInt() || + hasUnacceptableSideEffect(ExprResult, AllowSideEffects)) + return false; + + return true; +} /// 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; - +bool Expr::EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx, + bool InConstantContext) const { EvalInfo Info(Ctx, Result, EvalInfo::EM_IgnoreSideEffects); - return ::EvaluateAsRValue(Info, this, Result.Val); + Info.InConstantContext = InConstantContext; + return ::EvaluateAsRValue(this, Result, Ctx, Info); } bool Expr::EvaluateAsBooleanCondition(bool &Result, @@ -10715,24 +10948,10 @@ bool Expr::EvaluateAsBooleanCondition(bool &Result, HandleConversionToBool(Scratch.Val, Result); } -static bool hasUnacceptableSideEffect(Expr::EvalStatus &Result, - Expr::SideEffectsKind SEK) { - return (SEK < Expr::SE_AllowSideEffects && Result.HasSideEffects) || - (SEK < Expr::SE_AllowUndefinedBehavior && Result.HasUndefinedBehavior); -} - -bool Expr::EvaluateAsInt(APSInt &Result, const ASTContext &Ctx, +bool Expr::EvaluateAsInt(EvalResult &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects) const { - if (!getType()->isIntegralOrEnumerationType()) - return false; - - EvalResult ExprResult; - if (!EvaluateAsRValue(ExprResult, Ctx) || !ExprResult.Val.isInt() || - hasUnacceptableSideEffect(ExprResult, AllowSideEffects)) - return false; - - Result = ExprResult.Val.getInt(); - return true; + EvalInfo Info(Ctx, Result, EvalInfo::EM_IgnoreSideEffects); + return ::EvaluateAsInt(this, Result, Ctx, AllowSideEffects, Info); } bool Expr::EvaluateAsFloat(APFloat &Result, const ASTContext &Ctx, @@ -10790,6 +11009,7 @@ bool Expr::EvaluateAsInitializer(APValue &Value, const ASTContext &Ctx, ? EvalInfo::EM_ConstantExpression : EvalInfo::EM_ConstantFold); InitInfo.setEvaluatingDecl(VD, Value); + InitInfo.InConstantContext = true; LValue LVal; LVal.set(VD); @@ -10819,28 +11039,46 @@ bool Expr::EvaluateAsInitializer(APValue &Value, const ASTContext &Ctx, /// constant folded, but discard the result. bool Expr::isEvaluatable(const ASTContext &Ctx, SideEffectsKind SEK) const { EvalResult Result; - return EvaluateAsRValue(Result, Ctx) && + return EvaluateAsRValue(Result, Ctx, /* in constant context */ true) && !hasUnacceptableSideEffect(Result, SEK); } APSInt Expr::EvaluateKnownConstInt(const ASTContext &Ctx, SmallVectorImpl<PartialDiagnosticAt> *Diag) const { - EvalResult EvalResult; - EvalResult.Diag = Diag; - bool Result = EvaluateAsRValue(EvalResult, Ctx); + EvalResult EVResult; + EVResult.Diag = Diag; + EvalInfo Info(Ctx, EVResult, EvalInfo::EM_IgnoreSideEffects); + Info.InConstantContext = true; + + bool Result = ::EvaluateAsRValue(this, EVResult, Ctx, Info); (void)Result; assert(Result && "Could not evaluate expression"); - assert(EvalResult.Val.isInt() && "Expression did not evaluate to integer"); + assert(EVResult.Val.isInt() && "Expression did not evaluate to integer"); - return EvalResult.Val.getInt(); + return EVResult.Val.getInt(); +} + +APSInt Expr::EvaluateKnownConstIntCheckOverflow( + const ASTContext &Ctx, SmallVectorImpl<PartialDiagnosticAt> *Diag) const { + EvalResult EVResult; + EVResult.Diag = Diag; + EvalInfo Info(Ctx, EVResult, EvalInfo::EM_EvaluateForOverflow); + Info.InConstantContext = true; + + bool Result = ::EvaluateAsRValue(Info, this, EVResult.Val); + (void)Result; + assert(Result && "Could not evaluate expression"); + assert(EVResult.Val.isInt() && "Expression did not evaluate to integer"); + + return EVResult.Val.getInt(); } void Expr::EvaluateForOverflow(const ASTContext &Ctx) const { bool IsConst; - EvalResult EvalResult; - if (!FastEvaluateAsRValue(this, EvalResult, Ctx, IsConst)) { - EvalInfo Info(Ctx, EvalResult, EvalInfo::EM_EvaluateForOverflow); - (void)::EvaluateAsRValue(Info, this, EvalResult.Val); + EvalResult EVResult; + if (!FastEvaluateAsRValue(this, EVResult, Ctx, IsConst)) { + EvalInfo Info(Ctx, EVResult, EvalInfo::EM_EvaluateForOverflow); + (void)::EvaluateAsRValue(Info, this, EVResult.Val); } } @@ -10893,9 +11131,13 @@ static ICEDiag Worst(ICEDiag A, ICEDiag B) { return A.Kind >= B.Kind ? A : B; } static ICEDiag CheckEvalInICE(const Expr* E, const ASTContext &Ctx) { Expr::EvalResult EVResult; - if (!E->EvaluateAsRValue(EVResult, Ctx) || EVResult.HasSideEffects || + Expr::EvalStatus Status; + EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantExpression); + + Info.InConstantContext = true; + if (!::EvaluateAsRValue(E, EVResult, Ctx, Info) || EVResult.HasSideEffects || !EVResult.Val.isInt()) - return ICEDiag(IK_NotICE, E->getLocStart()); + return ICEDiag(IK_NotICE, E->getBeginLoc()); return NoDiag(); } @@ -10903,7 +11145,7 @@ static ICEDiag CheckEvalInICE(const Expr* E, const ASTContext &Ctx) { static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) { assert(!E->isValueDependent() && "Should not see value dependent exprs!"); if (!E->getType()->isIntegralOrEnumerationType()) - return ICEDiag(IK_NotICE, E->getLocStart()); + return ICEDiag(IK_NotICE, E->getBeginLoc()); switch (E->getStmtClass()) { #define ABSTRACT_STMT(Node) @@ -10987,7 +11229,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) { case Expr::CoawaitExprClass: case Expr::DependentCoawaitExprClass: case Expr::CoyieldExprClass: - return ICEDiag(IK_NotICE, E->getLocStart()); + return ICEDiag(IK_NotICE, E->getBeginLoc()); case Expr::InitListExprClass: { // C++03 [dcl.init]p13: If T is a scalar type, then a declaration of the @@ -10997,7 +11239,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) { if (E->isRValue()) if (cast<InitListExpr>(E)->getNumInits() == 1) return CheckICE(cast<InitListExpr>(E)->getInit(0), Ctx); - return ICEDiag(IK_NotICE, E->getLocStart()); + return ICEDiag(IK_NotICE, E->getBeginLoc()); } case Expr::SizeOfPackExprClass: @@ -11009,6 +11251,9 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) { return CheckICE(cast<SubstNonTypeTemplateParmExpr>(E)->getReplacement(), Ctx); + case Expr::ConstantExprClass: + return CheckICE(cast<ConstantExpr>(E)->getSubExpr(), Ctx); + case Expr::ParenExprClass: return CheckICE(cast<ParenExpr>(E)->getSubExpr(), Ctx); case Expr::GenericSelectionExprClass: @@ -11032,7 +11277,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) { const CallExpr *CE = cast<CallExpr>(E); if (CE->getBuiltinCallee()) return CheckEvalInICE(E, Ctx); - return ICEDiag(IK_NotICE, E->getLocStart()); + return ICEDiag(IK_NotICE, E->getBeginLoc()); } case Expr::DeclRefExprClass: { if (isa<EnumConstantDecl>(cast<DeclRefExpr>(E)->getDecl())) @@ -11062,7 +11307,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) { return ICEDiag(IK_NotICE, cast<DeclRefExpr>(E)->getLocation()); } } - return ICEDiag(IK_NotICE, E->getLocStart()); + return ICEDiag(IK_NotICE, E->getBeginLoc()); } case Expr::UnaryOperatorClass: { const UnaryOperator *Exp = cast<UnaryOperator>(E); @@ -11077,7 +11322,7 @@ static ICEDiag CheckICE(const Expr* E, const 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(IK_NotICE, E->getLocStart()); + return ICEDiag(IK_NotICE, E->getBeginLoc()); case UO_Extension: case UO_LNot: case UO_Plus: @@ -11087,9 +11332,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) { case UO_Imag: return CheckICE(Exp->getSubExpr(), Ctx); } - - // OffsetOf falls through here. - LLVM_FALLTHROUGH; + llvm_unreachable("invalid unary operator class"); } case Expr::OffsetOfExprClass: { // Note that per C99, offsetof must be an ICE. And AFAIK, using @@ -11104,7 +11347,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) { const UnaryExprOrTypeTraitExpr *Exp = cast<UnaryExprOrTypeTraitExpr>(E); if ((Exp->getKind() == UETT_SizeOf) && Exp->getTypeOfArgument()->isVariableArrayType()) - return ICEDiag(IK_NotICE, E->getLocStart()); + return ICEDiag(IK_NotICE, E->getBeginLoc()); return NoDiag(); } case Expr::BinaryOperatorClass: { @@ -11126,7 +11369,7 @@ static ICEDiag CheckICE(const Expr* E, const 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(IK_NotICE, E->getLocStart()); + return ICEDiag(IK_NotICE, E->getBeginLoc()); case BO_Mul: case BO_Div: @@ -11155,11 +11398,11 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) { if (LHSResult.Kind == IK_ICE && RHSResult.Kind == IK_ICE) { llvm::APSInt REval = Exp->getRHS()->EvaluateKnownConstInt(Ctx); if (REval == 0) - return ICEDiag(IK_ICEIfUnevaluated, E->getLocStart()); + return ICEDiag(IK_ICEIfUnevaluated, E->getBeginLoc()); if (REval.isSigned() && REval.isAllOnesValue()) { llvm::APSInt LEval = Exp->getLHS()->EvaluateKnownConstInt(Ctx); if (LEval.isMinSignedValue()) - return ICEDiag(IK_ICEIfUnevaluated, E->getLocStart()); + return ICEDiag(IK_ICEIfUnevaluated, E->getBeginLoc()); } } } @@ -11168,10 +11411,10 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) { // C99 6.6p3 introduces a strange edge case: comma can be in an ICE // if it isn't evaluated. if (LHSResult.Kind == IK_ICE && RHSResult.Kind == IK_ICE) - return ICEDiag(IK_ICEIfUnevaluated, E->getLocStart()); + return ICEDiag(IK_ICEIfUnevaluated, E->getBeginLoc()); } else { // In both C89 and C++, commas in ICEs are illegal. - return ICEDiag(IK_NotICE, E->getLocStart()); + return ICEDiag(IK_NotICE, E->getBeginLoc()); } } return Worst(LHSResult, RHSResult); @@ -11193,7 +11436,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) { return Worst(LHSResult, RHSResult); } } - LLVM_FALLTHROUGH; + llvm_unreachable("invalid binary operator kind"); } case Expr::ImplicitCastExprClass: case Expr::CStyleCastExprClass: @@ -11216,7 +11459,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) { if (FL->getValue().convertToInteger(IgnoredVal, llvm::APFloat::rmTowardZero, &Ignored) & APFloat::opInvalidOp) - return ICEDiag(IK_NotICE, E->getLocStart()); + return ICEDiag(IK_NotICE, E->getBeginLoc()); return NoDiag(); } } @@ -11229,7 +11472,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) { case CK_IntegralCast: return CheckICE(SubExpr, Ctx); default: - return ICEDiag(IK_NotICE, E->getLocStart()); + return ICEDiag(IK_NotICE, E->getBeginLoc()); } } case Expr::BinaryConditionalOperatorClass: { @@ -11330,12 +11573,20 @@ bool Expr::isIntegerConstantExpr(llvm::APSInt &Value, const ASTContext &Ctx, if (!isIntegerConstantExpr(Ctx, Loc)) return false; + // The only possible side-effects here are due to UB discovered in the // evaluation (for instance, INT_MAX + 1). In such a case, we are still // required to treat the expression as an ICE, so we produce the folded // value. - if (!EvaluateAsInt(Value, Ctx, SE_AllowSideEffects)) + EvalResult ExprResult; + Expr::EvalStatus Status; + EvalInfo Info(Ctx, Status, EvalInfo::EM_IgnoreSideEffects); + Info.InConstantContext = true; + + if (!::EvaluateAsInt(this, ExprResult, Ctx, SE_AllowSideEffects, Info)) llvm_unreachable("ICE cannot be evaluated!"); + + Value = ExprResult.Val.getInt(); return true; } @@ -11421,6 +11672,7 @@ bool Expr::isPotentialConstantExpr(const FunctionDecl *FD, EvalInfo Info(FD->getASTContext(), Status, EvalInfo::EM_PotentialConstantExpression); + Info.InConstantContext = true; const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD); const CXXRecordDecl *RD = MD ? MD->getParent()->getCanonicalDecl() : nullptr; |