[clang-tools-extra] [clang-tidy] add modernize-use-std-numbers (PR #66583)

Piotr Zegar via cfe-commits cfe-commits at lists.llvm.org
Fri Nov 3 10:51:22 PDT 2023


================
@@ -0,0 +1,284 @@
+//===--- UseStdNumbersCheck.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 "UseStdNumbersCheck.h"
+#include "../ClangTidyDiagnosticConsumer.h"
+#include "../utils/TransformerClangTidyCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/Stmt.h"
+#include "clang/AST/Type.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/ASTMatchers/ASTMatchersInternal.h"
+#include "clang/ASTMatchers/ASTMatchersMacros.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Tooling/Transformer/RewriteRule.h"
+#include "clang/Tooling/Transformer/Stencil.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/MathExtras.h"
+#include <cstdint>
+#include <cstdlib>
+#include <string>
+#include <utility>
+
+namespace {
+using namespace clang::ast_matchers;
+using clang::ast_matchers::internal::Matcher;
+using clang::transformer::addInclude;
+using clang::transformer::applyFirst;
+using clang::transformer::ASTEdit;
+using clang::transformer::cat;
+using clang::transformer::changeTo;
+using clang::transformer::edit;
+using clang::transformer::EditGenerator;
+using clang::transformer::flattenVector;
+using clang::transformer::RewriteRuleWith;
+using llvm::StringRef;
+
+constexpr auto DiffThreshold = 0.001;
+
+AST_MATCHER_P(clang::FloatingLiteral, near, double, Value) {
+  return std::abs(Node.getValueAsApproximateDouble() - Value) < DiffThreshold;
+}
+
+AST_MATCHER_P(clang::QualType, hasCanonicalTypeUnqualified,
+              Matcher<clang::QualType>, InnerMatcher) {
+  return InnerMatcher.matches(Node->getCanonicalTypeUnqualified(), Finder,
+                              Builder);
+}
+
+AST_MATCHER(clang::QualType, isArithmetic) { return Node->isArithmeticType(); }
+AST_MATCHER(clang::QualType, isFloating) { return Node->isFloatingType(); }
+
+auto ignoreImplicitAndArithmeticCasting(const Matcher<clang::Expr> Matcher) {
+  return expr(
+      ignoringImplicit(expr(hasType(qualType(isArithmetic())),
+                            ignoringParenCasts(ignoringImplicit(Matcher)))));
+}
+
+auto ignoreImplicitAndFloatingCasting(const Matcher<clang::Expr> Matcher) {
+  return expr(
+      ignoringImplicit(expr(hasType(qualType(isFloating())),
+                            ignoringParenCasts(ignoringImplicit(Matcher)))));
+}
+
+auto matchMathCall(const StringRef FunctionName,
+                   const Matcher<clang::Expr> ArgumentMatcher) {
+  return callExpr(
+      callee(functionDecl(hasName(FunctionName),
+                          hasParameter(0, hasType(isArithmetic())))),
+      hasArgument(0, ArgumentMatcher));
+}
+
+auto matchSqrt(const Matcher<clang::Expr> ArgumentMatcher) {
+  return matchMathCall("sqrt", ArgumentMatcher);
+}
+
+// Used for top-level matchers (i.e. the match that replaces Val with its
+// constant).
+//
+// E.g. The matcher of `std::numbers::pi` uses this matcher to look to
+// floatLiterals that have the value of pi.
+//
+// We only care about the literal if the match is for a top-level match
+auto matchFloatLiteralNear(const double Val) {
+  return expr(ignoreImplicitAndFloatingCasting(floatLiteral(near(Val))));
+}
+
+// Used for non-top-level matchers (i.e. matchers that are used as inner
+// matchers for top-level matchers).
+//
+// E.g.: The matcher of `std::numbers::log2e` uses this matcher to check if `e`
+// of `log2(e)` is declared constant and initialized with the value for eulers
+// number.
+//
+// Here, we do care about literals and about DeclRefExprs to variable
+// declarations that are constant and initialized with `Val`. This allows
+// top-level matchers to see through declared constants for their inner matches
+// like the `std::numbers::log2e` matcher.
+auto matchFloatValueNear(const double Val) {
+  const auto Float = floatLiteral(near(Val));
+
+  const auto Dref = declRefExpr(to(varDecl(
+      anyOf(isConstexpr(),
+            varDecl(hasType(qualType(isConstQualified(), isArithmetic())))),
----------------
PiotrZSL wrote:

Consier checking here CanonicalType to ignore all typedefs

https://github.com/llvm/llvm-project/pull/66583


More information about the cfe-commits mailing list