[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