ZaMaZaN4iK created this revision.
ZaMaZaN4iK added reviewers: JonasToth, Szelethus, aaron.ballman, lebedev.ri.
ZaMaZaN4iK added a project: clang-tools-extra.
Herald added subscribers: cfe-commits, mgorny.
Herald added a project: clang.

Hello.

I found quite interesting and useful FMPOV check for Clang Tidy - description 
<https://www.viva64.com/en/w/v624>, examples 
<https://www.viva64.com/en/examples/v624/>. Whole sense is in using standard 
(from cmath or math.h or math headers) math constants instead of written from 
scratch.

This patch is in status WIP. The main question is - do we want to see such 
check in Clang Tidy and should I continue work on it?

Thank you.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D65912

Files:
  clang-tools-extra/clang-tidy/misc/CMakeLists.txt
  clang-tools-extra/clang-tidy/misc/MathConstantsCheck.cpp
  clang-tools-extra/clang-tidy/misc/MathConstantsCheck.h
  clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  clang-tools-extra/docs/clang-tidy/checks/misc-math-constants.rst
  clang-tools-extra/test/clang-tidy/misc-math-constants.cpp

Index: clang-tools-extra/test/clang-tidy/misc-math-constants.cpp
===================================================================
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/misc-math-constants.cpp
@@ -0,0 +1,18 @@
+// RUN: %check_clang_tidy %s misc-math-constants %t
+
+// FIXME: Add something that triggers the check here.
+void f();
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: function 'f' is insufficiently awesome [misc-math-constants]
+
+// FIXME: Verify the applied fix.
+//   * Make the CHECK patterns specific enough and try to make verified lines
+//     unique to avoid incorrect matches.
+//   * Use {{}} for regular expressions.
+// CHECK-FIXES: {{^}}void awesome_f();{{$}}
+
+// FIXME: Add something that doesn't trigger the check here.
+void foo()
+{
+    double pi = 3.14;
+    double p_2 = 1.57;
+}
Index: clang-tools-extra/docs/clang-tidy/checks/misc-math-constants.rst
===================================================================
--- /dev/null
+++ clang-tools-extra/docs/clang-tidy/checks/misc-math-constants.rst
@@ -0,0 +1,6 @@
+.. title:: clang-tidy - misc-math-constants
+
+misc-math-constants
+===================
+
+FIXME: Describe what patterns does the check detect and why. Give examples.
Index: clang-tools-extra/docs/clang-tidy/checks/list.rst
===================================================================
--- clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -4,7 +4,6 @@
 =================
 
 .. toctree::
-
    abseil-duration-addition
    abseil-duration-comparison
    abseil-duration-conversion-cast
@@ -103,87 +102,87 @@
    cert-msc51-cpp
    cert-oop11-cpp (redirects to performance-move-constructor-init) <cert-oop11-cpp>
    cert-oop54-cpp (redirects to bugprone-unhandled-self-assignment) <cert-oop54-cpp>
