[clang-tools-extra] r260084 - [clang-tidy] Move incorrect-roundings to upstream.

Haojian Wu via cfe-commits cfe-commits at lists.llvm.org
Mon Feb 8 02:16:14 PST 2016


Author: hokein
Date: Mon Feb  8 04:16:13 2016
New Revision: 260084

URL: http://llvm.org/viewvc/llvm-project?rev=260084&view=rev
Log:
[clang-tidy] Move incorrect-roundings to upstream.

Summary: This is originally implemented by Jacques Pienaar.

Reviewers: alexfh

Subscribers: cfe-commits, jpienaar

Differential Revision: http://reviews.llvm.org/D16764

Added:
    clang-tools-extra/trunk/clang-tidy/misc/IncorrectRoundings.cpp
    clang-tools-extra/trunk/clang-tidy/misc/IncorrectRoundings.h
    clang-tools-extra/trunk/docs/clang-tidy/checks/misc-incorrect-roundings.rst
    clang-tools-extra/trunk/test/clang-tidy/misc-incorrect-roundings.cpp
Modified:
    clang-tools-extra/trunk/clang-tidy/misc/CMakeLists.txt
    clang-tools-extra/trunk/clang-tidy/misc/MiscTidyModule.cpp
    clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst

Modified: clang-tools-extra/trunk/clang-tidy/misc/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/misc/CMakeLists.txt?rev=260084&r1=260083&r2=260084&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/misc/CMakeLists.txt (original)
+++ clang-tools-extra/trunk/clang-tidy/misc/CMakeLists.txt Mon Feb  8 04:16:13 2016
@@ -7,11 +7,12 @@ add_clang_library(clangTidyMiscModule
   BoolPointerImplicitConversionCheck.cpp
   DefinitionsInHeadersCheck.cpp
   InaccurateEraseCheck.cpp
+  IncorrectRoundings.cpp
   InefficientAlgorithmCheck.cpp
   MacroParenthesesCheck.cpp
   MacroRepeatedSideEffectsCheck.cpp
   MiscTidyModule.cpp
-  MoveConstantArgumentCheck.cpp 
+  MoveConstantArgumentCheck.cpp
   MoveConstructorInitCheck.cpp
   NewDeleteOverloadsCheck.cpp
   NoexceptMoveConstructorCheck.cpp

Added: clang-tools-extra/trunk/clang-tidy/misc/IncorrectRoundings.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/misc/IncorrectRoundings.cpp?rev=260084&view=auto
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/misc/IncorrectRoundings.cpp (added)
+++ clang-tools-extra/trunk/clang-tidy/misc/IncorrectRoundings.cpp Mon Feb  8 04:16:13 2016
@@ -0,0 +1,74 @@
+//===--- IncorrectRoundings.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 "IncorrectRoundings.h"
+#include "clang/AST/DeclBase.h"
+#include "clang/AST/Type.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Lex/Lexer.h"
+
+namespace clang {
+namespace ast_matchers {
+AST_MATCHER(FloatingLiteral, floatHalf) {
+  const auto &literal = Node.getValue();
+  if ((&Node.getSemantics()) == &llvm::APFloat::IEEEsingle)
+    return literal.convertToFloat() == 0.5f;
+  if ((&Node.getSemantics()) == &llvm::APFloat::IEEEdouble)
+    return literal.convertToDouble() == 0.5;
+  return false;
+}
+
+// TODO(hokein): Moving it to ASTMatchers.h
+AST_MATCHER(BuiltinType, isFloatingPoint) {
+  return Node.isFloatingPoint();
+}
+} // namespace ast_matchers
+} // namespace clang
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+void IncorrectRoundings::registerMatchers(MatchFinder *MatchFinder) {
+  // Match a floating literal with value 0.5.
+  auto FloatHalf = floatLiteral(floatHalf());
+
+  // Match a floating point expression.
+  auto FloatType = expr(hasType(builtinType(isFloatingPoint())));
+
+  // Match a floating literal of 0.5 or a floating literal of 0.5 implicitly.
+  // cast to floating type.
+  auto FloatOrCastHalf =
+      anyOf(FloatHalf, implicitCastExpr(FloatType, has(FloatHalf)));
+
+  // Match if either the LHS or RHS is a floating literal of 0.5 or a floating
+  // literal of 0.5 and the other is of type double or vice versa.
+  auto OneSideHalf = anyOf(allOf(hasLHS(FloatOrCastHalf), hasRHS(FloatType)),
+                           allOf(hasRHS(FloatOrCastHalf), hasLHS(FloatType)));
+
+  // Find expressions of cast to int of the sum of a floating point expression
+  // and 0.5.
+  MatchFinder->addMatcher(
+      implicitCastExpr(
+          hasImplicitDestinationType(isInteger()),
+          ignoringParenCasts(binaryOperator(hasOperatorName("+"), OneSideHalf)))
+          .bind("CastExpr"),
+      this);
+}
+
+void IncorrectRoundings::check(const MatchFinder::MatchResult &Result) {
+  const auto *CastExpr = Result.Nodes.getStmtAs<ImplicitCastExpr>("CastExpr");
+  diag(CastExpr->getLocStart(),
+       "casting (double + 0.5) to integer leads to incorrect rounding; "
+       "consider using lround (#include <cmath>) instead");
+}
+
+} // namespace tidy
+} // namespace clang

