Skip to content

Commit 1082254

Browse files
committed
Add google-runtime-float Clang-Tidy check
1 parent 2bc019d commit 1082254

File tree

8 files changed

+186
-1
lines changed

8 files changed

+186
-1
lines changed

clang-tools-extra/clang-tidy/google/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ add_clang_library(clangTidyGoogleModule STATIC
1111
DefaultArgumentsCheck.cpp
1212
ExplicitConstructorCheck.cpp
1313
ExplicitMakePairCheck.cpp
14+
FloatTypesCheck.cpp
1415
FunctionNamingCheck.cpp
1516
GlobalNamesInHeadersCheck.cpp
1617
GlobalVariableDeclarationCheck.cpp
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "FloatTypesCheck.h"
10+
#include "clang/ASTMatchers/ASTMatchFinder.h"
11+
#include "clang/Lex/Lexer.h"
12+
13+
namespace clang {
14+
15+
using namespace ast_matchers;
16+
17+
namespace {
18+
19+
AST_MATCHER(TypeLoc, isTypeLocValidAndNotInMacro) {
20+
const SourceLocation Loc = Node.getBeginLoc();
21+
return Loc.isValid() && !Loc.isMacroID();
22+
}
23+
24+
AST_MATCHER(FloatingLiteral, isFLValidAndNotInMacro) {
25+
const SourceLocation Loc = Node.getBeginLoc();
26+
return Loc.isValid() && !Loc.isMacroID();
27+
}
28+
29+
AST_MATCHER(TypeLoc, isLongDoubleType) {
30+
TypeLoc TL = Node;
31+
if (auto QualLoc = Node.getAs<QualifiedTypeLoc>())
32+
TL = QualLoc.getUnqualifiedLoc();
33+
34+
const auto BuiltinLoc = TL.getAs<BuiltinTypeLoc>();
35+
if (!BuiltinLoc)
36+
return false;
37+
38+
return BuiltinLoc.getTypePtr()->getKind() == BuiltinType::LongDouble;
39+
}
40+
41+
AST_MATCHER(FloatingLiteral, isLongDoubleLiteral) {
42+
if (auto *BT = dyn_cast<BuiltinType>(Node.getType().getTypePtr()))
43+
return BT->getKind() == BuiltinType::LongDouble;
44+
return false;
45+
}
46+
47+
} // namespace
48+
49+
namespace tidy::google::runtime {
50+
51+
void RuntimeFloatCheck::registerMatchers(MatchFinder *Finder) {
52+
Finder->addMatcher(typeLoc(loc(realFloatingPointType()),
53+
isTypeLocValidAndNotInMacro(), isLongDoubleType())
54+
.bind("longDoubleTypeLoc"),
55+
this);
56+
Finder->addMatcher(
57+
floatLiteral(isFLValidAndNotInMacro(), isLongDoubleLiteral())
58+
.bind("longDoubleFloatLiteral"),
59+
this);
60+
IdentTable = std::make_unique<IdentifierTable>(getLangOpts());
61+
}
62+
63+
void RuntimeFloatCheck::check(const MatchFinder::MatchResult &Result) {
64+
if (const auto *TL = Result.Nodes.getNodeAs<TypeLoc>("longDoubleTypeLoc")) {
65+
diag(TL->getBeginLoc(),
66+
"consider replacing %0 with a 64-bit or 128-bit float type")
67+
<< TL->getType();
68+
}
69+
70+
if (const auto *FL =
71+
Result.Nodes.getNodeAs<FloatingLiteral>("longDoubleFloatLiteral")) {
72+
diag(FL->getBeginLoc(),
73+
"%0 type from literal suffix 'L' should not be used")
74+
<< FL->getType();
75+
}
76+
}
77+
78+
} // namespace tidy::google::runtime
79+
80+
} // namespace clang
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
2+
//===----------------------------------------------------------------------===//
3+
//
4+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5+
// See https://llvm.org/LICENSE.txt for license information.
6+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7+
//
8+
//===----------------------------------------------------------------------===//
9+
10+
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_FLOATTYPESCHECK_H
11+
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_FLOATTYPESCHECK_H
12+
13+
#include "../ClangTidyCheck.h"
14+
15+
namespace clang {
16+
17+
class IdentifierTable;
18+
19+
namespace tidy::google::runtime {
20+
21+
/// Finds usages of `long double` and suggests replacing them with other
22+
/// floating-point types.
23+
///
24+
/// For the user-facing documentation see:
25+
/// http://clang.llvm.org/extra/clang-tidy/checks/google/runtime-float.html
26+
class RuntimeFloatCheck : public ClangTidyCheck {
27+
public:
28+
RuntimeFloatCheck(StringRef Name, ClangTidyContext *Context)
29+
: ClangTidyCheck(Name, Context) {}
30+
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
31+
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
32+
bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
33+
return LangOpts.CPlusPlus && !LangOpts.ObjC;
34+
}
35+
36+
private:
37+
std::unique_ptr<IdentifierTable> IdentTable;
38+
};
39+
40+
} // namespace tidy::google::runtime
41+
42+
} // namespace clang
43+
44+
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_FLOATTYPESCHECK_H

