diff options
author | Clement Courbet <courbet@google.com> | 2018-05-23 07:58:41 +0000 |
---|---|---|
committer | Clement Courbet <courbet@google.com> | 2018-05-23 07:58:41 +0000 |
commit | 1c0a15c4449f862711cb0df0548d4c83a6ff8554 (patch) | |
tree | 11b067847a8a8dde752f73cac605aae9e5a357e5 /clang-tools-extra/clang-tidy/cppcoreguidelines | |
parent | 9b412153bfc4d3bed29f9b6c259b4b8777cc488f (diff) | |
download | bcm5719-llvm-1c0a15c4449f862711cb0df0548d4c83a6ff8554.tar.gz bcm5719-llvm-1c0a15c4449f862711cb0df0548d4c83a6ff8554.zip |
[clang-tidy] new cppcoreguidelines-narrowing-conversions check.
Summary:
Checks for narrowing conversions, e.g.
int i = 0;
i += 0.1;
This has what some might consider false positives for:
i += ceil(d);
Reviewers: alexfh, hokein
Subscribers: srhines, nemanjai, mgorny, JDevlieghere, xazax.hun, kbarton
Differential Revision: https://reviews.llvm.org/D38455
llvm-svn: 333066
Diffstat (limited to 'clang-tools-extra/clang-tidy/cppcoreguidelines')
4 files changed, 111 insertions, 0 deletions
diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt b/clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt index 2ce1a0800de..49fedd62203 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt @@ -4,6 +4,7 @@ add_clang_library(clangTidyCppCoreGuidelinesModule AvoidGotoCheck.cpp CppCoreGuidelinesTidyModule.cpp InterfacesGlobalInitCheck.cpp + NarrowingConversionsCheck.cpp NoMallocCheck.cpp OwningMemoryCheck.cpp ProBoundsArrayToPointerDecayCheck.cpp diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp index 51824eca9ac..a0392594696 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp @@ -13,6 +13,7 @@ #include "../misc/UnconventionalAssignOperatorCheck.h" #include "AvoidGotoCheck.h" #include "InterfacesGlobalInitCheck.h" +#include "NarrowingConversionsCheck.h" #include "NoMallocCheck.h" #include "OwningMemoryCheck.h" #include "ProBoundsArrayToPointerDecayCheck.h" @@ -40,6 +41,8 @@ public: "cppcoreguidelines-avoid-goto"); CheckFactories.registerCheck<InterfacesGlobalInitCheck>( "cppcoreguidelines-interfaces-global-init"); + CheckFactories.registerCheck<NarrowingConversionsCheck>( + "cppcoreguidelines-narrowing-conversions"); CheckFactories.registerCheck<NoMallocCheck>("cppcoreguidelines-no-malloc"); CheckFactories.registerCheck<OwningMemoryCheck>( "cppcoreguidelines-owning-memory"); diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/NarrowingConversionsCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/NarrowingConversionsCheck.cpp new file mode 100644 index 00000000000..2c5676e76a2 --- /dev/null +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/NarrowingConversionsCheck.cpp @@ -0,0 +1,70 @@ +//===--- NarrowingConversionsCheck.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 "NarrowingConversionsCheck.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" + +using namespace clang::ast_matchers; + +namespace clang { +namespace tidy { +namespace cppcoreguidelines { + +// FIXME: Check double -> float truncation. Pay attention to casts: +void NarrowingConversionsCheck::registerMatchers(MatchFinder *Finder) { + // ceil() and floor() are guaranteed to return integers, even though the type + // is not integral. + const auto IsCeilFloorCall = callExpr(callee(functionDecl( + hasAnyName("::ceil", "::std::ceil", "::floor", "::std::floor")))); + + const auto IsFloatExpr = + expr(hasType(realFloatingPointType()), unless(IsCeilFloorCall)); + + // 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); + + // 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())) + .bind("op"), + this); +} + +void NarrowingConversionsCheck::check(const MatchFinder::MatchResult &Result) { + if (const auto *Op = Result.Nodes.getNodeAs<BinaryOperator>("op")) { + if (Op->getLocStart().isMacroID()) + return; + diag(Op->getOperatorLoc(), "narrowing conversion from %0 to %1") + << Op->getRHS()->getType() << Op->getLHS()->getType(); + return; + } + const auto *Cast = Result.Nodes.getNodeAs<ImplicitCastExpr>("cast"); + if (Cast->getLocStart().isMacroID()) + return; + diag(Cast->getExprLoc(), "narrowing conversion from %0 to %1") + << Cast->getSubExpr()->getType() << Cast->getType(); +} + +} // namespace cppcoreguidelines +} // namespace tidy +} // namespace clang diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/NarrowingConversionsCheck.h b/clang-tools-extra/clang-tidy/cppcoreguidelines/NarrowingConversionsCheck.h new file mode 100644 index 00000000000..35f58bc220a --- /dev/null +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/NarrowingConversionsCheck.h @@ -0,0 +1,37 @@ +//===--- NarrowingConversionsCheck.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_CPPCOREGUIDELINES_NARROWING_CONVERSIONS_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_NARROWING_CONVERSIONS_H + +#include "../ClangTidy.h" + +namespace clang { +namespace tidy { +namespace cppcoreguidelines { + +/// Checks for narrowing conversions, e.g: +/// int i = 0; +/// i += 0.1; +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/cppcoreguidelines-narrowing-conversions.html +class NarrowingConversionsCheck : public ClangTidyCheck { +public: + NarrowingConversionsCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; +}; + +} // namespace cppcoreguidelines +} // namespace tidy +} // namespace clang + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_NARROWING_CONVERSIONS_H |