Added: clang-tools-extra/trunk/clang-tidy/misc/IncorrectRoundings.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/misc/IncorrectRoundings.h?rev=260084&view=auto
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/misc/IncorrectRoundings.h (added)
+++ clang-tools-extra/trunk/clang-tidy/misc/IncorrectRoundings.h Mon Feb  8 04:16:13 2016
@@ -0,0 +1,38 @@
+//===--- IncorrectRoundings.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_MISC_INCORRECTROUNDINGS_H_
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_INCORRECTROUNDINGS_H_
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+
+/// \brief Checks the usage of patterns known to produce incorrect rounding.
+/// Programmers often use
+///   (int)(double_expression + 0.5)
+/// to round the double expression to an integer. The problem with this
+///  1. It is unnecessarily slow.
+///  2. It is incorrect. The number 0.499999975 (smallest representable float
+///     number below 0.5) rounds to 1.0. Even worse behavior for negative
+///     numbers where both -0.5f and -1.4f both round to 0.0.
+class IncorrectRoundings : public ClangTidyCheck {
+public:
+  IncorrectRoundings(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace tidy
+} // namespace clang
+
+
+#endif  // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_INCORRECTROUNDINGS_H_

Modified: clang-tools-extra/trunk/clang-tidy/misc/MiscTidyModule.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/misc/MiscTidyModule.cpp?rev=260084&r1=260083&r2=260084&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/misc/MiscTidyModule.cpp (original)
+++ clang-tools-extra/trunk/clang-tidy/misc/MiscTidyModule.cpp Mon Feb  8 04:16:13 2016
@@ -16,6 +16,7 @@
 #include "BoolPointerImplicitConversionCheck.h"
 #include "DefinitionsInHeadersCheck.h"
 #include "InaccurateEraseCheck.h"
+#include "IncorrectRoundings.h"
 #include "InefficientAlgorithmCheck.h"
 #include "MacroParenthesesCheck.h"
 #include "MacroRepeatedSideEffectsCheck.h"
@@ -54,6 +55,8 @@ public:
         "misc-definitions-in-headers");
     CheckFactories.registerCheck<InaccurateEraseCheck>(
         "misc-inaccurate-erase");
