Prazek created this revision.
Herald added subscribers: xazax.hun, mgorny.

This check flags usages of ``std::numeric_limits<T>::{min,max}()`` for
unspecialized types. It is dangerous because returns T(), which might is
rarely
minimum or maximum for this type.

Consider scenario:

1. Have `typedef long long BigInt` in source code
2. Use `std::numeric_limits<BigInt>::min()`
3. Replace the `BigInt` typedef with class implementing BigIntegers
4. Compile silently your code and find it few years later that you have

of by
9223372036854775808 error.


https://reviews.llvm.org/D33470

Files:
  clang-tidy/misc/CMakeLists.txt
  clang-tidy/misc/DefaultNumericsCheck.cpp
  clang-tidy/misc/DefaultNumericsCheck.h
  clang-tidy/misc/MiscTidyModule.cpp
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/list.rst
  docs/clang-tidy/checks/misc-default-numerics.rst
  test/clang-tidy/misc-default-numerics.cpp

Index: test/clang-tidy/misc-default-numerics.cpp
===================================================================
--- /dev/null
+++ test/clang-tidy/misc-default-numerics.cpp
@@ -0,0 +1,42 @@
+// RUN: %check_clang_tidy %s misc-default-numerics %t
+
+namespace std {
+
+template <typename T>
+struct numeric_limit {
+  static T min() { return T(); }
+  static T max() { return T(); }
+};
+
+template <>
+struct numeric_limit<int> {
+  static int min() { return -1; }
+  static int max() { return 1; }
+};
+
+} // namespace std
+
+class MyType {};
+template <typename T>
+class MyTemplate {};
+
+void test() {
+  auto x = std::numeric_limit<int>::min();
+
+  auto y = std::numeric_limit<MyType>::min();
+  // CHECK-MESSAGES: [[@LINE-1]]:12: warning: called std::numeric_limit method on not specialized type
+
+  auto z = std::numeric_limit<MyTemplate<int>>::max();
+  // CHECK-MESSAGES: [[@LINE-1]]:12: warning: called std::numeric_limit method on not specialized type
+}
+
+template <typename T>
+void fun() {
+  auto x = std::numeric_limit<T>::min();
+}
+
+void testTemplate() {
+  fun<int>();
+  // FIXME: This should generate warning with backtrace.
+  fun<MyType>;
+}
Index: docs/clang-tidy/checks/misc-default-numerics.rst
===================================================================
--- /dev/null
+++ docs/clang-tidy/checks/misc-default-numerics.rst
@@ -0,0 +1,15 @@
+.. title:: clang-tidy - misc-default-numerics
+
+misc-default-numerics
+=====================
+
+This check flags usages of ``std::numeric_limits<T>::{min,max}()`` for
+unspecialized types. It is dangerous because returns T(), which might is rarely
+minimum or maximum for this type.
+
+Consider scenario:
+1. Have `typedef long long BigInt` in source code
+2. Use `std::numeric_limits<BigInt>::min()`
+3. Replace the `BigInt` typedef with class implementing BigIntegers
+4. Compile silently your code and find it few years later that you have of by
+9223372036854775808 error.
Index: docs/clang-tidy/checks/list.rst
===================================================================
--- docs/clang-tidy/checks/list.rst
+++ docs/clang-tidy/checks/list.rst
@@ -75,6 +75,7 @@
    misc-assert-side-effect
    misc-bool-pointer-implicit-conversion
    misc-dangling-handle
+   misc-default-numerics
    misc-definitions-in-headers
    misc-fold-init-type
    misc-forward-declaration-namespace
Index: docs/ReleaseNotes.rst
===================================================================
--- docs/ReleaseNotes.rst
+++ docs/ReleaseNotes.rst
@@ -71,7 +71,11 @@
   <http://clang.llvm.org/extra/clang-tidy/checks/cppcoreguidelines-no-malloc.html>`_ check
 
   Allow custom memory management functions to be considered as well.
