This patch instantiates objects for forward protocols and in general handles use of
protocols referenced in @protocol declarations.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@42191 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/Sema/SemaDecl.cpp b/Sema/SemaDecl.cpp
index f46ec42..a82aea9 100644
--- a/Sema/SemaDecl.cpp
+++ b/Sema/SemaDecl.cpp
@@ -905,16 +905,66 @@
IdentifierInfo *ProtocolName, SourceLocation ProtocolLoc,
IdentifierInfo **ProtoRefNames, unsigned NumProtoRefs) {
assert(ProtocolName && "Missing protocol identifier");
- ObjcProtocolDecl *PDecl;
+ ObjcProtocolDecl *PDecl = Context.getObjCProtocolDecl(ProtocolName);
+ if (PDecl) {
+ // Protocol already seen. Better be a forward protocol declaration
+ if (!PDecl->getIsForwardProtoDecl())
+ Diag(ProtocolLoc, diag::err_duplicate_protocol_def,
+ ProtocolName->getName());
+ else {
+ PDecl->setIsForwardProtoDecl(false);
+ PDecl->AllocReferencedProtocols(NumProtoRefs);
+ }
+ }
+ else {
+ PDecl = new ObjcProtocolDecl(AtProtoInterfaceLoc, NumProtoRefs,
+ ProtocolName);
+ PDecl->setIsForwardProtoDecl(false);
+ // Chain & install the protocol decl into the identifier.
+ PDecl->setNext(ProtocolName->getFETokenInfo<ScopedDecl>());
+ ProtocolName->setFETokenInfo(PDecl);
+ Context.setObjCProtocolDecl(ProtocolName, PDecl);
+ }
+
+ /// Check then save referenced protocols
+ for (unsigned int i = 0; i != NumProtoRefs; i++) {
+ ObjcProtocolDecl* RefPDecl = Context.getObjCProtocolDecl(ProtoRefNames[i]);
+ if (!RefPDecl || RefPDecl->getIsForwardProtoDecl())
+ Diag(ProtocolLoc, diag::err_undef_protocolref,
+ ProtoRefNames[i]->getName(),
+ ProtocolName->getName());
+ PDecl->setReferencedProtocols((int)i, RefPDecl);
+ }
- PDecl = new ObjcProtocolDecl(AtProtoInterfaceLoc, ProtocolName);
-
- // Chain & install the protocol decl into the identifier.
- PDecl->setNext(ProtocolName->getFETokenInfo<ScopedDecl>());
- ProtocolName->setFETokenInfo(PDecl);
return PDecl;
}
+/// ObjcForwardProtocolDeclaration -
+/// Scope will always be top level file scope.
+Action::DeclTy *
+Sema::ObjcForwardProtocolDeclaration(Scope *S, SourceLocation AtProtocolLoc,
+ IdentifierInfo **IdentList, unsigned NumElts) {
+ ObjcForwardProtocolDecl *FDecl = new ObjcForwardProtocolDecl(AtProtocolLoc,
+ NumElts);
+
+ for (unsigned i = 0; i != NumElts; ++i) {
+ ObjcProtocolDecl *PDecl;
+ PDecl = Context.getObjCProtocolDecl(IdentList[i]);
+ if (!PDecl) {// Already seen?
+ PDecl = new ObjcProtocolDecl(SourceLocation(), 0, IdentList[i], true);
+ // Chain & install the protocol decl into the identifier.
+ PDecl->setNext(IdentList[i]->getFETokenInfo<ScopedDecl>());
+ IdentList[i]->setFETokenInfo(PDecl);
+ Context.setObjCProtocolDecl(IdentList[i], PDecl);
+ }
+ // Remember that this needs to be removed when the scope is popped.
+ S->AddDecl(IdentList[i]);
+
+ FDecl->setForwardProtocolDecl((int)i, PDecl);
+ }
+ return FDecl;
+}
+
Sema::DeclTy *Sema::ObjcStartCatInterface(SourceLocation AtInterfaceLoc,
IdentifierInfo *ClassName, SourceLocation ClassLoc,
IdentifierInfo *CategoryName, SourceLocation CategoryLoc,