[clang-tools-extra] r289627 - [ClangTidy] Add new performance-type-promotion-in-math-fn check.

Justin Lebar via cfe-commits cfe-commits at lists.llvm.org
Tue Dec 13 19:15:01 PST 2016


Author: jlebar
Date: Tue Dec 13 21:15:01 2016
New Revision: 289627

URL: http://llvm.org/viewvc/llvm-project?rev=289627&view=rev
Log:
[ClangTidy] Add new performance-type-promotion-in-math-fn check.

Summary:
This checks for calls to double-precision math.h with single-precision
arguments.  For example, it suggests replacing ::sin(0.f) with
::sinf(0.f).

Subscribers: mgorny, cfe-commits

Differential Revision: https://reviews.llvm.org/D27284

Added:
    clang-tools-extra/trunk/clang-tidy/performance/TypePromotionInMathFnCheck.cpp
    clang-tools-extra/trunk/clang-tidy/performance/TypePromotionInMathFnCheck.h
    clang-tools-extra/trunk/docs/clang-tidy/checks/performance-type-promotion-in-math-fn.rst
    clang-tools-extra/trunk/test/clang-tidy/performance-type-promotion-in-math-fn.cpp
Modified:
    clang-tools-extra/trunk/clang-tidy/performance/CMakeLists.txt
    clang-tools-extra/trunk/clang-tidy/performance/PerformanceTidyModule.cpp
    clang-tools-extra/trunk/docs/ReleaseNotes.rst
    clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst

Modified: clang-tools-extra/trunk/clang-tidy/performance/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/performance/CMakeLists.txt?rev=289627&r1=289626&r2=289627&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/performance/CMakeLists.txt (original)
+++ clang-tools-extra/trunk/clang-tidy/performance/CMakeLists.txt Tue Dec 13 21:15:01 2016
@@ -6,6 +6,7 @@ add_clang_library(clangTidyPerformanceMo
   ImplicitCastInLoopCheck.cpp
   InefficientStringConcatenationCheck.cpp
   PerformanceTidyModule.cpp
+  TypePromotionInMathFnCheck.cpp
   UnnecessaryCopyInitialization.cpp
   UnnecessaryValueParamCheck.cpp
 

Modified: clang-tools-extra/trunk/clang-tidy/performance/PerformanceTidyModule.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/performance/PerformanceTidyModule.cpp?rev=289627&r1=289626&r2=289627&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/performance/PerformanceTidyModule.cpp (original)
+++ clang-tools-extra/trunk/clang-tidy/performance/PerformanceTidyModule.cpp Tue Dec 13 21:15:01 2016
@@ -10,11 +10,11 @@
 #include "../ClangTidy.h"
 #include "../ClangTidyModule.h"
 #include "../ClangTidyModuleRegistry.h"
-#include "InefficientStringConcatenationCheck.h"
-
 #include "FasterStringFindCheck.h"
 #include "ForRangeCopyCheck.h"
 #include "ImplicitCastInLoopCheck.h"
+#include "InefficientStringConcatenationCheck.h"
+#include "TypePromotionInMathFnCheck.h"
 #include "UnnecessaryCopyInitialization.h"
 #include "UnnecessaryValueParamCheck.h"
 
@@ -33,6 +33,8 @@ public:
         "performance-implicit-cast-in-loop");
     CheckFactories.registerCheck<InefficientStringConcatenationCheck>(
         "performance-inefficient-string-concatenation");
