summaryrefslogtreecommitdiffstats
path: root/clang-tools-extra/clang-tidy
diff options
context:
space:
mode:
authorHaojian Wu <hokein@google.com>2016-02-08 10:16:13 +0000
committerHaojian Wu <hokein@google.com>2016-02-08 10:16:13 +0000
commit25779e404b08eb92ff409a8f38080f3e46575bb7 (patch)
tree928d5a36135bccdab2938737b8cf487ba6d3d31e /clang-tools-extra/clang-tidy
parente1bfc2e793d9f9b529031ca0e19f06a3340ee5fc (diff)
downloadbcm5719-llvm-25779e404b08eb92ff409a8f38080f3e46575bb7.tar.gz
bcm5719-llvm-25779e404b08eb92ff409a8f38080f3e46575bb7.zip
[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 llvm-svn: 260084
Diffstat (limited to 'clang-tools-extra/clang-tidy')
-rw-r--r--clang-tools-extra/clang-tidy/misc/CMakeLists.txt3
-rw-r--r--clang-tools-extra/clang-tidy/misc/IncorrectRoundings.cpp74
-rw-r--r--clang-tools-extra/clang-tidy/misc/IncorrectRoundings.h38
-rw-r--r--clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp3
4 files changed, 117 insertions, 1 deletions
diff --git a/clang-tools-extra/clang-tidy/misc/CMakeLists.txt b/clang-tools-extra/clang-tidy/misc/CMakeLists.txt
index 6835c549c73..93f8af9f39d 100644
--- a/clang-tools-extra/clang-tidy/misc/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/misc/CMakeLists.txt
@@ -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
diff --git a/clang-tools-extra/clang-tidy/misc/IncorrectRoundings.cpp b/clang-tools-extra/clang-tidy/misc/IncorrectRoundings.cpp
new file mode 100644
index 00000000000..993af51d53e
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/misc/IncorrectRoundings.cpp
@@ -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
diff --git a/clang-tools-extra/clang-tidy/misc/IncorrectRoundings.h b/clang-tools-extra/clang-tidy/misc/IncorrectRoundings.h
new file mode 100644
index 00000000000..bb7cf144835
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/misc/IncorrectRoundings.h
@@ -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_
diff --git a/clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp b/clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp
index 62f6b0529fc..d34e35748ac 100644
--- a/clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp
@@ -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>(
OpenPOWER on IntegriCloud