From: Argyrios Kyrtzidis Date: Sat, 4 Mar 2017 17:54:53 +0000 (+0000) Subject: [index] ObjC: Improve handling of typedefs as base names in ObjC interface declarations X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=ea71a9a14a65c086f5737c4db7f28998404d6d7b;p=clang [index] ObjC: Improve handling of typedefs as base names in ObjC interface declarations - Report the typedef reference occurrence - Mark super or protocol references as 'implicit' when they come from a typedef. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@296974 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Index/IndexDecl.cpp b/lib/Index/IndexDecl.cpp index 6f9d693863..4c5a87b29b 100644 --- a/lib/Index/IndexDecl.cpp +++ b/lib/Index/IndexDecl.cpp @@ -225,14 +225,17 @@ public: } bool handleReferencedProtocols(const ObjCProtocolList &ProtList, - const ObjCContainerDecl *ContD) { + const ObjCContainerDecl *ContD, + SourceLocation SuperLoc) { ObjCInterfaceDecl::protocol_loc_iterator LI = ProtList.loc_begin(); for (ObjCInterfaceDecl::protocol_iterator I = ProtList.begin(), E = ProtList.end(); I != E; ++I, ++LI) { SourceLocation Loc = *LI; ObjCProtocolDecl *PD = *I; - TRY_TO(IndexCtx.handleReference(PD, Loc, ContD, ContD, - SymbolRoleSet(), + SymbolRoleSet roles{}; + if (Loc == SuperLoc) + roles |= (SymbolRoleSet)SymbolRole::Implicit; + TRY_TO(IndexCtx.handleReference(PD, Loc, ContD, ContD, roles, SymbolRelation{(unsigned)SymbolRole::RelationBaseOf, ContD})); } return true; @@ -241,12 +244,26 @@ public: bool VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) { if (D->isThisDeclarationADefinition()) { TRY_TO(IndexCtx.handleDecl(D)); + SourceLocation SuperLoc = D->getSuperClassLoc(); if (auto *SuperD = D->getSuperClass()) { - TRY_TO(IndexCtx.handleReference(SuperD, D->getSuperClassLoc(), D, D, - SymbolRoleSet(), + bool hasSuperTypedef = false; + if (auto *TInfo = D->getSuperClassTInfo()) { + if (auto *TT = TInfo->getType()->getAs()) { + if (auto *TD = TT->getDecl()) { + hasSuperTypedef = true; + TRY_TO(IndexCtx.handleReference(TD, SuperLoc, D, D, + SymbolRoleSet())); + } + } + } + SymbolRoleSet superRoles{}; + if (hasSuperTypedef) + superRoles |= (SymbolRoleSet)SymbolRole::Implicit; + TRY_TO(IndexCtx.handleReference(SuperD, SuperLoc, D, D, superRoles, SymbolRelation{(unsigned)SymbolRole::RelationBaseOf, D})); } - TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D)); + TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D, + SuperLoc)); TRY_TO(IndexCtx.indexDeclContext(D)); } else { return IndexCtx.handleReference(D, D->getLocation(), nullptr, @@ -258,7 +275,8 @@ public: bool VisitObjCProtocolDecl(const ObjCProtocolDecl *D) { if (D->isThisDeclarationADefinition()) { TRY_TO(IndexCtx.handleDecl(D)); - TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D)); + TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D, + /*superLoc=*/SourceLocation())); TRY_TO(IndexCtx.indexDeclContext(D)); } else { return IndexCtx.handleReference(D, D->getLocation(), nullptr, @@ -306,7 +324,8 @@ public: if (!CategoryLoc.isValid()) CategoryLoc = D->getLocation(); TRY_TO(IndexCtx.handleDecl(D, CategoryLoc)); - TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D)); + TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D, + /*superLoc=*/SourceLocation())); TRY_TO(IndexCtx.indexDeclContext(D)); return true; } diff --git a/test/Index/Core/index-source.m b/test/Index/Core/index-source.m index 794d72ca32..e54198ab86 100644 --- a/test/Index/Core/index-source.m +++ b/test/Index/Core/index-source.m @@ -202,20 +202,27 @@ extern int setjmp(jmp_buf); @protocol MyEnumerating @end -// CHECK: [[@LINE+4]]:41 | type-alias/C | MyEnumerator | c:index-source.m@T@MyEnumerator | | Def | rel: 0 +// CHECK: [[@LINE+4]]:41 | type-alias/C | MyEnumerator | [[MyEnumerator_USR:.*]] | | Def | rel: 0 // CHECK: [[@LINE+3]]:26 | protocol/ObjC | MyEnumerating | c:objc(pl)MyEnumerating | | Ref,RelCont | rel: 1 // CHECK: [[@LINE+2]]:9 | class/ObjC | MyGenCls | c:objc(cs)MyGenCls | _OBJC_CLASS_$_MyGenCls | Ref,RelCont | rel: 1 // CHECK: [[@LINE+1]]:18 | class/ObjC | Base | c:objc(cs)Base | _OBJC_CLASS_$_Base | Ref,RelCont | rel: 1 typedef MyGenCls MyEnumerator; -// CHECK: [[@LINE+5]]:12 | class/ObjC | PermanentEnumerator | c:objc(cs)PermanentEnumerator | _OBJC_CLASS_$_PermanentEnumerator | Decl | rel: 0 -// CHECK: [[@LINE+4]]:34 | class/ObjC | MyGenCls | c:objc(cs)MyGenCls | _OBJC_CLASS_$_MyGenCls | Ref,RelBase,RelCont | rel: 1 -// CHECK-NEXT: RelBase,RelCont | PermanentEnumerator | c:objc(cs)PermanentEnumerator -// CHECK: [[@LINE+2]]:34 | protocol/ObjC | MyEnumerating | c:objc(pl)MyEnumerating | | Ref,RelBase,RelCont | rel: 1 -// CHECK-NEXT: RelBase,RelCont | PermanentEnumerator | c:objc(cs)PermanentEnumerator +// CHECK: [[@LINE+7]]:12 | class/ObjC | PermanentEnumerator | [[PermanentEnumerator_USR:.*]] | _OBJC_CLASS_$_PermanentEnumerator | Decl | rel: 0 +// CHECK: [[@LINE+6]]:34 | type-alias/C | MyEnumerator | [[MyEnumerator_USR]] | | Ref,RelCont | rel: 1 +// CHECK-NEXT: RelCont | PermanentEnumerator | [[PermanentEnumerator_USR]] +// CHECK: [[@LINE+4]]:34 | class/ObjC | MyGenCls | c:objc(cs)MyGenCls | _OBJC_CLASS_$_MyGenCls | Ref,Impl,RelBase,RelCont | rel: 1 +// CHECK-NEXT: RelBase,RelCont | PermanentEnumerator | [[PermanentEnumerator_USR]] +// CHECK: [[@LINE+2]]:34 | protocol/ObjC | MyEnumerating | c:objc(pl)MyEnumerating | | Ref,Impl,RelBase,RelCont | rel: 1 +// CHECK-NEXT: RelBase,RelCont | PermanentEnumerator | [[PermanentEnumerator_USR]] @interface PermanentEnumerator : MyEnumerator @end +// CHECK: [[@LINE+2]]:48 | protocol/ObjC | Prot1 | c:objc(pl)Prot1 | | Ref,RelBase,RelCont | rel: 1 +// CHECK: [[@LINE+1]]:35 | protocol/ObjC | MyEnumerating | c:objc(pl)MyEnumerating | | Ref,Impl,RelBase,RelCont | rel: 1 +@interface PermanentEnumerator2 : MyEnumerator +@end + @interface I4 @property id foo; @end