diff --git a/clang-tools-extra/clangd/FindTarget.cpp b/clang-tools-extra/clangd/FindTarget.cpp --- a/clang-tools-extra/clangd/FindTarget.cpp +++ b/clang-tools-extra/clangd/FindTarget.cpp @@ -306,9 +306,6 @@ Outer.add(OME->getMethodDecl(), Flags); } void VisitObjCPropertyRefExpr(const ObjCPropertyRefExpr *OPRE) { - // FIXME: We miss visiting the class receiver if one exists, which - // means we skip the corresponding ObjCInterfaceDecl ref since it - // doesn't have a corresponding node. if (OPRE->isExplicitProperty()) Outer.add(OPRE->getExplicitProperty(), Flags); else { @@ -766,13 +763,6 @@ } void VisitObjCPropertyRefExpr(const ObjCPropertyRefExpr *E) { - // There's no contained TypeLoc node for a class receiver type. - if (E->isClassReceiver()) { - Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(), - E->getReceiverLocation(), - /*IsDecl=*/false, - {E->getClassReceiver()}}); - } Refs.push_back(ReferenceLoc{ NestedNameSpecifierLoc(), E->getLocation(), /*IsDecl=*/false, diff --git a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp --- a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp +++ b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp @@ -981,8 +981,7 @@ id value = [[Foo]].sharedInstance; } )cpp"; - // FIXME: We currently can't identify the interface here. - EXPECT_DECLS("ObjCPropertyRefExpr", "+ (id)sharedInstance"); + EXPECT_DECLS("ObjCInterfaceTypeLoc", "@interface Foo"); Code = R"cpp( @interface Foo diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -2638,7 +2638,16 @@ TRY_TO(TraverseTypeLoc(TInfo->getTypeLoc())); }) -DEF_TRAVERSE_STMT(ObjCPropertyRefExpr, {}) +DEF_TRAVERSE_STMT(ObjCPropertyRefExpr, { + if (S->isClassReceiver()) { + ObjCInterfaceDecl *IDecl = S->getClassReceiver(); + QualType Type = IDecl->getASTContext().getObjCInterfaceType(IDecl); + ObjCInterfaceLocInfo Data; + Data.NameLoc = S->getReceiverLocation(); + Data.NameEndLoc = Data.NameLoc; + TRY_TO(TraverseTypeLoc(TypeLoc(Type, &Data))); + } +}) DEF_TRAVERSE_STMT(ObjCSubscriptRefExpr, {}) DEF_TRAVERSE_STMT(ObjCProtocolExpr, {}) DEF_TRAVERSE_STMT(ObjCSelectorExpr, {}) diff --git a/clang/lib/Index/IndexBody.cpp b/clang/lib/Index/IndexBody.cpp --- a/clang/lib/Index/IndexBody.cpp +++ b/clang/lib/Index/IndexBody.cpp @@ -286,9 +286,6 @@ } bool VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) { - if (E->isClassReceiver()) - IndexCtx.handleReference(E->getClassReceiver(), E->getReceiverLocation(), - Parent, ParentDC); if (E->isExplicitProperty()) { SmallVector Relations; SymbolRoleSet Roles = getRolesForRef(E, Relations); diff --git a/clang/lib/Sema/SemaAvailability.cpp b/clang/lib/Sema/SemaAvailability.cpp --- a/clang/lib/Sema/SemaAvailability.cpp +++ b/clang/lib/Sema/SemaAvailability.cpp @@ -683,11 +683,7 @@ // to any useful diagnostics. bool TraverseCaseStmt(CaseStmt *CS) { return TraverseStmt(CS->getSubStmt()); } - bool VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *PRE) { - if (PRE->isClassReceiver()) - DiagnoseDeclAvailability(PRE->getClassReceiver(), PRE->getReceiverLocation()); - return true; - } + bool VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *PRE) { return true; } bool VisitObjCMessageExpr(ObjCMessageExpr *Msg) { if (ObjCMethodDecl *D = Msg->getMethodDecl()) { diff --git a/clang/test/Index/Core/index-source.m b/clang/test/Index/Core/index-source.m --- a/clang/test/Index/Core/index-source.m +++ b/clang/test/Index/Core/index-source.m @@ -405,15 +405,15 @@ void classReceivers() { ClassReceivers.p1 = 0; -// CHECK: [[@LINE-1]]:3 | class/ObjC | ClassReceivers | c:objc(cs)ClassReceivers | _OBJC_CLASS_$_ClassReceivers | Ref,RelCont | rel: 1 -// CHECK: [[@LINE-2]]:18 | instance-property/ObjC | p1 | c:objc(cs)ClassReceivers(cpy)p1 | | Ref,Writ,RelCont | rel: 1 +// CHECK: [[@LINE-1]]:18 | instance-property/ObjC | p1 | c:objc(cs)ClassReceivers(cpy)p1 | | Ref,Writ,RelCont | rel: 1 // CHECK-NEXT: RelCont | classReceivers | c:@F@classReceivers +// CHECK: [[@LINE-3]]:3 | class/ObjC | ClassReceivers | c:objc(cs)ClassReceivers | _OBJC_CLASS_$_ClassReceivers | Ref,RelCont | rel: 1 // CHECK: [[@LINE-4]]:18 | class-method/acc-set/ObjC | setP1: | c:objc(cs)ClassReceivers(cm)setP1: | +[ClassReceivers setP1:] | Ref,Call,Impl,RelCall,RelCont | rel: 1 // CHECK-NEXT: RelCall,RelCont | classReceivers | c:@F@classReceivers (void)ClassReceivers.p1; -// CHECK: [[@LINE-1]]:9 | class/ObjC | ClassReceivers | c:objc(cs)ClassReceivers | _OBJC_CLASS_$_ClassReceivers | Ref,RelCont | rel: 1 -// CHECK: [[@LINE-2]]:24 | instance-property/ObjC | p1 | c:objc(cs)ClassReceivers(cpy)p1 | | Ref,RelCont | rel: 1 +// CHECK: [[@LINE-1]]:24 | instance-property/ObjC | p1 | c:objc(cs)ClassReceivers(cpy)p1 | | Ref,RelCont | rel: 1 // CHECK-NEXT: RelCont | classReceivers | c:@F@classReceivers +// CHECK: [[@LINE-3]]:9 | class/ObjC | ClassReceivers | c:objc(cs)ClassReceivers | _OBJC_CLASS_$_ClassReceivers | Ref,RelCont | rel: 1 // CHECK: [[@LINE-4]]:24 | class-method/acc-get/ObjC | p1 | c:objc(cs)ClassReceivers(cm)p1 | +[ClassReceivers p1] | Ref,Call,Impl,RelCall,RelCont | rel: 1 // CHECK-NEXT: RelCall,RelCont | classReceivers | c:@F@classReceivers