rnkovacs updated this revision to Diff 108605.
rnkovacs edited the summary of this revision.

https://reviews.llvm.org/D35932

Files:
  clang-tidy/bugprone/BugproneTidyModule.cpp
  clang-tidy/bugprone/CMakeLists.txt
  clang-tidy/bugprone/IntegerDivisionCheck.cpp
  clang-tidy/bugprone/IntegerDivisionCheck.h
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/bugprone-integer-division.rst
  docs/clang-tidy/checks/list.rst
  test/clang-tidy/bugprone-integer-division.cpp

Index: test/clang-tidy/bugprone-integer-division.cpp
===================================================================
--- /dev/null
+++ test/clang-tidy/bugprone-integer-division.cpp
@@ -0,0 +1,130 @@
+// RUN: %check_clang_tidy %s bugprone-integer-division %t
+
+// Functions expecting a floating-point parameter.
+void floatArg(float x) {}
+void doubleArg(double x) {}
+void longDoubleArg(long double x) {}
+
+// Functions expected to return a floating-point value.
+float singleDiv() {
+  int x = -5;
+  int y = 2;
+  return x/y;
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: integer division; possible precision loss [bugprone-integer-division]
+}
+
+double wrongOrder(int x, int y) {
+  return x/y/0.1;
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: integer division; possible precision loss [bugprone-integer-division]
+}
+
+long double rightOrder(int x, int y) {
+  return 0.1/x/y; // OK
+}
+
+// Typical mathematical functions.
+float sin(float);
+double acos(double);
+long double tanh(long double);
+
+namespace std {
+  using ::sin;
+}
+
+template <typename T>
+void intDivSin(T x) {
+  sin(x);
+}
+
+int intFunc(int);
+
+struct X {
+  int n;
+  void m() {
+    sin(n / 3);
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: integer division; possible precision loss [bugprone-integer-division]
+  }
+};
+
+void integerDivision() {
+  char a = 2;
+  short b = -5;
+  int c = 9784;
+  enum third { x, y, z=2 };
+  third d = z;
+  char e[] = {'a', 'b', 'c'};
+  char f = *(e + 1 / a);
+  bool g = 1;
+
+  sin(1 + c / (2 + 2));
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: integer division; possible precision loss [bugprone-integer-division]
+  sin(c / (1 + .5));
+  sin((c + .5) / 3);
+
+  sin(intFunc(3) / 5);
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: integer division; possible precision loss [bugprone-integer-division]
+  acos(2 / intFunc(7));
+// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: integer division; possible precision loss [bugprone-integer-division]
+
+  floatArg(1 + 2 / 3);
+// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: integer division; possible precision loss [bugprone-integer-division]
+  sin(1 + 2 / 3);
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: integer division; possible precision loss [bugprone-integer-division]
+  intFunc(sin(1 + 2 / 3));
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: integer division; possible precision loss [bugprone-integer-division]
+
+  floatArg(1 + intFunc(1 + 2 / 3));
+  floatArg(1 + 3 * intFunc(a / b));
+
+  1 << (2 / 3);
+  1 << intFunc(2 / 3);
+
+#define M_SIN sin(a / b);
+  M_SIN
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: integer division; possible precision loss [bugprone-integer-division]
+
+  intDivSin<float>(a / b);
+// CHECK-MESSAGES: :[[@LINE-1]]:20: warning: integer division; possible precision loss [bugprone-integer-division]
+  intDivSin<double>(c / d);
+// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: integer division; possible precision loss [bugprone-integer-division]
+  intDivSin<long double>(f / g);
+// CHECK-MESSAGES: :[[@LINE-1]]:26: warning: integer division; possible precision loss [bugprone-integer-division]
+
+  floatArg(1 / 3);
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: integer division; possible precision loss [bugprone-integer-division]
+  doubleArg(a / b);
+// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: integer division; possible precision loss [bugprone-integer-division]
+  longDoubleArg(3 / d);
+// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: integer division; possible precision loss [bugprone-integer-division]
+  floatArg(a / b / 0.1);
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: integer division; possible precision loss [bugprone-integer-division]
+  doubleArg(1 / 3 / 0.1);
+// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: integer division; possible precision loss [bugprone-integer-division]
+  longDoubleArg(2 / 3 / 5);
+// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: integer division; possible precision loss [bugprone-integer-division]
+
+  std::sin(2 / 3);
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: integer division; possible precision loss [bugprone-integer-division]
+  ::acos(7 / d);
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: integer division; possible precision loss [bugprone-integer-division]
+  tanh(f / g);
+// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: integer division; possible precision loss [bugprone-integer-division]
+
+  floatArg(0.1 / a / b);
+  doubleArg(0.1 / 3 / 1);
+
+  singleDiv();
+  wrongOrder(a,b);
+  rightOrder(a,b);
+
+  sin(a / b);
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: integer division; possible precision loss [bugprone-integer-division]
+  acos(f / d);
+// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: integer division; possible precision loss [bugprone-integer-division]
+  tanh(c / g);
+// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: integer division; possible precision loss [bugprone-integer-division]
+
+  sin(3.0 / a);
+  acos(b / 3.14);
+  tanh(3.14 / f / g);
+}
Index: docs/clang-tidy/checks/list.rst
===================================================================
--- docs/clang-tidy/checks/list.rst
+++ docs/clang-tidy/checks/list.rst
@@ -9,6 +9,7 @@
    android-cloexec-open
    android-cloexec-socket
    boost-use-to-string
