[clang-tools-extra] 774116b - [clang-tidy] Update llvmlibc-implementation-in-namespace to new rules (#66504)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Sep 21 08:05:51 PDT 2023
Author: Guillaume Chatelet
Date: 2023-09-21T17:05:47+02:00
New Revision: 774116b8f669a5a1fc12aaef6ebb408a5f064172
URL: https://github.com/llvm/llvm-project/commit/774116b8f669a5a1fc12aaef6ebb408a5f064172
DIFF: https://github.com/llvm/llvm-project/commit/774116b8f669a5a1fc12aaef6ebb408a5f064172.diff
LOG: [clang-tidy] Update llvmlibc-implementation-in-namespace to new rules (#66504)
This is the implementation of step 3 of
https://discourse.llvm.org/t/rfc-customizable-namespace-to-allow-testing-the-libc-when-the-system-libc-is-also-llvms-libc/73079.
Added:
Modified:
clang-tools-extra/clang-tidy/llvmlibc/ImplementationInNamespaceCheck.cpp
clang-tools-extra/docs/ReleaseNotes.rst
clang-tools-extra/docs/clang-tidy/checks/llvmlibc/implementation-in-namespace.rst
clang-tools-extra/test/clang-tidy/checkers/llvmlibc/implementation-in-namespace.cpp
Removed:
################################################################################
diff --git a/clang-tools-extra/clang-tidy/llvmlibc/ImplementationInNamespaceCheck.cpp b/clang-tools-extra/clang-tidy/llvmlibc/ImplementationInNamespaceCheck.cpp
index d05310f09ef773a..4489179c4423419 100644
--- a/clang-tools-extra/clang-tidy/llvmlibc/ImplementationInNamespaceCheck.cpp
+++ b/clang-tools-extra/clang-tidy/llvmlibc/ImplementationInNamespaceCheck.cpp
@@ -14,11 +14,16 @@ using namespace clang::ast_matchers;
namespace clang::tidy::llvm_libc {
-const static StringRef RequiredNamespace = "__llvm_libc";
+const static StringRef RequiredNamespaceStart = "__llvm_libc";
+const static StringRef RequiredNamespaceMacroName = "LIBC_NAMESPACE";
+
void ImplementationInNamespaceCheck::registerMatchers(MatchFinder *Finder) {
Finder->addMatcher(
- decl(hasParent(translationUnitDecl()), unless(linkageSpecDecl()))
- .bind("child_of_translation_unit"),
+ translationUnitDecl(
+ forEach(decl(isExpansionInMainFile(), unless(linkageSpecDecl()),
+ // anonymous namespaces generate usingDirective
+ unless(usingDirectiveDecl(isImplicit())))
+ .bind("child_of_translation_unit"))),
this);
}
@@ -26,19 +31,24 @@ void ImplementationInNamespaceCheck::check(
const MatchFinder::MatchResult &Result) {
const auto *MatchedDecl =
Result.Nodes.getNodeAs<Decl>("child_of_translation_unit");
- if (!Result.SourceManager->isInMainFile(MatchedDecl->getLocation()))
+ MatchedDecl->dump();
+ const auto *NS = dyn_cast<NamespaceDecl>(MatchedDecl);
+ if (NS == nullptr || NS->isAnonymousNamespace()) {
+ diag(MatchedDecl->getLocation(),
+ "declaration must be enclosed within the '%0' namespace")
+ << RequiredNamespaceMacroName;
return;
-
- if (const auto *NS = dyn_cast<NamespaceDecl>(MatchedDecl)) {
- if (NS->getName() != RequiredNamespace) {
- diag(NS->getLocation(), "'%0' needs to be the outermost namespace")
- << RequiredNamespace;
- }
+ }
+ if (Result.SourceManager->isMacroBodyExpansion(NS->getLocation()) == false) {
+ diag(NS->getLocation(), "the outermost namespace should be the '%0' macro")
+ << RequiredNamespaceMacroName;
+ return;
+ }
+ if (NS->getName().starts_with(RequiredNamespaceStart) == false) {
+ diag(NS->getLocation(), "the '%0' macro should start with '%1'")
+ << RequiredNamespaceMacroName << RequiredNamespaceStart;
return;
}
- diag(MatchedDecl->getLocation(),
- "declaration must be declared within the '%0' namespace")
- << RequiredNamespace;
}
} // namespace clang::tidy::llvm_libc
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index b4660db333f3c14..466c9b08c578890 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -241,6 +241,11 @@ Changes in existing checks
<clang-tidy/checks/llvm/namespace-comment>` check to provide fixes for
``inline`` namespaces in the same format as :program:`clang-format`.
+- Improved :doc:`llvmlibc-implementation-in-namespace
+ <clang-tidy/checks/llvmlibc/implementation-in-namespace>` to support
+ customizable namespace. This further allows for testing the libc when the
+ system-libc is also LLVM's libc.
+
- Improved :doc:`misc-include-cleaner
<clang-tidy/checks/misc/include-cleaner>` check by adding option
`DeduplicateFindings` to output one finding per symbol occurrence.
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
index 33d6dc8ff125c84..47ea2b866a93404 100644
--- 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
@@ -8,21 +8,30 @@ correct namespace.
.. code-block:: c++
- // Correct: implementation inside the correct namespace.
- 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 {
void LLVM_LIBC_ENTRYPOINT(strcpy)(char *dest, const char *src) {}
- // Namespaces within __llvm_libc namespace are allowed.
- namespace inner{
+ // Namespaces within LIBC_NAMESPACE namespace are allowed.
+ namespace inner {
int localVar = 0;
}
// Functions with C linkage are allowed.
- extern "C" void str_fuzz(){}
+ extern "C" void str_fuzz() {}
}
- // Incorrect: implementation not in a namespace.
+ // Incorrect: implementation not in the LIBC_NAMESPACE namespace.
void LLVM_LIBC_ENTRYPOINT(strcpy)(char *dest, const char *src) {}
- // Incorrect: outer most namespace is not correct.
+ // Incorrect: outer most namespace is not the LIBC_NAMESPACE macro.
namespace something_else {
void LLVM_LIBC_ENTRYPOINT(strcpy)(char *dest, const char *src) {}
}
+
+ // Incorrect: outer most namespace expansion does not start with `__llvm_libc`.
+ #define LIBC_NAMESPACE custom_namespace
+ namespace LIBC_NAMESPACE {
+ 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
index e75556a623b655c..2246a430dd1f573 100644
--- 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
@@ -3,19 +3,30 @@
#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
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: declaration must be enclosed within the 'LIBC_NAMESPACE' namespace
struct StructC {};
-// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: declaration must be declared within the '__llvm_libc' namespace
+// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: declaration must be enclosed within the 'LIBC_NAMESPACE' namespace
char *VarD = MACRO_A;
-// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: declaration must be declared within the '__llvm_libc' namespace
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: declaration must be enclosed within the 'LIBC_NAMESPACE' namespace
typedef int typeE;
-// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: declaration must be declared within the '__llvm_libc' namespace
+// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: declaration must be enclosed within the 'LIBC_NAMESPACE' namespace
void funcF() {}
-// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: declaration must be declared within the '__llvm_libc' namespace
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: declaration must be enclosed within the 'LIBC_NAMESPACE' namespace
+
+namespace outer_most {
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: the outermost namespace should be the 'LIBC_NAMESPACE' macro
+ class A {};
+}
+
+// Wrapped in anonymous namespace.
+namespace {
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: declaration must be enclosed within the 'LIBC_NAMESPACE' namespace
+ class A {};
+}
namespace namespaceG {
-// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: '__llvm_libc' needs to be the outermost namespace
-namespace __llvm_libc{
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: the outermost namespace should be the 'LIBC_NAMESPACE' macro
+namespace __llvm_libc {
namespace namespaceH {
class ClassB;
} // namespace namespaceH
@@ -26,9 +37,20 @@ typedef int typeE;
void funcF() {}
} // namespace namespaceG
-// Wrapped in correct namespace.
-namespace __llvm_libc {
-// Namespaces within __llvim_libc namespace allowed.
+// Wrapped in macro namespace but with an incorrect name
+#define LIBC_NAMESPACE custom_namespace
+namespace LIBC_NAMESPACE {
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: the 'LIBC_NAMESPACE' macro should start with '__llvm_libc'
+namespace namespaceH {
+class ClassB;
+} // namespace namespaceH
+} // namespace LIBC_NAMESPACE
+
+
+// Wrapped in macro namespace with a valid name, LIBC_NAMESPACE starts with '__llvm_libc'
+#undef LIBC_NAMESPACE
+#define LIBC_NAMESPACE __llvm_libc_xyz
+namespace LIBC_NAMESPACE {
namespace namespaceI {
class ClassB;
} // namespace namespaceI
@@ -37,4 +59,4 @@ char *VarD = MACRO_A;
typedef int typeE;
void funcF() {}
extern "C" void extern_funcJ() {}
-} // namespace __llvm_libc
+} // namespace LIBC_NAMESPACE
More information about the cfe-commits
mailing list