+    CheckFactories.registerCheck<TypePromotionInMathFnCheck>(
+        "performance-type-promotion-in-math-fn");
     CheckFactories.registerCheck<UnnecessaryCopyInitialization>(
         "performance-unnecessary-copy-initialization");
     CheckFactories.registerCheck<UnnecessaryValueParamCheck>(

Added: clang-tools-extra/trunk/clang-tidy/performance/TypePromotionInMathFnCheck.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/performance/TypePromotionInMathFnCheck.cpp?rev=289627&view=auto
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/performance/TypePromotionInMathFnCheck.cpp (added)
+++ clang-tools-extra/trunk/clang-tidy/performance/TypePromotionInMathFnCheck.cpp Tue Dec 13 21:15:01 2016
@@ -0,0 +1,172 @@
+//===--- TypePromotionInMathFnCheck.cpp - clang-tidy-----------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "TypePromotionInMathFnCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "llvm/ADT/StringSet.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace performance {
+
+namespace {
+AST_MATCHER_P(Type, isBuiltinType, BuiltinType::Kind, Kind) {
+  if (const auto *BT = dyn_cast<BuiltinType>(&Node)) {
+    return BT->getKind() == Kind;
+  }
+  return false;
+}
+} // anonymous namespace
+
+void TypePromotionInMathFnCheck::registerMatchers(MatchFinder *Finder) {
+  constexpr BuiltinType::Kind IntTy = BuiltinType::Int;
+  constexpr BuiltinType::Kind LongTy = BuiltinType::Long;
+  constexpr BuiltinType::Kind FloatTy = BuiltinType::Float;
+  constexpr BuiltinType::Kind DoubleTy = BuiltinType::Double;
+  constexpr BuiltinType::Kind LongDoubleTy = BuiltinType::LongDouble;
+
+  auto hasBuiltinTyParam = [](int Pos, BuiltinType::Kind Kind) {
+    return hasParameter(Pos, hasType(isBuiltinType(Kind)));
+  };
+  auto hasBuiltinTyArg = [](int Pos, BuiltinType::Kind Kind) {
+    return hasArgument(Pos, hasType(isBuiltinType(Kind)));
+  };
+
+  // Match calls to foo(double) with a float argument.
+  auto OneDoubleArgFns = hasAnyName(
+      "::acos", "::acosh", "::asin", "::asinh", "::atan", "::atanh", "::cbrt",
+      "::ceil", "::cos", "::cosh", "::erf", "::erfc", "::exp", "::exp2",
+      "::expm1", "::fabs", "::floor", "::ilogb", "::lgamma", "::llrint",
+      "::log", "::log10", "::log1p", "::log2", "::logb", "::lrint", "::modf",
+      "::nearbyint", "::rint", "::round", "::sin", "::sinh", "::sqrt", "::tan",
+      "::tanh", "::tgamma", "::trunc", "::llround", "::lround");
+  Finder->addMatcher(
+      callExpr(callee(functionDecl(OneDoubleArgFns, parameterCountIs(1),
+                                   hasBuiltinTyParam(0, DoubleTy))),
+               hasBuiltinTyArg(0, FloatTy))
+          .bind("call"),
+      this);
+
+  // Match calls to foo(double, double) where both args are floats.
+  auto TwoDoubleArgFns = hasAnyName("::atan2", "::copysign", "::fdim", "::fmax",
+                                    "::fmin", "::fmod", "::hypot", "::ldexp",
+                                    "::nextafter", "::pow", "::remainder");
+  Finder->addMatcher(
+      callExpr(callee(functionDecl(TwoDoubleArgFns, parameterCountIs(2),
+                                   hasBuiltinTyParam(0, DoubleTy),
+                                   hasBuiltinTyParam(1, DoubleTy))),
+               hasBuiltinTyArg(0, FloatTy), hasBuiltinTyArg(1, FloatTy))
+          .bind("call"),
+      this);
+
+  // Match calls to fma(double, double, double) where all args are floats.
+  Finder->addMatcher(
+      callExpr(callee(functionDecl(hasName("::fma"), parameterCountIs(3),
+                                   hasBuiltinTyParam(0, DoubleTy),
+                                   hasBuiltinTyParam(1, DoubleTy),
+                                   hasBuiltinTyParam(2, DoubleTy))),
+               hasBuiltinTyArg(0, FloatTy), hasBuiltinTyArg(1, FloatTy),
+               hasBuiltinTyArg(2, FloatTy))
+          .bind("call"),
+      this);
+
+  // Match calls to frexp(double, int*) where the first arg is a float.
+  Finder->addMatcher(
+      callExpr(callee(functionDecl(
+                   hasName("::frexp"), parameterCountIs(2),
+                   hasBuiltinTyParam(0, DoubleTy),
+                   hasParameter(1, parmVarDecl(hasType(pointerType(
+                                       pointee(isBuiltinType(IntTy)))))))),
+               hasBuiltinTyArg(0, FloatTy))
+          .bind("call"),
+      this);
+
+  // Match calls to nexttoward(double, long double) where the first arg is a
+  // float.
+  Finder->addMatcher(
+      callExpr(callee(functionDecl(hasName("::nexttoward"), parameterCountIs(2),
+                                   hasBuiltinTyParam(0, DoubleTy),
+                                   hasBuiltinTyParam(1, LongDoubleTy))),
+               hasBuiltinTyArg(0, FloatTy))
+          .bind("call"),
+      this);
+
+  // Match calls to remquo(double, double, int*) where the first two args are
+  // floats.
+  Finder->addMatcher(
+      callExpr(
+          callee(functionDecl(
+              hasName("::remquo"), parameterCountIs(3),
+              hasBuiltinTyParam(0, DoubleTy), hasBuiltinTyParam(1, DoubleTy),
+              hasParameter(2, parmVarDecl(hasType(pointerType(
+                                  pointee(isBuiltinType(IntTy)))))))),
+          hasBuiltinTyArg(0, FloatTy), hasBuiltinTyArg(1, FloatTy))
+          .bind("call"),
+      this);
+
+  // Match calls to scalbln(double, long) where the first arg is a float.
+  Finder->addMatcher(
+      callExpr(callee(functionDecl(hasName("::scalbln"), parameterCountIs(2),
+                                   hasBuiltinTyParam(0, DoubleTy),
+                                   hasBuiltinTyParam(1, LongTy))),
+               hasBuiltinTyArg(0, FloatTy))
+          .bind("call"),
+      this);
+
+  // Match calls to scalbn(double, int) where the first arg is a float.
+  Finder->addMatcher(
+      callExpr(callee(functionDecl(hasName("::scalbn"), parameterCountIs(2),
+                                   hasBuiltinTyParam(0, DoubleTy),
+                                   hasBuiltinTyParam(1, IntTy))),
+               hasBuiltinTyArg(0, FloatTy))
+          .bind("call"),
+      this);
+
+  // modf(double, double*) is omitted because the second parameter forces the
+  // type -- there's no conversion from float* to double*.
+}
+
+void TypePromotionInMathFnCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *Call = Result.Nodes.getNodeAs<CallExpr>("call");
+  assert(Call != nullptr);
+
+  StringRef OldFnName = Call->getDirectCallee()->getName();
+
+  // In C++ mode, we prefer std::foo to ::foof.  But some of these suggestions
+  // are only valid in C++11 and newer.
+  static llvm::StringSet<> Cpp11OnlyFns = {
+      "acosh",     "asinh",      "atanh",     "cbrt",   "copysign", "erf",
+      "erfc",      "exp2",       "expm1",     "fdim",   "fma",      "fmax",
+      "fmin",      "hypot",      "ilogb",     "lgamma", "llrint",   "llround",
+      "log1p",     "log2",       "logb",      "lrint",  "lround",   "nearbyint",
+      "nextafter", "nexttoward", "remainder", "remquo", "rint",     "round",
+      "scalbln",   "scalbn",     "tgamma",    "trunc"};
+  bool StdFnRequiresCpp11 = Cpp11OnlyFns.count(OldFnName);
+
+  std::string NewFnName;
+  if (getLangOpts().CPlusPlus &&
+      (!StdFnRequiresCpp11 || getLangOpts().CPlusPlus11))
+    NewFnName = ("std::" + OldFnName).str();
+  else
+    NewFnName = (OldFnName + "f").str();
+
+  diag(Call->getExprLoc(), "call to '%0' promotes float to double")
+      << OldFnName << FixItHint::CreateReplacement(
+                          Call->getCallee()->getSourceRange(), NewFnName);
+
+  // FIXME: Perhaps we should suggest #include <cmath> if we suggest a cmath
+  // function and cmath is not already included.
+}
+
+} // namespace performance
+} // namespace tidy
+} // namespace clang