-  
+
+- New `misc-default-numerics
+  <http://clang.llvm.org/extra/clang-tidy/checks/misc-default-numerics.html>`_ check
+  Finds uses of ``std::numeric_limit<T>`` for unspecialized types
+
 - New `misc-forwarding-reference-overload
   <http://clang.llvm.org/extra/clang-tidy/checks/misc-forwarding-reference-overload.html>`_ check
 
Index: clang-tidy/misc/MiscTidyModule.cpp
===================================================================
--- clang-tidy/misc/MiscTidyModule.cpp
+++ clang-tidy/misc/MiscTidyModule.cpp
@@ -14,6 +14,7 @@
 #include "AssertSideEffectCheck.h"
 #include "BoolPointerImplicitConversionCheck.h"
 #include "DanglingHandleCheck.h"
+#include "DefaultNumericsCheck.h"
 #include "DefinitionsInHeadersCheck.h"
 #include "FoldInitTypeCheck.h"
 #include "ForwardDeclarationNamespaceCheck.h"
@@ -66,6 +67,7 @@
     CheckFactories.registerCheck<ArgumentCommentCheck>("misc-argument-comment");
     CheckFactories.registerCheck<AssertSideEffectCheck>(
         "misc-assert-side-effect");
+    CheckFactories.registerCheck<DefaultNumericsCheck>("misc-default-numerics");
     CheckFactories.registerCheck<ForwardingReferenceOverloadCheck>(
         "misc-forwarding-reference-overload");
     CheckFactories.registerCheck<MisplacedConstCheck>("misc-misplaced-const");
Index: clang-tidy/misc/DefaultNumericsCheck.h
===================================================================
--- /dev/null
+++ clang-tidy/misc/DefaultNumericsCheck.h
@@ -0,0 +1,37 @@
+//===--- DefaultNumericsCheck.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_DEFAULT_NUMERICS_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_DEFAULT_NUMERICS_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace misc {
+
+/// This check flags usages of ``std::numeric_limits<T>::{min,max}()`` for
+/// unspecialized types. It is dangerous because returns T(), which might is
+/// rarely minimum or maximum for this type.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/misc-default-numerics.html
+class DefaultNumericsCheck : public ClangTidyCheck {
+public:
+  DefaultNumericsCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace misc
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_DEFAULT_NUMERICS_H
Index: clang-tidy/misc/DefaultNumericsCheck.cpp
===================================================================
--- /dev/null
+++ clang-tidy/misc/DefaultNumericsCheck.cpp
@@ -0,0 +1,46 @@
+//===--- DefaultNumericsCheck.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 "DefaultNumericsCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace misc {
+
+void DefaultNumericsCheck::registerMatchers(MatchFinder *Finder) {
+  if (!getLangOpts().CPlusPlus)
+    return;
+  // FIXME: We should also warn in template intantiations, but it would require
+  // printing backtrace.
+  Finder->addMatcher(
+      callExpr(
+          callee(cxxMethodDecl(
+              hasAnyName("min", "max"),
+              ofClass(cxxRecordDecl(unless(isExplicitTemplateSpecialization()),
+                                    hasName("::std::numeric_limit"))))),
+          unless(isInTemplateInstantiation()))
+          .bind("call"),
+      this);
+}
+
+void DefaultNumericsCheck::check(const MatchFinder::MatchResult &Result) {
+
+  const auto *MatchedDecl = Result.Nodes.getNodeAs<CallExpr>("call");
+
+  diag(MatchedDecl->getLocStart(),
+       "called std::numeric_limit method on not specialized type");
+}
+
+} // namespace misc
+} // namespace tidy
+} // namespace clang
Index: clang-tidy/misc/CMakeLists.txt
===================================================================
--- clang-tidy/misc/CMakeLists.txt
+++ clang-tidy/misc/CMakeLists.txt
@@ -3,6 +3,7 @@
 add_clang_library(clangTidyMiscModule
   ArgumentCommentCheck.cpp
   AssertSideEffectCheck.cpp
+  DefaultNumericsCheck.cpp
   ForwardingReferenceOverloadCheck.cpp
   MisplacedConstCheck.cpp
   UnconventionalAssignOperatorCheck.cpp
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to