diff options
Diffstat (limited to 'clang/lib/Sema/SemaChecking.cpp')
-rw-r--r-- | clang/lib/Sema/SemaChecking.cpp | 178 |
1 files changed, 110 insertions, 68 deletions
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index b3e8ae1aed0..e8bcc83e762 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -84,6 +84,7 @@ #include "llvm/Support/Format.h" #include "llvm/Support/Locale.h" #include "llvm/Support/MathExtras.h" +#include "llvm/Support/SaveAndRestore.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> #include <cassert> @@ -307,7 +308,8 @@ void Sema::checkFortifiedBuiltinMemoryFunction(FunctionDecl *FD, // - Analyze the format string of sprintf to see how much of buffer is used. // - Evaluate strlen of strcpy arguments, use as object size. - if (TheCall->isValueDependent() || TheCall->isTypeDependent()) + if (TheCall->isValueDependent() || TheCall->isTypeDependent() || + isConstantEvaluated()) return; unsigned BuiltinID = FD->getBuiltinID(/*ConsiderWrappers=*/true); @@ -4059,7 +4061,8 @@ static void CheckNonNullArgument(Sema &S, SourceLocation CallSiteLoc) { if (CheckNonNullExpr(S, ArgExpr)) S.DiagRuntimeBehavior(CallSiteLoc, ArgExpr, - S.PDiag(diag::warn_null_arg) << ArgExpr->getSourceRange()); + S.PDiag(diag::warn_null_arg) + << ArgExpr->getSourceRange()); } bool Sema::GetFormatNSStringIdx(const FormatAttr *Format, unsigned &Idx) { @@ -4129,6 +4132,9 @@ static void CheckNonNullArguments(Sema &S, SourceLocation CallSiteLoc) { assert((FDecl || Proto) && "Need a function declaration or prototype"); + // Already checked by by constant evaluator. + if (S.isConstantEvaluated()) + return; // Check the attributes attached to the method/function itself. llvm::SmallBitVector NonNullArgs; if (FDecl) { @@ -6059,6 +6065,8 @@ bool Sema::SemaBuiltinConstantArg(CallExpr *TheCall, int ArgNum, /// TheCall is a constant expression in the range [Low, High]. bool Sema::SemaBuiltinConstantArgRange(CallExpr *TheCall, int ArgNum, int Low, int High, bool RangeIsError) { + if (isConstantEvaluated()) + return false; llvm::APSInt Result; // We can't check the value of a dependent argument. @@ -6565,6 +6573,8 @@ checkFormatStringExpr(Sema &S, const Expr *E, ArrayRef<const Expr *> Args, llvm::SmallBitVector &CheckedVarArgs, UncoveredArgHandler &UncoveredArg, llvm::APSInt Offset) { + if (S.isConstantEvaluated()) + return SLCT_NotALiteral; tryAgain: assert(Offset.isSigned() && "invalid offset"); @@ -6594,7 +6604,8 @@ checkFormatStringExpr(Sema &S, const Expr *E, ArrayRef<const Expr *> Args, bool CheckLeft = true, CheckRight = true; bool Cond; - if (C->getCond()->EvaluateAsBooleanCondition(Cond, S.getASTContext())) { + if (C->getCond()->EvaluateAsBooleanCondition(Cond, S.getASTContext(), + S.isConstantEvaluated())) { if (Cond) CheckRight = false; else @@ -6795,8 +6806,10 @@ checkFormatStringExpr(Sema &S, const Expr *E, ArrayRef<const Expr *> Args, if (BinOp->isAdditiveOp()) { Expr::EvalResult LResult, RResult; - bool LIsInt = BinOp->getLHS()->EvaluateAsInt(LResult, S.Context); - bool RIsInt = BinOp->getRHS()->EvaluateAsInt(RResult, S.Context); + bool LIsInt = BinOp->getLHS()->EvaluateAsInt( + LResult, S.Context, Expr::SE_NoSideEffects, S.isConstantEvaluated()); + bool RIsInt = BinOp->getRHS()->EvaluateAsInt( + RResult, S.Context, Expr::SE_NoSideEffects, S.isConstantEvaluated()); if (LIsInt != RIsInt) { BinaryOperatorKind BinOpKind = BinOp->getOpcode(); @@ -6822,7 +6835,9 @@ checkFormatStringExpr(Sema &S, const Expr *E, ArrayRef<const Expr *> Args, auto ASE = dyn_cast<ArraySubscriptExpr>(UnaOp->getSubExpr()); if (UnaOp->getOpcode() == UO_AddrOf && ASE) { Expr::EvalResult IndexResult; - if (ASE->getRHS()->EvaluateAsInt(IndexResult, S.Context)) { + if (ASE->getRHS()->EvaluateAsInt(IndexResult, S.Context, + Expr::SE_NoSideEffects, + S.isConstantEvaluated())) { sumOffsets(Offset, IndexResult.Val.getInt(), BO_Add, /*RHS is int*/ true); E = ASE->getBase(); @@ -9902,12 +9917,13 @@ static QualType GetExprType(const Expr *E) { /// range of values it might take. /// /// \param MaxWidth - the width to which the value will be truncated -static IntRange GetExprRange(ASTContext &C, const Expr *E, unsigned MaxWidth) { +static IntRange GetExprRange(ASTContext &C, const Expr *E, unsigned MaxWidth, + bool InConstantContext) { E = E->IgnoreParens(); // Try a full evaluation first. Expr::EvalResult result; - if (E->EvaluateAsRValue(result, C)) + if (E->EvaluateAsRValue(result, C, InConstantContext)) return GetValueRange(C, result.Val, GetExprType(E), MaxWidth); // I think we only want to look through implicit casts here; if the @@ -9915,7 +9931,7 @@ static IntRange GetExprRange(ASTContext &C, const Expr *E, unsigned MaxWidth) { // being of the new, wider type. if (const auto *CE = dyn_cast<ImplicitCastExpr>(E)) { if (CE->getCastKind() == CK_NoOp || CE->getCastKind() == CK_LValueToRValue) - return GetExprRange(C, CE->getSubExpr(), MaxWidth); + return GetExprRange(C, CE->getSubExpr(), MaxWidth, InConstantContext); IntRange OutputTypeRange = IntRange::forValueOfType(C, GetExprType(CE)); @@ -9926,9 +9942,9 @@ static IntRange GetExprRange(ASTContext &C, const Expr *E, unsigned MaxWidth) { if (!isIntegerCast) return OutputTypeRange; - IntRange SubRange - = GetExprRange(C, CE->getSubExpr(), - std::min(MaxWidth, OutputTypeRange.Width)); + IntRange SubRange = GetExprRange(C, CE->getSubExpr(), + std::min(MaxWidth, OutputTypeRange.Width), + InConstantContext); // Bail out if the subexpr's range is as wide as the cast type. if (SubRange.Width >= OutputTypeRange.Width) @@ -9944,13 +9960,15 @@ static IntRange GetExprRange(ASTContext &C, const Expr *E, unsigned MaxWidth) { // If we can fold the condition, just take that operand. bool CondResult; if (CO->getCond()->EvaluateAsBooleanCondition(CondResult, C)) - return GetExprRange(C, CondResult ? CO->getTrueExpr() - : CO->getFalseExpr(), - MaxWidth); + return GetExprRange(C, + CondResult ? CO->getTrueExpr() : CO->getFalseExpr(), + MaxWidth, InConstantContext); // Otherwise, conservatively merge. - IntRange L = GetExprRange(C, CO->getTrueExpr(), MaxWidth); - IntRange R = GetExprRange(C, CO->getFalseExpr(), MaxWidth); + IntRange L = + GetExprRange(C, CO->getTrueExpr(), MaxWidth, InConstantContext); + IntRange R = + GetExprRange(C, CO->getFalseExpr(), MaxWidth, InConstantContext); return IntRange::join(L, R); } @@ -9986,7 +10004,7 @@ static IntRange GetExprRange(ASTContext &C, const Expr *E, unsigned MaxWidth) { // been coerced to the LHS type. case BO_Assign: // TODO: bitfields? - return GetExprRange(C, BO->getRHS(), MaxWidth); + return GetExprRange(C, BO->getRHS(), MaxWidth, InConstantContext); // Operations with opaque sources are black-listed. case BO_PtrMemD: @@ -9996,8 +10014,9 @@ static IntRange GetExprRange(ASTContext &C, const Expr *E, unsigned MaxWidth) { // Bitwise-and uses the *infinum* of the two source ranges. case BO_And: case BO_AndAssign: - return IntRange::meet(GetExprRange(C, BO->getLHS(), MaxWidth), - GetExprRange(C, BO->getRHS(), MaxWidth)); + return IntRange::meet( + GetExprRange(C, BO->getLHS(), MaxWidth, InConstantContext), + GetExprRange(C, BO->getRHS(), MaxWidth, InConstantContext)); // Left shift gets black-listed based on a judgement call. case BO_Shl: @@ -10018,7 +10037,7 @@ static IntRange GetExprRange(ASTContext &C, const Expr *E, unsigned MaxWidth) { // Right shift by a constant can narrow its left argument. case BO_Shr: case BO_ShrAssign: { - IntRange L = GetExprRange(C, BO->getLHS(), MaxWidth); + IntRange L = GetExprRange(C, BO->getLHS(), MaxWidth, InConstantContext); // If the shift amount is a positive constant, drop the width by // that much. @@ -10037,7 +10056,7 @@ static IntRange GetExprRange(ASTContext &C, const Expr *E, unsigned MaxWidth) { // Comma acts as its right operand. case BO_Comma: - return GetExprRange(C, BO->getRHS(), MaxWidth); + return GetExprRange(C, BO->getRHS(), MaxWidth, InConstantContext); // Black-list pointer subtractions. case BO_Sub: @@ -10050,7 +10069,7 @@ static IntRange GetExprRange(ASTContext &C, const Expr *E, unsigned MaxWidth) { case BO_Div: { // Don't 'pre-truncate' the operands. unsigned opWidth = C.getIntWidth(GetExprType(E)); - IntRange L = GetExprRange(C, BO->getLHS(), opWidth); + IntRange L = GetExprRange(C, BO->getLHS(), opWidth, InConstantContext); // If the divisor is constant, use that. llvm::APSInt divisor; @@ -10064,7 +10083,7 @@ static IntRange GetExprRange(ASTContext &C, const Expr *E, unsigned MaxWidth) { } // Otherwise, just use the LHS's width. - IntRange R = GetExprRange(C, BO->getRHS(), opWidth); + IntRange R = GetExprRange(C, BO->getRHS(), opWidth, InConstantContext); return IntRange(L.Width, L.NonNegative && R.NonNegative); } @@ -10073,8 +10092,8 @@ static IntRange GetExprRange(ASTContext &C, const Expr *E, unsigned MaxWidth) { case BO_Rem: { // Don't 'pre-truncate' the operands. unsigned opWidth = C.getIntWidth(GetExprType(E)); - IntRange L = GetExprRange(C, BO->getLHS(), opWidth); - IntRange R = GetExprRange(C, BO->getRHS(), opWidth); + IntRange L = GetExprRange(C, BO->getLHS(), opWidth, InConstantContext); + IntRange R = GetExprRange(C, BO->getRHS(), opWidth, InConstantContext); IntRange meet = IntRange::meet(L, R); meet.Width = std::min(meet.Width, MaxWidth); @@ -10091,8 +10110,8 @@ static IntRange GetExprRange(ASTContext &C, const Expr *E, unsigned MaxWidth) { // The default case is to treat the operation as if it were closed // on the narrowest type that encompasses both operands. - IntRange L = GetExprRange(C, BO->getLHS(), MaxWidth); - IntRange R = GetExprRange(C, BO->getRHS(), MaxWidth); + IntRange L = GetExprRange(C, BO->getLHS(), MaxWidth, InConstantContext); + IntRange R = GetExprRange(C, BO->getRHS(), MaxWidth, InConstantContext); return IntRange::join(L, R); } @@ -10108,12 +10127,12 @@ static IntRange GetExprRange(ASTContext &C, const Expr *E, unsigned MaxWidth) { return IntRange::forValueOfType(C, GetExprType(E)); default: - return GetExprRange(C, UO->getSubExpr(), MaxWidth); + return GetExprRange(C, UO->getSubExpr(), MaxWidth, InConstantContext); } } if (const auto *OVE = dyn_cast<OpaqueValueExpr>(E)) - return GetExprRange(C, OVE->getSourceExpr(), MaxWidth); + return GetExprRange(C, OVE->getSourceExpr(), MaxWidth, InConstantContext); if (const auto *BitField = E->getSourceBitField()) return IntRange(BitField->getBitWidthValue(C), @@ -10122,8 +10141,9 @@ static IntRange GetExprRange(ASTContext &C, const Expr *E, unsigned MaxWidth) { return IntRange::forValueOfType(C, GetExprType(E)); } -static IntRange GetExprRange(ASTContext &C, const Expr *E) { - return GetExprRange(C, E, C.getIntWidth(GetExprType(E))); +static IntRange GetExprRange(ASTContext &C, const Expr *E, + bool InConstantContext) { + return GetExprRange(C, E, C.getIntWidth(GetExprType(E)), InConstantContext); } /// Checks whether the given value, which currently has the given @@ -10411,13 +10431,14 @@ static bool CheckTautologicalComparison(Sema &S, BinaryOperator *E, // cases involving boolean values for historical reasons. We should pick a // consistent way of presenting these diagnostics. if (!InRange || Other->isKnownToHaveBooleanValue()) { + S.DiagRuntimeBehavior( - E->getOperatorLoc(), E, - S.PDiag(!InRange ? diag::warn_out_of_range_compare - : diag::warn_tautological_bool_compare) - << OS.str() << classifyConstantValue(Constant) - << OtherT << OtherIsBooleanDespiteType << *Result - << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange()); + E->getOperatorLoc(), E, + S.PDiag(!InRange ? diag::warn_out_of_range_compare + : diag::warn_tautological_bool_compare) + << OS.str() << classifyConstantValue(Constant) << OtherT + << OtherIsBooleanDespiteType << *Result + << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange()); } else { unsigned Diag = (isKnownToHaveUnsignedValue(OriginalOther) && Value == 0) ? (HasEnumType(OriginalOther) @@ -10521,7 +10542,8 @@ static void AnalyzeComparison(Sema &S, BinaryOperator *E) { } // Otherwise, calculate the effective range of the signed operand. - IntRange signedRange = GetExprRange(S.Context, signedOperand); + IntRange signedRange = + GetExprRange(S.Context, signedOperand, S.isConstantEvaluated()); // Go ahead and analyze implicit conversions in the operands. Note // that we skip the implicit conversions on both sides. @@ -10538,7 +10560,8 @@ static void AnalyzeComparison(Sema &S, BinaryOperator *E) { // change the result of the comparison. if (E->isEqualityOp()) { unsigned comparisonWidth = S.Context.getIntWidth(T); - IntRange unsignedRange = GetExprRange(S.Context, unsignedOperand); + IntRange unsignedRange = + GetExprRange(S.Context, unsignedOperand, S.isConstantEvaluated()); // We should never be unable to prove that the unsigned operand is // non-negative. @@ -10549,9 +10572,9 @@ static void AnalyzeComparison(Sema &S, BinaryOperator *E) { } S.DiagRuntimeBehavior(E->getOperatorLoc(), E, - S.PDiag(diag::warn_mixed_sign_comparison) - << LHS->getType() << RHS->getType() - << LHS->getSourceRange() << RHS->getSourceRange()); + S.PDiag(diag::warn_mixed_sign_comparison) + << LHS->getType() << RHS->getType() + << LHS->getSourceRange() << RHS->getSourceRange()); } /// Analyzes an attempt to assign the given value to a bitfield. @@ -10719,8 +10742,8 @@ static void DiagnoseImpCast(Sema &S, Expr *E, QualType SourceType, QualType T, if (pruneControlFlow) { S.DiagRuntimeBehavior(E->getExprLoc(), E, S.PDiag(diag) - << SourceType << T << E->getSourceRange() - << SourceRange(CContext)); + << SourceType << T << E->getSourceRange() + << SourceRange(CContext)); return; } S.Diag(E->getExprLoc(), diag) @@ -11255,8 +11278,8 @@ CheckImplicitConversion(Sema &S, Expr *E, QualType T, SourceLocation CC, if (Source->isFixedPointType()) { if (Target->isUnsaturatedFixedPointType()) { Expr::EvalResult Result; - if (E->EvaluateAsFixedPoint(Result, S.Context, - Expr::SE_AllowSideEffects)) { + if (E->EvaluateAsFixedPoint(Result, S.Context, Expr::SE_AllowSideEffects, + S.isConstantEvaluated())) { APFixedPoint Value = Result.Val.getFixedPoint(); APFixedPoint MaxVal = S.Context.getFixedPointMax(T); APFixedPoint MinVal = S.Context.getFixedPointMin(T); @@ -11271,7 +11294,8 @@ CheckImplicitConversion(Sema &S, Expr *E, QualType T, SourceLocation CC, } } else if (Target->isIntegerType()) { Expr::EvalResult Result; - if (E->EvaluateAsFixedPoint(Result, S.Context, + if (!S.isConstantEvaluated() && + E->EvaluateAsFixedPoint(Result, S.Context, Expr::SE_AllowSideEffects)) { APFixedPoint FXResult = Result.Val.getFixedPoint(); @@ -11293,7 +11317,8 @@ CheckImplicitConversion(Sema &S, Expr *E, QualType T, SourceLocation CC, } else if (Target->isUnsaturatedFixedPointType()) { if (Source->isIntegerType()) { Expr::EvalResult Result; - if (E->EvaluateAsInt(Result, S.Context, Expr::SE_AllowSideEffects)) { + if (!S.isConstantEvaluated() && + E->EvaluateAsInt(Result, S.Context, Expr::SE_AllowSideEffects)) { llvm::APSInt Value = Result.Val.getInt(); bool Overflowed; @@ -11324,14 +11349,15 @@ CheckImplicitConversion(Sema &S, Expr *E, QualType T, SourceLocation CC, if (Target->isSpecificBuiltinType(BuiltinType::Bool)) return; - IntRange SourceRange = GetExprRange(S.Context, E); + IntRange SourceRange = GetExprRange(S.Context, E, S.isConstantEvaluated()); IntRange TargetRange = IntRange::forTargetOfCanonicalType(S.Context, Target); if (SourceRange.Width > TargetRange.Width) { // If the source is a constant, use a default-on diagnostic. // TODO: this should happen for bitfield stores, too. Expr::EvalResult Result; - if (E->EvaluateAsInt(Result, S.Context, Expr::SE_AllowSideEffects)) { + if (E->EvaluateAsInt(Result, S.Context, Expr::SE_AllowSideEffects, + S.isConstantEvaluated())) { llvm::APSInt Value(32); Value = Result.Val.getInt(); @@ -11341,11 +11367,11 @@ CheckImplicitConversion(Sema &S, Expr *E, QualType T, SourceLocation CC, std::string PrettySourceValue = Value.toString(10); std::string PrettyTargetValue = PrettyPrintInRange(Value, TargetRange); - S.DiagRuntimeBehavior(E->getExprLoc(), E, - S.PDiag(diag::warn_impcast_integer_precision_constant) - << PrettySourceValue << PrettyTargetValue - << E->getType() << T << E->getSourceRange() - << clang::SourceRange(CC)); + S.DiagRuntimeBehavior( + E->getExprLoc(), E, + S.PDiag(diag::warn_impcast_integer_precision_constant) + << PrettySourceValue << PrettyTargetValue << E->getType() << T + << E->getSourceRange() << clang::SourceRange(CC)); return; } @@ -12093,7 +12119,8 @@ class SequenceChecker : public EvaluatedExprVisitor<SequenceChecker> { bool evaluate(const Expr *E, bool &Result) { if (!EvalOK || E->isValueDependent()) return false; - EvalOK = E->EvaluateAsBooleanCondition(Result, Self.SemaRef.Context); + EvalOK = E->EvaluateAsBooleanCondition( + Result, Self.SemaRef.Context, Self.SemaRef.isConstantEvaluated()); return EvalOK; } @@ -12446,6 +12473,8 @@ void Sema::CheckUnsequencedOperations(Expr *E) { void Sema::CheckCompletedExpr(Expr *E, SourceLocation CheckLoc, bool IsConstexpr) { + llvm::SaveAndRestore<bool> ConstantContext( + isConstantEvaluatedOverride, IsConstexpr || isa<ConstantExpr>(E)); CheckImplicitConversions(E, CheckLoc); if (!E->isInstantiationDependent()) CheckUnsequencedOperations(E); @@ -12684,6 +12713,10 @@ static bool IsTailPaddedMemberArray(Sema &S, const llvm::APInt &Size, void Sema::CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr, const ArraySubscriptExpr *ASE, bool AllowOnePastEnd, bool IndexNegated) { + // Already diagnosed by the constant evaluator. + if (isConstantEvaluated()) + return; + IndexExpr = IndexExpr->IgnoreParenImpCasts(); if (IndexExpr->isValueDependent()) return; @@ -13821,8 +13854,13 @@ static bool isLayoutCompatible(ASTContext &C, QualType T1, QualType T2) { /// \param VD Declaration of an identifier that appears in a type tag. /// /// \param MagicValue Type tag magic value. +/// +/// \param isConstantEvaluated wether the evalaution should be performed in + +/// constant context. static bool FindTypeTagExpr(const Expr *TypeExpr, const ASTContext &Ctx, - const ValueDecl **VD, uint64_t *MagicValue) { + const ValueDecl **VD, uint64_t *MagicValue, + bool isConstantEvaluated) { while(true) { if (!TypeExpr) return false; @@ -13860,7 +13898,8 @@ static bool FindTypeTagExpr(const Expr *TypeExpr, const ASTContext &Ctx, const AbstractConditionalOperator *ACO = cast<AbstractConditionalOperator>(TypeExpr); bool Result; - if (ACO->getCond()->EvaluateAsBooleanCondition(Result, Ctx)) { + if (ACO->getCond()->EvaluateAsBooleanCondition(Result, Ctx, + isConstantEvaluated)) { if (Result) TypeExpr = ACO->getTrueExpr(); else @@ -13896,14 +13935,17 @@ static bool FindTypeTagExpr(const Expr *TypeExpr, const ASTContext &Ctx, /// /// \param TypeInfo Information about the corresponding C type. /// +/// \param isConstantEvaluated wether the evalaution should be performed in +/// constant context. +/// /// \returns true if the corresponding C type was found. static bool GetMatchingCType( - const IdentifierInfo *ArgumentKind, - const Expr *TypeExpr, const ASTContext &Ctx, - const llvm::DenseMap<Sema::TypeTagMagicValue, - Sema::TypeTagData> *MagicValues, - bool &FoundWrongKind, - Sema::TypeTagData &TypeInfo) { + const IdentifierInfo *ArgumentKind, const Expr *TypeExpr, + const ASTContext &Ctx, + const llvm::DenseMap<Sema::TypeTagMagicValue, Sema::TypeTagData> + *MagicValues, + bool &FoundWrongKind, Sema::TypeTagData &TypeInfo, + bool isConstantEvaluated) { FoundWrongKind = false; // Variable declaration that has type_tag_for_datatype attribute. @@ -13911,7 +13953,7 @@ static bool GetMatchingCType( uint64_t MagicValue; - if (!FindTypeTagExpr(TypeExpr, Ctx, &VD, &MagicValue)) + if (!FindTypeTagExpr(TypeExpr, Ctx, &VD, &MagicValue, isConstantEvaluated)) return false; if (VD) { @@ -13989,8 +14031,8 @@ void Sema::CheckArgumentWithTypeTag(const ArgumentWithTypeTagAttr *Attr, bool FoundWrongKind; TypeTagData TypeInfo; if (!GetMatchingCType(ArgumentKind, TypeTagExpr, Context, - TypeTagForDatatypeMagicValues.get(), - FoundWrongKind, TypeInfo)) { + TypeTagForDatatypeMagicValues.get(), FoundWrongKind, + TypeInfo, isConstantEvaluated())) { if (FoundWrongKind) Diag(TypeTagExpr->getExprLoc(), diag::warn_type_tag_for_datatype_wrong_kind) |