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" 20 namespace performance {
24 if (
const auto *BT = dyn_cast<BuiltinType>(&Node)) {
25 return BT->getKind() ==
Kind;
31 TypePromotionInMathFnCheck::TypePromotionInMathFnCheck(
34 IncludeStyle(utils::IncludeSorter::parseIncludeStyle(
35 Options.getLocalOrGlobal(
"IncludeStyle",
"llvm"))) {}
38 const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) {
39 IncludeInserter = llvm::make_unique<utils::IncludeInserter>(SM,
getLangOpts(),
41 PP->addPPCallbacks(IncludeInserter->CreatePPCallbacks());
58 return hasParameter(Pos, hasType(isBuiltinType(
Kind)));
61 return hasArgument(Pos, hasType(isBuiltinType(
Kind)));
65 auto OneDoubleArgFns = hasAnyName(
66 "::acos",
"::acosh",
"::asin",
"::asinh",
"::atan",
"::atanh",
"::cbrt",
67 "::ceil",
"::cos",
"::cosh",
"::erf",
"::erfc",
"::exp",
"::exp2",
68 "::expm1",
"::fabs",
"::floor",
"::ilogb",
"::lgamma",
"::llrint",
69 "::log",
"::log10",
"::log1p",
"::log2",
"::logb",
"::lrint",
"::modf",
70 "::nearbyint",
"::rint",
"::round",
"::sin",
"::sinh",
"::sqrt",
"::tan",
71 "::tanh",
"::tgamma",
"::trunc",
"::llround",
"::lround");
73 callExpr(callee(functionDecl(OneDoubleArgFns, parameterCountIs(1),
74 hasBuiltinTyParam(0, DoubleTy))),
75 hasBuiltinTyArg(0, FloatTy))
80 auto TwoDoubleArgFns = hasAnyName(
"::atan2",
"::copysign",
"::fdim",
"::fmax",
81 "::fmin",
"::fmod",
"::hypot",
"::ldexp",
82 "::nextafter",
"::pow",
"::remainder");
84 callExpr(callee(functionDecl(TwoDoubleArgFns, parameterCountIs(2),
85 hasBuiltinTyParam(0, DoubleTy),
86 hasBuiltinTyParam(1, DoubleTy))),
87 hasBuiltinTyArg(0, FloatTy), hasBuiltinTyArg(1, FloatTy))
93 callExpr(callee(functionDecl(hasName(
"::fma"), parameterCountIs(3),
94 hasBuiltinTyParam(0, DoubleTy),
95 hasBuiltinTyParam(1, DoubleTy),
96 hasBuiltinTyParam(2, DoubleTy))),
97 hasBuiltinTyArg(0, FloatTy), hasBuiltinTyArg(1, FloatTy),
98 hasBuiltinTyArg(2, FloatTy))
104 callExpr(callee(functionDecl(
105 hasName(
"::frexp"), parameterCountIs(2),
106 hasBuiltinTyParam(0, DoubleTy),
107 hasParameter(1, parmVarDecl(hasType(pointerType(
108 pointee(isBuiltinType(IntTy)))))))),
109 hasBuiltinTyArg(0, FloatTy))
116 callExpr(callee(functionDecl(hasName(
"::nexttoward"), parameterCountIs(2),
117 hasBuiltinTyParam(0, DoubleTy),
118 hasBuiltinTyParam(1, LongDoubleTy))),
119 hasBuiltinTyArg(0, FloatTy))
128 hasName(
"::remquo"), parameterCountIs(3),
129 hasBuiltinTyParam(0, DoubleTy), hasBuiltinTyParam(1, DoubleTy),
130 hasParameter(2, parmVarDecl(hasType(pointerType(
131 pointee(isBuiltinType(IntTy)))))))),
132 hasBuiltinTyArg(0, FloatTy), hasBuiltinTyArg(1, FloatTy))
138 callExpr(callee(functionDecl(hasName(
"::scalbln"), parameterCountIs(2),
139 hasBuiltinTyParam(0, DoubleTy),
140 hasBuiltinTyParam(1, LongTy))),
141 hasBuiltinTyArg(0, FloatTy))
147 callExpr(callee(functionDecl(hasName(
"::scalbn"), parameterCountIs(2),
148 hasBuiltinTyParam(0, DoubleTy),
149 hasBuiltinTyParam(1, IntTy))),
150 hasBuiltinTyArg(0, FloatTy))
159 const auto *Call = Result.Nodes.getNodeAs<CallExpr>(
"call");
160 assert(Call !=
nullptr);
162 StringRef OldFnName = Call->getDirectCallee()->getName();
166 static llvm::StringSet<> Cpp11OnlyFns = {
167 "acosh",
"asinh",
"atanh",
"cbrt",
"copysign",
"erf",
168 "erfc",
"exp2",
"expm1",
"fdim",
"fma",
"fmax",
169 "fmin",
"hypot",
"ilogb",
"lgamma",
"llrint",
"llround",
170 "log1p",
"log2",
"logb",
"lrint",
"lround",
"nearbyint",
171 "nextafter",
"nexttoward",
"remainder",
"remquo",
"rint",
"round",
172 "scalbln",
"scalbn",
"tgamma",
"trunc"};
173 bool StdFnRequiresCpp11 = Cpp11OnlyFns.count(OldFnName);
175 std::string NewFnName;
176 bool FnInCmath =
false;
178 (!StdFnRequiresCpp11 ||
getLangOpts().CPlusPlus11)) {
179 NewFnName = (
"std::" + OldFnName).str();
182 NewFnName = (OldFnName +
"f").str();
185 auto Diag =
diag(Call->getExprLoc(),
"call to '%0' promotes float to double")
187 << FixItHint::CreateReplacement(
188 Call->getCallee()->getSourceRange(), NewFnName);
195 if (
auto IncludeFixit = IncludeInserter->CreateIncludeInsertion(
196 Result.Context->getSourceManager().getFileID(Call->getBeginLoc()),
198 Diag << *IncludeFixit;
static StringRef toString(IncludeStyle Style)
Converts IncludeStyle to string representation.
Base class for all clang-tidy checks.
const LangOptions & getLangOpts() const
Returns the language options from the context.
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.
static constexpr llvm::StringLiteral Name
std::map< std::string, std::string > OptionMap
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Every ClangTidyCheck reports errors through a DiagnosticsEngine provided by this context.
llvm::Optional< llvm::Expected< tooling::AtomicChanges > > Result
DiagnosticBuilder diag(SourceLocation Loc, StringRef Description, DiagnosticIDs::Level Level=DiagnosticIDs::Warning)
Add a diagnostic with the check's name.
AST_MATCHER_P(CXXMethodDecl, hasCanonicalDecl, ast_matchers::internal::Matcher< CXXMethodDecl >, InnerMatcher)