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 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 +#include +#include + +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 NameInC; + const Optional NameInCpp20; + const double Value; + }; + + const std::vector Constants; + const utils::IncludeSorter::IncludeStyle IncludeStyle; + std::string ChosenHeaderName; + std::unique_ptr 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 +#include +#include + +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(SM, getLangOpts(), + IncludeStyle); + PP->addPPCallbacks(Inserter->CreatePPCallbacks()); +} + +void MathConstantsCheck::check(const MatchFinder::MatchResult &Result) { + const auto *MatchedDecl = Result.Nodes.getNodeAs(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/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( "misc-definitions-in-headers"); + CheckFactories.registerCheck( + "misc-math-constants"); CheckFactories.registerCheck("misc-misplaced-const"); CheckFactories.registerCheck( "misc-new-delete-overloads"); 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 + ` check. + + FIXME: add release notes. + Improvements to clang-include-fixer ----------------------------------- 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-oop54-cpp (redirects to bugprone-unhandled-self-assignment) - clang-analyzer-core.CallAndMessage - clang-analyzer-core.DivideZero + clang-analyzer-core.CallAndMessage (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-core.DivideZero (redirects to https://clang.llvm.org/docs/analyzer/checkers) 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.NullDereference (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-core.StackAddressEscape (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-core.UndefinedBinaryOperatorResult (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-core.VLASize (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-core.uninitialized.ArraySubscript (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-core.uninitialized.Assign (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-core.uninitialized.Branch (redirects to https://clang.llvm.org/docs/analyzer/checkers) 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-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.NewDelete (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-cplusplus.NewDeleteLeaks (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-deadcode.DeadStores (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-nullability.NullPassedToNonnull (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-nullability.NullReturnedFromNonnull (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-nullability.NullableDereferenced (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-nullability.NullablePassedToNonnull (redirects to https://clang.llvm.org/docs/analyzer/checkers) 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.VirtualCall (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-optin.mpi.MPI-Checker (redirects to https://clang.llvm.org/docs/analyzer/checkers) 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.NonLocalizedStringChecker (redirects to https://clang.llvm.org/docs/analyzer/checkers) 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.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.cocoa.AtSync (redirects to https://clang.llvm.org/docs/analyzer/checkers) 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.Dealloc (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-osx.cocoa.IncompatibleMethodTypes (redirects to https://clang.llvm.org/docs/analyzer/checkers) 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.NSError (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-osx.cocoa.NilArg (redirects to https://clang.llvm.org/docs/analyzer/checkers) 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.RetainCount (redirects to https://clang.llvm.org/docs/analyzer/checkers) 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.SuperDealloc (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-osx.cocoa.UnusedIvars (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-osx.cocoa.VariadicMethodTypes (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-osx.coreFoundation.CFError (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-osx.coreFoundation.CFNumber (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-osx.coreFoundation.CFRetainRelease (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-osx.coreFoundation.containers.OutOfBounds (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-osx.coreFoundation.containers.PointerSizedValues (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-security.FloatLoopCounter (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-security.insecureAPI.UncheckedReturn (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-security.insecureAPI.bcmp (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-security.insecureAPI.bcopy (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-security.insecureAPI.bzero (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-security.insecureAPI.getpw (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-security.insecureAPI.gets (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-security.insecureAPI.mkstemp (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-security.insecureAPI.mktemp (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-security.insecureAPI.rand (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-security.insecureAPI.strcpy (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-security.insecureAPI.vfork (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-unix.API (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-unix.Malloc (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-unix.MallocSizeof (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-unix.MismatchedDeallocator (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-unix.Vfork (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-unix.cstring.BadSizeArg (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-unix.cstring.NullArg (redirects to https://clang.llvm.org/docs/analyzer/checkers) 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/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/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; +}