3636#include " clang/Basic/LangOptions.h"
3737#include " clang/Basic/SourceLocation.h"
3838#include " clang/Basic/Specifiers.h"
39+ #include " llvm/ADT/APFloat.h"
3940#include " llvm/ADT/APInt.h"
4041#include " llvm/ADT/APSInt.h"
4142#include " llvm/ADT/ArrayRef.h"
@@ -70,19 +71,19 @@ static SourceLocation GetEndLoc(Decl *D) {
7071 return D->getLocation ();
7172}
7273
73- // / Returns true on constant values based around a single IntegerLiteral.
74- // / Allow for use of parentheses, integer casts, and negative signs.
75- // / FIXME: it would be good to unify this function with
76- // / getIntegerLiteralSubexpressionValue at some point given the similarity
77- // / between the functions.
74+ // / Returns true on constant values based around a single IntegerLiteral,
75+ // / CharacterLiteral, or FloatingLiteral. Allow for use of parentheses, integer
76+ // / casts, and negative signs.
7877
79- static bool IsIntegerLiteralConstantExpr (const Expr *E) {
78+ static bool IsLiteralConstantExpr (const Expr *E) {
8079 // Allow parentheses
8180 E = E->IgnoreParens ();
8281
83- // Allow conversions to different integer kind.
82+ // Allow conversions to different integer kind, and integer to floating point
83+ // (to account for float comparing with int).
8484 if (const auto *CE = dyn_cast<CastExpr>(E)) {
85- if (CE->getCastKind () != CK_IntegralCast)
85+ if (CE->getCastKind () != CK_IntegralCast &&
86+ CE->getCastKind () != CK_IntegralToFloating)
8687 return false ;
8788 E = CE->getSubExpr ();
8889 }
@@ -93,16 +94,15 @@ static bool IsIntegerLiteralConstantExpr(const Expr *E) {
9394 return false ;
9495 E = UO->getSubExpr ();
9596 }
96-
97- return isa<IntegerLiteral>(E);
97+ return isa<IntegerLiteral, CharacterLiteral, FloatingLiteral>(E);
9898}
9999
100100// / Helper for tryNormalizeBinaryOperator. Attempts to extract an IntegerLiteral
101- // / constant expression or EnumConstantDecl from the given Expr. If it fails,
102- // / returns nullptr.
103- static const Expr *tryTransformToIntOrEnumConstant (const Expr *E) {
101+ // / FloatingLiteral, CharacterLiteral or EnumConstantDecl from the given Expr.
102+ // / If it fails, returns nullptr.
103+ static const Expr *tryTransformToLiteralConstant (const Expr *E) {
104104 E = E->IgnoreParens ();
105- if (IsIntegerLiteralConstantExpr (E))
105+ if (IsLiteralConstantExpr (E))
106106 return E;
107107 if (auto *DR = dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts ()))
108108 return isa<EnumConstantDecl>(DR->getDecl ()) ? DR : nullptr ;
@@ -119,7 +119,7 @@ tryNormalizeBinaryOperator(const BinaryOperator *B) {
119119 BinaryOperatorKind Op = B->getOpcode ();
120120
121121 const Expr *MaybeDecl = B->getLHS ();
122- const Expr *Constant = tryTransformToIntOrEnumConstant (B->getRHS ());
122+ const Expr *Constant = tryTransformToLiteralConstant (B->getRHS ());
123123 // Expr looked like `0 == Foo` instead of `Foo == 0`
124124 if (Constant == nullptr ) {
125125 // Flip the operator
@@ -133,7 +133,7 @@ tryNormalizeBinaryOperator(const BinaryOperator *B) {
133133 Op = BO_GE;
134134
135135 MaybeDecl = B->getRHS ();
136- Constant = tryTransformToIntOrEnumConstant (B->getLHS ());
136+ Constant = tryTransformToLiteralConstant (B->getLHS ());
137137 }
138138
139139 return std::make_tuple (MaybeDecl, Op, Constant);
@@ -1082,10 +1082,10 @@ class CFGBuilder {
10821082 return std::nullopt ;
10831083 }
10841084
1085+ template <typename APFloatOrInt>
10851086 TryResult analyzeLogicOperatorCondition (BinaryOperatorKind Relation,
1086- const llvm::APSInt &Value1,
1087- const llvm::APSInt &Value2) {
1088- assert (Value1.isSigned () == Value2.isSigned ());
1087+ const APFloatOrInt &Value1,
1088+ const APFloatOrInt &Value2) {
10891089 switch (Relation) {
10901090 default :
10911091 return TryResult ();
@@ -1170,82 +1170,120 @@ class CFGBuilder {
11701170 if (!areExprTypesCompatible (NumExpr1, NumExpr2))
11711171 return {};
11721172
1173+ // Check that the two expressions are of the same type.
11731174 Expr::EvalResult L1Result, L2Result;
1174- if (!NumExpr1->EvaluateAsInt (L1Result, *Context) ||
1175- !NumExpr2->EvaluateAsInt (L2Result, *Context))
1176- return {};
1177-
1178- llvm::APSInt L1 = L1Result.Val .getInt ();
1179- llvm::APSInt L2 = L2Result.Val .getInt ();
1180-
1181- // Can't compare signed with unsigned or with different bit width.
1182- if (L1.isSigned () != L2.isSigned () || L1.getBitWidth () != L2.getBitWidth ())
1175+ if (!NumExpr1->EvaluateAsRValue (L1Result, *Context) ||
1176+ !NumExpr2->EvaluateAsRValue (L2Result, *Context))
11831177 return {};
11841178
1185- // Values that will be used to determine if result of logical
1186- // operator is always true/false
1187- const llvm::APSInt Values[] = {
1188- // Value less than both Value1 and Value2
1189- llvm::APSInt::getMinValue (L1.getBitWidth (), L1.isUnsigned ()),
1190- // L1
1191- L1,
1192- // Value between Value1 and Value2
1193- ((L1 < L2) ? L1 : L2) + llvm::APSInt (llvm::APInt (L1.getBitWidth (), 1 ),
1194- L1.isUnsigned ()),
1195- // L2
1196- L2,
1197- // Value greater than both Value1 and Value2
1198- llvm::APSInt::getMaxValue (L1.getBitWidth (), L1.isUnsigned ()),
1199- };
1200-
1201- // Check whether expression is always true/false by evaluating the following
1179+ // Check whether expression is always true/false by evaluating the
1180+ // following
12021181 // * variable x is less than the smallest literal.
12031182 // * variable x is equal to the smallest literal.
12041183 // * Variable x is between smallest and largest literal.
12051184 // * Variable x is equal to the largest literal.
12061185 // * Variable x is greater than largest literal.
1207- bool AlwaysTrue = true , AlwaysFalse = true ;
1208- // Track value of both subexpressions. If either side is always
1209- // true/false, another warning should have already been emitted.
1210- bool LHSAlwaysTrue = true , LHSAlwaysFalse = true ;
1211- bool RHSAlwaysTrue = true , RHSAlwaysFalse = true ;
1212- for (const llvm::APSInt &Value : Values) {
1213- TryResult Res1, Res2;
1214- Res1 = analyzeLogicOperatorCondition (BO1, Value, L1);
1215- Res2 = analyzeLogicOperatorCondition (BO2, Value, L2);
1216-
1217- if (!Res1.isKnown () || !Res2.isKnown ())
1218- return {};
1186+ // This isn't technically correct, as it doesn't take into account the
1187+ // possibility that the variable could be NaN. However, this is a very rare
1188+ // case.
1189+ auto AnalyzeConditions = [&](const auto &Values,
1190+ const BinaryOperatorKind *BO1,
1191+ const BinaryOperatorKind *BO2) -> TryResult {
1192+ bool AlwaysTrue = true , AlwaysFalse = true ;
1193+ // Track value of both subexpressions. If either side is always
1194+ // true/false, another warning should have already been emitted.
1195+ bool LHSAlwaysTrue = true , LHSAlwaysFalse = true ;
1196+ bool RHSAlwaysTrue = true , RHSAlwaysFalse = true ;
1197+
1198+ for (const auto &Value : Values) {
1199+ TryResult Res1 =
1200+ analyzeLogicOperatorCondition (*BO1, Value, Values[1 ] /* L1 */ );
1201+ TryResult Res2 =
1202+ analyzeLogicOperatorCondition (*BO2, Value, Values[3 ] /* L2 */ );
1203+
1204+ if (!Res1.isKnown () || !Res2.isKnown ())
1205+ return {};
1206+
1207+ const bool IsAnd = B->getOpcode () == BO_LAnd;
1208+ const bool Combine = IsAnd ? (Res1.isTrue () && Res2.isTrue ())
1209+ : (Res1.isTrue () || Res2.isTrue ());
1210+
1211+ AlwaysTrue &= Combine;
1212+ AlwaysFalse &= !Combine;
1213+
1214+ LHSAlwaysTrue &= Res1.isTrue ();
1215+ LHSAlwaysFalse &= Res1.isFalse ();
1216+ RHSAlwaysTrue &= Res2.isTrue ();
1217+ RHSAlwaysFalse &= Res2.isFalse ();
1218+ }
12191219
1220- if (B-> getOpcode () == BO_LAnd ) {
1221- AlwaysTrue &= (Res1. isTrue () && Res2. isTrue ());
1222- AlwaysFalse &= !(Res1. isTrue () && Res2. isTrue ());
1223- } else {
1224- AlwaysTrue &= (Res1. isTrue () || Res2. isTrue ());
1225- AlwaysFalse &= !(Res1. isTrue () || Res2. isTrue () );
1220+ if (AlwaysTrue || AlwaysFalse ) {
1221+ if (!LHSAlwaysTrue && !LHSAlwaysFalse && !RHSAlwaysTrue &&
1222+ !RHSAlwaysFalse && BuildOpts. Observer ) {
1223+ BuildOpts. Observer -> compareAlwaysTrue (B, AlwaysTrue);
1224+ }
1225+ return TryResult (AlwaysTrue );
12261226 }
1227+ return {};
1228+ };
12271229
1228- LHSAlwaysTrue &= Res1.isTrue ();
1229- LHSAlwaysFalse &= Res1.isFalse ();
1230- RHSAlwaysTrue &= Res2.isTrue ();
1231- RHSAlwaysFalse &= Res2.isFalse ();
1230+ // Handle integer comparison.
1231+ if (L1Result.Val .getKind () == APValue::Int &&
1232+ L2Result.Val .getKind () == APValue::Int) {
1233+ llvm::APSInt L1 = L1Result.Val .getInt ();
1234+ llvm::APSInt L2 = L2Result.Val .getInt ();
1235+
1236+ // Can't compare signed with unsigned or with different bit width.
1237+ if (L1.isSigned () != L2.isSigned () ||
1238+ L1.getBitWidth () != L2.getBitWidth ())
1239+ return {};
1240+
1241+ // Values that will be used to determine if result of logical
1242+ // operator is always true/false
1243+ const llvm::APSInt Values[] = {
1244+ // Value less than both Value1 and Value2
1245+ llvm::APSInt::getMinValue (L1.getBitWidth (), L1.isUnsigned ()),
1246+ // L1
1247+ L1,
1248+ // Value between Value1 and Value2
1249+ ((L1 < L2) ? L1 : L2) +
1250+ llvm::APSInt (llvm::APInt (L1.getBitWidth (), 1 ), L1.isUnsigned ()),
1251+ // L2
1252+ L2,
1253+ // Value greater than both Value1 and Value2
1254+ llvm::APSInt::getMaxValue (L1.getBitWidth (), L1.isUnsigned ()),
1255+ };
1256+
1257+ return AnalyzeConditions (Values, &BO1, &BO2);
12321258 }
12331259
1234- if (AlwaysTrue || AlwaysFalse) {
1235- if (!LHSAlwaysTrue && !LHSAlwaysFalse && !RHSAlwaysTrue &&
1236- !RHSAlwaysFalse && BuildOpts.Observer )
1237- BuildOpts.Observer ->compareAlwaysTrue (B, AlwaysTrue);
1238- return TryResult (AlwaysTrue);
1260+ // Handle float comparison.
1261+ if (L1Result.Val .getKind () == APValue::Float &&
1262+ L2Result.Val .getKind () == APValue::Float) {
1263+ llvm::APFloat L1 = L1Result.Val .getFloat ();
1264+ llvm::APFloat L2 = L2Result.Val .getFloat ();
1265+ llvm::APFloat MidValue = L1;
1266+ MidValue.add (L2, llvm::APFloat::rmNearestTiesToEven);
1267+ MidValue.divide (llvm::APFloat (MidValue.getSemantics (), " 2.0" ),
1268+ llvm::APFloat::rmNearestTiesToEven);
1269+
1270+ const llvm::APFloat Values[] = {
1271+ llvm::APFloat::getSmallest (L1.getSemantics (), true ), L1, MidValue, L2,
1272+ llvm::APFloat::getLargest (L2.getSemantics (), false ),
1273+ };
1274+
1275+ return AnalyzeConditions (Values, &BO1, &BO2);
12391276 }
1277+
12401278 return {};
12411279 }
12421280
12431281 // / A bitwise-or with a non-zero constant always evaluates to true.
12441282 TryResult checkIncorrectBitwiseOrOperator (const BinaryOperator *B) {
12451283 const Expr *LHSConstant =
1246- tryTransformToIntOrEnumConstant (B->getLHS ()->IgnoreParenImpCasts ());
1284+ tryTransformToLiteralConstant (B->getLHS ()->IgnoreParenImpCasts ());
12471285 const Expr *RHSConstant =
1248- tryTransformToIntOrEnumConstant (B->getRHS ()->IgnoreParenImpCasts ());
1286+ tryTransformToLiteralConstant (B->getRHS ()->IgnoreParenImpCasts ());
12491287
12501288 if ((LHSConstant && RHSConstant) || (!LHSConstant && !RHSConstant))
12511289 return {};
0 commit comments