+   bugprone-integer-division
    bugprone-suspicious-memset-usage
    bugprone-undefined-memory-manipulation
    cert-dcl03-c (redirects to misc-static-assert) <cert-dcl03-c>
Index: docs/clang-tidy/checks/bugprone-integer-division.rst
===================================================================
--- /dev/null
+++ docs/clang-tidy/checks/bugprone-integer-division.rst
@@ -0,0 +1,24 @@
+.. title:: clang-tidy - bugprone-integer-division
+
+bugprone-integer-division
+=========================
+
+Finds integer divisions in environments otherwise requiring floating-point
+values indicating unintended precision loss.
+
+Examples:
+
+.. code-block:: c++
+
+  float floatFunc(float);
+  int intFunc(int);
+
+  // Warn, floating-point values expected.
+  floatFunc(1 + 7 / 2);
+  floatFunc(7 / (2 + 3));
+  intFunc(floatFunc(1 + 7 / 2));
+
+  // Do not warn, there are signs of deliberateness.
+  floatFunc(intFunc(3) / 5);
+  floatFunc(1 + intFunc(1 + 7 / 2));
+  1 << 2 / 3;
Index: docs/ReleaseNotes.rst
===================================================================
--- docs/ReleaseNotes.rst
+++ docs/ReleaseNotes.rst
@@ -57,6 +57,12 @@
 Improvements to clang-tidy
 --------------------------
 
+- New `bugprone-integer-division
+  <http://clang.llvm.org/extra/clang-tidy/checks/bugprone-integer-division.html>`_ check
+
+  Finds integer divisions in environments otherwise requiring floating-point
+  values indicating unintended precision loss.
+
 The improvements are...
 
 Improvements to include-fixer
Index: clang-tidy/bugprone/IntegerDivisionCheck.h
===================================================================
--- /dev/null
+++ clang-tidy/bugprone/IntegerDivisionCheck.h
@@ -0,0 +1,36 @@
+//===--- IntegerDivisionCheck.h - clang-tidy---------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_INTEGER_DIVISION_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_INTEGER_DIVISION_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+/// Finds integer divisions in environments otherwise requiring floating-point
+/// values indicating unintended precision loss.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone-integer-division.html
+class IntegerDivisionCheck : public ClangTidyCheck {
+public:
+  IntegerDivisionCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_INTEGER_DIVISION_H
Index: clang-tidy/bugprone/IntegerDivisionCheck.cpp
===================================================================
--- /dev/null
+++ clang-tidy/bugprone/IntegerDivisionCheck.cpp
@@ -0,0 +1,41 @@
+//===--- IntegerDivisionCheck.cpp - clang-tidy-----------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "IntegerDivisionCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+void IntegerDivisionCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(
+      binaryOperator(
+          hasOperatorName("/"), hasLHS(expr(hasType(isInteger())).bind("LHS")),
+          hasRHS(expr(hasType(isInteger())).bind("RHS")),
+          hasAncestor(castExpr(hasCastKind(CK_IntegralToFloating),
+                               unless(hasDescendant(callExpr(
+                                   hasType(isInteger()),
+                                   unless(anyOf(equalsBoundNode("LHS"),
+                                                equalsBoundNode("RHS")))))))))
+          .bind("BinOp"),
+      this);
+}
+
+void IntegerDivisionCheck::check(const MatchFinder::MatchResult &Result) {
+  const Expr *BinOp = Result.Nodes.getNodeAs<Expr>("BinOp");
+  diag(BinOp->getLocStart(), "integer division; possible precision loss");
+}
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
Index: clang-tidy/bugprone/CMakeLists.txt
===================================================================
--- clang-tidy/bugprone/CMakeLists.txt
+++ clang-tidy/bugprone/CMakeLists.txt
@@ -2,6 +2,7 @@
 
 add_clang_library(clangTidyBugproneModule
   BugproneTidyModule.cpp
+  IntegerDivisionCheck.cpp
   SuspiciousMemsetUsageCheck.cpp
   UndefinedMemoryManipulationCheck.cpp
 
Index: clang-tidy/bugprone/BugproneTidyModule.cpp
===================================================================
--- clang-tidy/bugprone/BugproneTidyModule.cpp
+++ clang-tidy/bugprone/BugproneTidyModule.cpp
@@ -10,6 +10,7 @@
 #include "../ClangTidy.h"
 #include "../ClangTidyModule.h"
 #include "../ClangTidyModuleRegistry.h"
+#include "IntegerDivisionCheck.h"
 #include "SuspiciousMemsetUsageCheck.h"
 #include "UndefinedMemoryManipulationCheck.h"
 
@@ -20,6 +21,8 @@
 class BugproneModule : public ClangTidyModule {
 public:
   void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
+    CheckFactories.registerCheck<IntegerDivisionCheck>(
+        "bugprone-integer-division");
     CheckFactories.registerCheck<SuspiciousMemsetUsageCheck>(
         "bugprone-suspicious-memset-usage");
     CheckFactories.registerCheck<UndefinedMemoryManipulationCheck>(
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to