From 48045c89617e0ed953b3bbd14224258a4ab87088 Mon Sep 17 00:00:00 2001 From: Davide Cunial Date: Wed, 29 Oct 2025 18:56:29 +0100 Subject: [PATCH 1/4] [clang] Make 'fileScopeAsmDecl' matcher public --- .../clang-tidy/hicpp/NoAssemblerCheck.cpp | 9 +-------- clang/docs/LibASTMatchersReference.html | 9 +++++++++ clang/include/clang/ASTMatchers/ASTMatchers.h | 10 ++++++++++ clang/lib/ASTMatchers/ASTMatchersInternal.cpp | 2 ++ clang/lib/ASTMatchers/Dynamic/Registry.cpp | 1 + clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp | 4 ++++ 6 files changed, 27 insertions(+), 8 deletions(-) diff --git a/clang-tools-extra/clang-tidy/hicpp/NoAssemblerCheck.cpp b/clang-tools-extra/clang-tidy/hicpp/NoAssemblerCheck.cpp index a89a896b32981..e7d97b2a26b2f 100644 --- a/clang-tools-extra/clang-tidy/hicpp/NoAssemblerCheck.cpp +++ b/clang-tools-extra/clang-tidy/hicpp/NoAssemblerCheck.cpp @@ -13,17 +13,10 @@ using namespace clang::ast_matchers; namespace clang::tidy::hicpp { -namespace { -AST_MATCHER(VarDecl, isAsm) { return Node.hasAttr(); } -const ast_matchers::internal::VariadicDynCastAllOfMatcher - fileScopeAsmDecl; // NOLINT(readability-identifier-*) preserve clang style -} // namespace - void NoAssemblerCheck::registerMatchers(MatchFinder *Finder) { Finder->addMatcher(asmStmt().bind("asm-stmt"), this); Finder->addMatcher(fileScopeAsmDecl().bind("asm-file-scope"), this); - Finder->addMatcher(varDecl(isAsm()).bind("asm-var"), this); + Finder->addMatcher(varDecl(hasAttr(attr::AsmLabel)).bind("asm-var"), this); } void NoAssemblerCheck::check(const MatchFinder::MatchResult &Result) { diff --git a/clang/docs/LibASTMatchersReference.html b/clang/docs/LibASTMatchersReference.html index 5b2a96d00d592..47fe57e545e4b 100644 --- a/clang/docs/LibASTMatchersReference.html +++ b/clang/docs/LibASTMatchersReference.html @@ -825,6 +825,15 @@

Node Matchers

+Matcher<Decl>fileScopeAsmDeclMatcher<FileScopeAsmDecl>... +
Matches top level asm declarations.
+
+ __asm__("nop");
+fileScopeAsmDecl()
+  matches '__asm__("nop")'
+
+ + Matcher<Decl>friendDeclMatcher<FriendDecl>...
Matches friend declarations.
 
diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h
index 98e62de2a9bfb..92107043e122e 100644
--- a/clang/include/clang/ASTMatchers/ASTMatchers.h
+++ b/clang/include/clang/ASTMatchers/ASTMatchers.h
@@ -2478,6 +2478,16 @@ extern const internal::VariadicDynCastAllOfMatcher nullStmt;
 ///   matches '__asm("mov al, 2")'
 extern const internal::VariadicDynCastAllOfMatcher asmStmt;
 
+/// Matches top level asm declarations.
+///
+/// \code
+///  __asm__("nop");
+/// \endcode
+/// fileScopeAsmDecl()
+///   matches '__asm__("nop")'
+extern const internal::VariadicDynCastAllOfMatcher
+    fileScopeAsmDecl;
+
 /// Matches bool literals.
 ///
 /// Example matches true
diff --git a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp
index 42f124ba852ed..0874b3d0c45f5 100644
--- a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp
+++ b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp
@@ -954,6 +954,8 @@ const internal::VariadicDynCastAllOfMatcher cxxTryStmt;
 const internal::VariadicDynCastAllOfMatcher cxxThrowExpr;
 const internal::VariadicDynCastAllOfMatcher nullStmt;
 const internal::VariadicDynCastAllOfMatcher asmStmt;
+const internal::VariadicDynCastAllOfMatcher
+    fileScopeAsmDecl;
 const internal::VariadicDynCastAllOfMatcher
     cxxBoolLiteral;
 const internal::VariadicDynCastAllOfMatcher stringLiteral;
diff --git a/clang/lib/ASTMatchers/Dynamic/Registry.cpp b/clang/lib/ASTMatchers/Dynamic/Registry.cpp
index 01c03f309a77b..66848f7c42127 100644
--- a/clang/lib/ASTMatchers/Dynamic/Registry.cpp
+++ b/clang/lib/ASTMatchers/Dynamic/Registry.cpp
@@ -246,6 +246,7 @@ RegistryMaps::RegistryMaps() {
   REGISTER_MATCHER(expr);
   REGISTER_MATCHER(exprWithCleanups);
   REGISTER_MATCHER(fieldDecl);
+  REGISTER_MATCHER(fileScopeAsmDecl);
   REGISTER_MATCHER(fixedPointLiteral);
   REGISTER_MATCHER(floatLiteral);
   REGISTER_MATCHER(forCallable);
diff --git a/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
index 9692d6e6fae97..1d641924f9571 100644
--- a/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
+++ b/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
@@ -1179,6 +1179,10 @@ TEST_P(ASTMatchersTest, PredefinedExpr) {
                                      has(stringLiteral()))));
 }
 
