10#include "clang/AST/ASTContext.h"
11#include "clang/ASTMatchers/ASTMatchFinder.h"
12#include "clang/Frontend/CompilerInstance.h"
13#include "clang/Lex/Preprocessor.h"
14#include "llvm/ADT/StringSet.h"
22 if (
const auto *BT = dyn_cast<BuiltinType>(&Node)) {
23 return BT->getKind() ==
Kind;
32 IncludeInserter(Options.getLocalOrGlobal(
"IncludeStyle",
33 utils::IncludeSorter::IS_LLVM),
34 areDiagsSelfContained()) {}
37 const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) {
47 constexpr BuiltinType::Kind IntTy = BuiltinType::Int;
48 constexpr BuiltinType::Kind LongTy = BuiltinType::Long;
49 constexpr BuiltinType::Kind FloatTy = BuiltinType::Float;
50 constexpr BuiltinType::Kind DoubleTy = BuiltinType::Double;
51 constexpr BuiltinType::Kind LongDoubleTy = BuiltinType::LongDouble;
53 auto HasBuiltinTyParam = [](
int Pos, BuiltinType::Kind
Kind) {
54 return hasParameter(
Pos, hasType(isBuiltinType(
Kind)));
56 auto HasBuiltinTyArg = [](
int Pos, BuiltinType::Kind
Kind) {
57 return hasArgument(
Pos, hasType(isBuiltinType(
Kind)));
61 auto OneDoubleArgFns = hasAnyName(
62 "::acos",
"::acosh",
"::asin",
"::asinh",
"::atan",
"::atanh",
"::cbrt",
63 "::ceil",
"::cos",
"::cosh",
"::erf",
"::erfc",
"::exp",
"::exp2",
64 "::expm1",
"::fabs",
"::floor",
"::ilogb",
"::lgamma",
"::llrint",
65 "::log",
"::log10",
"::log1p",
"::log2",
"::logb",
"::lrint",
"::modf",
66 "::nearbyint",
"::rint",
"::round",
"::sin",
"::sinh",
"::sqrt",
"::tan",
67 "::tanh",
"::tgamma",
"::trunc",
"::llround",
"::lround");
69 callExpr(callee(functionDecl(OneDoubleArgFns, parameterCountIs(1),
70 HasBuiltinTyParam(0, DoubleTy))),
71 HasBuiltinTyArg(0, FloatTy))
76 auto TwoDoubleArgFns = hasAnyName(
"::atan2",
"::copysign",
"::fdim",
"::fmax",
77 "::fmin",
"::fmod",
"::hypot",
"::ldexp",
78 "::nextafter",
"::pow",
"::remainder");
80 callExpr(callee(functionDecl(TwoDoubleArgFns, parameterCountIs(2),
81 HasBuiltinTyParam(0, DoubleTy),
82 HasBuiltinTyParam(1, DoubleTy))),
83 HasBuiltinTyArg(0, FloatTy), HasBuiltinTyArg(1, FloatTy))
89 callExpr(callee(functionDecl(hasName(
"::fma"), parameterCountIs(3),
90 HasBuiltinTyParam(0, DoubleTy),
91 HasBuiltinTyParam(1, DoubleTy),
92 HasBuiltinTyParam(2, DoubleTy))),
93 HasBuiltinTyArg(0, FloatTy), HasBuiltinTyArg(1, FloatTy),
94 HasBuiltinTyArg(2, FloatTy))
100 callExpr(callee(functionDecl(
101 hasName(
"::frexp"), parameterCountIs(2),
102 HasBuiltinTyParam(0, DoubleTy),
103 hasParameter(1, parmVarDecl(hasType(pointerType(
104 pointee(isBuiltinType(IntTy)))))))),
105 HasBuiltinTyArg(0, FloatTy))
112 callExpr(callee(functionDecl(hasName(
"::nexttoward"), parameterCountIs(2),
113 HasBuiltinTyParam(0, DoubleTy),
114 HasBuiltinTyParam(1, LongDoubleTy))),
115 HasBuiltinTyArg(0, FloatTy))
124 hasName(
"::remquo"), parameterCountIs(3),
125 HasBuiltinTyParam(0, DoubleTy), HasBuiltinTyParam(1, DoubleTy),
126 hasParameter(2, parmVarDecl(hasType(pointerType(
127 pointee(isBuiltinType(IntTy)))))))),
128 HasBuiltinTyArg(0, FloatTy), HasBuiltinTyArg(1, FloatTy))
134 callExpr(callee(functionDecl(hasName(
"::scalbln"), parameterCountIs(2),
135 HasBuiltinTyParam(0, DoubleTy),
136 HasBuiltinTyParam(1, LongTy))),
137 HasBuiltinTyArg(0, FloatTy))
143 callExpr(callee(functionDecl(hasName(
"::scalbn"), parameterCountIs(2),
144 HasBuiltinTyParam(0, DoubleTy),
145 HasBuiltinTyParam(1, IntTy))),
146 HasBuiltinTyArg(0, FloatTy))
155 const auto *Call = Result.Nodes.getNodeAs<CallExpr>(
"call");
156 assert(Call !=
nullptr);
158 StringRef OldFnName = Call->getDirectCallee()->getName();
162 static llvm::StringSet<> Cpp11OnlyFns = {
163 "acosh",
"asinh",
"atanh",
"cbrt",
"copysign",
"erf",
164 "erfc",
"exp2",
"expm1",
"fdim",
"fma",
"fmax",
165 "fmin",
"hypot",
"ilogb",
"lgamma",
"llrint",
"llround",
166 "log1p",
"log2",
"logb",
"lrint",
"lround",
"nearbyint",
167 "nextafter",
"nexttoward",
"remainder",
"remquo",
"rint",
"round",
168 "scalbln",
"scalbn",
"tgamma",
"trunc"};
169 bool StdFnRequiresCpp11 = Cpp11OnlyFns.count(OldFnName);
171 std::string NewFnName;
172 bool FnInCmath =
false;
174 (!StdFnRequiresCpp11 ||
getLangOpts().CPlusPlus11)) {
175 NewFnName = (
"std::" + OldFnName).str();
178 NewFnName = (OldFnName +
"f").str();
181 auto Diag =
diag(Call->getExprLoc(),
"call to '%0' promotes float to double")
183 << FixItHint::CreateReplacement(
184 Call->getCallee()->getSourceRange(), NewFnName);
192 Result.Context->getSourceManager().getFileID(Call->getBeginLoc()),
llvm::SmallString< 256U > Name
void store(ClangTidyOptions::OptionMap &Options, StringRef LocalName, StringRef Value) const
Stores an option with the check-local name LocalName with string value Value to Options.
Base class for all clang-tidy checks.
DiagnosticBuilder diag(SourceLocation Loc, StringRef Description, DiagnosticIDs::Level Level=DiagnosticIDs::Warning)
Add a diagnostic with the check's name.
const LangOptions & getLangOpts() const
Returns the language options from the context.
Every ClangTidyCheck reports errors through a DiagnosticsEngine provided by this context.
void registerPreprocessor(Preprocessor *PP)
Registers this with the Preprocessor PP, must be called before this class is used.
std::optional< FixItHint > createIncludeInsertion(FileID FileID, llvm::StringRef Header)
Creates a Header inclusion directive fixit in the File FileID.
IncludeSorter::IncludeStyle getStyle() const
AST_MATCHER_P(UserDefinedLiteral, hasLiteral, clang::ast_matchers::internal::Matcher< Expr >, InnerMatcher)
llvm::StringMap< ClangTidyValue > OptionMap