gchatelet updated this revision to Diff 170605.
gchatelet marked 2 inline comments as done.
gchatelet added a comment.

- Addressing comments


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D53488

Files:
  clang-tidy/cppcoreguidelines/NarrowingConversionsCheck.cpp
  test/clang-tidy/cppcoreguidelines-narrowing-conversions.cpp

Index: test/clang-tidy/cppcoreguidelines-narrowing-conversions.cpp
===================================================================
--- test/clang-tidy/cppcoreguidelines-narrowing-conversions.cpp
+++ test/clang-tidy/cppcoreguidelines-narrowing-conversions.cpp
@@ -9,12 +9,12 @@
 namespace floats {
 
 struct ConvertsToFloat {
-  operator float() const { return 0.5; }
+  operator float() const { return 0.5f; }
 };
 
-float operator "" _Pa(unsigned long long);
+float operator"" _float(unsigned long long);
 
-void not_ok(double d) {
+void narrow_double_to_int_not_ok(double d) {
   int i = 0;
   i = d;
   // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: narrowing conversion from 'double' to 'int' [cppcoreguidelines-narrowing-conversions]
@@ -24,11 +24,11 @@
   // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: narrowing conversion from 'float' to 'int' [cppcoreguidelines-narrowing-conversions]
   i = ConvertsToFloat();
   // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: narrowing conversion from 'float' to 'int' [cppcoreguidelines-narrowing-conversions]
-  i = 15_Pa;
+  i = 15_float;
   // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: narrowing conversion from 'float' to 'int' [cppcoreguidelines-narrowing-conversions]
 }
 
-void not_ok_binary_ops(double d) {
+void narrow_double_to_int_not_ok_binary_ops(double d) {
   int i = 0;
   i += 0.5;
   // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: narrowing conversion from 'double' to 'int' [cppcoreguidelines-narrowing-conversions]
@@ -52,6 +52,43 @@
   // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: narrowing conversion from 'double' to 'int' [cppcoreguidelines-narrowing-conversions]
 }
 
+double operator"" _double(unsigned long long);
+
+float narrow_double_to_float_return() {
+  return 0.5;
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: narrowing conversion from 'double' to 'float' [cppcoreguidelines-narrowing-conversions]
+}
+
+void narrow_double_to_float_not_ok(double d) {
+  float f = 0;
+  f = d;
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: narrowing conversion from 'double' to 'float' [cppcoreguidelines-narrowing-conversions]
+  f = 0.5;
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: narrowing conversion from 'double' to 'float' [cppcoreguidelines-narrowing-conversions]
+  f = 15_double;
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: narrowing conversion from 'double' to 'float' [cppcoreguidelines-narrowing-conversions]
+}
+
+void narrow_double_to_float_not_ok_binary_ops(double d) {
+  float f = 0;
+  f += 0.5;
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: narrowing conversion from 'double' to 'float' [cppcoreguidelines-narrowing-conversions]
+  f += d;
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: narrowing conversion from 'double' to 'float' [cppcoreguidelines-narrowing-conversions]
+  // 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;
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: narrowing conversion from 'double' to 'float' [cppcoreguidelines-narrowing-conversions]
+
+  f *= 0.5;
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: narrowing conversion from 'double' to 'float' [cppcoreguidelines-narrowing-conversions]
+  f /= 0.5;
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: narrowing conversion from 'double' to 'float' [cppcoreguidelines-narrowing-conversions]
+  f += (double)0.5f;
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: narrowing conversion from 'double' to 'float' [cppcoreguidelines-narrowing-conversions]
+}
+
 void ok(double d) {
   int i = 0;
   i = 1;
@@ -89,15 +126,19 @@
 
 void template_context() {
   f(1, 2);
+  f(1, .5f);
   f(1, .5);
+  f(1, .5l);
 }
 
 #define DERP(i, j) (i += j)
 
 void macro_context() {
   int i = 0;
   DERP(i, 2);
+  DERP(i, .5f);
   DERP(i, .5);
+  DERP(i, .5l);
 }
 
-}  // namespace floats
+} // namespace floats
Index: clang-tidy/cppcoreguidelines/NarrowingConversionsCheck.cpp
===================================================================
--- clang-tidy/cppcoreguidelines/NarrowingConversionsCheck.cpp
+++ clang-tidy/cppcoreguidelines/NarrowingConversionsCheck.cpp
@@ -27,42 +27,61 @@
   const auto IsFloatExpr =
       expr(hasType(realFloatingPointType()), unless(IsCeilFloorCall));
 
-  // casts:
+  // Casts:
   //   i = 0.5;
   //   void f(int); f(0.5);
-  Finder->addMatcher(implicitCastExpr(hasImplicitDestinationType(isInteger()),
-                                      hasSourceExpression(IsFloatExpr),
-                                      unless(hasParent(castExpr())),
-                                      unless(isInTemplateInstantiation()))
-                         .bind("cast"),
-                     this);
+  Finder->addMatcher(
+      implicitCastExpr(
+          anyOf(hasImplicitDestinationType(isInteger()),
+                hasImplicitDestinationType(realFloatingPointType())),
+          hasSourceExpression(IsFloatExpr), unless(hasParent(castExpr())),
+          unless(isInTemplateInstantiation()))
+          .bind("cast"),
+      this);
 
   // Binary operators:
   //   i += 0.5;
   Finder->addMatcher(
-      binaryOperator(isAssignmentOperator(),
-                     // The `=` case generates an implicit cast which is covered
-                     // by the previous matcher.
-                     unless(hasOperatorName("=")),
-                     hasLHS(hasType(isInteger())), hasRHS(IsFloatExpr),
-                     unless(isInTemplateInstantiation()))
+      binaryOperator(
+          isAssignmentOperator(),
+          // The `=` case generates an implicit cast which is covered
+          // by the previous matcher.
+          unless(hasOperatorName("=")),
+          hasLHS(anyOf(hasType(isInteger()), hasType(realFloatingPointType()))),
+          hasRHS(IsFloatExpr), unless(isInTemplateInstantiation()))
           .bind("op"),
       this);
 }
 
+static bool IsNarrower(const ASTContext *const Context, const QualType Lhs,
+                       const QualType Rhs) {
+  assert(Lhs->isRealType());     // Either integer or floating point.
+  assert(Rhs->isFloatingType()); // Floating point only.
+  return Lhs->isIntegerType() ||
+         (Context->getTypeSize(Rhs) > Context->getTypeSize(Lhs));
+}
+
 void NarrowingConversionsCheck::check(const MatchFinder::MatchResult &Result) {
-  if (const auto *Op = Result.Nodes.getNodeAs<BinaryOperator>("op")) {
+  const auto &Nodes = Result.Nodes;
+  if (const auto *Op = Nodes.getNodeAs<BinaryOperator>("op")) {
     if (Op->getBeginLoc().isMacroID())
       return;
-    diag(Op->getOperatorLoc(), "narrowing conversion from %0 to %1")
-        << Op->getRHS()->getType() << Op->getLHS()->getType();
-    return;
+    const auto LhsType = Op->getLHS()->getType();
+    const auto RhsType = Op->getRHS()->getType();
+    if (IsNarrower(Result.Context, LhsType, RhsType))
+      diag(Op->getOperatorLoc(), "narrowing conversion from %0 to %1")
+          << RhsType << LhsType;
+  } else if (const auto *Cast = Nodes.getNodeAs<ImplicitCastExpr>("cast")) {
+    if (Cast->getBeginLoc().isMacroID())
+      return;
+    const auto LhsType = Cast->getType();
+    const auto RhsType = Cast->getSubExpr()->getType();
+    if (IsNarrower(Result.Context, LhsType, RhsType))
+      diag(Cast->getExprLoc(), "narrowing conversion from %0 to %1")
+          << RhsType << LhsType;
+  } else {
+    llvm_unreachable("Invalid state");
   }
-  const auto *Cast = Result.Nodes.getNodeAs<ImplicitCastExpr>("cast");
-  if (Cast->getBeginLoc().isMacroID())
-    return;
-  diag(Cast->getExprLoc(), "narrowing conversion from %0 to %1")
-      << Cast->getSubExpr()->getType() << Cast->getType();
 }
 
 } // namespace cppcoreguidelines
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to