================
@@ -458,6 +458,35 @@ class ASTWalker : public RecursiveASTVisitor<ASTWalker> {
       if (auto *Setter = E->getImplicitPropertySetter())
         report(E->getLocation(), Setter);
     }
+
+    // Report the receiver to ensure its declaring header is kept.
----------------
nico wrote:

Tests still seem to pass with this removed, with an I think benign test tweak:

```diff
diff --git a/clang-tools-extra/include-cleaner/lib/WalkAST.cpp 
b/clang-tools-extra/include-cleaner/lib/WalkAST.cpp
index 12396758e583..c6d182799f1c 100644
--- a/clang-tools-extra/include-cleaner/lib/WalkAST.cpp
+++ b/clang-tools-extra/include-cleaner/lib/WalkAST.cpp
@@ -473,42 +473,10 @@ public:
       if (auto *Setter = E->getImplicitPropertySetter())
         report(E->getLocation(), Setter);
     }
-
-    // Report the receiver to ensure its declaring header is kept.
-    if (E->isObjectReceiver()) {
-      QualType Type = E->getBase()->IgnoreImpCasts()->getType();
-      if (const auto *ObjCPtr = Type->getAs<ObjCObjectPointerType>()) {
-        if (auto *Interface = ObjCPtr->getInterfaceDecl()) {
-          report(E->getLocation(), Interface, RefType::Implicit);
-        }
-        for (auto *Proto : ObjCPtr->quals()) {
-          report(E->getLocation(), Proto, RefType::Implicit);
-        }
-      }
-    } else if (E->isClassReceiver()) {
-      if (auto *Interface = E->getClassReceiver()) {
-        report(E->getLocation(), Interface, RefType::Implicit);
-      }
-    } else if (E->isSuperReceiver()) {
-      QualType Type = E->getSuperReceiverType();
-      if (const auto *ObjCPtr = Type->getAs<ObjCObjectPointerType>()) {
-        if (auto *Interface = ObjCPtr->getInterfaceDecl()) {
-          report(E->getLocation(), Interface, RefType::Implicit);
-        }
-        for (auto *Proto : ObjCPtr->quals()) {
-          report(E->getLocation(), Proto, RefType::Implicit);
-        }
-      } else if (const auto *ObjCType = Type->getAs<ObjCObjectType>()) {
-        // This is for handling `super.foo` property references.
-        if (auto *Interface = ObjCType->getInterface()) {
-          report(E->getLocation(), Interface, RefType::Implicit);
-        }
-        // The foo declaration could be in a protocol on super.
-        for (auto *Proto : ObjCType->quals()) {
-          report(E->getLocation(), Proto, RefType::Implicit);
-        }
-      }
-    }
     return true;
   }
 
diff --git a/clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp 
b/clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp
index 2a29fefc07a7..924817b765a0 100644
--- a/clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp
+++ b/clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp
@@ -791,7 +791,7 @@ TEST(WalkAST, ObjCPropertyRefExprProtocol) {
 
 TEST(WalkAST, ObjCPropertyRefExprClassReceiver) {
   testWalk(R"objc(
-    @interface $implicit^MyClass
+    @interface MyClass
     @property(class, nonatomic) int $explicit^foo;
     @end
   )objc",
@@ -803,6 +803,22 @@ TEST(WalkAST, ObjCPropertyRefExprClassReceiver) {
            {"-x", "objective-c"});
 }
```

Since we already have the `$explicit^`, I think the former `$implicit^` was 
redundant.

If needed, here's an explicit test for the receiver:

```diff
+TEST(WalkAST, ObjCPropertyRefExprClassReceiverInterface) {
+  testWalk(R"objc(
+    @interface $explicit^MyClass
+    @property(class, nonatomic) int foo;
+    @end
+  )objc",
+           R"objc(
+    void test() {
+      int x = ^MyClass.foo;
+    }
+  )objc",
+           {"-x", "objective-c"});
+}
+
 TEST(WalkAST, ObjCPropertyRefExprSuperReceiver) {
   testWalk(R"objc(
     @interface $implicit^ParentClass
```

I think this works because clang/include/clang/AST/RecursiveASTVisitor.h:2801:

```
// PseudoObjectExpr is a special case because of the weirdness with
// syntactic expressions and opaque values.
DEF_TRAVERSE_STMT(PseudoObjectExpr, {
  TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getSyntacticForm());
  for (PseudoObjectExpr::semantics_iterator i = S->semantics_begin(),
                                            e = S->semantics_end();
       i != e; ++i) {
    Expr *sub = *i;
    if (OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(sub))
      sub = OVE->getSourceExpr();
    TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(sub);
  }
  ShouldVisitChildren = false;
})
```

Property accesses are PseudoObjectExprs, and its semantics contain 
ObjCMessageExpr.

(I should add that I'm not an expert in this code at all, but I do know clang 
AST a bit. So I'd say there's a 50% chance I'm missing something!)

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

Reply via email to