Added: clang-tools-extra/trunk/clang-tidy/performance/TypePromotionInMathFnCheck.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/performance/TypePromotionInMathFnCheck.h?rev=289627&view=auto
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/performance/TypePromotionInMathFnCheck.h (added)
+++ clang-tools-extra/trunk/clang-tidy/performance/TypePromotionInMathFnCheck.h Tue Dec 13 21:15:01 2016
@@ -0,0 +1,40 @@
+//===--- TypePromotionInMathFnCheck.h - clang-tidy---------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_TYPE_PROMOTION_IN_MATH_FN_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_TYPE_PROMOTION_IN_MATH_FN_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace performance {
+
+/// Finds calls to C math library functions with implicit float to double
+/// promotions.
+///
+/// For example, warns on ::sin(0.f), because this funciton's parameter is a
+/// double.  You probably meant to call std::sin(0.f) (in C++), or sinf(0.f) (in
+/// C).
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/performance-type-promotion-in-math-fn.html
+class TypePromotionInMathFnCheck : public ClangTidyCheck {
+public:
+  TypePromotionInMathFnCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace performance
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_TYPE_PROMOTION_IN_MATH_FN_H

Modified: clang-tools-extra/trunk/docs/ReleaseNotes.rst
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/ReleaseNotes.rst?rev=289627&r1=289626&r2=289627&view=diff
==============================================================================
--- clang-tools-extra/trunk/docs/ReleaseNotes.rst (original)
+++ clang-tools-extra/trunk/docs/ReleaseNotes.rst Tue Dec 13 21:15:01 2016
@@ -124,6 +124,12 @@ Improvements to clang-tidy
   Warns about the performance overhead arising from concatenating strings using
   the ``operator+``, instead of ``operator+=``.
 
+- New `performance-type-promotion-in-math-fn
+  <http://clang.llvm.org/extra/clang-tidy/checks/performance-type-promotion-in-math-fn.html>`_ check
+
+  Replaces uses of C-style standard math functions with double parameters and float
+  arguments with an equivalent function that takes a float parameter.
+
 - `readability-container-size-empty
   <http://clang.llvm.org/extra/clang-tidy/checks/readability-container-size-empty.html>`_ check
   supports arbitrary containers with with suitable ``empty()`` and ``size()``

Modified: clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst?rev=289627&r1=289626&r2=289627&view=diff
==============================================================================
--- clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst (original)
+++ clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst Tue Dec 13 21:15:01 2016
@@ -123,6 +123,7 @@ Clang-Tidy Checks
    performance-for-range-copy
    performance-implicit-cast-in-loop
    performance-inefficient-string-concatenation
+   performance-type-promotion-in-math-fn
    performance-unnecessary-copy-initialization
    performance-unnecessary-value-param
    readability-avoid-const-params-in-decls

Added: clang-tools-extra/trunk/docs/clang-tidy/checks/performance-type-promotion-in-math-fn.rst
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/clang-tidy/checks/performance-type-promotion-in-math-fn.rst?rev=289627&view=auto
==============================================================================
--- clang-tools-extra/trunk/docs/clang-tidy/checks/performance-type-promotion-in-math-fn.rst (added)
+++ clang-tools-extra/trunk/docs/clang-tidy/checks/performance-type-promotion-in-math-fn.rst Tue Dec 13 21:15:01 2016
@@ -0,0 +1,11 @@
+.. title:: clang-tidy - performance-type-promotion-in-math-fn
+
+performance-type-promotion-in-math-fn
+=====================================
+
+Finds calls to C math library functions (from ``math.h`` or, in C++, ``cmath``)
+with implicit ``float`` to ``double`` promotions.
+
+For example, warns on ``::sin(0.f)``, because this funciton's parameter is a
+double. You probably meant to call ``std::sin(0.f)`` (in C++), or ``sinf(0.f)``
+(in C).

Added: clang-tools-extra/trunk/test/clang-tidy/performance-type-promotion-in-math-fn.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/performance-type-promotion-in-math-fn.cpp?rev=289627&view=auto
==============================================================================
--- clang-tools-extra/trunk/test/clang-tidy/performance-type-promotion-in-math-fn.cpp (added)
+++ clang-tools-extra/trunk/test/clang-tidy/performance-type-promotion-in-math-fn.cpp Tue Dec 13 21:15:01 2016
@@ -0,0 +1,314 @@
+// RUN: %check_clang_tidy %s performance-type-promotion-in-math-fn %t
+
+double acos(double);
+double acosh(double);
+double asin(double);
+double asinh(double);
+double atan2(double, double);
+double atan(double);
+double atanh(double);
+double cbrt(double);
+double ceil(double);
+double copysign(double, double);
+double cos(double);
+double cosh(double);
+double erfc(double);
+double erf(double);
+double exp2(double);
+double exp(double);
+double expm1(double);
+double fabs(double);
+double fdim(double, double);
+double floor(double);
+double fma(double, double, double);
+double fmax(double, double);
+double fmin(double, double);
+double fmod(double, double);
+double frexp(double, int *);
+double hypot(double, double);
+double ilogb(double);
+double ldexp(double, double);
+double lgamma(double);
+long long llrint(double);
+double log10(double);
+double log1p(double);
+double log2(double);
+double logb(double);
+double log(double);
+long lrint(double);
+double modf(double);
+double nearbyint(double);
+double nextafter(double, double);
+double nexttoward(double, long double);
+double pow(double, double);
+double remainder(double, double);
+double remquo(double, double, int *);
+double rint(double);
+double round(double);
+double scalbln(double, long);
+double scalbn(double, int);
+double sin(double);
+double sinh(double);
+double sqrt(double);
+double tan(double);
+double tanh(double);
+double tgamma(double);
+double trunc(double);
+long long llround(double);
+long lround(double);
+
+void check_all_fns() {
+  float a, b, c;
+  int i;
+  long l;
+  int *int_ptr;
+
+  acos(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'acos' promotes float to double [performance-type-promotion-in-math-fn]
+  // CHECK-FIXES: {{^}}  std::acos(a);{{$}}
+  acosh(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'acosh'
+  // CHECK-FIXES: {{^}}  std::acosh(a);{{$}}
+  asin(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'asin'
+  // CHECK-FIXES: {{^}}  std::asin(a);{{$}}
+  asinh(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'asinh'
+  // CHECK-FIXES: {{^}}  std::asinh(a);{{$}}
+  atan2(a, b);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'atan2'
+  // CHECK-FIXES: {{^}}  std::atan2(a, b);{{$}}
+  atan(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'atan'
+  // CHECK-FIXES: {{^}}  std::atan(a);{{$}}
+  atanh(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'atanh'
+  // CHECK-FIXES: {{^}}  std::atanh(a);{{$}}
+  cbrt(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'cbrt'
+  // CHECK-FIXES: {{^}}  std::cbrt(a);{{$}}
+  ceil(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'ceil'
+  // CHECK-FIXES: {{^}}  std::ceil(a);{{$}}
+  copysign(a, b);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'copysign'
+  // CHECK-FIXES: {{^}}  std::copysign(a, b);{{$}}
+  cos(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'cos'
+  // CHECK-FIXES: {{^}}  std::cos(a);{{$}}
+  cosh(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'cosh'
+  // CHECK-FIXES: {{^}}  std::cosh(a);{{$}}
+  erf(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'erf'
+  // CHECK-FIXES: {{^}}  std::erf(a);{{$}}
+  erfc(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'erfc'
+  // CHECK-FIXES: {{^}}  std::erfc(a);{{$}}
+  exp2(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'exp2'
+  // CHECK-FIXES: {{^}}  std::exp2(a);{{$}}
+  exp(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'exp'
+  // CHECK-FIXES: {{^}}  std::exp(a);{{$}}
+  expm1(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'expm1'
+  // CHECK-FIXES: {{^}}  std::expm1(a);{{$}}
+  fabs(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'fabs'
+  // CHECK-FIXES: {{^}}  std::fabs(a);{{$}}
+  fdim(a, b);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'fdim'
+  // CHECK-FIXES: {{^}}  std::fdim(a, b);{{$}}
+  floor(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'floor'
+  // CHECK-FIXES: {{^}}  std::floor(a);{{$}}
+  fma(a, b, c);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'fma'
+  // CHECK-FIXES: {{^}}  std::fma(a, b, c);{{$}}
+  fmax(a, b);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'fmax'
+  // CHECK-FIXES: {{^}}  std::fmax(a, b);{{$}}
+  fmin(a, b);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'fmin'
+  // CHECK-FIXES: {{^}}  std::fmin(a, b);{{$}}
+  fmod(a, b);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'fmod'
+  // CHECK-FIXES: {{^}}  std::fmod(a, b);{{$}}
+  frexp(a, int_ptr);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'frexp'
+  // CHECK-FIXES: {{^}}  std::frexp(a, int_ptr);{{$}}
+  hypot(a, b);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'hypot'
+  // CHECK-FIXES: {{^}}  std::hypot(a, b);{{$}}
+  ilogb(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'ilogb'
+  // CHECK-FIXES: {{^}}  std::ilogb(a);{{$}}
+  ldexp(a, b);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'ldexp'
+  // CHECK-FIXES: {{^}}  std::ldexp(a, b);{{$}}
+  lgamma(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'lgamma'
+  // CHECK-FIXES: {{^}}  std::lgamma(a);{{$}}
+  llrint(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'llrint'
+  // CHECK-FIXES: {{^}}  std::llrint(a);{{$}}
+  llround(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'llround'
+  // CHECK-FIXES: {{^}}  std::llround(a);{{$}}
+  log10(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'log10'
+  // CHECK-FIXES: {{^}}  std::log10(a);{{$}}
+  log1p(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'log1p'
+  // CHECK-FIXES: {{^}}  std::log1p(a);{{$}}
+  log2(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'log2'
+  // CHECK-FIXES: {{^}}  std::log2(a);{{$}}
+  log(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'log'
+  // CHECK-FIXES: {{^}}  std::log(a);{{$}}
+  logb(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'logb'
+  // CHECK-FIXES: {{^}}  std::logb(a);{{$}}
+  lrint(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'lrint'
+  // CHECK-FIXES: {{^}}  std::lrint(a);{{$}}
+  lround(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'lround'
+  // CHECK-FIXES: {{^}}  std::lround(a);{{$}}
+  nearbyint(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'nearbyint'
+  // CHECK-FIXES: {{^}}  std::nearbyint(a);{{$}}
+  nextafter(a, b);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'nextafter'
+  // CHECK-FIXES: {{^}}  std::nextafter(a, b);{{$}}
+  nexttoward(a, b);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'nexttoward'
+  // CHECK-FIXES: {{^}}  std::nexttoward(a, b);{{$}}
+  pow(a, b);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'pow'
+  // CHECK-FIXES: {{^}}  std::pow(a, b);{{$}}
+  remainder(a, b);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'remainder'
+  // CHECK-FIXES: {{^}}  std::remainder(a, b);{{$}}
+  remquo(a, b, int_ptr);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'remquo'
+  // CHECK-FIXES: {{^}}  std::remquo(a, b, int_ptr);{{$}}
+  rint(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'rint'
+  // CHECK-FIXES: {{^}}  std::rint(a);{{$}}
+  round(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'round'
+  // CHECK-FIXES: {{^}}  std::round(a);{{$}}
+  scalbln(a, l);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'scalbln'
+  // CHECK-FIXES: {{^}}  std::scalbln(a, l);{{$}}
+  scalbn(a, i);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'scalbn'
+  // CHECK-FIXES: {{^}}  std::scalbn(a, i);{{$}}
+  sin(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'sin'
+  // CHECK-FIXES: {{^}}  std::sin(a);{{$}}
+  sinh(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'sinh'
+  // CHECK-FIXES: {{^}}  std::sinh(a);{{$}}
+  sqrt(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'sqrt'
+  // CHECK-FIXES: {{^}}  std::sqrt(a);{{$}}
+  tan(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'tan'
+  // CHECK-FIXES: {{^}}  std::tan(a);{{$}}
+  tanh(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'tanh'
+  // CHECK-FIXES: {{^}}  std::tanh(a);{{$}}
+  tgamma(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'tgamma'
+  // CHECK-FIXES: {{^}}  std::tgamma(a);{{$}}
+  trunc(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'trunc'
+  // CHECK-FIXES: {{^}}  std::trunc(a);{{$}}
+}
+
+// nexttoward/nexttowardf are weird -- the second param is always long double.
+// So we warn if the first arg is a float, regardless of what the second arg is.
+void check_nexttoward() {
+  nexttoward(0.f, 0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'nexttoward'
+  // CHECK-FIXES: {{^}}  std::nexttoward(0.f, 0);{{$}}
+  nexttoward(0.f, 0l);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'nexttoward'
+  // CHECK-FIXES: {{^}}  std::nexttoward(0.f, 0l);{{$}}
+  nexttoward(0.f, 0.f);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'nexttoward'
+  // CHECK-FIXES: {{^}}  std::nexttoward(0.f, 0.f);{{$}}
+  nexttoward(0.f, 0.);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'nexttoward'
+  // CHECK-FIXES: {{^}}  std::nexttoward(0.f, 0.);{{$}}
+
+  // No warnings for these.
+  nexttoward(0., 0);
+  nexttoward(0., 0.f);
+  nexttoward(0., 0.);
+}
+
+// The second parameter to scalbn and scalbnf is an int, so we don't care what
+// type you pass as that argument; we warn iff the first argument is a float.
+void check_scalbn() {
+  scalbn(0.f, 0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'scalbn'
+  // CHECK-FIXES: {{^}}  std::scalbn(0.f, 0);{{$}}
+  scalbn(0.f, static_cast<char>(0));
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'scalbn'
+  // CHECK-FIXES: {{^}}  std::scalbn(0.f, static_cast<char>(0));{{$}}
+
+  // No warnings for these.
+  scalbn(0., 0);
+  scalbn(0., static_cast<char>(0));
+}
+
+// scalbln/scalblnf are like scalbn/scalbnf except their second arg is a long.
+// Again, doesn't matter what we pass for the second arg; we warn iff the first
+// arg is a float.
+void check_scalbln() {
+  scalbln(0.f, 0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'scalbln'
+  // CHECK-FIXES: {{^}}  std::scalbln(0.f, 0);{{$}}
+  scalbln(0.f, 0l);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'scalbln'
+  // CHECK-FIXES: {{^}}  std::scalbln(0.f, 0l);{{$}}
+
+  // No warnings for these.
+  scalbln(0., 0);
+  scalbln(0., 0l);
+}
+
+float cosf(float);
+double foo(double);         // not a math.h function
+float cos(float);           // not a math.h function (wrong signature)
+double cos(double, double); // not a math.h function (wrong signature)
+
+namespace std {
+void cos(float);
+} // namespace std
+
+void check_no_warnings() {
+  foo(0.); // no warning because not a math.h function.
+
+  sin(0);        // no warning because arg is an int
+  cos(0.);       // no warning because arg is a double
+  std::cos(0.f); // no warning because not ::cos.
+  cosf(0.f);     // no warning; we expect this to take a float
+  cos(0.f);      // does not match the expected signature of ::cos
+  cos(0.f, 0.f); // does not match the expected signature of ::cos
+
+  // No warnings because all args are not floats.
+  remainder(0., 0.f);
+  remainder(0.f, 0.);
+  remainder(0, 0.f);
+  remainder(0.f, 0);
+  fma(0.f, 0.f, 0);
+  fma(0.f, 0.f, 0.);
+  fma(0.f, 0., 0.f);
+  fma(0., 0.f, 0.f);
+}




More information about the cfe-commits mailing list