[PATCH] D53488: [clang-tidy] Catching narrowing from double to float.

Jonas Toth via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Tue Oct 30 09:16:29 PDT 2018


JonasToth added inline comments.


================
Comment at: clang-tidy/cppcoreguidelines/NarrowingConversionsCheck.cpp:25
 
 // FIXME: Check double -> float truncation. Pay attention to casts:
 void NarrowingConversionsCheck::registerMatchers(MatchFinder *Finder) {
----------------
I think this comment is now outdated.


================
Comment at: clang-tidy/cppcoreguidelines/NarrowingConversionsCheck.cpp:42
+                       unless(hasParent(castExpr())),
+                       unless(isInTemplateInstantiation()))
+          .bind("cast"),
----------------
Here and in the matcher below:

`isInTemplateInstantiation` is a wide range, if you match only on `isTypeDependent()` it would remove the false negatives from templates but still catch clear cases that are within a template function.

With the current implementation non-type-templates would be ignored as well.
IMHO that could be done in a follow-up to keep the scope on one thing.


================
Comment at: clang-tidy/cppcoreguidelines/NarrowingConversionsCheck.cpp:66
+
+struct IntegerRange {
+  bool Contains(const IntegerRange &From) const {
----------------
Please enclose that `struct` with an anonymous namespace


================
Comment at: clang-tidy/cppcoreguidelines/NarrowingConversionsCheck.cpp:85
+  if (T->isFloatingPoint()) {
+    const unsigned PrecisionBits = llvm::APFloatBase::semanticsPrecision(
+        Context.getFloatTypeSemantics(T->desugar()));
----------------
please remove that `const` as its uncommon to qualify values in LLVM code.


================
Comment at: clang-tidy/cppcoreguidelines/NarrowingConversionsCheck.cpp:92
+
+    // 'One' is created with PrecisionBits plus two bytes:
+    // - One to express the missing negative value of 2's complement
----------------
Maybe repleace `One` with `1.0`? It sounds slightly weird with the following `One`s


================
Comment at: clang-tidy/cppcoreguidelines/NarrowingConversionsCheck.cpp:118
+  if (ToType == FromType || ToType == nullptr || FromType == nullptr ||
+      ToType->isDependentType() || FromType->isDependentType())
+    return false;
----------------
what about value dependentness? That is resolveable, but i believe ignored here


================
Comment at: clang-tidy/cppcoreguidelines/NarrowingConversionsCheck.cpp:125
+  if (FromType->isIntegerType() && ToType->isIntegerType())
+    return ToType->getScalarTypeKind() == clang::Type::STK_Bool
+               ? false
----------------
narrowing to `bool` is not nice either. I would prefer diagnosing these too.


================
Comment at: clang-tidy/cppcoreguidelines/NarrowingConversionsCheck.cpp:132
+
+  const auto FromIntegerRange = createFromType(Context, FromType);
+  const auto ToIntegerRange = createFromType(Context, ToType);
----------------
please no `const` and `auto` as well, as the type is not obvious.


================
Comment at: clang-tidy/cppcoreguidelines/NarrowingConversionsCheck.cpp:147
+                                                     const Expr *Rhs) {
+  const QualType LhsType = Lhs->getType();
+  const QualType RhsType = Rhs->getType();
----------------
please no `const`


================
Comment at: clang-tidy/cppcoreguidelines/NarrowingConversionsCheck.cpp:149
+  const QualType RhsType = Rhs->getType();
+  if (Lhs->isValueDependent() || Rhs->isValueDependent() ||
+      LhsType->isDependentType() || RhsType->isDependentType())
----------------
you can shorten this condition with `isDependentType`


================
Comment at: clang-tidy/cppcoreguidelines/NarrowingConversionsCheck.cpp:155
+    return false;
+  const auto LhsIntegerRange = createFromType(Context, getBuiltinType(Lhs));
+  if (!LhsIntegerRange.Contains(IntegerConstant))
----------------
please no `const`


================
Comment at: clang-tidy/cppcoreguidelines/NarrowingConversionsCheck.cpp:165
+  if (const auto *CO = llvm::dyn_cast<ConditionalOperator>(Rhs)) {
+    const bool NarrowLhs = diagIfNarrowConstant(
+        Context, CO->getLHS()->getExprLoc(), Lhs, CO->getLHS());
----------------
you could remove both temporaries and return directly and then ellide the braces.
If you don't like that please remove the `const`


================
Comment at: docs/clang-tidy/checks/cppcoreguidelines-narrowing-conversions.rst:15
 
-We enforce only part of the guideline, more specifically, we flag:
- - All floating-point to integer conversions that are not marked by an explicit
-   cast (c-style or ``static_cast``). For example: ``int i = 0; i += 0.1;``,
-   ``void f(int); f(0.1);``,
- - All applications of binary operators where the left-hand-side is an integer
-   and the right-hand-size is a floating-point. For example:
-   ``int i; i+= 0.1;``.
+A narrowing conversion is currently defined as a conversion from:
+ - an integer to a narrower integer (e.g. ``char`` to ``unsigned char``),
----------------
Please reword that slightly. The narrowing conversions are defined by the standard, we just implement it "partially" or so.


================
Comment at: test/clang-tidy/cppcoreguidelines-narrowing-conversions.cpp:80
+  // We warn on the following even though it's not dangerous because there is no reason to use a double literal here.
+  // TODO(courbet): Provide an automatic fix.
+  f += 2.0;
----------------
llvm doesn't add a name to the TODOs.

The necessity to use the correct literal might still be there even if the number is in range: the precisions differ. I believe it could have differences on non-integer values what literal you use respectively.


================
Comment at: test/clang-tidy/cppcoreguidelines-narrowing-conversions.cpp:102
+    int i;       // 32 bits
+    float f = i; // doesn't fit in 24 bits
+    // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: narrowing conversion from 'int' to 'float' [cppcoreguidelines-narrowing-conversions]
----------------
could you please add tests with integer arithmetic?

E.g. this: 
```
short n1, n2;
float result = n1 + n2; // 'n1 + n2' is of type 'int' because of integer rules
```


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D53488





More information about the cfe-commits mailing list