Split ObjCInterfaceDecl::ReferencedProtocols into two lists: ReferencedProtocols and AllReferencedProtocols. ReferencedProtocols
(and thus protocol_begin(), protocol_end()) now only contains the list of protocols that were directly referenced in
an @interface declaration. 'all_referenced_protocol_[begin,end]()' now returns the set of protocols that were referenced
in both the @interface and class extensions. The latter is needed for semantic analysis/codegen, while the former is
needed to maintain the lexical information of the original source.
Fixes <rdar://problem/8380046>.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@112691 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h
index da1278c..ad26748 100644
--- a/include/clang/AST/DeclObjC.h
+++ b/include/clang/AST/DeclObjC.h
@@ -443,8 +443,11 @@
/// Class's super class.
ObjCInterfaceDecl *SuperClass;
- /// Protocols referenced in interface header declaration
+ /// Protocols referenced in the @interface declaration
ObjCProtocolList ReferencedProtocols;
+
+ /// Protocols reference in both the @interface and class extensions.
+ ObjCList<ObjCProtocolDecl> AllReferencedProtocols;
/// List of categories defined for this class.
/// FIXME: Why is this a linked list??
@@ -489,23 +492,44 @@
}
typedef ObjCProtocolList::iterator protocol_iterator;
- protocol_iterator protocol_begin() const {return ReferencedProtocols.begin();}
- protocol_iterator protocol_end() const { return ReferencedProtocols.end(); }
+
+ protocol_iterator protocol_begin() const {
+ return ReferencedProtocols.begin();
+ }
+ protocol_iterator protocol_end() const {
+ return ReferencedProtocols.end();
+ }
+
typedef ObjCProtocolList::loc_iterator protocol_loc_iterator;
+
protocol_loc_iterator protocol_loc_begin() const {
return ReferencedProtocols.loc_begin();
}
+
protocol_loc_iterator protocol_loc_end() const {
return ReferencedProtocols.loc_end();
}
- unsigned protocol_size() const { return ReferencedProtocols.size(); }
+
+ typedef ObjCList<ObjCProtocolDecl>::iterator all_protocol_iterator;
+
+ all_protocol_iterator all_referenced_protocol_begin() const {
+ return AllReferencedProtocols.empty() ? protocol_begin()
+ : AllReferencedProtocols.begin();
+ }
+ all_protocol_iterator all_referenced_protocol_end() const {
+ return AllReferencedProtocols.empty() ? protocol_end()
+ : AllReferencedProtocols.end();
+ }
typedef specific_decl_iterator<ObjCIvarDecl> ivar_iterator;
+
ivar_iterator ivar_begin() const { return ivar_iterator(decls_begin()); }
ivar_iterator ivar_end() const { return ivar_iterator(decls_end()); }
+
unsigned ivar_size() const {
return std::distance(ivar_begin(), ivar_end());
}
+
bool ivar_empty() const { return ivar_begin() == ivar_end(); }
ObjCIvarDecl *all_declared_ivar_begin();
@@ -522,7 +546,6 @@
/// into the protocol list for this class.
void mergeClassExtensionProtocolList(ObjCProtocolDecl *const* List,
unsigned Num,
- const SourceLocation *Locs,
ASTContext &C);
bool isForwardDecl() const { return ForwardDecl; }
@@ -604,6 +627,9 @@
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(const ObjCInterfaceDecl *D) { return true; }
static bool classofKind(Kind K) { return K == ObjCInterface; }
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
};
/// ObjCIvarDecl - Represents an ObjC instance variable. In general, ObjC
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 8c61b5c..574ada3 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -897,8 +897,10 @@
void ASTContext::CollectInheritedProtocols(const Decl *CDecl,
llvm::SmallPtrSet<ObjCProtocolDecl*, 8> &Protocols) {
if (const ObjCInterfaceDecl *OI = dyn_cast<ObjCInterfaceDecl>(CDecl)) {
- for (ObjCInterfaceDecl::protocol_iterator P = OI->protocol_begin(),
- PE = OI->protocol_end(); P != PE; ++P) {
+ // We can use protocol_iterator here instead of
+ // all_referenced_protocol_iterator since we are walking all categories.
+ for (ObjCInterfaceDecl::all_protocol_iterator P = OI->all_referenced_protocol_begin(),
+ PE = OI->all_referenced_protocol_end(); P != PE; ++P) {
ObjCProtocolDecl *Proto = (*P);
Protocols.insert(Proto);
for (ObjCProtocolDecl::protocol_iterator P = Proto->protocol_begin(),
@@ -918,7 +920,7 @@
SD = SD->getSuperClass();
}
} else if (const ObjCCategoryDecl *OC = dyn_cast<ObjCCategoryDecl>(CDecl)) {
- for (ObjCInterfaceDecl::protocol_iterator P = OC->protocol_begin(),
+ for (ObjCCategoryDecl::protocol_iterator P = OC->protocol_begin(),
PE = OC->protocol_end(); P != PE; ++P) {
ObjCProtocolDecl *Proto = (*P);
Protocols.insert(Proto);
diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp
index eee41a6..2edd09c 100644
--- a/lib/AST/ASTImporter.cpp
+++ b/lib/AST/ASTImporter.cpp
@@ -2553,6 +2553,8 @@
llvm::SmallVector<SourceLocation, 4> ProtocolLocs;
ObjCInterfaceDecl::protocol_loc_iterator
FromProtoLoc = D->protocol_loc_begin();
+
+ // FIXME: Should we be usng all_referenced_protocol_begin() here?
for (ObjCInterfaceDecl::protocol_iterator FromProto = D->protocol_begin(),
FromProtoEnd = D->protocol_end();
FromProto != FromProtoEnd;
diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp
index 28c7a49..d952cc3 100644
--- a/lib/AST/DeclObjC.cpp
+++ b/lib/AST/DeclObjC.cpp
@@ -120,8 +120,9 @@
return P;
// Look through protocols.
- for (ObjCInterfaceDecl::protocol_iterator
- I = OID->protocol_begin(), E = OID->protocol_end(); I != E; ++I)
+ for (ObjCInterfaceDecl::all_protocol_iterator
+ I = OID->all_referenced_protocol_begin(),
+ E = OID->all_referenced_protocol_end(); I != E; ++I)
if (ObjCPropertyDecl *P = (*I)->FindPropertyDeclaration(PropertyId))
return P;
@@ -157,8 +158,9 @@
return PD;
// Look through protocols.
- for (ObjCInterfaceDecl::protocol_iterator
- I = protocol_begin(), E = protocol_end(); I != E; ++I)
+ for (ObjCInterfaceDecl::all_protocol_iterator
+ I = all_referenced_protocol_begin(),
+ E = all_referenced_protocol_end(); I != E; ++I)
if (ObjCPropertyDecl *P = (*I)->FindPropertyDeclaration(PropertyId))
return P;
@@ -167,23 +169,23 @@
void ObjCInterfaceDecl::mergeClassExtensionProtocolList(
ObjCProtocolDecl *const* ExtList, unsigned ExtNum,
- const SourceLocation *Locs,
ASTContext &C)
{
- if (ReferencedProtocols.empty()) {
- ReferencedProtocols.set(ExtList, ExtNum, Locs, C);
+ if (AllReferencedProtocols.empty() && ReferencedProtocols.empty()) {
+ AllReferencedProtocols.set(ExtList, ExtNum, C);
return;
}
+
// Check for duplicate protocol in class's protocol list.
- // This is (O)2. But it is extremely rare and number of protocols in
+ // This is O(n*m). But it is extremely rare and number of protocols in
// class or its extension are very few.
llvm::SmallVector<ObjCProtocolDecl*, 8> ProtocolRefs;
- llvm::SmallVector<SourceLocation, 8> ProtocolLocs;
for (unsigned i = 0; i < ExtNum; i++) {
bool protocolExists = false;
ObjCProtocolDecl *ProtoInExtension = ExtList[i];
- for (protocol_iterator p = protocol_begin(), e = protocol_end();
- p != e; p++) {
+ for (all_protocol_iterator
+ p = all_referenced_protocol_begin(),
+ e = all_referenced_protocol_end(); p != e; ++p) {
ObjCProtocolDecl *Proto = (*p);
if (C.ProtocolCompatibleWithProtocol(ProtoInExtension, Proto)) {
protocolExists = true;
@@ -192,22 +194,20 @@
}
// Do we want to warn on a protocol in extension class which
// already exist in the class? Probably not.
- if (!protocolExists) {
+ if (!protocolExists)
ProtocolRefs.push_back(ProtoInExtension);
- ProtocolLocs.push_back(Locs[i]);
- }
}
+
if (ProtocolRefs.empty())
return;
+
// Merge ProtocolRefs into class's protocol list;
- protocol_loc_iterator pl = protocol_loc_begin();
- for (protocol_iterator p = protocol_begin(), e = protocol_end();
- p != e; ++p, ++pl) {
+ for (all_protocol_iterator p = all_referenced_protocol_begin(),
+ e = all_referenced_protocol_end(); p != e; ++p) {
ProtocolRefs.push_back(*p);
- ProtocolLocs.push_back(*pl);
}
- unsigned NumProtoRefs = ProtocolRefs.size();
- setProtocolList(ProtocolRefs.data(), NumProtoRefs, ProtocolLocs.data(), C);
+
+ AllReferencedProtocols.set(ProtocolRefs.data(), ProtocolRefs.size(), C);
}
/// getFirstClassExtension - Find first class extension of the given class.
diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp
index f4ff951..f397c56 100644
--- a/lib/CodeGen/CGObjCMac.cpp
+++ b/lib/CodeGen/CGObjCMac.cpp
@@ -1990,8 +1990,9 @@
Prop));
}
if (const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(OCD)) {
- for (ObjCInterfaceDecl::protocol_iterator P = OID->protocol_begin(),
- E = OID->protocol_end(); P != E; ++P)
+ for (ObjCInterfaceDecl::all_protocol_iterator
+ P = OID->all_referenced_protocol_begin(),
+ E = OID->all_referenced_protocol_end(); P != E; ++P)
PushProtocolProperties(PropertySet, Properties, Container, (*P),
ObjCTypes);
}
@@ -2179,8 +2180,8 @@
const_cast<ObjCInterfaceDecl*>(ID->getClassInterface());
llvm::Constant *Protocols =
EmitProtocolList("\01L_OBJC_CLASS_PROTOCOLS_" + ID->getName(),
- Interface->protocol_begin(),
- Interface->protocol_end());
+ Interface->all_referenced_protocol_begin(),
+ Interface->all_referenced_protocol_end());
unsigned Flags = eClassFlags_Factory;
if (ID->getNumIvarInitializers())
Flags |= eClassFlags_HasCXXStructors;
@@ -4804,8 +4805,8 @@
assert(OID && "CGObjCNonFragileABIMac::BuildClassRoTInitializer");
Values[ 6] = EmitProtocolList("\01l_OBJC_CLASS_PROTOCOLS_$_"
+ OID->getName(),
- OID->protocol_begin(),
- OID->protocol_end());
+ OID->all_referenced_protocol_begin(),
+ OID->all_referenced_protocol_end());
if (flags & CLS_META)
Values[ 7] = llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy);
diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp
index cef3546..7088e55 100644
--- a/lib/Sema/SemaCodeComplete.cpp
+++ b/lib/Sema/SemaCodeComplete.cpp
@@ -2686,9 +2686,9 @@
}
// Look through protocols.
- for (ObjCInterfaceDecl::protocol_iterator I = IFace->protocol_begin(),
- E = IFace->protocol_end();
- I != E; ++I)
+ for (ObjCInterfaceDecl::all_protocol_iterator
+ I = IFace->all_referenced_protocol_begin(),
+ E = IFace->all_referenced_protocol_end(); I != E; ++I)
AddObjCProperties(*I, AllowCategories, CurContext, Results);
// Look in the superclass.
@@ -2698,8 +2698,8 @@
} else if (const ObjCCategoryDecl *Category
= dyn_cast<ObjCCategoryDecl>(Container)) {
// Look through protocols.
- for (ObjCInterfaceDecl::protocol_iterator P = Category->protocol_begin(),
- PEnd = Category->protocol_end();
+ for (ObjCCategoryDecl::protocol_iterator P = Category->protocol_begin(),
+ PEnd = Category->protocol_end();
P != PEnd; ++P)
AddObjCProperties(*P, AllowCategories, CurContext, Results);
}
diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp
index 3c6f224..a6902a3 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -485,8 +485,7 @@
// Protocols in the class extension belong to the class.
if (CDecl->IsClassExtension())
IDecl->mergeClassExtensionProtocolList((ObjCProtocolDecl**)ProtoRefs,
- NumProtoRefs, ProtoLocs,
- Context);
+ NumProtoRefs, Context);
}
CheckObjCDeclScope(CDecl);
@@ -924,8 +923,9 @@
}
if (ObjCInterfaceDecl *I = dyn_cast<ObjCInterfaceDecl> (CDecl)) {
// Check for any implementation of a methods declared in protocol.
- for (ObjCInterfaceDecl::protocol_iterator PI = I->protocol_begin(),
- E = I->protocol_end(); PI != E; ++PI)
+ for (ObjCInterfaceDecl::all_protocol_iterator
+ PI = I->all_referenced_protocol_begin(),
+ E = I->all_referenced_protocol_end(); PI != E; ++PI)
MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen,
IMPDecl,
(*PI), IncompleteImpl, false);
@@ -971,8 +971,9 @@
// implemented in the implementation class.
if (ObjCInterfaceDecl *I = dyn_cast<ObjCInterfaceDecl> (CDecl)) {
- for (ObjCInterfaceDecl::protocol_iterator PI = I->protocol_begin(),
- E = I->protocol_end(); PI != E; ++PI)
+ for (ObjCInterfaceDecl::all_protocol_iterator
+ PI = I->all_referenced_protocol_begin(),
+ E = I->all_referenced_protocol_end(); PI != E; ++PI)
CheckProtocolMethodDefs(IMPDecl->getLocation(), *PI, IncompleteImpl,
InsMap, ClsMap, I);
// Check class extensions (unnamed categories)
diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp
index 1e04710..306e95a 100644
--- a/lib/Sema/SemaLookup.cpp
+++ b/lib/Sema/SemaLookup.cpp
@@ -2502,8 +2502,9 @@
}
// Traverse protocols.
- for (ObjCInterfaceDecl::protocol_iterator I = IFace->protocol_begin(),
- E = IFace->protocol_end(); I != E; ++I) {
+ for (ObjCInterfaceDecl::all_protocol_iterator
+ I = IFace->all_referenced_protocol_begin(),
+ E = IFace->all_referenced_protocol_end(); I != E; ++I) {
ShadowContextRAII Shadow(Visited);
LookupVisibleDecls(*I, Result, QualifiedNameLookup, false, Consumer,
Visited);
diff --git a/lib/Sema/SemaObjCProperty.cpp b/lib/Sema/SemaObjCProperty.cpp
index 7c3918a..7181d58 100644
--- a/lib/Sema/SemaObjCProperty.cpp
+++ b/lib/Sema/SemaObjCProperty.cpp
@@ -731,15 +731,17 @@
}
if (ObjCInterfaceDecl *MDecl = dyn_cast<ObjCInterfaceDecl>(ClassDecl)) {
- for (ObjCInterfaceDecl::protocol_iterator P = MDecl->protocol_begin(),
- E = MDecl->protocol_end(); P != E; ++P)
+ for (ObjCInterfaceDecl::all_protocol_iterator
+ P = MDecl->all_referenced_protocol_begin(),
+ E = MDecl->all_referenced_protocol_end(); P != E; ++P)
// Match properties of class IDecl with those of protocol (*P).
MatchOneProtocolPropertiesInClass(IDecl, *P);
// Go thru the list of protocols for this class and recursively match
// their properties with those declared in the class.
- for (ObjCInterfaceDecl::protocol_iterator P = IDecl->protocol_begin(),
- E = IDecl->protocol_end(); P != E; ++P)
+ for (ObjCInterfaceDecl::all_protocol_iterator
+ P = IDecl->all_referenced_protocol_begin(),
+ E = IDecl->all_referenced_protocol_end(); P != E; ++P)
CompareProperties(IDecl, *P);
} else {
ObjCProtocolDecl *MD = cast<ObjCProtocolDecl>(ClassDecl);
@@ -812,8 +814,9 @@
PropMap[Prop->getIdentifier()] = Prop;
}
// scan through class's protocols.
- for (ObjCInterfaceDecl::protocol_iterator PI = IDecl->protocol_begin(),
- E = IDecl->protocol_end(); PI != E; ++PI)
+ for (ObjCInterfaceDecl::all_protocol_iterator
+ PI = IDecl->all_referenced_protocol_begin(),
+ E = IDecl->all_referenced_protocol_end(); PI != E; ++PI)
CollectImmediateProperties((*PI), PropMap, SuperPropMap);
}
if (ObjCCategoryDecl *CATDecl = dyn_cast<ObjCCategoryDecl>(CDecl)) {
@@ -824,7 +827,7 @@
PropMap[Prop->getIdentifier()] = Prop;
}
// scan through class's protocols.
- for (ObjCInterfaceDecl::protocol_iterator PI = CATDecl->protocol_begin(),
+ for (ObjCCategoryDecl::protocol_iterator PI = CATDecl->protocol_begin(),
E = CATDecl->protocol_end(); PI != E; ++PI)
CollectImmediateProperties((*PI), PropMap, SuperPropMap);
}
@@ -859,8 +862,9 @@
ObjCPropertyDecl *Prop = (*P);
PropMap[Prop->getIdentifier()] = Prop;
}
- for (ObjCInterfaceDecl::protocol_iterator PI = IDecl->protocol_begin(),
- E = IDecl->protocol_end(); PI != E; ++PI)
+ for (ObjCInterfaceDecl::all_protocol_iterator
+ PI = IDecl->all_referenced_protocol_begin(),
+ E = IDecl->all_referenced_protocol_end(); PI != E; ++PI)
CollectClassPropertyImplementations((*PI), PropMap);
}
else if (ObjCProtocolDecl *PDecl = dyn_cast<ObjCProtocolDecl>(CDecl)) {
@@ -902,8 +906,9 @@
return Prop;
}
// scan through class's protocols.
- for (ObjCInterfaceDecl::protocol_iterator PI = IDecl->protocol_begin(),
- E = IDecl->protocol_end(); PI != E; ++PI) {
+ for (ObjCInterfaceDecl::all_protocol_iterator
+ PI = IDecl->all_referenced_protocol_begin(),
+ E = IDecl->all_referenced_protocol_end(); PI != E; ++PI) {
ObjCPropertyDecl *Prop = LookupPropertyDecl((*PI), II);
if (Prop)
return Prop;
diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp
index 9795bd0..512d4b5 100644
--- a/lib/Serialization/ASTReaderDecl.cpp
+++ b/lib/Serialization/ASTReaderDecl.cpp
@@ -374,6 +374,8 @@
ID->setTypeForDecl(Reader.GetType(Record[Idx++]).getTypePtr());
ID->setSuperClass(cast_or_null<ObjCInterfaceDecl>
(Reader.GetDecl(Record[Idx++])));
+
+ // Read the directly referenced protocols and their SourceLocations.
unsigned NumProtocols = Record[Idx++];
llvm::SmallVector<ObjCProtocolDecl *, 16> Protocols;
Protocols.reserve(NumProtocols);
@@ -385,6 +387,17 @@
ProtoLocs.push_back(SourceLocation::getFromRawEncoding(Record[Idx++]));
ID->setProtocolList(Protocols.data(), NumProtocols, ProtoLocs.data(),
*Reader.getContext());
+
+ // Read the transitive closure of protocols referenced by this class.
+ NumProtocols = Record[Idx++];
+ Protocols.clear();
+ Protocols.reserve(NumProtocols);
+ for (unsigned I = 0; I != NumProtocols; ++I)
+ Protocols.push_back(cast<ObjCProtocolDecl>(Reader.GetDecl(Record[Idx++])));
+ ID->AllReferencedProtocols.set(Protocols.data(), NumProtocols,
+ *Reader.getContext());
+
+ // Read the ivars.
unsigned NumIvars = Record[Idx++];
llvm::SmallVector<ObjCIvarDecl *, 16> IVars;
IVars.reserve(NumIvars);
diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp
index 9ac12fb..90d135d 100644
--- a/lib/Serialization/ASTWriterDecl.cpp
+++ b/lib/Serialization/ASTWriterDecl.cpp
@@ -343,7 +343,9 @@
VisitObjCContainerDecl(D);
Writer.AddTypeRef(QualType(D->getTypeForDecl(), 0), Record);
Writer.AddDeclRef(D->getSuperClass(), Record);
- Record.push_back(D->protocol_size());
+
+ // Write out the protocols that are directly referenced by the @interface.
+ Record.push_back(D->ReferencedProtocols.size());
for (ObjCInterfaceDecl::protocol_iterator P = D->protocol_begin(),
PEnd = D->protocol_end();
P != PEnd; ++P)
@@ -352,6 +354,16 @@
PLEnd = D->protocol_loc_end();
PL != PLEnd; ++PL)
Writer.AddSourceLocation(*PL, Record);
+
+ // Write out the protocols that are transitively referenced.
+ Record.push_back(D->AllReferencedProtocols.size());
+ for (ObjCList<ObjCProtocolDecl>::iterator
+ P = D->AllReferencedProtocols.begin(),
+ PEnd = D->AllReferencedProtocols.end();
+ P != PEnd; ++P)
+ Writer.AddDeclRef(*P, Record);
+
+ // Write out the ivars.
Record.push_back(D->ivar_size());
for (ObjCInterfaceDecl::ivar_iterator I = D->ivar_begin(),
IEnd = D->ivar_end(); I != IEnd; ++I)
diff --git a/test/Index/local-symbols.m b/test/Index/local-symbols.m
index 8557e7f..b9f4fe2 100644
--- a/test/Index/local-symbols.m
+++ b/test/Index/local-symbols.m
@@ -15,6 +15,17 @@
}
@end
+// From: <rdar://problem/8380046>
+
+@protocol Prot8380046
+@end
+
+@interface R8380046
+@end
+
+@interface R8380046 () <Prot8380046>
+@end
+
// CHECK: local-symbols.m:6:12: ObjCInterfaceDecl=Foo:6:12 Extent=[6:1 - 10:5]
// CHECK: local-symbols.m:7:6: ObjCIvarDecl=x:7:6 (Definition) Extent=[7:6 - 7:7]
// CHECK: local-symbols.m:7:3: TypeRef=id:0:0 Extent=[7:3 - 7:5]
@@ -23,4 +34,11 @@
// CHECK: local-symbols.m:12:1: ObjCImplementationDecl=Foo:12:1 (Definition) Extent=[12:1 - 16:2]
// CHECK: local-symbols.m:13:1: ObjCInstanceMethodDecl=bar:13:1 (Definition) Extent=[13:1 - 15:2]
// CHECK: local-symbols.m:13:4: TypeRef=id:0:0 Extent=[13:4 - 13:6]
+// CHECK: local-symbols.m:14:10: UnexposedExpr= Extent=[14:10 - 14:11]
+// CHECK: local-symbols.m:14:10: UnexposedExpr= Extent=[14:10 - 14:11]
+// CHECK: local-symbols.m:20:1: ObjCProtocolDecl=Prot8380046:20:1 (Definition) Extent=[20:1 - 21:5]
+// CHECK: local-symbols.m:23:12: ObjCInterfaceDecl=R8380046:23:12 Extent=[23:1 - 24:5]
+// CHECK: local-symbols.m:26:12: ObjCCategoryDecl=:26:12 Extent=[26:1 - 27:5]
+// CHECK: local-symbols.m:26:12: ObjCClassRef=R8380046:23:12 Extent=[26:12 - 26:20]
+// CHECK: local-symbols.m:26:25: ObjCProtocolRef=Prot8380046:20:1 Extent=[26:25 - 26:36]