https://github.com/brenfwd created 
https://github.com/llvm/llvm-project/pull/156763

Add a new checker to clang-tidy for use of the `long double` type [per Google 
style 
guide](https://google.github.io/styleguide/cppguide.html#Floating-Point_Types).

>From 1082254d96f3c427f4cb867fcf964c19655e1876 Mon Sep 17 00:00:00 2001
From: Brenden Forward <bforw...@google.com>
Date: Tue, 2 Sep 2025 18:16:46 -0700
Subject: [PATCH] Add google-runtime-float Clang-Tidy check

---
 .../clang-tidy/google/CMakeLists.txt          |  1 +
 .../clang-tidy/google/FloatTypesCheck.cpp     | 80 +++++++++++++++++++
 .../clang-tidy/google/FloatTypesCheck.h       | 44 ++++++++++
 .../clang-tidy/google/GoogleTidyModule.cpp    |  3 +
 clang-tools-extra/docs/ReleaseNotes.rst       |  6 ++
 .../checks/google/runtime-float.rst           | 11 +++
 .../docs/clang-tidy/checks/list.rst           |  3 +-
 .../checkers/google/runtime-float.cpp         | 39 +++++++++
 8 files changed, 186 insertions(+), 1 deletion(-)
 create mode 100644 clang-tools-extra/clang-tidy/google/FloatTypesCheck.cpp
 create mode 100644 clang-tools-extra/clang-tidy/google/FloatTypesCheck.h
 create mode 100644 
clang-tools-extra/docs/clang-tidy/checks/google/runtime-float.rst
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/google/runtime-float.cpp

diff --git a/clang-tools-extra/clang-tidy/google/CMakeLists.txt 
b/clang-tools-extra/clang-tidy/google/CMakeLists.txt
index 2470c089ef7ca..1d4229ebb7b09 100644
--- a/clang-tools-extra/clang-tidy/google/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/google/CMakeLists.txt
@@ -11,6 +11,7 @@ add_clang_library(clangTidyGoogleModule STATIC
   DefaultArgumentsCheck.cpp
   ExplicitConstructorCheck.cpp
   ExplicitMakePairCheck.cpp
+  FloatTypesCheck.cpp
   FunctionNamingCheck.cpp
   GlobalNamesInHeadersCheck.cpp
   GlobalVariableDeclarationCheck.cpp
diff --git a/clang-tools-extra/clang-tidy/google/FloatTypesCheck.cpp 
b/clang-tools-extra/clang-tidy/google/FloatTypesCheck.cpp
new file mode 100644
index 0000000000000..b8afe803230d3
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/google/FloatTypesCheck.cpp
@@ -0,0 +1,80 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 "FloatTypesCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Lex/Lexer.h"
+
+namespace clang {
+
+using namespace ast_matchers;
+
+namespace {
+
+AST_MATCHER(TypeLoc, isTypeLocValidAndNotInMacro) {
+  const SourceLocation Loc = Node.getBeginLoc();
+  return Loc.isValid() && !Loc.isMacroID();
+}
+
+AST_MATCHER(FloatingLiteral, isFLValidAndNotInMacro) {
+  const SourceLocation Loc = Node.getBeginLoc();
+  return Loc.isValid() && !Loc.isMacroID();
+}
+
+AST_MATCHER(TypeLoc, isLongDoubleType) {
+  TypeLoc TL = Node;
+  if (auto QualLoc = Node.getAs<QualifiedTypeLoc>())
+    TL = QualLoc.getUnqualifiedLoc();
+
+  const auto BuiltinLoc = TL.getAs<BuiltinTypeLoc>();
+  if (!BuiltinLoc)
+    return false;
+
+  return BuiltinLoc.getTypePtr()->getKind() == BuiltinType::LongDouble;
+}
+
+AST_MATCHER(FloatingLiteral, isLongDoubleLiteral) {
+  if (auto *BT = dyn_cast<BuiltinType>(Node.getType().getTypePtr()))
+    return BT->getKind() == BuiltinType::LongDouble;
+  return false;
+}
+
+} // namespace
+
+namespace tidy::google::runtime {
+
+void RuntimeFloatCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(typeLoc(loc(realFloatingPointType()),
+                             isTypeLocValidAndNotInMacro(), isLongDoubleType())
+                         .bind("longDoubleTypeLoc"),
+                     this);
+  Finder->addMatcher(
+      floatLiteral(isFLValidAndNotInMacro(), isLongDoubleLiteral())
+          .bind("longDoubleFloatLiteral"),
+      this);
+  IdentTable = std::make_unique<IdentifierTable>(getLangOpts());
+}
+
+void RuntimeFloatCheck::check(const MatchFinder::MatchResult &Result) {
+  if (const auto *TL = Result.Nodes.getNodeAs<TypeLoc>("longDoubleTypeLoc")) {
+    diag(TL->getBeginLoc(),
+         "consider replacing %0 with a 64-bit or 128-bit float type")
+        << TL->getType();
+  }
+
+  if (const auto *FL =
+          Result.Nodes.getNodeAs<FloatingLiteral>("longDoubleFloatLiteral")) {
+    diag(FL->getBeginLoc(),
+         "%0 type from literal suffix 'L' should not be used")
+        << FL->getType();
+  }
+}
+
+} // namespace tidy::google::runtime
+
+} // namespace clang
diff --git a/clang-tools-extra/clang-tidy/google/FloatTypesCheck.h 
b/clang-tools-extra/clang-tidy/google/FloatTypesCheck.h
new file mode 100644
index 0000000000000..54327b6d7e53b
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/google/FloatTypesCheck.h
@@ -0,0 +1,44 @@
+
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_FLOATTYPESCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_FLOATTYPESCHECK_H
+
+#include "../ClangTidyCheck.h"
+
+namespace clang {
+
+class IdentifierTable;
+
+namespace tidy::google::runtime {
+
+/// Finds usages of `long double` and suggests replacing them with other
+/// floating-point types.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/google/runtime-float.html
+class RuntimeFloatCheck : public ClangTidyCheck {
+public:
+  RuntimeFloatCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+  bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
+    return LangOpts.CPlusPlus && !LangOpts.ObjC;
+  }
+
+private:
+  std::unique_ptr<IdentifierTable> IdentTable;
+};
+
+} // namespace tidy::google::runtime
+
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_FLOATTYPESCHECK_H
diff --git a/clang-tools-extra/clang-tidy/google/GoogleTidyModule.cpp 
b/clang-tools-extra/clang-tidy/google/GoogleTidyModule.cpp
index 5343e2b3a5975..eb5666be62bcf 100644
--- a/clang-tools-extra/clang-tidy/google/GoogleTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/google/GoogleTidyModule.cpp
@@ -19,6 +19,7 @@
 #include "DefaultArgumentsCheck.h"
 #include "ExplicitConstructorCheck.h"
 #include "ExplicitMakePairCheck.h"
+#include "FloatTypesCheck.h"
 #include "FunctionNamingCheck.h"
 #include "GlobalNamesInHeadersCheck.h"
 #include "GlobalVariableDeclarationCheck.h"
@@ -57,6 +58,8 @@ class GoogleModule : public ClangTidyModule {
         "google-objc-function-naming");
     CheckFactories.registerCheck<objc::GlobalVariableDeclarationCheck>(
         "google-objc-global-variable-declaration");
+    CheckFactories.registerCheck<runtime::RuntimeFloatCheck>(
+        "google-runtime-float");
     CheckFactories.registerCheck<runtime::IntegerTypesCheck>(
         "google-runtime-int");
     CheckFactories.registerCheck<runtime::OverloadedUnaryAndCheck>(
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst 
b/clang-tools-extra/docs/ReleaseNotes.rst
index 32e4dfb8aa329..af62797e9ea91 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -142,6 +142,12 @@ New checks
   Finds calls to ``operator[]`` in STL containers and suggests replacing them
   with safe alternatives.
 
+- New :doc:`google-runtime-float
+  <clang-tidy/checks/google/runtime-float>` check.
+
+  Checks for and warns of uses of the ``long double`` type, which is
+  problematic since it produces non-portable code.
+
 - New :doc:`llvm-mlir-op-builder
   <clang-tidy/checks/llvm/use-new-mlir-op-builder>` check.
 
diff --git a/clang-tools-extra/docs/clang-tidy/checks/google/runtime-float.rst 
b/clang-tools-extra/docs/clang-tidy/checks/google/runtime-float.rst
new file mode 100644
index 0000000000000..5a5f9a4e6ae0f
--- /dev/null
+++ b/clang-tools-extra/docs/clang-tidy/checks/google/runtime-float.rst
@@ -0,0 +1,11 @@
+.. title:: clang-tidy - google-runtime-float
+
+google-runtime-float
+====================
+
+Finds uses of ``long double`` and suggests replacing them with 64-bit
+or 128-bit floating-point types.
+
+The corresponding style guide rule:
+https://google.github.io/styleguide/cppguide.html#Floating-Point_Types
+
diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst 
b/clang-tools-extra/docs/clang-tidy/checks/list.rst
index 5e3ffc4f8aca3..9c60c0766dbc4 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -238,6 +238,7 @@ Clang-Tidy Checks
    :doc:`google-readability-avoid-underscore-in-googletest-name 
<google/readability-avoid-underscore-in-googletest-name>`,
    :doc:`google-readability-casting <google/readability-casting>`,
    :doc:`google-readability-todo <google/readability-todo>`,
+   :doc:`google-runtime-float <google/runtime-float>`, "Yes"
    :doc:`google-runtime-int <google/runtime-int>`,
    :doc:`google-runtime-operator <google/runtime-operator>`,
    :doc:`google-upgrade-googletest-case <google/upgrade-googletest-case>`, 
"Yes"
@@ -249,12 +250,12 @@ Clang-Tidy Checks
    :doc:`linuxkernel-must-check-errs <linuxkernel/must-check-errs>`,
    :doc:`llvm-header-guard <llvm/header-guard>`,
    :doc:`llvm-include-order <llvm/include-order>`, "Yes"
-   :doc:`llvm-use-new-mlir-op-builder <llvm/use-new-mlir-op-builder>`, "Yes"
    :doc:`llvm-namespace-comment <llvm/namespace-comment>`,
    :doc:`llvm-prefer-isa-or-dyn-cast-in-conditionals 
<llvm/prefer-isa-or-dyn-cast-in-conditionals>`, "Yes"
    :doc:`llvm-prefer-register-over-unsigned 
<llvm/prefer-register-over-unsigned>`, "Yes"
    :doc:`llvm-prefer-static-over-anonymous-namespace 
<llvm/prefer-static-over-anonymous-namespace>`,
    :doc:`llvm-twine-local <llvm/twine-local>`, "Yes"
+   :doc:`llvm-use-new-mlir-op-builder <llvm/use-new-mlir-op-builder>`, "Yes"
    :doc:`llvmlibc-callee-namespace <llvmlibc/callee-namespace>`,
    :doc:`llvmlibc-implementation-in-namespace 
<llvmlibc/implementation-in-namespace>`,
    :doc:`llvmlibc-inline-function-decl <llvmlibc/inline-function-decl>`, "Yes"
diff --git 
a/clang-tools-extra/test/clang-tidy/checkers/google/runtime-float.cpp 
b/clang-tools-extra/test/clang-tidy/checkers/google/runtime-float.cpp
new file mode 100644
index 0000000000000..4ddf623fb955a
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/google/runtime-float.cpp
@@ -0,0 +1,39 @@
+// RUN: %check_clang_tidy %s google-runtime-float %t
+
+long double foo;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: consider replacing 'long double' 
with a 64-bit or 128-bit float type [google-runtime-float]
+
+typedef long double MyLongDouble;
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: consider replacing 'long double' 
with a 64-bit or 128-bit float type [google-runtime-float]
+
+typedef long double MyOtherLongDouble; // NOLINT
+
+template <typename T>
+void tmpl() { T i; }
+
+long volatile double v = 10;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: consider replacing 'volatile long 
double' with a 64-bit or 128-bit float type [google-runtime-float]
+
+long double h(long const double aaa, long double bbb = 0.5L) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: consider replacing 'long double' 
with a 64-bit or 128-bit float type [google-runtime-float]
+  // CHECK-MESSAGES: :[[@LINE-2]]:15: warning: consider replacing 'const long 
double' with a 64-bit or 128-bit float type [google-runtime-float]
+  // CHECK-MESSAGES: :[[@LINE-3]]:38: warning: consider replacing 'long 
double' with a 64-bit or 128-bit float type [google-runtime-float]
+  // CHECK-MESSAGES: :[[@LINE-4]]:56: warning: 'long double' type from literal 
suffix 'L' should not be used [google-runtime-float]
+  double x = 0.1;
+  double y = 0.2L;
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: 'long double' type from literal 
suffix 'L' should not be used [google-runtime-float]
+#define ldtype long double
+  ldtype z;
+  tmpl<long double>();
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: consider replacing 'long double' 
with a 64-bit or 128-bit float type [google-runtime-float]
+  return 0;
+}
+
+struct S{};
+constexpr S operator"" _baz(unsigned long long) {
+  long double j;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: consider replacing 'long double' 
with a 64-bit or 128-bit float type [google-runtime-float]
+  MyOtherLongDouble x;
+  return S{};
+}
+

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to