[clang-tools-extra] b7b28c6 - [clang-tidy][libc] Add an inline function checker for the libc project.
Siva Chandra Reddy via cfe-commits
cfe-commits at lists.llvm.org
Sun Feb 12 22:03:44 PST 2023
Author: Siva Chandra Reddy
Date: 2023-02-13T06:03:36Z
New Revision: b7b28c6cfe04b8ca59dec0f2e2b9b7493c1c71d3
URL: https://github.com/llvm/llvm-project/commit/b7b28c6cfe04b8ca59dec0f2e2b9b7493c1c71d3
DIFF: https://github.com/llvm/llvm-project/commit/b7b28c6cfe04b8ca59dec0f2e2b9b7493c1c71d3.diff
LOG: [clang-tidy][libc] Add an inline function checker for the libc project.
The new checker checks if inline functions defined in header files are
tagged with the LIBC_INLINE macro. See https://libc.llvm.org/code_style.html
for more information about this macro.
Reviewed By: carlosgalvezp
Differential Revision: https://reviews.llvm.org/D142592
Added:
clang-tools-extra/clang-tidy/llvmlibc/InlineFunctionDeclCheck.cpp
clang-tools-extra/clang-tidy/llvmlibc/InlineFunctionDeclCheck.h
clang-tools-extra/docs/clang-tidy/checks/llvmlibc/inline-function-decl.rst
clang-tools-extra/test/clang-tidy/checkers/llvmlibc/inline-function-decl.hpp
Modified:
clang-tools-extra/clang-tidy/llvmlibc/CMakeLists.txt
clang-tools-extra/clang-tidy/llvmlibc/LLVMLibcTidyModule.cpp
clang-tools-extra/docs/ReleaseNotes.rst
clang-tools-extra/docs/clang-tidy/checks/list.rst
Removed:
################################################################################
diff --git a/clang-tools-extra/clang-tidy/llvmlibc/CMakeLists.txt b/clang-tools-extra/clang-tidy/llvmlibc/CMakeLists.txt
index 85b22d157a0ec..811137762c165 100644
--- a/clang-tools-extra/clang-tidy/llvmlibc/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/llvmlibc/CMakeLists.txt
@@ -6,6 +6,7 @@ set(LLVM_LINK_COMPONENTS
add_clang_library(clangTidyLLVMLibcModule
CalleeNamespaceCheck.cpp
ImplementationInNamespaceCheck.cpp
+ InlineFunctionDeclCheck.cpp
LLVMLibcTidyModule.cpp
RestrictSystemLibcHeadersCheck.cpp
diff --git a/clang-tools-extra/clang-tidy/llvmlibc/InlineFunctionDeclCheck.cpp b/clang-tools-extra/clang-tidy/llvmlibc/InlineFunctionDeclCheck.cpp
new file mode 100644
index 0000000000000..3f93521498ba8
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/llvmlibc/InlineFunctionDeclCheck.cpp
@@ -0,0 +1,71 @@
+//===-- InlineFunctionDeclCheck.cpp ---------------------------------------===//
+//
+// 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 "InlineFunctionDeclCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+#include "llvm/ADT/StringSet.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::llvm_libc {
+
+InlineFunctionDeclCheck::InlineFunctionDeclCheck(StringRef Name,
+ ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context),
+ RawStringHeaderFileExtensions(Options.getLocalOrGlobal(
+ "HeaderFileExtensions", utils::defaultHeaderFileExtensions())) {
+ if (!utils::parseFileExtensions(RawStringHeaderFileExtensions,
+ HeaderFileExtensions,
+ utils::defaultFileExtensionDelimiters())) {
+ this->configurationDiag("Invalid header file extension: '%0'")
+ << RawStringHeaderFileExtensions;
+ }
+}
+
+void InlineFunctionDeclCheck::registerMatchers(MatchFinder *Finder) {
+ Finder->addMatcher(decl(functionDecl()).bind("func_decl"), this);
+}
+
+void InlineFunctionDeclCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
+ Options.store(Opts, "HeaderFileExtensions", RawStringHeaderFileExtensions);
+ if (!utils::parseFileExtensions(RawStringHeaderFileExtensions,
+ HeaderFileExtensions,
+ utils::defaultFileExtensionDelimiters())) {
+ this->configurationDiag("Invalid header file extension: '%0'")
+ << RawStringHeaderFileExtensions;
+ }
+}
+
+void InlineFunctionDeclCheck::check(const MatchFinder::MatchResult &Result) {
+ const auto *FuncDecl = Result.Nodes.getNodeAs<FunctionDecl>("func_decl");
+
+ // Consider only explicitly or implicitly inline functions.
+ if (FuncDecl == nullptr || !FuncDecl->isInlined())
+ return;
+
+ SourceLocation SrcBegin = FuncDecl->getBeginLoc();
+ // Consider functions only in header files.
+ if (!utils::isSpellingLocInHeaderFile(SrcBegin, *Result.SourceManager,
+ HeaderFileExtensions))
+ return;
+
+ // Check if decl starts with LIBC_INLINE
+ auto Loc = FullSourceLoc(Result.SourceManager->getFileLoc(SrcBegin),
+ *Result.SourceManager);
+ llvm::StringRef SrcText = Loc.getBufferData().drop_front(Loc.getFileOffset());
+ if (SrcText.starts_with("LIBC_INLINE"))
+ return;
+
+ diag(SrcBegin, "%0 must be tagged with the LIBC_INLINE macro; the macro "
+ "should be placed at the beginning of the declaration")
+ << FuncDecl;
+}
+
+} // namespace clang::tidy::llvm_libc
diff --git a/clang-tools-extra/clang-tidy/llvmlibc/InlineFunctionDeclCheck.h b/clang-tools-extra/clang-tidy/llvmlibc/InlineFunctionDeclCheck.h
new file mode 100644
index 0000000000000..a69a5dcc9c2db
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/llvmlibc/InlineFunctionDeclCheck.h
@@ -0,0 +1,44 @@
+//===-- InlineFunctionDeclCheck.h -------------------------------*- C++ -*-===//
+//
+// 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_LLVMLIBC_INLINEFUNCTIONDECLCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVMLIBC_INLINEFUNCTIONDECLCHECK_H
+
+#include "../ClangTidyCheck.h"
+#include "../utils/FileExtensionsUtils.h"
+
+namespace clang::tidy::llvm_libc {
+
+/// Checks that explicitly and implicitly inline functions in headers files
+/// are tagged with the LIBC_INLINE macro.
+///
+/// For more information about the LIBC_INLINE macro, see
+/// https://libc.llvm.org/code_style.html.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/llvmlibc/inline-function-decl-check.html
+class InlineFunctionDeclCheck : public ClangTidyCheck {
+public:
+ InlineFunctionDeclCheck(StringRef Name, ClangTidyContext *Context);
+
+ bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
+ return LangOpts.CPlusPlus;
+ }
+
+ void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
+ void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+ void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+private:
+ const StringRef RawStringHeaderFileExtensions;
+ utils::FileExtensionsSet HeaderFileExtensions;
+};
+
+} // namespace clang::tidy::llvm_libc
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVMLIBC_INLINEFUNCTIONDECLCHECK_H
diff --git a/clang-tools-extra/clang-tidy/llvmlibc/LLVMLibcTidyModule.cpp b/clang-tools-extra/clang-tidy/llvmlibc/LLVMLibcTidyModule.cpp
index 670be8b0cc64d..7f26840be7372 100644
--- a/clang-tools-extra/clang-tidy/llvmlibc/LLVMLibcTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/llvmlibc/LLVMLibcTidyModule.cpp
@@ -11,6 +11,7 @@
#include "../ClangTidyModuleRegistry.h"
#include "CalleeNamespaceCheck.h"
#include "ImplementationInNamespaceCheck.h"
+#include "InlineFunctionDeclCheck.h"
#include "RestrictSystemLibcHeadersCheck.h"
namespace clang::tidy {
@@ -23,6 +24,8 @@ class LLVMLibcModule : public ClangTidyModule {
"llvmlibc-callee-namespace");
CheckFactories.registerCheck<ImplementationInNamespaceCheck>(
"llvmlibc-implementation-in-namespace");
+ CheckFactories.registerCheck<InlineFunctionDeclCheck>(
+ "llvmlibc-inline-function-decl");
CheckFactories.registerCheck<RestrictSystemLibcHeadersCheck>(
"llvmlibc-restrict-system-libc-headers");
}
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 8c8868f2f7b57..48e7da0741f3e 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -110,6 +110,12 @@ New checks
Warns when lambda specify a capture default and capture ``this``.
+- New :doc: `llvmlibc-inline-function-decl
+ <clang-tidy/checks/llvmlibc/inline-function-decl>` check.
+
+ Checks that all implicit and explicit inline functions in header files are
+ tagged with the ``LIBC_INLINE`` macro.
+
New check aliases
^^^^^^^^^^^^^^^^^
diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst
index b23fdc1dee56b..5a2f9c877a961 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -244,6 +244,7 @@ Clang-Tidy Checks
`llvm-twine-local <llvm/twine-local.html>`_, "Yes"
`llvmlibc-callee-namespace <llvmlibc/callee-namespace.html>`_,
`llvmlibc-implementation-in-namespace <llvmlibc/implementation-in-namespace.html>`_,
+ `llvmlibc-inline-function-decl <llvmlibc/inline-function-decl.html>`_,
`llvmlibc-restrict-system-libc-headers <llvmlibc/restrict-system-libc-headers.html>`_, "Yes"
`misc-confusable-identifiers <misc/confusable-identifiers.html>`_,
`misc-const-correctness <misc/const-correctness.html>`_, "Yes"
diff --git a/clang-tools-extra/docs/clang-tidy/checks/llvmlibc/inline-function-decl.rst b/clang-tools-extra/docs/clang-tidy/checks/llvmlibc/inline-function-decl.rst
new file mode 100644
index 0000000000000..d3b658eddce71
--- /dev/null
+++ b/clang-tools-extra/docs/clang-tidy/checks/llvmlibc/inline-function-decl.rst
@@ -0,0 +1,19 @@
+.. title:: clang-tidy - llvmlibc-inline-function-decl
+
+llvmlibc-inline-function-decl
+=============================
+
+Checks that all implicit and explicit inline functions in header files are
+tagged with the ``LIBC_INLINE`` macro. See the `libc style guide
+<https://libc.llvm.org/code_style.html>`_ for more information about this macro.
+
+Options
+-------
+
+.. option:: HeaderFileExtensions
+
+ A comma-separated list of filename extensions of header files (the filename
+ extensions should not include "." prefix). Default is "h,hh,hpp,hxx".
+ For header files without an extension, use an empty string (if there are no
+ other desired extensions) or leave an empty element in the list. E.g.,
+ "h,hh,hpp,hxx," (note the trailing comma).
diff --git a/clang-tools-extra/test/clang-tidy/checkers/llvmlibc/inline-function-decl.hpp b/clang-tools-extra/test/clang-tidy/checkers/llvmlibc/inline-function-decl.hpp
new file mode 100644
index 0000000000000..b59c2d20be054
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/llvmlibc/inline-function-decl.hpp
@@ -0,0 +1,65 @@
+// RUN: %check_clang_tidy %s llvmlibc-inline-function-decl %t
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_TEST_CLANG_TIDY_CHECKERS_LLVMLIBC_INLINEFUNCTIONDECL_H
+#define LLVM_CLANG_TOOLS_EXTRA_TEST_CLANG_TIDY_CHECKERS_LLVMLIBC_INLINEFUNCTIONDECL_H
+
+#define LIBC_INLINE inline
+
+namespace __llvm_libc {
+
+LIBC_INLINE int addi(int a, int b) {
+ return a + b;
+}
+
+LIBC_INLINE constexpr long addl(long a, long b) {
+ return a + b;
+}
+
+constexpr long long addll(long long a, long long b) {
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: 'addll' must be tagged with the LIBC_INLINE macro; the macro should be placed at the beginning of the declaration [llvmlibc-inline-function-decl]
+ return a + b;
+}
+
+inline unsigned long addul(unsigned long a, unsigned long b) {
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: 'addul' must be tagged with the LIBC_INLINE macro; the macro should be placed at the beginning of the declaration [llvmlibc-inline-function-decl]
+ return a + b;
+}
+
+class MyClass {
+ int A;
+public:
+ MyClass() : A(123) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'MyClass' must be tagged with the LIBC_INLINE macro; the macro should be placed at the beginning of the declaration [llvmlibc-inline-function-decl]
+
+ LIBC_INLINE MyClass(int V) : A(V) {}
+
+ constexpr operator int() const { return A; }
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'operator int' must be tagged with the LIBC_INLINE macro; the macro should be placed at the beginning of the declaration [llvmlibc-inline-function-decl]
+
+ LIBC_INLINE bool operator==(const MyClass &RHS) {
+ return RHS.A == A;
+ }
+
+ static int getVal(const MyClass &V) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'getVal' must be tagged with the LIBC_INLINE macro; the macro should be placed at the beginning of the declaration [llvmlibc-inline-function-decl]
+ return V.A;
+ }
+
+ LIBC_INLINE static void setVal(MyClass &V, int A) {
+ V.A = A;
+ }
+
+ constexpr static int addInt(MyClass &V, int A) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'addInt' must be tagged with the LIBC_INLINE macro; the macro should be placed at the beginning of the declaration [llvmlibc-inline-function-decl]
+ return V.A += A;
+ }
+
+ static LIBC_INLINE int mulInt(MyClass &V, int A) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'mulInt' must be tagged with the LIBC_INLINE macro; the macro should be placed at the beginning of the declaration [llvmlibc-inline-function-decl]
+ return V.A *= A;
+ }
+};
+
+} // namespace __llvm_libc
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_TEST_CLANG_TIDY_CHECKERS_LLVMLIBC_INLINEFUNCTIONDECL_H
More information about the cfe-commits
mailing list