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
This commit is contained in:
Fariborz Jahanian 2007-09-21 15:40:54 +00:00
Родитель 763051df06
Коммит 894c57f565
10 изменённых файлов: 197 добавлений и 16 удалений

Просмотреть файл

@ -29,6 +29,7 @@ static unsigned nInterfaceDecls = 0;
static unsigned nClassDecls = 0;
static unsigned nMethodDecls = 0;
static unsigned nProtocolDecls = 0;
static unsigned nForwardProtocolDecls = 0;
static unsigned nCategoryDecls = 0;
static unsigned nIvarDecls = 0;
@ -59,6 +60,8 @@ const char *Decl::getDeclKindName() const {
return "ObjcProtoMethod";
case ObjcProtocol:
return "ObjcProtocol";
case ObjcForwardProtocol:
return "ObjcForwardProtocol";
case Struct:
return "Struct";
case Union:
@ -122,6 +125,9 @@ void Decl::PrintStats() {
fprintf(stderr, " %d protocol decls, %d each (%d bytes)\n",
nProtocolDecls, (int)sizeof(ObjcProtocolDecl),
int(nProtocolDecls*sizeof(ObjcProtocolDecl)));
fprintf(stderr, " %d forward protocol decls, %d each (%d bytes)\n",
nForwardProtocolDecls, (int)sizeof(ObjcForwardProtocolDecl),
int(nForwardProtocolDecls*sizeof(ObjcForwardProtocolDecl)));
fprintf(stderr, " %d category decls, %d each (%d bytes)\n",
nCategoryDecls, (int)sizeof(ObjcCategoryDecl),
int(nCategoryDecls*sizeof(ObjcCategoryDecl)));
@ -178,6 +184,9 @@ void Decl::addDeclKind(const Kind k) {
case ObjcProtocol:
nProtocolDecls++;
break;
case ObjcForwardProtocol:
nForwardProtocolDecls++;
break;
case ObjcCategory:
nCategoryDecls++;
break;

Просмотреть файл

@ -109,6 +109,23 @@ MinimalAction::ObjcClassDeclaration(Scope *S, SourceLocation AtClassLoc,
return 0;
}
/// ObjcForwardProtocolDeclaration -
/// Scope will always be top level file scope.
Action::DeclTy *
MinimalAction::ObjcForwardProtocolDeclaration(Scope *S, SourceLocation AtClassLoc,
IdentifierInfo **IdentList, unsigned NumElts) {
for (unsigned i = 0; i != NumElts; ++i) {
TypeNameInfo *TI =
new TypeNameInfo(1, IdentList[i]->getFETokenInfo<TypeNameInfo>());
IdentList[i]->setFETokenInfo(TI);
// Remember that this needs to be removed when the scope is popped.
S->AddDecl(IdentList[i]);
}
return 0;
}
/// PopScope - When a scope is popped, if any typedefs are now out-of-scope,
/// they are removed from the IdentifierInfo::FETokenInfo field.
void MinimalAction::PopScope(SourceLocation Loc, Scope *S) {

Просмотреть файл

@ -713,13 +713,13 @@ Parser::DeclTy *Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc) {
IdentifierInfo *protocolName = Tok.getIdentifierInfo();
SourceLocation nameLoc = ConsumeToken();
if (Tok.getKind() == tok::semi) { // forward declaration.
llvm::SmallVector<IdentifierInfo *, 8> ProtocolRefs;
if (Tok.getKind() == tok::semi) { // forward declaration of one protocol.
ConsumeToken();
return 0; // FIXME: add protocolName
ProtocolRefs.push_back(protocolName);
}
if (Tok.getKind() == tok::comma) { // list of forward declarations.
// Parse the list of forward declarations.
llvm::SmallVector<IdentifierInfo *, 8> ProtocolRefs;
ProtocolRefs.push_back(protocolName);
while (1) {
@ -738,10 +738,12 @@ Parser::DeclTy *Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc) {
// Consume the ';'.
if (ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "@protocol"))
return 0;
return 0; // FIXME
}
if (ProtocolRefs.size() > 0)
return Actions.ObjcForwardProtocolDeclaration(CurScope, AtLoc,
&ProtocolRefs[0],
ProtocolRefs.size());
// Last, and definitely not least, parse a protocol declaration.
llvm::SmallVector<IdentifierInfo *, 8> ProtocolRefs;
if (Tok.getKind() == tok::less) {
if (ParseObjCProtocolReferences(ProtocolRefs))
return 0;

Просмотреть файл

@ -370,6 +370,11 @@ public:
virtual DeclTy *ObjcClassDeclaration(Scope *S, SourceLocation AtClassLoc,
IdentifierInfo **IdentList,
unsigned NumElts);
virtual DeclTy *ObjcForwardProtocolDeclaration(Scope *S,
SourceLocation AtProtocolLoc,
IdentifierInfo **IdentList,
unsigned NumElts);
virtual void ObjcAddMethodsToClass(DeclTy *ClassDecl,
DeclTy **allMethods, unsigned allNum);

Просмотреть файл

@ -905,16 +905,66 @@ Sema::DeclTy *Sema::ObjcStartProtoInterface(SourceLocation AtProtoInterfaceLoc,
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,

Просмотреть файл

@ -38,6 +38,7 @@ class ASTContext {
llvm::FoldingSet<FunctionTypeProto> FunctionTypeProtos;
llvm::DenseMap<const RecordDecl*, const RecordLayout*> RecordLayoutInfo;
llvm::DenseMap<const IdentifierInfo*, ObjcInterfaceDecl*> ClassNameInfo;
llvm::DenseMap<const IdentifierInfo*, ObjcProtocolDecl*> ProtocolNameInfo;
RecordDecl *CFConstantStringTypeDecl;
public:
@ -165,6 +166,12 @@ public:
ObjcInterfaceDecl* InterfaceDecl)
{ ClassNameInfo[ClassName] = InterfaceDecl; }
ObjcProtocolDecl* getObjCProtocolDecl(const IdentifierInfo* ProtocolName)
{ return ProtocolNameInfo[ProtocolName]; }
void setObjCProtocolDecl(const IdentifierInfo* ProtocolName,
ObjcProtocolDecl* ProtocolDecl)
{ ProtocolNameInfo[ProtocolName] = ProtocolDecl; }
//===--------------------------------------------------------------------===//
// Type Operators
//===--------------------------------------------------------------------===//

Просмотреть файл

@ -38,7 +38,7 @@ public:
Function, BlockVariable, FileVariable, ParmVariable, EnumConstant,
// Concrete sub-classes of TypeDecl
Typedef, Struct, Union, Class, Enum, ObjcInterface, ObjcClass, ObjcMethod,
ObjcProtoMethod, ObjcProtocol, ObjcCategory,
ObjcProtoMethod, ObjcProtocol, ObjcForwardProtocol, ObjcCategory,
// Concrete sub-class of Decl
Field, ObjcIvar
};
@ -680,6 +680,10 @@ public:
};
class ObjcProtocolDecl : public TypeDecl {
/// referenced protocols
ObjcProtocolDecl **ReferencedProtocols; // Null if none
int NumReferencedProtocols; // -1 if none
/// protocol instance methods
ObjcMethodDecl **ProtoInsMethods; // Null if not defined
int NumProtoInsMethods; // -1 if not defined
@ -690,20 +694,62 @@ class ObjcProtocolDecl : public TypeDecl {
bool isForwardProtoDecl; // declared with @protocol.
public:
ObjcProtocolDecl(SourceLocation L, IdentifierInfo *Id, bool FD = false)
ObjcProtocolDecl(SourceLocation L, unsigned numRefProtos,
IdentifierInfo *Id, bool FD = false)
: TypeDecl(ObjcProtocol, L, Id, 0),
ReferencedProtocols(0), NumReferencedProtocols(-1),
ProtoInsMethods(0), NumProtoInsMethods(-1),
ProtoClsMethods(0), NumProtoClsMethods(-1),
isForwardProtoDecl(FD) { }
isForwardProtoDecl(FD) {
AllocReferencedProtocols(numRefProtos);
}
void AllocReferencedProtocols(unsigned numRefProtos) {
if (numRefProtos) {
ReferencedProtocols = new ObjcProtocolDecl*[numRefProtos];
memset(ReferencedProtocols, '\0',
numRefProtos*sizeof(ObjcProtocolDecl*));
NumReferencedProtocols = numRefProtos;
}
}
void ObjcAddProtoMethods(ObjcMethodDecl **insMethods, unsigned numInsMembers,
ObjcMethodDecl **clsMethods, unsigned numClsMembers);
void setReferencedProtocols(int idx, ObjcProtocolDecl *OID) {
assert((idx < NumReferencedProtocols) && "index out of range");
ReferencedProtocols[idx] = OID;
}
bool getIsForwardProtoDecl() const { return isForwardProtoDecl; }
void setIsForwardProtoDecl(bool val) { isForwardProtoDecl = val; }
static bool classof(const Decl *D) {
return D->getKind() == ObjcProtocol;
}
static bool classof(const ObjcProtocolDecl *D) { return true; }
};
class ObjcForwardProtocolDecl : public TypeDecl {
ObjcProtocolDecl **ForwardProtocolDecls; // Null if not defined.
int NumForwardProtocolDecls; // -1 if not defined.
public:
ObjcForwardProtocolDecl(SourceLocation L, unsigned nElts)
: TypeDecl(ObjcForwardProtocol, L, 0, 0) {
if (nElts) {
ForwardProtocolDecls = new ObjcProtocolDecl*[nElts];
memset(ForwardProtocolDecls, '\0', nElts*sizeof(ObjcProtocolDecl*));
NumForwardProtocolDecls = nElts;
}
}
void setForwardProtocolDecl(int idx, ObjcProtocolDecl *OID) {
assert((idx < NumForwardProtocolDecls) && "index out of range");
ForwardProtocolDecls[idx] = OID;
}
static bool classof(const Decl *D) {
return D->getKind() == ObjcForwardProtocol;
}
static bool classof(const ObjcForwardProtocolDecl *D) { return true; }
};
class ObjcCategoryDecl : public ScopedDecl {
/// category instance methods

Просмотреть файл

@ -412,7 +412,10 @@ DIAG(err_undef_superclass, ERROR,
"cannot find interface declaration for '%0', superclass of '%1'")
DIAG(err_duplicate_class_def, ERROR,
"duplicate interface declaration for class '%0'")
DIAG(err_undef_protocolref, ERROR,
"cannot find protocol definition for '%0', referenced by '%1'")
DIAG(err_duplicate_protocol_def, ERROR,
"duplicate protocol declaration of '%0'")
//===----------------------------------------------------------------------===//
// Semantic Analysis

Просмотреть файл

@ -502,6 +502,14 @@ public:
unsigned NumElts) {
return 0;
}
virtual DeclTy *ObjcForwardProtocolDeclaration(Scope *S,
SourceLocation AtProtocolLoc,
IdentifierInfo **IdentList,
unsigned NumElts) {
return 0;
}
virtual void ObjCStartCategoryInterface() { // FIXME
return;
}
@ -548,6 +556,11 @@ public:
IdentifierInfo **IdentList,
unsigned NumElts);
virtual DeclTy *ObjcForwardProtocolDeclaration(Scope *S,
SourceLocation AtProtocolLoc,
IdentifierInfo **IdentList,
unsigned NumElts);
virtual DeclTy *ObjcStartClassInterface(SourceLocation AtInterafceLoc,
IdentifierInfo *ClassName, SourceLocation ClassLoc,
IdentifierInfo *SuperName, SourceLocation SuperLoc,

Просмотреть файл

@ -0,0 +1,29 @@
@interface INTF1 @end
@protocol p1,p2,p3;
@protocol p1;
@protocol PROTO1
- (INTF1<p1>*) meth;
@end
@protocol PROTO2<p1> // expected-error {{cannot find protocol definition for 'p1', referenced by 'PROTO2'}}
@end
@protocol p1 @end
@protocol PROTO<p1>
@end
@protocol PROTO<p1> // expected-error {{duplicate protocol declaration of 'PROTO'}}
@end
@protocol PROTO3<p1, p1>
@end
@protocol p2 <p1>
@end
@protocol PROTO4 <p1, p2, PROTO, PROTO3, p3> // expected-error {{cannot find protocol definition for 'p3', referenced by 'PROTO4'}}
@end