-   clang-analyzer-core.CallAndMessage
-   clang-analyzer-core.DivideZero
+   clang-analyzer-core.CallAndMessage (redirects to https://clang.llvm.org/docs/analyzer/checkers) <clang-analyzer-core.CallAndMessage>
+   clang-analyzer-core.DivideZero (redirects to https://clang.llvm.org/docs/analyzer/checkers) <clang-analyzer-core.DivideZero>
    clang-analyzer-core.DynamicTypePropagation
-   clang-analyzer-core.NonNullParamChecker
-   clang-analyzer-core.NullDereference
-   clang-analyzer-core.StackAddressEscape
-   clang-analyzer-core.UndefinedBinaryOperatorResult
-   clang-analyzer-core.VLASize
-   clang-analyzer-core.uninitialized.ArraySubscript
-   clang-analyzer-core.uninitialized.Assign
-   clang-analyzer-core.uninitialized.Branch
+   clang-analyzer-core.NonNullParamChecker (redirects to https://clang.llvm.org/docs/analyzer/checkers) <clang-analyzer-core.NonNullParamChecker>
+   clang-analyzer-core.NullDereference (redirects to https://clang.llvm.org/docs/analyzer/checkers) <clang-analyzer-core.NullDereference>
+   clang-analyzer-core.StackAddressEscape (redirects to https://clang.llvm.org/docs/analyzer/checkers) <clang-analyzer-core.StackAddressEscape>
+   clang-analyzer-core.UndefinedBinaryOperatorResult (redirects to https://clang.llvm.org/docs/analyzer/checkers) <clang-analyzer-core.UndefinedBinaryOperatorResult>
+   clang-analyzer-core.VLASize (redirects to https://clang.llvm.org/docs/analyzer/checkers) <clang-analyzer-core.VLASize>
+   clang-analyzer-core.uninitialized.ArraySubscript (redirects to https://clang.llvm.org/docs/analyzer/checkers) <clang-analyzer-core.uninitialized.ArraySubscript>
+   clang-analyzer-core.uninitialized.Assign (redirects to https://clang.llvm.org/docs/analyzer/checkers) <clang-analyzer-core.uninitialized.Assign>
+   clang-analyzer-core.uninitialized.Branch (redirects to https://clang.llvm.org/docs/analyzer/checkers) <clang-analyzer-core.uninitialized.Branch>
    clang-analyzer-core.uninitialized.CapturedBlockVariable
-   clang-analyzer-core.uninitialized.UndefReturn
+   clang-analyzer-core.uninitialized.UndefReturn (redirects to https://clang.llvm.org/docs/analyzer/checkers) <clang-analyzer-core.uninitialized.UndefReturn>
    clang-analyzer-cplusplus.InnerPointer
-   clang-analyzer-cplusplus.Move
-   clang-analyzer-cplusplus.NewDelete
-   clang-analyzer-cplusplus.NewDeleteLeaks
-   clang-analyzer-deadcode.DeadStores
-   clang-analyzer-nullability.NullPassedToNonnull
-   clang-analyzer-nullability.NullReturnedFromNonnull
-   clang-analyzer-nullability.NullableDereferenced
-   clang-analyzer-nullability.NullablePassedToNonnull
+   clang-analyzer-cplusplus.Move (redirects to https://clang.llvm.org/docs/analyzer/checkers) <clang-analyzer-cplusplus.Move>
+   clang-analyzer-cplusplus.NewDelete (redirects to https://clang.llvm.org/docs/analyzer/checkers) <clang-analyzer-cplusplus.NewDelete>
+   clang-analyzer-cplusplus.NewDeleteLeaks (redirects to https://clang.llvm.org/docs/analyzer/checkers) <clang-analyzer-cplusplus.NewDeleteLeaks>
+   clang-analyzer-deadcode.DeadStores (redirects to https://clang.llvm.org/docs/analyzer/checkers) <clang-analyzer-deadcode.DeadStores>
+   clang-analyzer-nullability.NullPassedToNonnull (redirects to https://clang.llvm.org/docs/analyzer/checkers) <clang-analyzer-nullability.NullPassedToNonnull>
+   clang-analyzer-nullability.NullReturnedFromNonnull (redirects to https://clang.llvm.org/docs/analyzer/checkers) <clang-analyzer-nullability.NullReturnedFromNonnull>
+   clang-analyzer-nullability.NullableDereferenced (redirects to https://clang.llvm.org/docs/analyzer/checkers) <clang-analyzer-nullability.NullableDereferenced>
+   clang-analyzer-nullability.NullablePassedToNonnull (redirects to https://clang.llvm.org/docs/analyzer/checkers) <clang-analyzer-nullability.NullablePassedToNonnull>
    clang-analyzer-nullability.NullableReturnedFromNonnull
-   clang-analyzer-optin.cplusplus.UninitializedObject
-   clang-analyzer-optin.cplusplus.VirtualCall
-   clang-analyzer-optin.mpi.MPI-Checker
+   clang-analyzer-optin.cplusplus.UninitializedObject (redirects to https://clang.llvm.org/docs/analyzer/checkers) <clang-analyzer-optin.cplusplus.UninitializedObject>
+   clang-analyzer-optin.cplusplus.VirtualCall (redirects to https://clang.llvm.org/docs/analyzer/checkers) <clang-analyzer-optin.cplusplus.VirtualCall>
+   clang-analyzer-optin.mpi.MPI-Checker (redirects to https://clang.llvm.org/docs/analyzer/checkers) <clang-analyzer-optin.mpi.MPI-Checker>
    clang-analyzer-optin.osx.OSObjectCStyleCast
-   clang-analyzer-optin.osx.cocoa.localizability.EmptyLocalizationContextChecker
-   clang-analyzer-optin.osx.cocoa.localizability.NonLocalizedStringChecker
+   clang-analyzer-optin.osx.cocoa.localizability.EmptyLocalizationContextChecker (redirects to https://clang.llvm.org/docs/analyzer/checkers) <clang-analyzer-optin.osx.cocoa.localizability.EmptyLocalizationContextChecker>
+   clang-analyzer-optin.osx.cocoa.localizability.NonLocalizedStringChecker (redirects to https://clang.llvm.org/docs/analyzer/checkers) <clang-analyzer-optin.osx.cocoa.localizability.NonLocalizedStringChecker>
    clang-analyzer-optin.performance.GCDAntipattern
    clang-analyzer-optin.performance.Padding
    clang-analyzer-optin.portability.UnixAPI
-   clang-analyzer-osx.API
+   clang-analyzer-osx.API (redirects to https://clang.llvm.org/docs/analyzer/checkers) <clang-analyzer-osx.API>
    clang-analyzer-osx.MIG
    clang-analyzer-osx.NumberObjectConversion
    clang-analyzer-osx.OSObjectRetainCount
    clang-analyzer-osx.ObjCProperty
-   clang-analyzer-osx.SecKeychainAPI
-   clang-analyzer-osx.cocoa.AtSync
+   clang-analyzer-osx.SecKeychainAPI (redirects to https://clang.llvm.org/docs/analyzer/checkers) <clang-analyzer-osx.SecKeychainAPI>
+   clang-analyzer-osx.cocoa.AtSync (redirects to https://clang.llvm.org/docs/analyzer/checkers) <clang-analyzer-osx.cocoa.AtSync>
    clang-analyzer-osx.cocoa.AutoreleaseWrite
-   clang-analyzer-osx.cocoa.ClassRelease
-   clang-analyzer-osx.cocoa.Dealloc
-   clang-analyzer-osx.cocoa.IncompatibleMethodTypes
+   clang-analyzer-osx.cocoa.ClassRelease (redirects to https://clang.llvm.org/docs/analyzer/checkers) <clang-analyzer-osx.cocoa.ClassRelease>
+   clang-analyzer-osx.cocoa.Dealloc (redirects to https://clang.llvm.org/docs/analyzer/checkers) <clang-analyzer-osx.cocoa.Dealloc>
+   clang-analyzer-osx.cocoa.IncompatibleMethodTypes (redirects to https://clang.llvm.org/docs/analyzer/checkers) <clang-analyzer-osx.cocoa.IncompatibleMethodTypes>
    clang-analyzer-osx.cocoa.Loops
    clang-analyzer-osx.cocoa.MissingSuperCall
-   clang-analyzer-osx.cocoa.NSAutoreleasePool
-   clang-analyzer-osx.cocoa.NSError
-   clang-analyzer-osx.cocoa.NilArg
+   clang-analyzer-osx.cocoa.NSAutoreleasePool (redirects to https://clang.llvm.org/docs/analyzer/checkers) <clang-analyzer-osx.cocoa.NSAutoreleasePool>
+   clang-analyzer-osx.cocoa.NSError (redirects to https://clang.llvm.org/docs/analyzer/checkers) <clang-analyzer-osx.cocoa.NSError>
+   clang-analyzer-osx.cocoa.NilArg (redirects to https://clang.llvm.org/docs/analyzer/checkers) <clang-analyzer-osx.cocoa.NilArg>
    clang-analyzer-osx.cocoa.NonNilReturnValue
-   clang-analyzer-osx.cocoa.ObjCGenerics
-   clang-analyzer-osx.cocoa.RetainCount
+   clang-analyzer-osx.cocoa.ObjCGenerics (redirects to https://clang.llvm.org/docs/analyzer/checkers) <clang-analyzer-osx.cocoa.ObjCGenerics>
+   clang-analyzer-osx.cocoa.RetainCount (redirects to https://clang.llvm.org/docs/analyzer/checkers) <clang-analyzer-osx.cocoa.RetainCount>
    clang-analyzer-osx.cocoa.RunLoopAutoreleaseLeak
-   clang-analyzer-osx.cocoa.SelfInit
-   clang-analyzer-osx.cocoa.SuperDealloc
-   clang-analyzer-osx.cocoa.UnusedIvars
-   clang-analyzer-osx.cocoa.VariadicMethodTypes
-   clang-analyzer-osx.coreFoundation.CFError
-   clang-analyzer-osx.coreFoundation.CFNumber
-   clang-analyzer-osx.coreFoundation.CFRetainRelease
-   clang-analyzer-osx.coreFoundation.containers.OutOfBounds
-   clang-analyzer-osx.coreFoundation.containers.PointerSizedValues
-   clang-analyzer-security.FloatLoopCounter
-   clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling
-   clang-analyzer-security.insecureAPI.UncheckedReturn
-   clang-analyzer-security.insecureAPI.bcmp
-   clang-analyzer-security.insecureAPI.bcopy
-   clang-analyzer-security.insecureAPI.bzero
-   clang-analyzer-security.insecureAPI.getpw
-   clang-analyzer-security.insecureAPI.gets
-   clang-analyzer-security.insecureAPI.mkstemp
-   clang-analyzer-security.insecureAPI.mktemp
-   clang-analyzer-security.insecureAPI.rand
-   clang-analyzer-security.insecureAPI.strcpy
-   clang-analyzer-security.insecureAPI.vfork
-   clang-analyzer-unix.API
-   clang-analyzer-unix.Malloc
-   clang-analyzer-unix.MallocSizeof
-   clang-analyzer-unix.MismatchedDeallocator
-   clang-analyzer-unix.Vfork
-   clang-analyzer-unix.cstring.BadSizeArg
-   clang-analyzer-unix.cstring.NullArg
+   clang-analyzer-osx.cocoa.SelfInit (redirects to https://clang.llvm.org/docs/analyzer/checkers) <clang-analyzer-osx.cocoa.SelfInit>
+   clang-analyzer-osx.cocoa.SuperDealloc (redirects to https://clang.llvm.org/docs/analyzer/checkers) <clang-analyzer-osx.cocoa.SuperDealloc>
+   clang-analyzer-osx.cocoa.UnusedIvars (redirects to https://clang.llvm.org/docs/analyzer/checkers) <clang-analyzer-osx.cocoa.UnusedIvars>
+   clang-analyzer-osx.cocoa.VariadicMethodTypes (redirects to https://clang.llvm.org/docs/analyzer/checkers) <clang-analyzer-osx.cocoa.VariadicMethodTypes>
+   clang-analyzer-osx.coreFoundation.CFError (redirects to https://clang.llvm.org/docs/analyzer/checkers) <clang-analyzer-osx.coreFoundation.CFError>
+   clang-analyzer-osx.coreFoundation.CFNumber (redirects to https://clang.llvm.org/docs/analyzer/checkers) <clang-analyzer-osx.coreFoundation.CFNumber>
+   clang-analyzer-osx.coreFoundation.CFRetainRelease (redirects to https://clang.llvm.org/docs/analyzer/checkers) <clang-analyzer-osx.coreFoundation.CFRetainRelease>
+   clang-analyzer-osx.coreFoundation.containers.OutOfBounds (redirects to https://clang.llvm.org/docs/analyzer/checkers) <clang-analyzer-osx.coreFoundation.containers.OutOfBounds>
+   clang-analyzer-osx.coreFoundation.containers.PointerSizedValues (redirects to https://clang.llvm.org/docs/analyzer/checkers) <clang-analyzer-osx.coreFoundation.containers.PointerSizedValues>
+   clang-analyzer-security.FloatLoopCounter (redirects to https://clang.llvm.org/docs/analyzer/checkers) <clang-analyzer-security.FloatLoopCounter>
+   clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling (redirects to https://clang.llvm.org/docs/analyzer/checkers) <clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling>
+   clang-analyzer-security.insecureAPI.UncheckedReturn (redirects to https://clang.llvm.org/docs/analyzer/checkers) <clang-analyzer-security.insecureAPI.UncheckedReturn>
+   clang-analyzer-security.insecureAPI.bcmp (redirects to https://clang.llvm.org/docs/analyzer/checkers) <clang-analyzer-security.insecureAPI.bcmp>
+   clang-analyzer-security.insecureAPI.bcopy (redirects to https://clang.llvm.org/docs/analyzer/checkers) <clang-analyzer-security.insecureAPI.bcopy>
+   clang-analyzer-security.insecureAPI.bzero (redirects to https://clang.llvm.org/docs/analyzer/checkers) <clang-analyzer-security.insecureAPI.bzero>
+   clang-analyzer-security.insecureAPI.getpw (redirects to https://clang.llvm.org/docs/analyzer/checkers) <clang-analyzer-security.insecureAPI.getpw>
+   clang-analyzer-security.insecureAPI.gets (redirects to https://clang.llvm.org/docs/analyzer/checkers) <clang-analyzer-security.insecureAPI.gets>
+   clang-analyzer-security.insecureAPI.mkstemp (redirects to https://clang.llvm.org/docs/analyzer/checkers) <clang-analyzer-security.insecureAPI.mkstemp>
+   clang-analyzer-security.insecureAPI.mktemp (redirects to https://clang.llvm.org/docs/analyzer/checkers) <clang-analyzer-security.insecureAPI.mktemp>
+   clang-analyzer-security.insecureAPI.rand (redirects to https://clang.llvm.org/docs/analyzer/checkers) <clang-analyzer-security.insecureAPI.rand>
+   clang-analyzer-security.insecureAPI.strcpy (redirects to https://clang.llvm.org/docs/analyzer/checkers) <clang-analyzer-security.insecureAPI.strcpy>
+   clang-analyzer-security.insecureAPI.vfork (redirects to https://clang.llvm.org/docs/analyzer/checkers) <clang-analyzer-security.insecureAPI.vfork>
+   clang-analyzer-unix.API (redirects to https://clang.llvm.org/docs/analyzer/checkers) <clang-analyzer-unix.API>
+   clang-analyzer-unix.Malloc (redirects to https://clang.llvm.org/docs/analyzer/checkers) <clang-analyzer-unix.Malloc>
+   clang-analyzer-unix.MallocSizeof (redirects to https://clang.llvm.org/docs/analyzer/checkers) <clang-analyzer-unix.MallocSizeof>
+   clang-analyzer-unix.MismatchedDeallocator (redirects to https://clang.llvm.org/docs/analyzer/checkers) <clang-analyzer-unix.MismatchedDeallocator>
+   clang-analyzer-unix.Vfork (redirects to https://clang.llvm.org/docs/analyzer/checkers) <clang-analyzer-unix.Vfork>
+   clang-analyzer-unix.cstring.BadSizeArg (redirects to https://clang.llvm.org/docs/analyzer/checkers) <clang-analyzer-unix.cstring.BadSizeArg>
+   clang-analyzer-unix.cstring.NullArg (redirects to https://clang.llvm.org/docs/analyzer/checkers) <clang-analyzer-unix.cstring.NullArg>
    clang-analyzer-valist.CopyToSelf
    clang-analyzer-valist.Uninitialized
    clang-analyzer-valist.Unterminated
@@ -276,6 +275,7 @@
    llvm-prefer-isa-or-dyn-cast-in-conditionals
    llvm-twine-local
    misc-definitions-in-headers
+   misc-math-constants
    misc-misplaced-const
    misc-new-delete-overloads
    misc-non-copyable-objects
Index: clang-tools-extra/docs/ReleaseNotes.rst
===================================================================
--- clang-tools-extra/docs/ReleaseNotes.rst
+++ clang-tools-extra/docs/ReleaseNotes.rst
@@ -85,6 +85,11 @@
 
 The improvements are...
 
+- New :doc:`misc-math-constants
+  <clang-tidy/checks/misc-math-constants>` check.
+
+  FIXME: add release notes.
+
 Improvements to clang-include-fixer
 -----------------------------------
 
Index: clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp
===================================================================
--- clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp
+++ clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp
@@ -10,6 +10,7 @@
 #include "../ClangTidyModule.h"
 #include "../ClangTidyModuleRegistry.h"
 #include "DefinitionsInHeadersCheck.h"
+#include "MathConstantsCheck.h"
 #include "MisplacedConstCheck.h"
 #include "NewDeleteOverloadsCheck.h"
 #include "NonCopyableObjects.h"
@@ -32,6 +33,8 @@
   void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
     CheckFactories.registerCheck<DefinitionsInHeadersCheck>(
         "misc-definitions-in-headers");
+    CheckFactories.registerCheck<MathConstantsCheck>(
+        "misc-math-constants");
     CheckFactories.registerCheck<MisplacedConstCheck>("misc-misplaced-const");
     CheckFactories.registerCheck<NewDeleteOverloadsCheck>(
         "misc-new-delete-overloads");
Index: clang-tools-extra/clang-tidy/misc/MathConstantsCheck.h
===================================================================
--- /dev/null
+++ clang-tools-extra/clang-tidy/misc/MathConstantsCheck.h
@@ -0,0 +1,59 @@
+//===--- MathConstantsCheck.h - clang-tidy ----------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_MATHCONSTANTSCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_MATHCONSTANTSCHECK_H
+
+#include "../ClangTidyCheck.h"
+
+#include "../utils/IncludeInserter.h"
+
+#include "llvm/ADT/Optional.h"
+
+#include <memory>
+#include <string>
+#include <vector>
+
+namespace clang {
+namespace tidy {
+namespace misc {
+
+/// FIXME: Write a short description.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/misc-math-constants.html
+class MathConstantsCheck : public ClangTidyCheck {
+public:
+  MathConstantsCheck(StringRef Name, ClangTidyContext *Context);
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+  void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP,
+                           Preprocessor *ModuleExpanderPP) override;
+  void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
+
+private:
+  void insertHeader(DiagnosticBuilder &Diag, FileID FD);
+
+  struct MathConstantDescription
+  {
+      const Optional<std::string> NameInC;
+      const Optional<std::string> NameInCpp20;
+      const double Value;
+  };
+
+  const std::vector<MathConstantDescription> Constants;
+  const utils::IncludeSorter::IncludeStyle IncludeStyle;
+  std::string ChosenHeaderName;
+  std::unique_ptr<utils::IncludeInserter> Inserter;
+};
+
+} // namespace misc
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_MATHCONSTANTSCHECK_H
Index: clang-tools-extra/clang-tidy/misc/MathConstantsCheck.cpp
===================================================================
--- /dev/null
+++ clang-tools-extra/clang-tidy/misc/MathConstantsCheck.cpp
@@ -0,0 +1,153 @@
+//===--- MathConstantsCheck.cpp - clang-tidy ------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "MathConstantsCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "../../../clang/unittests/AST/Language.h"
+
+#include <cmath>
+#include <iostream>
+#include <string>
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace misc {
+
+namespace
+{
+
+constexpr char StdMathHeader[] = "math";
+constexpr char StdCmathHeader[] = "cmath";
+constexpr char StdCHeader[] = "math.h";
+constexpr char FloatType[] = "floatLiteral";
+constexpr double Epsilon = 0.01;
+
+std::string GetAngledName(const std::string& filename)
+{
+    return "<" + filename + ">";
+}
+
+} // namespace
+
+MathConstantsCheck::MathConstantsCheck(StringRef Name, ClangTidyContext *Context)
+    : ClangTidyCheck(Name, Context),
+    Constants
+    {
+            {{"M_E"}, {"std::math::e"}, 2.7182818284590452354},
+            {{"M_LOG2E"}, {"std::math::log2e"}, 1.4426950408889634074},
+            {{"M_LOG10E"}, {"std::math::log10e"}, 0.43429448190325182765},
+            {{"M_LN2"}, {"std::math::ln2"}, 0.69314718055994530942},
+            {{"M_LN10"}, {"std::math::ln10"}, 2.30258509299404568402},
+            {{"M_PI"}, {"std::math::pi"}, 3.14159265358979323846},
+            {{"M_PI_2"}, {}, 1.57079632679489661923},
+            {{"M_PI_4"}, {}, 0.78539816339744830962},
+            {{"M_1_PI"}, {"std::math::inv_pi"}, 0.31830988618379067154},
+            {{"M_2_PI"}, {}, 0.63661977236758134308},
+            {{"M_2_SQRTPI"}, {"std::math::inv_sqrtpi"}, 1.12837916709551257390},
+            {{"M_SQRT2"}, {"std::math::sqrt2"}, 1.41421356237309504880},
+            {{"M_SQRT1_2"}, {"std::math::"}, 0.70710678118654752440},
+            {{}, {"std::math::phi"}, 1.6180339887498948482},
+            {{}, {"std::math::egamma"}, 0.5772156649015328606 }
+    },
+    IncludeStyle(utils::IncludeSorter::parseIncludeStyle(
+              Options.getLocalOrGlobal("IncludeStyle", "llvm")))
+{
+}
+
+void MathConstantsCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
+    Options.store(Opts, "IncludeStyle", IncludeStyle);
+}
+
+void MathConstantsCheck::registerMatchers(MatchFinder *Finder) {
+  // FIXME: Add matchers.
+  Finder->addMatcher(floatLiteral().bind(FloatType), this);
+}
+
+void MathConstantsCheck::registerPPCallbacks(const SourceManager &SM,
+                                             Preprocessor *PP,
+                                             Preprocessor *ModuleExpanderPP) {
+        Inserter = llvm::make_unique<utils::IncludeInserter>(SM, getLangOpts(),
+                                                             IncludeStyle);
+        PP->addPPCallbacks(Inserter->CreatePPCallbacks());
+}
+
+void MathConstantsCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *MatchedDecl = Result.Nodes.getNodeAs<FloatingLiteral>(FloatType);
+  const auto MatchedFloatConstant = MatchedDecl->getValue().convertToDouble();
+
+  const auto Language = getLangOpts();
+
+  for (const auto& MathConstant : Constants)
+  {
+      // Match constant
+      if (std::fabs(MatchedFloatConstant - MathConstant.Value) < Epsilon)
+      {
+          std::string ConstantName;
+          if(getLangOpts().CPlusPlus2a)
+          {
+              if(MathConstant.NameInCpp20.hasValue())
+              {
+                  ConstantName = MathConstant.NameInCpp20.getValue();
+                  ChosenHeaderName = StdMathHeader;
+              }
+              else
+              {
+                  ConstantName = MathConstant.NameInC.getValue();
+                  ChosenHeaderName = StdCmathHeader;
+              }
+          }
+          else // For other C++ standards and whole C
+          {
+              if(!MathConstant.NameInC.hasValue())
+              {
+                  // We have not such constant for old standards
+                  return;
+              }
+
+              ConstantName = MathConstant.NameInC.getValue();
+              if (Language.C99 || Language.C11 || Language.C17 || Language.C2x)
+              {
+                  ChosenHeaderName = StdCHeader;
+              }
+              else if (Language.CPlusPlus)
+              {
+                  ChosenHeaderName = StdCmathHeader;
+              }
+          }
+
+          diag(MatchedDecl->getLocation(), "The constant " + std::to_string(MatchedFloatConstant) + " is being utilized. "
+            "The resulting value could be inaccurate. Consider using the " + ConstantName +
+            " constant from " + GetAngledName(ChosenHeaderName));
+
+          // Fix-hint
+          auto Diag = diag(MatchedDecl->getLocation(), "insert '" + ConstantName + "'", DiagnosticIDs::Note)
+                  << FixItHint::CreateReplacement(MatchedDecl->getLocation(), ConstantName);
+
+          SourceManager &SM = *Result.SourceManager;
+          insertHeader(Diag, SM.getFileID(MatchedDecl->getExprLoc()));
+      }
+  }
+}
+
+void MathConstantsCheck::insertHeader(DiagnosticBuilder &Diag, FileID FD) {
+    if (ChosenHeaderName.empty()) {
+        return;
+    }
+    if (auto IncludeFixit = Inserter->CreateIncludeInsertion(
+            FD, ChosenHeaderName,
+            true)) {
+        Diag << *IncludeFixit;
+    }
+}
+
+} // namespace misc
+} // namespace tidy
+} // namespace clang
Index: clang-tools-extra/clang-tidy/misc/CMakeLists.txt
===================================================================
--- clang-tools-extra/clang-tidy/misc/CMakeLists.txt
+++ clang-tools-extra/clang-tidy/misc/CMakeLists.txt
@@ -2,6 +2,7 @@
 
 add_clang_library(clangTidyMiscModule
   DefinitionsInHeadersCheck.cpp
+  MathConstantsCheck.cpp
   MiscTidyModule.cpp
   MisplacedConstCheck.cpp
   NewDeleteOverloadsCheck.cpp
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to