+TEST_P(ASTMatchersTest, FileScopeAsmDecl) {
+  EXPECT_TRUE(matches("__asm__(\"nop\");", fileScopeAsmDecl()));
+}
+
 TEST_P(ASTMatchersTest, AsmStatement) {
   EXPECT_TRUE(matches("void foo() { __asm(\"mov al, 2\"); }", asmStmt()));
 }

From 72cd0ba6d97af291dcf84b70b57437531c60783c Mon Sep 17 00:00:00 2001
From: Davide Cunial 
Date: Thu, 30 Oct 2025 11:24:42 +0100
Subject: [PATCH 2/4] [clang-tidy] Update test for fileScopeAmsDecl

---
 clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
index 1d641924f9571..8542c72b69c4a 100644
--- a/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
+++ b/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
@@ -1181,6 +1181,8 @@ TEST_P(ASTMatchersTest, PredefinedExpr) {
 
 TEST_P(ASTMatchersTest, FileScopeAsmDecl) {
   EXPECT_TRUE(matches("__asm__(\"nop\");", fileScopeAsmDecl()));
+  EXPECT_TRUE(
+      notMatches("void foo() { __asm(\"mov al, 2\"); }", fileScopeAsmDecl()));
 }
 
 TEST_P(ASTMatchersTest, AsmStatement) {

From e6ac98afe1c8c6a4b3507f0403c146979cc9f044 Mon Sep 17 00:00:00 2001
From: Davide Cunial 
Date: Thu, 30 Oct 2025 20:48:11 +0100
Subject: [PATCH 3/4] [clang-tidy] Revert ASTMatcherNodeTest.cpp

Test `__asm` syntax vs `__asm__`
---
 clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
index 8542c72b69c4a..a53b0d2f509b5 100644
--- a/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
+++ b/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
@@ -1180,7 +1180,7 @@ TEST_P(ASTMatchersTest, PredefinedExpr) {
 }
 
 TEST_P(ASTMatchersTest, FileScopeAsmDecl) {
-  EXPECT_TRUE(matches("__asm__(\"nop\");", fileScopeAsmDecl()));
+  EXPECT_TRUE(matches("__asm(\"nop\");", fileScopeAsmDecl()));
   EXPECT_TRUE(
       notMatches("void foo() { __asm(\"mov al, 2\"); }", fileScopeAsmDecl()));
 }
@@ -2448,7 +2448,8 @@ TEST_P(ASTMatchersTest, LambdaCaptureTest_BindsToCaptureOfReferenceType) {
                       "int main() {"
                       "  int a;"
                       "  f(a);"
-                      "}", matcher));
+                      "}",
+                      matcher));
   EXPECT_FALSE(matches("template  void f(T &...args) {"
                        "  [...args = args] () mutable {"
                        "  }();"
@@ -2456,7 +2457,8 @@ TEST_P(ASTMatchersTest, LambdaCaptureTest_BindsToCaptureOfReferenceType) {
                        "int main() {"
                        "  int a;"
                        "  f(a);"
-                       "}", matcher));
+                       "}",
+                       matcher));
 }
 
 TEST_P(ASTMatchersTest, IsDerivedFromRecursion) {
@@ -2634,7 +2636,7 @@ TEST(ASTMatchersTestObjC, ObjCStringLiteral) {
                           "    [Test someFunction:@\"Ola!\"]; "
                           "}\n"
                           "@end ";
-    EXPECT_TRUE(matchesObjC(Objc1String, objcStringLiteral()));
+  EXPECT_TRUE(matchesObjC(Objc1String, objcStringLiteral()));
 }
 
 TEST(ASTMatchersTestObjC, ObjCDecls) {

From 9cfa021a4594a22161665a31cb3df65e1b3670c8 Mon Sep 17 00:00:00 2001
From: Davide Cunial 
Date: Fri, 31 Oct 2025 08:30:49 +0000
Subject: [PATCH 4/4] [clang-tidy] Update documentation for 'fileScopeAsmDecl'

---
 clang/docs/LibASTMatchersReference.html             | 9 +++++++--
 clang/include/clang/ASTMatchers/ASTMatchers.h       | 9 +++++++--
 clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp | 2 +-
 3 files changed, 15 insertions(+), 5 deletions(-)

diff --git a/clang/docs/LibASTMatchersReference.html b/clang/docs/LibASTMatchersReference.html
index 47fe57e545e4b..ac1abb4d9f381 100644
--- a/clang/docs/LibASTMatchersReference.html
+++ b/clang/docs/LibASTMatchersReference.html
@@ -828,9 +828,14 @@ 

Node Matchers

Matcher<Decl>fileScopeAsmDeclMatcher<FileScopeAsmDecl>...
Matches top level asm declarations.
 
- __asm__("nop");
+Given
+   __asm("nop");
+   void f() {
+     __asm("mov al, 2");
+   }
 fileScopeAsmDecl()
-  matches '__asm__("nop")'
+  matches '__asm("nop")',
+  but not '__asm("mov al, 2")'.
 
diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h index 92107043e122e..bca2d8425b3f5 100644 --- a/clang/include/clang/ASTMatchers/ASTMatchers.h +++ b/clang/include/clang/ASTMatchers/ASTMatchers.h @@ -2480,11 +2480,16 @@ extern const internal::VariadicDynCastAllOfMatcher asmStmt; /// Matches top level asm declarations. /// +/// Given /// \code -/// __asm__("nop"); +/// __asm("nop"); +/// void f() { +/// __asm("mov al, 2"); +/// } /// \endcode /// fileScopeAsmDecl() -/// matches '__asm__("nop")' +/// matches '__asm("nop")', +/// but not '__asm("mov al, 2")'. extern const internal::VariadicDynCastAllOfMatcher fileScopeAsmDecl; diff --git a/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp index a53b0d2f509b5..3fcb5582d3dd7 100644 --- a/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp +++ b/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp @@ -1182,7 +1182,7 @@ TEST_P(ASTMatchersTest, PredefinedExpr) { TEST_P(ASTMatchersTest, FileScopeAsmDecl) { EXPECT_TRUE(matches("__asm(\"nop\");", fileScopeAsmDecl())); EXPECT_TRUE( - notMatches("void foo() { __asm(\"mov al, 2\"); }", fileScopeAsmDecl())); + notMatches("void f() { __asm(\"mov al, 2\"); }", fileScopeAsmDecl())); } TEST_P(ASTMatchersTest, AsmStatement) {