clang-tools-extra/clang-tidy/google/GoogleTidyModule.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "DefaultArgumentsCheck.h"
2020
#include "ExplicitConstructorCheck.h"
2121
#include "ExplicitMakePairCheck.h"
22+
#include "FloatTypesCheck.h"
2223
#include "FunctionNamingCheck.h"
2324
#include "GlobalNamesInHeadersCheck.h"
2425
#include "GlobalVariableDeclarationCheck.h"
@@ -57,6 +58,8 @@ class GoogleModule : public ClangTidyModule {
5758
"google-objc-function-naming");
5859
CheckFactories.registerCheck<objc::GlobalVariableDeclarationCheck>(
5960
"google-objc-global-variable-declaration");
61+
CheckFactories.registerCheck<runtime::RuntimeFloatCheck>(
62+
"google-runtime-float");
6063
CheckFactories.registerCheck<runtime::IntegerTypesCheck>(
6164
"google-runtime-int");
6265
CheckFactories.registerCheck<runtime::OverloadedUnaryAndCheck>(

clang-tools-extra/docs/ReleaseNotes.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,12 @@ New checks
142142
Finds calls to ``operator[]`` in STL containers and suggests replacing them
143143
with safe alternatives.
144144

145+
- New :doc:`google-runtime-float
146+
<clang-tidy/checks/google/runtime-float>` check.
147+
148+
Checks for and warns of uses of the ``long double`` type, which is
149+
problematic since it produces non-portable code.
150+
145151
- New :doc:`llvm-mlir-op-builder
146152
<clang-tidy/checks/llvm/use-new-mlir-op-builder>` check.
147153

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
.. title:: clang-tidy - google-runtime-float
2+
3+
google-runtime-float
4+
====================
5+
6+
Finds uses of ``long double`` and suggests replacing them with 64-bit
7+
or 128-bit floating-point types.
8+
9+
The corresponding style guide rule:
10+
https://google.github.io/styleguide/cppguide.html#Floating-Point_Types
11+

clang-tools-extra/docs/clang-tidy/checks/list.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,7 @@ Clang-Tidy Checks
238238
:doc:`google-readability-avoid-underscore-in-googletest-name <google/readability-avoid-underscore-in-googletest-name>`,
239239
:doc:`google-readability-casting <google/readability-casting>`,
240240
:doc:`google-readability-todo <google/readability-todo>`,
241+
:doc:`google-runtime-float <google/runtime-float>`, "Yes"
241242
:doc:`google-runtime-int <google/runtime-int>`,
242243
:doc:`google-runtime-operator <google/runtime-operator>`,
243244
:doc:`google-upgrade-googletest-case <google/upgrade-googletest-case>`, "Yes"
@@ -249,12 +250,12 @@ Clang-Tidy Checks
249250
:doc:`linuxkernel-must-check-errs <linuxkernel/must-check-errs>`,
250251
:doc:`llvm-header-guard <llvm/header-guard>`,
251252
:doc:`llvm-include-order <llvm/include-order>`, "Yes"
252-
:doc:`llvm-use-new-mlir-op-builder <llvm/use-new-mlir-op-builder>`, "Yes"
253253
:doc:`llvm-namespace-comment <llvm/namespace-comment>`,
254254
:doc:`llvm-prefer-isa-or-dyn-cast-in-conditionals <llvm/prefer-isa-or-dyn-cast-in-conditionals>`, "Yes"
255255
:doc:`llvm-prefer-register-over-unsigned <llvm/prefer-register-over-unsigned>`, "Yes"
256256
:doc:`llvm-prefer-static-over-anonymous-namespace <llvm/prefer-static-over-anonymous-namespace>`,
257257
:doc:`llvm-twine-local <llvm/twine-local>`, "Yes"
258+
:doc:`llvm-use-new-mlir-op-builder <llvm/use-new-mlir-op-builder>`, "Yes"
258259
:doc:`llvmlibc-callee-namespace <llvmlibc/callee-namespace>`,
259260
:doc:`llvmlibc-implementation-in-namespace <llvmlibc/implementation-in-namespace>`,
260261
:doc:`llvmlibc-inline-function-decl <llvmlibc/inline-function-decl>`, "Yes"
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// RUN: %check_clang_tidy %s google-runtime-float %t
2+
3+
long double foo;
4+
// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: consider replacing 'long double' with a 64-bit or 128-bit float type [google-runtime-float]
5+
6+
typedef long double MyLongDouble;
7+
// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: consider replacing 'long double' with a 64-bit or 128-bit float type [google-runtime-float]
8+
9+
typedef long double MyOtherLongDouble; // NOLINT
10+
11+
template <typename T>
12+
void tmpl() { T i; }
13+
14+
long volatile double v = 10;
15+
// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: consider replacing 'volatile long double' with a 64-bit or 128-bit float type [google-runtime-float]
16+
17+
long double h(long const double aaa, long double bbb = 0.5L) {
18+
// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: consider replacing 'long double' with a 64-bit or 128-bit float type [google-runtime-float]
19+
// CHECK-MESSAGES: :[[@LINE-2]]:15: warning: consider replacing 'const long double' with a 64-bit or 128-bit float type [google-runtime-float]
20+
// CHECK-MESSAGES: :[[@LINE-3]]:38: warning: consider replacing 'long double' with a 64-bit or 128-bit float type [google-runtime-float]
21+
// CHECK-MESSAGES: :[[@LINE-4]]:56: warning: 'long double' type from literal suffix 'L' should not be used [google-runtime-float]
22+
double x = 0.1;
23+
double y = 0.2L;
24+
// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: 'long double' type from literal suffix 'L' should not be used [google-runtime-float]
25+
#define ldtype long double
26+
ldtype z;
27+
tmpl<long double>();
28+
// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: consider replacing 'long double' with a 64-bit or 128-bit float type [google-runtime-float]
29+
return 0;
30+
}
31+
32+
struct S{};
33+
constexpr S operator"" _baz(unsigned long long) {
34+
long double j;
35+
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: consider replacing 'long double' with a 64-bit or 128-bit float type [google-runtime-float]
36+
MyOtherLongDouble x;
37+
return S{};
38+
}
39+

0 commit comments

Comments
 (0)