From: Alex Lorenz Date: Mon, 3 Jul 2017 10:34:46 +0000 (+0000) Subject: [index] Remove 'implicit' role for message sends in implicit ObjC X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=0305311a4e50b9a1d54a9a1d050d93754f26f9cf;p=clang [index] Remove 'implicit' role for message sends in implicit ObjC property references rdar://32375673 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@307016 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Index/IndexBody.cpp b/lib/Index/IndexBody.cpp index d3632b8b9b..6bbd381025 100644 --- a/lib/Index/IndexBody.cpp +++ b/lib/Index/IndexBody.cpp @@ -230,7 +230,31 @@ public: SmallVector Relations; addCallRole(Roles, Relations); Stmt *Containing = getParentStmt(); - if (E->isImplicit() || (Containing && isa(Containing))) + + auto IsImplicitProperty = [](const PseudoObjectExpr *POE) -> bool { + const auto *E = POE->getSyntacticForm(); + if (const auto *BinOp = dyn_cast(E)) + E = BinOp->getLHS(); + const auto *PRE = dyn_cast(E); + if (!PRE) + return false; + if (PRE->isExplicitProperty()) + return false; + if (const ObjCMethodDecl *Getter = PRE->getImplicitPropertyGetter()) { + // Class properties that are explicitly defined using @property + // declarations are represented implicitly as there is no ivar for + // class properties. + if (Getter->isClassMethod() && + Getter->getCanonicalDecl()->findPropertyDecl()) + return false; + } + return true; + }; + bool IsPropCall = Containing && isa(Containing); + // Implicit property message sends are not 'implicit'. + if ((E->isImplicit() || IsPropCall) && + !(IsPropCall && + IsImplicitProperty(cast(Containing)))) Roles |= (unsigned)SymbolRole::Implicit; if (isDynamic(E)) { diff --git a/test/Index/Core/index-source.m b/test/Index/Core/index-source.m index a64c34ad2a..c911973a70 100644 --- a/test/Index/Core/index-source.m +++ b/test/Index/Core/index-source.m @@ -413,3 +413,28 @@ void classReceivers() { (void)ClassReceivers.implicit; // CHECK: [[@LINE-1]]:9 | class/ObjC | ClassReceivers | c:objc(cs)ClassReceivers | _OBJC_CLASS_$_ClassReceivers | Ref,RelCont | rel: 1 } + +@interface ImplicitProperties + +- (int)implicit; +- (void)setImplicit:(int)x; + ++ (int)classImplicit; ++ (void)setClassImplicit:(int)y; + +@end + +void testImplicitProperties(ImplicitProperties *c) { + c.implicit = 0; +// CHECK: [[@LINE-1]]:5 | instance-method/ObjC | setImplicit: | c:objc(cs)ImplicitProperties(im)setImplicit: | -[ImplicitProperties setImplicit:] | Ref,Call,Dyn,RelRec,RelCall,RelCont | rel: 2 +// CHECK-NEXT: RelCall,RelCont | testImplicitProperties | c:@F@testImplicitProperties + c.implicit; +// CHECK: [[@LINE-1]]:5 | instance-method/ObjC | implicit | c:objc(cs)ImplicitProperties(im)implicit | -[ImplicitProperties implicit] | Ref,Call,Dyn,RelRec,RelCall,RelCont | rel: 2 +// CHECK-NEXT: RelCall,RelCont | testImplicitProperties | c:@F@testImplicitProperties + ImplicitProperties.classImplicit = 1; +// CHECK: [[@LINE-1]]:22 | class-method/ObjC | setClassImplicit: | c:objc(cs)ImplicitProperties(cm)setClassImplicit: | +[ImplicitProperties setClassImplicit:] | Ref,Call,RelCall,RelCont | rel: 1 +// CHECK-NEXT: RelCall,RelCont | testImplicitProperties | c:@F@testImplicitProperties + ImplicitProperties.classImplicit; +// CHECK: [[@LINE-1]]:22 | class-method/ObjC | classImplicit | c:objc(cs)ImplicitProperties(cm)classImplicit | +[ImplicitProperties classImplicit] | Ref,Call,RelCall,RelCont | rel: 1 +// CHECK-NEXT: RelCall,RelCont | testImplicitProperties | c:@F@testImplicitProperties +}