[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