From 125ccd3751472a0c709498f83671577ffed394a6 Mon Sep 17 00:00:00 2001 From: Carlos Galvez Date: Mon, 19 Dec 2022 18:34:35 +0000 Subject: [PATCH] [ASTMatchers] Add isInAnonymousNamespace narrowing matcher Used in a couple clang-tidy checks so it could be extracted out as its own matcher. Differential Revision: https://reviews.llvm.org/D140328 --- clang/docs/LibASTMatchersReference.html | 19 ++++++++++ clang/docs/ReleaseNotes.rst | 1 + clang/include/clang/ASTMatchers/ASTMatchers.h | 24 +++++++++++++ .../ASTMatchers/ASTMatchersNarrowingTest.cpp | 35 +++++++++++++++++++ 4 files changed, 79 insertions(+) diff --git a/clang/docs/LibASTMatchersReference.html b/clang/docs/LibASTMatchersReference.html index 61844ffc9de906..f9cb9f2e942bbd 100644 --- a/clang/docs/LibASTMatchersReference.html +++ b/clang/docs/LibASTMatchersReference.html @@ -3962,6 +3962,25 @@

Narrowing Matchers

cxxRecordDecl(hasName("vector"), isInStdNamespace()) will match only #1. +Matcher<Decl>isInAnonymousNamespace +
Matches declarations in an anonymous namespace.
+
+Given
+  class vector {};
+  namespace foo {
+    class vector {};
+    namespace {
+      class vector {}; // #1
+    }
+  }
+  namespace {
+    class vector {}; // #2
+    namespace foo {
+      class vector{}; // #3
+    }
+  }
+cxxRecordDecl(hasName("vector"), isInAnonymousNamespace()) will match #1, #2 and #3.
+
Matcher<Decl>isInstantiated
Matches declarations that are template instantiations or are inside
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 8c288a98eec991..48ffafafb1bb72 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -859,6 +859,7 @@ Build System Changes
 
 AST Matchers
 ------------
+- Add ``isInAnoymousNamespace`` matcher to match declarations in an anonymous namespace.
 
 clang-format
 ------------
diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h
index dfea432c16adba..5d3d458b6409f4 100644
--- a/clang/include/clang/ASTMatchers/ASTMatchers.h
+++ b/clang/include/clang/ASTMatchers/ASTMatchers.h
@@ -7813,6 +7813,30 @@ AST_MATCHER(NamespaceDecl, isAnonymous) {
 /// cxxRecordDecl(hasName("vector"), isInStdNamespace()) will match only #1.
 AST_MATCHER(Decl, isInStdNamespace) { return Node.isInStdNamespace(); }
 
+/// Matches declarations in an anonymous namespace.
+///
+/// Given
+/// \code
+///   class vector {};
+///   namespace foo {
+///     class vector {};
+///     namespace {
+///       class vector {}; // #1
+///     }
+///   }
+///   namespace {
+///     class vector {}; // #2
+///     namespace foo {
+///       class vector{}; // #3
+///     }
+///   }
+/// \endcode
+/// cxxRecordDecl(hasName("vector"), isInAnonymousNamespace()) will match
+/// #1, #2 and #3.
+AST_MATCHER(Decl, isInAnonymousNamespace) {
+  return Node.isInAnonymousNamespace();
+}
+
 /// If the given case statement does not use the GNU case range
 /// extension, matches the constant given in the statement.
 ///
diff --git a/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
index 752a736ae800e2..2c8b67f2644fd7 100644
--- a/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
+++ b/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
@@ -3550,6 +3550,41 @@ TEST_P(ASTMatchersTest, InStdNamespace) {
                       cxxRecordDecl(hasName("vector"), isInStdNamespace())));
 }
 
+TEST_P(ASTMatchersTest, InAnonymousNamespace) {
+  if (!GetParam().isCXX()) {
+    return;
+  }
+
+  EXPECT_TRUE(
+      notMatches("class vector {};"
+                 "namespace foo {"
+                 "  class vector {};"
+                 "}",
+                 cxxRecordDecl(hasName("vector"), isInAnonymousNamespace())));
+
+  EXPECT_TRUE(
+      matches("namespace {"
+              "  class vector {};"
+              "}",
+              cxxRecordDecl(hasName("vector"), isInAnonymousNamespace())));
+
+  EXPECT_TRUE(
+      matches("namespace foo {"
+              "  namespace {"
+              "    class vector {};"
+              "  }"
+              "}",
+              cxxRecordDecl(hasName("vector"), isInAnonymousNamespace())));
+
+  EXPECT_TRUE(
+      matches("namespace {"
+              "  namespace foo {"
+              "    class vector {};"
+              "  }"
+              "}",
+              cxxRecordDecl(hasName("vector"), isInAnonymousNamespace())));
+}
+
 TEST_P(ASTMatchersTest, InStdNamespace_CXX11) {
   if (!GetParam().isCXX11OrLater()) {
     return;