+    CheckFactories.registerCheck<IncorrectRoundings>(
+        "misc-incorrect-roundings");
     CheckFactories.registerCheck<InefficientAlgorithmCheck>(
         "misc-inefficient-algorithm");
     CheckFactories.registerCheck<MacroParenthesesCheck>(

Modified: clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst?rev=260084&r1=260083&r2=260084&view=diff
==============================================================================
--- clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst (original)
+++ clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst Mon Feb  8 04:16:13 2016
@@ -49,6 +49,7 @@ Clang-Tidy Checks
    misc-bool-pointer-implicit-conversion
    misc-definitions-in-headers
    misc-inaccurate-erase
+   misc-incorrect-roundings
    misc-inefficient-algorithm
    misc-macro-parentheses
    misc-macro-repeated-side-effects

Added: clang-tools-extra/trunk/docs/clang-tidy/checks/misc-incorrect-roundings.rst
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/clang-tidy/checks/misc-incorrect-roundings.rst?rev=260084&view=auto
==============================================================================
--- clang-tools-extra/trunk/docs/clang-tidy/checks/misc-incorrect-roundings.rst (added)
+++ clang-tools-extra/trunk/docs/clang-tidy/checks/misc-incorrect-roundings.rst Mon Feb  8 04:16:13 2016
@@ -0,0 +1,12 @@
+misc-incorrect-roundings
+========================
+
+Checks the usage of patterns known to produce incorrect rounding.
+Programmers often use
+  (int)(double_expression + 0.5)
+to round the double expression to an integer. The problem with this:
+
+1. It is unnecessarily slow.
+2. It is incorrect. The number 0.499999975 (smallest representable float
+   number below 0.5) rounds to 1.0. Even worse behavior for negative
+   numbers where both -0.5f and -1.4f both round to 0.0.

Added: clang-tools-extra/trunk/test/clang-tidy/misc-incorrect-roundings.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/misc-incorrect-roundings.cpp?rev=260084&view=auto
==============================================================================
--- clang-tools-extra/trunk/test/clang-tidy/misc-incorrect-roundings.cpp (added)
+++ clang-tools-extra/trunk/test/clang-tidy/misc-incorrect-roundings.cpp Mon Feb  8 04:16:13 2016
@@ -0,0 +1,86 @@
+// RUN: %check_clang_tidy %s misc-incorrect-roundings %t
+
+void b(int x) {}
+
+void f1() {
+  float f;
+  double d;
+  long double ld;
+  int x;
+
+  x = (d + 0.5);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: casting (double + 0.5) to integer leads to incorrect rounding; consider using lround (#include <cmath>) instead [misc-incorrect-roundings]
+  x = (d + 0.5f);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: casting (double + 0.5)
+  x = (f + 0.5);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: casting (double + 0.5)
+  x = (f + 0.5f);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: casting (double + 0.5)
+  x = (0.5 + d);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: casting (double + 0.5)
+  x = (0.5f + d);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: casting (double + 0.5)
+  x = (0.5 + ld);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: casting (double + 0.5)
+  x = (0.5f + ld);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: casting (double + 0.5)
+  x = (0.5 + f);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: casting (double + 0.5)
+  x = (0.5f + f);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: casting (double + 0.5)
+  x = (int)(d + 0.5);
+  // CHECK-MESSAGES: [[@LINE-1]]:12: warning: casting (double + 0.5)
+  x = (int)(d + 0.5f);
+  // CHECK-MESSAGES: [[@LINE-1]]:12: warning: casting (double + 0.5)
+  x = (int)(ld + 0.5);
+  // CHECK-MESSAGES: [[@LINE-1]]:12: warning: casting (double + 0.5)
+  x = (int)(ld + 0.5f);
+  // CHECK-MESSAGES: [[@LINE-1]]:12: warning: casting (double + 0.5)
+  x = (int)(f + 0.5);
+  // CHECK-MESSAGES: [[@LINE-1]]:12: warning: casting (double + 0.5)
+  x = (int)(f + 0.5f);
+  // CHECK-MESSAGES: [[@LINE-1]]:12: warning: casting (double + 0.5)
+  x = (int)(0.5 + d);
+  // CHECK-MESSAGES: [[@LINE-1]]:12: warning: casting (double + 0.5)
+  x = (int)(0.5f + d);
+  // CHECK-MESSAGES: [[@LINE-1]]:12: warning: casting (double + 0.5)
+  x = (int)(0.5 + ld);
+  // CHECK-MESSAGES: [[@LINE-1]]:12: warning: casting (double + 0.5)
+  x = (int)(0.5f + ld);
+  // CHECK-MESSAGES: [[@LINE-1]]:12: warning: casting (double + 0.5)
+  x = (int)(0.5 + f);
+  // CHECK-MESSAGES: [[@LINE-1]]:12: warning: casting (double + 0.5)
+  x = (int)(0.5f + f);
+  // CHECK-MESSAGES: [[@LINE-1]]:12: warning: casting (double + 0.5)
+  x = static_cast<int>(d + 0.5);
+  // CHECK-MESSAGES: [[@LINE-1]]:24: warning: casting (double + 0.5)
+  x = static_cast<int>(d + 0.5f);
+  // CHECK-MESSAGES: [[@LINE-1]]:24: warning: casting (double + 0.5)
+  x = static_cast<int>(ld + 0.5);
+  // CHECK-MESSAGES: [[@LINE-1]]:24: warning: casting (double + 0.5)
+  x = static_cast<int>(ld + 0.5f);
+  // CHECK-MESSAGES: [[@LINE-1]]:24: warning: casting (double + 0.5)
+  x = static_cast<int>(f + 0.5);
+  // CHECK-MESSAGES: [[@LINE-1]]:24: warning: casting (double + 0.5)
+  x = static_cast<int>(f + 0.5f);
+  // CHECK-MESSAGES: [[@LINE-1]]:24: warning: casting (double + 0.5)
+  x = static_cast<int>(0.5 + d);
+  // CHECK-MESSAGES: [[@LINE-1]]:24: warning: casting (double + 0.5)
+  x = static_cast<int>(0.5f + d);
+  // CHECK-MESSAGES: [[@LINE-1]]:24: warning: casting (double + 0.5)
+  x = static_cast<int>(0.5 + ld);
+  // CHECK-MESSAGES: [[@LINE-1]]:24: warning: casting (double + 0.5)
+  x = static_cast<int>(0.5f + ld);
+  // CHECK-MESSAGES: [[@LINE-1]]:24: warning: casting (double + 0.5)
+  x = static_cast<int>(0.5 + f);
+  // CHECK-MESSAGES: [[@LINE-1]]:24: warning: casting (double + 0.5)
+  x = static_cast<int>(0.5f + f);
+  // CHECK-MESSAGES: [[@LINE-1]]:24: warning: casting (double + 0.5)
+
+  // Don't warn if constant is not 0.5.
+  x = (int)(d + 0.6);
+  x = (int)(0.6 + d);
+
+  // Don't warn if binary operator is not directly beneath cast.
+  x = (int)(1 + (0.5 + f));
+}




More information about the cfe-commits mailing list