Author: Dave MacLachlan
Date: 2026-09-05T14:24:14-07:00
New Revision: 94cb123a68a133ddcc1f7492a6a760f50c4d771e

URL: 
https://github.com/llvm/llvm-project/commit/94cb123a68a133ddcc1f7492a6a760f50c4d771e
DIFF: 
https://github.com/llvm/llvm-project/commit/94cb123a68a133ddcc1f7492a6a760f50c4d771e.diff

LOG: [include-cleaner] Support Objective-C literals and boxed expressions in 
WalkAST (#216201)

This change adds AST visitors for ObjCBoxedExpr, ObjCArrayLiteral,
ObjCDictionaryLiteral, and ObjCStringLiteral. This ensures that the
underlying class interfaces (such as NSNumber, NSArray, NSDictionary,
and NSString) and any associated categories used for these literals are
correctly reported as referenced. Unit tests are included to verify the
new behavior.

Added: 
    

Modified: 
    clang-tools-extra/include-cleaner/lib/WalkAST.cpp
    clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp

Removed: 
    


################################################################################
diff  --git a/clang-tools-extra/include-cleaner/lib/WalkAST.cpp 
b/clang-tools-extra/include-cleaner/lib/WalkAST.cpp
index 17e7bd6ed683f..5449411371e60 100644
--- a/clang-tools-extra/include-cleaner/lib/WalkAST.cpp
+++ b/clang-tools-extra/include-cleaner/lib/WalkAST.cpp
@@ -622,6 +622,34 @@ class ASTWalker : public RecursiveASTVisitor<ASTWalker> {
     }
     return true;
   }
+
+  void reportObjCLiteralMethod(SourceLocation Loc, ObjCMethodDecl *Method) {
+    if (!Method)
+      return;
+    report(Loc, Method->getClassInterface());
+  }
+
+  bool VisitObjCBoxedExpr(ObjCBoxedExpr *E) {
+    // Handles NSNumber literals and NSValue literals.
+    reportObjCLiteralMethod(E->getBeginLoc(), E->getBoxingMethod());
+    return true;
+  }
+
+  bool VisitObjCArrayLiteral(ObjCArrayLiteral *E) {
+    reportObjCLiteralMethod(E->getBeginLoc(), E->getArrayWithObjectsMethod());
+    return true;
+  }
+
+  bool VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *E) {
+    reportObjCLiteralMethod(E->getBeginLoc(), E->getDictWithObjectsMethod());
+    return true;
+  }
+
+  bool VisitObjCStringLiteral(ObjCStringLiteral *E) {
+    report(E->getBeginLoc(),
+           E->getType()->getAs<ObjCObjectPointerType>()->getInterfaceDecl());
+    return true;
+  }
 };
 
 } // namespace

diff  --git a/clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp 
b/clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp
index ace55ea7aa23f..742a74aae41e3 100644
--- a/clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp
+++ b/clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp
@@ -1545,5 +1545,80 @@ TEST(WalkAST, ObjCEncodeExpr) {
            {"-x", "objective-c"});
 }
 
+TEST(WalkAST, ObjCBoxedExprInt) {
+  testWalk(R"objc(
+    @interface $explicit^NSNumber
+    + (id)numberWithInt:(int)val;
+    @end
+  )objc",
+           R"objc(
+    void test() {
+      id x = ^@42;
+    }
+  )objc",
+           {"-x", "objective-c"});
+}
+
+TEST(WalkAST, ObjCBoxedExprStruct) {
+  testWalk(R"objc(
+    struct __attribute__((objc_boxable)) Point {
+      int x, y;
+    };
+    @interface $explicit^NSValue
+    + (id)valueWithBytes:(const void *)bytes objCType:(const char *)type;
+    @end
+  )objc",
+           R"objc(
+    void test() {
+    struct Point p = {1, 2};
+      id x = ^@(p);
+    }
+  )objc",
+           {"-x", "objective-c"});
+}
+
+TEST(WalkAST, ObjCArrayLiteral) {
+  testWalk(R"objc(
+    @interface $explicit^NSArray
+    + (id)arrayWithObjects:(const id *)objects count:(unsigned long)cnt;
+    @end
+  )objc",
+           R"objc(
+    void test(id a, id b) {
+      id arr = ^@[a, b];
+    }
+  )objc",
+           {"-x", "objective-c"});
+}
+
+TEST(WalkAST, ObjCDictionaryLiteral) {
+  testWalk(R"objc(
+    @interface $explicit^NSDictionary
+    + (id)dictionaryWithObjects:(const id *)objects
+                        forKeys:(const id *)keys
+                          count:(unsigned long)cnt;
+    @end
+  )objc",
+           R"objc(
+    void test(id k, id v) {
+      id dict = ^@{k: v};
+    }
+  )objc",
+           {"-x", "objective-c"});
+}
+
+TEST(WalkAST, ObjCStringLiteral) {
+  testWalk(R"objc(
+    @interface $explicit^NSString
+    @end
+  )objc",
+           R"objc(
+    void test() {
+      id s = ^@"hello";
+    }
+  )objc",
+           {"-x", "objective-c"});
+}
+
 } // namespace
 } // namespace clang::include_cleaner


        
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to