зеркало из https://github.com/microsoft/clang-1.git
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:
Родитель
763051df06
Коммит
894c57f565
|
@ -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
|
Загрузка…
Ссылка в новой задаче