diff --git a/clang-tools-extra/clang-tidy/llvmlibc/CalleeNamespaceCheck.cpp b/clang-tools-extra/clang-tidy/llvmlibc/CalleeNamespaceCheck.cpp index 98ae857b589fd..af977bff70f7c 100644 --- a/clang-tools-extra/clang-tidy/llvmlibc/CalleeNamespaceCheck.cpp +++ b/clang-tools-extra/clang-tidy/llvmlibc/CalleeNamespaceCheck.cpp @@ -7,9 +7,11 @@ //===----------------------------------------------------------------------===// #include "CalleeNamespaceCheck.h" +#include "NamespaceConstants.h" #include "clang/AST/ASTContext.h" #include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/ASTMatchers/ASTMatchers.h" #include "llvm/ADT/StringSet.h" using namespace clang::ast_matchers; @@ -45,9 +47,11 @@ void CalleeNamespaceCheck::check(const MatchFinder::MatchResult &Result) { if (FuncDecl->getBuiltinID() != 0) return; - // If the outermost namespace of the function is __llvm_libc, we're good. + // If the outermost namespace of the function is a macro that starts with + // __llvm_libc, we're good. const auto *NS = dyn_cast(getOutermostNamespace(FuncDecl)); - if (NS && NS->getName() == "__llvm_libc") + if (NS && Result.SourceManager->isMacroBodyExpansion(NS->getLocation()) && + NS->getName().starts_with(RequiredNamespaceStart)) return; const DeclarationName &Name = FuncDecl->getDeclName(); @@ -55,9 +59,10 @@ void CalleeNamespaceCheck::check(const MatchFinder::MatchResult &Result) { IgnoredFunctions.contains(Name.getAsIdentifierInfo()->getName())) return; - diag(UsageSiteExpr->getBeginLoc(), "%0 must resolve to a function declared " - "within the '__llvm_libc' namespace") - << FuncDecl; + diag(UsageSiteExpr->getBeginLoc(), + "%0 must resolve to a function declared " + "within the namespace defined by the '%1' macro") + << FuncDecl << RequiredNamespaceMacroName; diag(FuncDecl->getLocation(), "resolves to this declaration", clang::DiagnosticIDs::Note); diff --git a/clang-tools-extra/clang-tidy/llvmlibc/ImplementationInNamespaceCheck.cpp b/clang-tools-extra/clang-tidy/llvmlibc/ImplementationInNamespaceCheck.cpp index bbc60217cdb1d..ae9819ed97502 100644 --- a/clang-tools-extra/clang-tidy/llvmlibc/ImplementationInNamespaceCheck.cpp +++ b/clang-tools-extra/clang-tidy/llvmlibc/ImplementationInNamespaceCheck.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "ImplementationInNamespaceCheck.h" +#include "NamespaceConstants.h" #include "clang/AST/ASTContext.h" #include "clang/ASTMatchers/ASTMatchFinder.h" @@ -14,9 +15,6 @@ using namespace clang::ast_matchers; namespace clang::tidy::llvm_libc { -const static StringRef RequiredNamespaceStart = "__llvm_libc"; -const static StringRef RequiredNamespaceMacroName = "LIBC_NAMESPACE"; - void ImplementationInNamespaceCheck::registerMatchers(MatchFinder *Finder) { Finder->addMatcher( translationUnitDecl( diff --git a/clang-tools-extra/clang-tidy/llvmlibc/NamespaceConstants.h b/clang-tools-extra/clang-tidy/llvmlibc/NamespaceConstants.h new file mode 100644 index 0000000000000..31fcdaa7b273b --- /dev/null +++ b/clang-tools-extra/clang-tidy/llvmlibc/NamespaceConstants.h @@ -0,0 +1,16 @@ +//===--- NamespaceConstants.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 +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/StringRef.h" + +namespace clang::tidy::llvm_libc { + +const static StringRef RequiredNamespaceStart = "__llvm_libc"; +const static StringRef RequiredNamespaceMacroName = "LIBC_NAMESPACE"; + +} // namespace clang::tidy::llvm_libc diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 8fc28c0903418..14f9e19c50102 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -241,6 +241,11 @@ Changes in existing checks ` check to provide fixes for ``inline`` namespaces in the same format as :program:`clang-format`. +- Improved :doc:`llvmlibc-callee-namespace + ` to support + customizable namespace. This matches the change made to implementation in + namespace. + - Improved :doc:`llvmlibc-implementation-in-namespace ` to support customizable namespace. This further allows for testing the libc when the @@ -321,6 +326,7 @@ Changes in existing checks ` check to identify calls to static member functions with out-of-class inline definitions. + Removed checks ^^^^^^^^^^^^^^ diff --git a/clang-tools-extra/docs/clang-tidy/checks/llvmlibc/callee-namespace.rst b/clang-tools-extra/docs/clang-tidy/checks/llvmlibc/callee-namespace.rst index c072dd069e747..ba742b5e1cab5 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/llvmlibc/callee-namespace.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/llvmlibc/callee-namespace.rst @@ -3,14 +3,18 @@ llvmlibc-callee-namespace ==================================== -Checks all calls resolve to functions within ``__llvm_libc`` namespace. +Checks all calls resolve to functions within correct namespace. .. code-block:: c++ - namespace __llvm_libc { + // Implementation inside the LIBC_NAMESPACE namespace. + // Correct if: + // - LIBC_NAMESPACE is a macro + // - LIBC_NAMESPACE expansion starts with `__llvm_libc` + namespace LIBC_NAMESPACE { // Allow calls with the fully qualified name. - __llvm_libc::strlen("hello"); + LIBC_NAMESPACE::strlen("hello"); // Allow calls to compiler provided functions. (void)__builtin_abs(-1); @@ -21,4 +25,4 @@ Checks all calls resolve to functions within ``__llvm_libc`` namespace. // Disallow calling into functions in the global namespace. ::strlen("!"); - } // namespace __llvm_libc + } // namespace LIBC_NAMESPACE diff --git a/clang-tools-extra/test/clang-tidy/checkers/llvmlibc/callee-namespace.cpp b/clang-tools-extra/test/clang-tidy/checkers/llvmlibc/callee-namespace.cpp index f18ab2b89e786..c867b92d5881c 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/llvmlibc/callee-namespace.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/llvmlibc/callee-namespace.cpp @@ -1,6 +1,16 @@ // RUN: %check_clang_tidy %s llvmlibc-callee-namespace %t +#define OTHER_MACRO_NAMESPACE custom_namespace +namespace OTHER_MACRO_NAMESPACE { + void wrong_name_macro_func() {} +} + namespace __llvm_libc { + void right_name_no_macro_func() {} +} + +#define LIBC_NAMESPACE __llvm_libc_xyz +namespace LIBC_NAMESPACE { namespace nested { void nested_func() {} } // namespace nested @@ -22,12 +32,12 @@ struct global_struct { int operator()() const { return 0; } }; -namespace __llvm_libc { +namespace LIBC_NAMESPACE { void Test() { // Allow calls with the fully qualified name. - __llvm_libc::libc_api_func(); - __llvm_libc::nested::nested_func(); - void (*qualifiedPtr)(void) = __llvm_libc::libc_api_func; + LIBC_NAMESPACE::libc_api_func(); + LIBC_NAMESPACE::nested::nested_func(); + void (*qualifiedPtr)(void) = LIBC_NAMESPACE::libc_api_func; qualifiedPtr(); // Should not trigger on compiler provided function calls. @@ -36,22 +46,22 @@ void Test() { // Bare calls are allowed as long as they resolve to the correct namespace. libc_api_func(); nested::nested_func(); - void (*barePtr)(void) = __llvm_libc::libc_api_func; + void (*barePtr)(void) = LIBC_NAMESPACE::libc_api_func; barePtr(); // Allow calling entities defined in the namespace. - __llvm_libc::libc_api_struct{}(); + LIBC_NAMESPACE::libc_api_struct{}(); // Disallow calling into global namespace for implemented entrypoints. ::libc_api_func(); - // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'libc_api_func' must resolve to a function declared within the '__llvm_libc' namespace - // CHECK-MESSAGES: :15:6: note: resolves to this declaration + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'libc_api_func' must resolve to a function declared within the namespace defined by the 'LIBC_NAMESPACE' macro + // CHECK-MESSAGES: :25:6: note: resolves to this declaration // Disallow indirect references to functions in global namespace. void (*badPtr)(void) = ::libc_api_func; badPtr(); - // CHECK-MESSAGES: :[[@LINE-2]]:26: warning: 'libc_api_func' must resolve to a function declared within the '__llvm_libc' namespace - // CHECK-MESSAGES: :15:6: note: resolves to this declaration + // CHECK-MESSAGES: :[[@LINE-2]]:26: warning: 'libc_api_func' must resolve to a function declared within the namespace defined by the 'LIBC_NAMESPACE' macro + // CHECK-MESSAGES: :25:6: note: resolves to this declaration // Allow calling into global namespace for specific functions. ::malloc(); @@ -59,8 +69,18 @@ void Test() { // Disallow calling on entities that are not in the namespace, but make sure // no crashes happen. global_struct{}(); - // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: 'operator()' must resolve to a function declared within the '__llvm_libc' namespace - // CHECK-MESSAGES: :22:7: note: resolves to this declaration + // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: 'operator()' must resolve to a function declared within the namespace defined by the 'LIBC_NAMESPACE' macro + // CHECK-MESSAGES: :32:7: note: resolves to this declaration + + OTHER_MACRO_NAMESPACE::wrong_name_macro_func(); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'wrong_name_macro_func' must resolve to a function declared within the namespace defined by the 'LIBC_NAMESPACE' macro + // CHECK-MESSAGES: :3:31: note: expanded from macro 'OTHER_MACRO_NAMESPACE' + // CHECK-MESSAGES: :5:8: note: resolves to this declaration + + __llvm_libc::right_name_no_macro_func(); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'right_name_no_macro_func' must resolve to a function declared within the namespace defined by the 'LIBC_NAMESPACE' macro + // CHECK-MESSAGES: :9:8: note: resolves to this declaration + } } // namespace __llvm_libc