diff options
Diffstat (limited to 'clang/lib/AST/ExprConstant.cpp')
-rw-r--r-- | clang/lib/AST/ExprConstant.cpp | 100 |
1 files changed, 50 insertions, 50 deletions
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 0d12161..20b7c44 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -9741,10 +9741,19 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr *E) { case CK_AddressSpaceConversion: if (!Visit(SubExpr)) return false; - // Bitcasts to cv void* are static_casts, not reinterpret_casts, so are - // 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 (E->getType()->isFunctionPointerType() || + SubExpr->getType()->isFunctionPointerType()) { + // Casting between two function pointer types, or between a function + // pointer and an object pointer, is always a reinterpret_cast. + CCEDiag(E, diag::note_constexpr_invalid_cast) + << diag::ConstexprInvalidCastKind::ThisConversionOrReinterpret + << Info.Ctx.getLangOpts().CPlusPlus; + Result.Designator.setInvalid(); + } else if (!E->getType()->isVoidPointerType()) { + // Bitcasts to cv void* are static_casts, not reinterpret_casts, so are + // permitted in constant expressions in C++11. Bitcasts from cv void* are + // also static_casts, but we disallow them as a resolution to DR1312. + // // In some circumstances, we permit casting from void* to cv1 T*, when the // actual pointee object is actually a cv2 T. bool HasValidResult = !Result.InvalidBase && !Result.Designator.Invalid && @@ -14636,7 +14645,9 @@ EvaluateComparisonBinaryOperator(EvalInfo &Info, const BinaryOperator *E, if (!LHSDesignator.Invalid && !RHSDesignator.Invalid && IsRelational) { bool WasArrayIndex; unsigned Mismatch = FindDesignatorMismatch( - getType(LHSValue.Base), LHSDesignator, RHSDesignator, WasArrayIndex); + LHSValue.Base.isNull() ? QualType() + : getType(LHSValue.Base).getNonReferenceType(), + LHSDesignator, RHSDesignator, WasArrayIndex); // At the point where the designators diverge, the comparison has a // specified value if: // - we are comparing array indices @@ -14680,7 +14691,7 @@ EvaluateComparisonBinaryOperator(EvalInfo &Info, const BinaryOperator *E, // compare pointers within the object in question; otherwise, the result // depends on where the object is located in memory. if (!LHSValue.Base.isNull() && IsRelational) { - QualType BaseTy = getType(LHSValue.Base); + QualType BaseTy = getType(LHSValue.Base).getNonReferenceType(); if (BaseTy->isIncompleteType()) return Error(E); CharUnits Size = Info.Ctx.getTypeSizeInChars(BaseTy); @@ -16847,31 +16858,31 @@ static bool EvaluateAsRValue(EvalInfo &Info, const Expr *E, APValue &Result) { CheckMemoryLeaks(Info); } -static bool FastEvaluateAsRValue(const Expr *Exp, Expr::EvalResult &Result, +static bool FastEvaluateAsRValue(const Expr *Exp, APValue &Result, const ASTContext &Ctx, bool &IsConst) { // Fast-path evaluations of integer literals, since we sometimes see files // containing vast quantities of these. if (const auto *L = dyn_cast<IntegerLiteral>(Exp)) { - Result.Val = APValue(APSInt(L->getValue(), - L->getType()->isUnsignedIntegerType())); + Result = + APValue(APSInt(L->getValue(), L->getType()->isUnsignedIntegerType())); IsConst = true; return true; } if (const auto *L = dyn_cast<CXXBoolLiteralExpr>(Exp)) { - Result.Val = APValue(APSInt(APInt(1, L->getValue()))); + Result = APValue(APSInt(APInt(1, L->getValue()))); IsConst = true; return true; } if (const auto *FL = dyn_cast<FloatingLiteral>(Exp)) { - Result.Val = APValue(FL->getValue()); + Result = APValue(FL->getValue()); IsConst = true; return true; } if (const auto *L = dyn_cast<CharacterLiteral>(Exp)) { - Result.Val = APValue(Ctx.MakeIntValue(L->getValue(), L->getType())); + Result = APValue(Ctx.MakeIntValue(L->getValue(), L->getType())); IsConst = true; return true; } @@ -16880,7 +16891,7 @@ static bool FastEvaluateAsRValue(const Expr *Exp, Expr::EvalResult &Result, if (CE->hasAPValueResult()) { APValue APV = CE->getAPValueResult(); if (!APV.isLValue()) { - Result.Val = std::move(APV); + Result = std::move(APV); IsConst = true; return true; } @@ -16910,7 +16921,7 @@ static bool EvaluateAsRValue(const Expr *E, Expr::EvalResult &Result, const ASTContext &Ctx, EvalInfo &Info) { assert(!E->isValueDependent()); bool IsConst; - if (FastEvaluateAsRValue(E, Result, Ctx, IsConst)) + if (FastEvaluateAsRValue(E, Result.Val, Ctx, IsConst)) return IsConst; return EvaluateAsRValue(Info, E, Result.Val); @@ -17067,7 +17078,8 @@ bool Expr::EvaluateAsConstantExpr(EvalResult &Result, const ASTContext &Ctx, assert(!isValueDependent() && "Expression evaluator can't be called on a dependent expression."); bool IsConst; - if (FastEvaluateAsRValue(this, Result, Ctx, IsConst) && Result.Val.hasValue()) + if (FastEvaluateAsRValue(this, Result.Val, Ctx, IsConst) && + Result.Val.hasValue()) return true; ExprTimeTraceScope TimeScope(this, Ctx, "EvaluateAsConstantExpr"); @@ -17282,7 +17294,7 @@ void Expr::EvaluateForOverflow(const ASTContext &Ctx) const { ExprTimeTraceScope TimeScope(this, Ctx, "EvaluateForOverflow"); bool IsConst; EvalResult EVResult; - if (!FastEvaluateAsRValue(this, EVResult, Ctx, IsConst)) { + if (!FastEvaluateAsRValue(this, EVResult.Val, Ctx, IsConst)) { EvalInfo Info(Ctx, EVResult, EvalInfo::EM_IgnoreSideEffects); Info.CheckingForUndefinedBehavior = true; (void)::EvaluateAsRValue(Info, this, EVResult.Val); @@ -17301,8 +17313,7 @@ bool Expr::EvalResult::isGlobalLValue() const { /// comma, etc // CheckICE - This function does the fundamental ICE checking: the returned -// ICEDiag contains an ICEKind indicating whether the expression is an ICE, -// and a (possibly null) SourceLocation indicating the location of the problem. +// ICEDiag contains an ICEKind indicating whether the expression is an ICE. // // Note that to reduce code duplication, this helper does no evaluation // itself; the caller checks whether the expression is evaluatable, and @@ -17766,60 +17777,51 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) { /// Evaluate an expression as a C++11 integral constant expression. static bool EvaluateCPlusPlus11IntegralConstantExpr(const ASTContext &Ctx, const Expr *E, - llvm::APSInt *Value, - SourceLocation *Loc) { - if (!E->getType()->isIntegralOrUnscopedEnumerationType()) { - if (Loc) *Loc = E->getExprLoc(); + llvm::APSInt *Value) { + if (!E->getType()->isIntegralOrUnscopedEnumerationType()) return false; - } APValue Result; - if (!E->isCXX11ConstantExpr(Ctx, &Result, Loc)) + if (!E->isCXX11ConstantExpr(Ctx, &Result)) return false; - if (!Result.isInt()) { - if (Loc) *Loc = E->getExprLoc(); + if (!Result.isInt()) return false; - } if (Value) *Value = Result.getInt(); return true; } -bool Expr::isIntegerConstantExpr(const ASTContext &Ctx, - SourceLocation *Loc) const { +bool Expr::isIntegerConstantExpr(const ASTContext &Ctx) const { assert(!isValueDependent() && "Expression evaluator can't be called on a dependent expression."); ExprTimeTraceScope TimeScope(this, Ctx, "isIntegerConstantExpr"); if (Ctx.getLangOpts().CPlusPlus11) - return EvaluateCPlusPlus11IntegralConstantExpr(Ctx, this, nullptr, Loc); + return EvaluateCPlusPlus11IntegralConstantExpr(Ctx, this, nullptr); ICEDiag D = CheckICE(this, Ctx); - if (D.Kind != IK_ICE) { - if (Loc) *Loc = D.Loc; + if (D.Kind != IK_ICE) return false; - } return true; } std::optional<llvm::APSInt> -Expr::getIntegerConstantExpr(const ASTContext &Ctx, SourceLocation *Loc) const { +Expr::getIntegerConstantExpr(const ASTContext &Ctx) const { if (isValueDependent()) { // Expression evaluator can't succeed on a dependent expression. return std::nullopt; } - APSInt Value; - if (Ctx.getLangOpts().CPlusPlus11) { - if (EvaluateCPlusPlus11IntegralConstantExpr(Ctx, this, &Value, Loc)) + APSInt Value; + if (EvaluateCPlusPlus11IntegralConstantExpr(Ctx, this, &Value)) return Value; return std::nullopt; } - if (!isIntegerConstantExpr(Ctx, Loc)) + if (!isIntegerConstantExpr(Ctx)) return std::nullopt; // The only possible side-effects here are due to UB discovered in the @@ -17844,8 +17846,7 @@ bool Expr::isCXX98IntegralConstantExpr(const ASTContext &Ctx) const { return CheckICE(this, Ctx).Kind == IK_ICE; } -bool Expr::isCXX11ConstantExpr(const ASTContext &Ctx, APValue *Result, - SourceLocation *Loc) const { +bool Expr::isCXX11ConstantExpr(const ASTContext &Ctx, APValue *Result) const { assert(!isValueDependent() && "Expression evaluator can't be called on a dependent expression."); @@ -17853,28 +17854,27 @@ bool Expr::isCXX11ConstantExpr(const ASTContext &Ctx, APValue *Result, // issues. assert(Ctx.getLangOpts().CPlusPlus); + bool IsConst; + APValue Scratch; + if (FastEvaluateAsRValue(this, Scratch, Ctx, IsConst) && Scratch.hasValue()) { + if (Result) + *Result = Scratch; + return true; + } + // Build evaluation settings. Expr::EvalStatus Status; SmallVector<PartialDiagnosticAt, 8> Diags; Status.Diag = &Diags; EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantExpression); - APValue Scratch; bool IsConstExpr = ::EvaluateAsRValue(Info, this, Result ? *Result : Scratch) && // FIXME: We don't produce a diagnostic for this, but the callers that // call us on arbitrary full-expressions should generally not care. Info.discardCleanups() && !Status.HasSideEffects; - if (!Diags.empty()) { - IsConstExpr = false; - if (Loc) *Loc = Diags[0].first; - } else if (!IsConstExpr) { - // FIXME: This shouldn't happen. - if (Loc) *Loc = getExprLoc(); - } - - return IsConstExpr; + return IsConstExpr && Diags.empty(); } bool Expr::EvaluateWithSubstitution(APValue &Value, ASTContext &Ctx, |