Author: Paula Toth Date: 2020-04-06T10:49:49-07:00 New Revision: 00a57558978d3e4f11d08bed486497a8674000e3
URL: https://github.com/llvm/llvm-project/commit/00a57558978d3e4f11d08bed486497a8674000e3 DIFF: https://github.com/llvm/llvm-project/commit/00a57558978d3e4f11d08bed486497a8674000e3.diff LOG: [clang-tidy] Add check llvmlibc-implementation-in-namespace. Summary: This check makes sure all llvm-libc implementations falls within the `__llvm_libc` namespace. Reviewers: alexfh, aaron.ballman, hokein, njames93 Reviewed By: aaron.ballman Subscribers: Eugene.Zelenko, libc-commits, mgorny, xazax.hun, MaskRay, cfe-commits, sivachandra Tags: #clang-tools-extra, #clang Differential Revision: https://reviews.llvm.org/D76818 Added: clang-tools-extra/clang-tidy/llvmlibc/ImplementationInNamespaceCheck.cpp clang-tools-extra/clang-tidy/llvmlibc/ImplementationInNamespaceCheck.h clang-tools-extra/docs/clang-tidy/checks/llvmlibc-implementation-in-namespace.rst clang-tools-extra/test/clang-tidy/checkers/llvmlibc-implementation-in-namespace.cpp 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 cc213d35a572..15e80a734ad1 100644 --- a/clang-tools-extra/clang-tidy/llvmlibc/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/llvmlibc/CMakeLists.txt @@ -1,6 +1,7 @@ set(LLVM_LINK_COMPONENTS support) add_clang_library(clangTidyLLVMLibcModule + ImplementationInNamespaceCheck.cpp LLVMLibcTidyModule.cpp RestrictSystemLibcHeadersCheck.cpp diff --git a/clang-tools-extra/clang-tidy/llvmlibc/ImplementationInNamespaceCheck.cpp b/clang-tools-extra/clang-tidy/llvmlibc/ImplementationInNamespaceCheck.cpp new file mode 100644 index 000000000000..42b697076b35 --- /dev/null +++ b/clang-tools-extra/clang-tidy/llvmlibc/ImplementationInNamespaceCheck.cpp @@ -0,0 +1,49 @@ +//===--- ImplementationInNamespaceCheck.cpp - clang-tidy ------------------===// +// +// 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 "ImplementationInNamespaceCheck.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" + +using namespace clang::ast_matchers; + +namespace clang { +namespace tidy { +namespace llvm_libc { + +const static StringRef RequiredNamespace = "__llvm_libc"; +void ImplementationInNamespaceCheck::registerMatchers(MatchFinder *Finder) { + Finder->addMatcher( + decl(hasParent(translationUnitDecl()), unless(linkageSpecDecl())) + .bind("child_of_translation_unit"), + this); +} + +void ImplementationInNamespaceCheck::check( + const MatchFinder::MatchResult &Result) { + const auto *MatchedDecl = + Result.Nodes.getNodeAs<Decl>("child_of_translation_unit"); + if (!Result.SourceManager->isInMainFile(MatchedDecl->getLocation())) + return; + + if (const auto *NS = dyn_cast<NamespaceDecl>(MatchedDecl)) { + if (NS->getName() != RequiredNamespace) { + diag(NS->getLocation(), "'%0' needs to be the outermost namespace") + << RequiredNamespace; + } + return; + } + diag(MatchedDecl->getLocation(), + "declaration must be declared within the '%0' namespace") + << RequiredNamespace; + return; +} + +} // namespace llvm_libc +} // namespace tidy +} // namespace clang diff --git a/clang-tools-extra/clang-tidy/llvmlibc/ImplementationInNamespaceCheck.h b/clang-tools-extra/clang-tidy/llvmlibc/ImplementationInNamespaceCheck.h new file mode 100644 index 000000000000..dcd29b381a41 --- /dev/null +++ b/clang-tools-extra/clang-tidy/llvmlibc/ImplementationInNamespaceCheck.h @@ -0,0 +1,38 @@ +//===--- ImplementationInNamespaceCheck.h - clang-tidy ----------*- 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_IMPLEMENTATIONINNAMESPACECHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVMLIBC_IMPLEMENTATIONINNAMESPACECHECK_H + +#include "../ClangTidyCheck.h" + +namespace clang { +namespace tidy { +namespace llvm_libc { + +/// Checks all llvm-libc implementation is within the correct namespace. +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/llvmlibc-implementation-in-namespace.html +class ImplementationInNamespaceCheck : public ClangTidyCheck { +public: + ImplementationInNamespaceCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} + + bool isLanguageVersionSupported(const LangOptions &LangOpts) const override { + return LangOpts.CPlusPlus; + } + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; +}; + +} // namespace llvm_libc +} // namespace tidy +} // namespace clang + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVMLIBC_IMPLEMENTATIONINNAMESPACECHECK_H diff --git a/clang-tools-extra/clang-tidy/llvmlibc/LLVMLibcTidyModule.cpp b/clang-tools-extra/clang-tidy/llvmlibc/LLVMLibcTidyModule.cpp index 9874cae17d34..8c5a7ac20161 100644 --- a/clang-tools-extra/clang-tidy/llvmlibc/LLVMLibcTidyModule.cpp +++ b/clang-tools-extra/clang-tidy/llvmlibc/LLVMLibcTidyModule.cpp @@ -9,6 +9,7 @@ #include "../ClangTidy.h" #include "../ClangTidyModule.h" #include "../ClangTidyModuleRegistry.h" +#include "ImplementationInNamespaceCheck.h" #include "RestrictSystemLibcHeadersCheck.h" namespace clang { @@ -18,6 +19,8 @@ namespace llvm_libc { class LLVMLibcModule : public ClangTidyModule { public: void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override { + CheckFactories.registerCheck<ImplementationInNamespaceCheck>( + "llvmlibc-implementation-in-namespace"); 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 745a1d1035ed..d6802838b9d1 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -113,6 +113,11 @@ New checks Flags use of the `C` standard library functions ``memset``, ``memcpy`` and ``memcmp`` and similar derivatives on non-trivial types. +- New :doc:`llvmlibc-implementation-in-namespace + <clang-tidy/checks/llvmlibc-implementation-in-namespace>` check. + + Checks all llvm-libc implementation is within the correct namespace. + - New :doc:`llvmlibc-restrict-system-libc-headers <clang-tidy/checks/llvmlibc-restrict-system-libc-headers>` check. diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst index 333a7ea4d5b4..28a98e828ca0 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/list.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst @@ -188,6 +188,7 @@ Clang-Tidy Checks `llvm-prefer-isa-or-dyn-cast-in-conditionals <llvm-prefer-isa-or-dyn-cast-in-conditionals.html>`_, "Yes" `llvm-prefer-register-over-unsigned <llvm-prefer-register-over-unsigned.html>`_, "Yes" `llvm-twine-local <llvm-twine-local.html>`_, "Yes" + `llvmlibc-implementation-in-namespace <llvmlibc-implementation-in-namespace.html>`_, `llvmlibc-restrict-system-libc-headers <llvmlibc-restrict-system-libc-headers.html>`_, "Yes" `misc-definitions-in-headers <misc-definitions-in-headers.html>`_, "Yes" `misc-misplaced-const <misc-misplaced-const.html>`_, diff --git a/clang-tools-extra/docs/clang-tidy/checks/llvmlibc-implementation-in-namespace.rst b/clang-tools-extra/docs/clang-tidy/checks/llvmlibc-implementation-in-namespace.rst new file mode 100644 index 000000000000..33d6dc8ff125 --- /dev/null +++ b/clang-tools-extra/docs/clang-tidy/checks/llvmlibc-implementation-in-namespace.rst @@ -0,0 +1,28 @@ +.. title:: clang-tidy - llvmlibc-implementation-in-namespace + +llvmlibc-implementation-in-namespace +==================================== + +Checks that all declarations in the llvm-libc implementation are within the +correct namespace. + +.. code-block:: c++ + + // Correct: implementation inside the correct namespace. + namespace __llvm_libc { + void LLVM_LIBC_ENTRYPOINT(strcpy)(char *dest, const char *src) {} + // Namespaces within __llvm_libc namespace are allowed. + namespace inner{ + int localVar = 0; + } + // Functions with C linkage are allowed. + extern "C" void str_fuzz(){} + } + + // Incorrect: implementation not in a namespace. + void LLVM_LIBC_ENTRYPOINT(strcpy)(char *dest, const char *src) {} + + // Incorrect: outer most namespace is not correct. + namespace something_else { + void LLVM_LIBC_ENTRYPOINT(strcpy)(char *dest, const char *src) {} + } diff --git a/clang-tools-extra/test/clang-tidy/checkers/llvmlibc-implementation-in-namespace.cpp b/clang-tools-extra/test/clang-tidy/checkers/llvmlibc-implementation-in-namespace.cpp new file mode 100644 index 000000000000..e75556a623b6 --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/llvmlibc-implementation-in-namespace.cpp @@ -0,0 +1,40 @@ +// RUN: %check_clang_tidy %s llvmlibc-implementation-in-namespace %t + +#define MACRO_A "defining macros outside namespace is valid" + +class ClassB; +// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: declaration must be declared within the '__llvm_libc' namespace +struct StructC {}; +// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: declaration must be declared within the '__llvm_libc' namespace +char *VarD = MACRO_A; +// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: declaration must be declared within the '__llvm_libc' namespace +typedef int typeE; +// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: declaration must be declared within the '__llvm_libc' namespace +void funcF() {} +// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: declaration must be declared within the '__llvm_libc' namespace + +namespace namespaceG { +// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: '__llvm_libc' needs to be the outermost namespace +namespace __llvm_libc{ +namespace namespaceH { +class ClassB; +} // namespace namespaceH +struct StructC {}; +} // namespace __llvm_libc +char *VarD = MACRO_A; +typedef int typeE; +void funcF() {} +} // namespace namespaceG + +// Wrapped in correct namespace. +namespace __llvm_libc { +// Namespaces within __llvim_libc namespace allowed. +namespace namespaceI { +class ClassB; +} // namespace namespaceI +struct StructC {}; +char *VarD = MACRO_A; +typedef int typeE; +void funcF() {} +extern "C" void extern_funcJ() {} +} // namespace __llvm_libc _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits