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.contains(OldFnName);
171 std::string NewFnName;
172 bool FnInCmath =
false;
173 if (getLangOpts().CPlusPlus &&
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);
191 Diag << IncludeInserter.createIncludeInsertion(
192 Result.Context->getSourceManager().getFileID(Call->getBeginLoc()),
Every ClangTidyCheck reports errors through a DiagnosticsEngine provided by this context.