[cfe-commits] r42191 - in /cfe/trunk: AST/Decl.cpp Parse/MinimalAction.cpp Parse/ParseObjc.cpp Sema/Sema.h Sema/SemaDecl.cpp include/clang/AST/ASTContext.h include/clang/AST/Decl.h include/clang/Basic/DiagnosticKinds.def include/clang/Parse/Action.h test/Sema/protocol-test-2.m
Fariborz Jahanian
fjahanian at apple.com
Fri Sep 21 08:40:54 PDT 2007
Author: fjahanian
Date: Fri Sep 21 10:40:54 2007
New Revision: 42191
URL: http://llvm.org/viewvc/llvm-project?rev=42191&view=rev
Log:
This patch instantiates objects for forward protocols and in general handles use of
protocols referenced in @protocol declarations.
Added:
cfe/trunk/test/Sema/protocol-test-2.m
Modified:
cfe/trunk/AST/Decl.cpp
cfe/trunk/Parse/MinimalAction.cpp
cfe/trunk/Parse/ParseObjc.cpp
cfe/trunk/Sema/Sema.h
cfe/trunk/Sema/SemaDecl.cpp
cfe/trunk/include/clang/AST/ASTContext.h
cfe/trunk/include/clang/AST/Decl.h
cfe/trunk/include/clang/Basic/DiagnosticKinds.def
cfe/trunk/include/clang/Parse/Action.h
Modified: cfe/trunk/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/AST/Decl.cpp?rev=42191&r1=42190&r2=42191&view=diff
==============================================================================
--- cfe/trunk/AST/Decl.cpp (original)
+++ cfe/trunk/AST/Decl.cpp Fri Sep 21 10:40:54 2007
@@ -29,6 +29,7 @@
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 @@
return "ObjcProtoMethod";
case ObjcProtocol:
return "ObjcProtocol";
+ case ObjcForwardProtocol:
+ return "ObjcForwardProtocol";
case Struct:
return "Struct";
case Union:
@@ -122,6 +125,9 @@
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 @@
case ObjcProtocol:
nProtocolDecls++;
break;
+ case ObjcForwardProtocol:
+ nForwardProtocolDecls++;
+ break;
case ObjcCategory:
nCategoryDecls++;
break;
Modified: cfe/trunk/Parse/MinimalAction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Parse/MinimalAction.cpp?rev=42191&r1=42190&r2=42191&view=diff
==============================================================================
--- cfe/trunk/Parse/MinimalAction.cpp (original)
+++ cfe/trunk/Parse/MinimalAction.cpp Fri Sep 21 10:40:54 2007
@@ -109,6 +109,23 @@
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) {
Modified: cfe/trunk/Parse/ParseObjc.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Parse/ParseObjc.cpp?rev=42191&r1=42190&r2=42191&view=diff
==============================================================================
--- cfe/trunk/Parse/ParseObjc.cpp (original)
+++ cfe/trunk/Parse/ParseObjc.cpp Fri Sep 21 10:40:54 2007
@@ -713,13 +713,13 @@
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 @@
// 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;
Modified: cfe/trunk/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Sema/Sema.h?rev=42191&r1=42190&r2=42191&view=diff
==============================================================================
--- cfe/trunk/Sema/Sema.h (original)
+++ cfe/trunk/Sema/Sema.h Fri Sep 21 10:40:54 2007
@@ -370,6 +370,11 @@
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);
Modified: cfe/trunk/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Sema/SemaDecl.cpp?rev=42191&r1=42190&r2=42191&view=diff
==============================================================================
--- cfe/trunk/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/Sema/SemaDecl.cpp Fri Sep 21 10:40:54 2007
@@ -905,16 +905,66 @@
IdentifierInfo *ProtocolName, SourceLocation ProtocolLoc,
IdentifierInfo **ProtoRefNames, unsigned NumProtoRefs) {
assert(ProtocolName && "Missing protocol identifier");
- ObjcProtocolDecl *PDecl;
-
- PDecl = new ObjcProtocolDecl(AtProtoInterfaceLoc, ProtocolName);
+ 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);
+ }
- // 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,
Modified: cfe/trunk/include/clang/AST/ASTContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=42191&r1=42190&r2=42191&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Fri Sep 21 10:40:54 2007
@@ -38,6 +38,7 @@
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 @@
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
//===--------------------------------------------------------------------===//
Modified: cfe/trunk/include/clang/AST/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=42191&r1=42190&r2=42191&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Fri Sep 21 10:40:54 2007
@@ -38,7 +38,7 @@
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 @@
};
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 @@
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
Modified: cfe/trunk/include/clang/Basic/DiagnosticKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticKinds.def?rev=42191&r1=42190&r2=42191&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticKinds.def Fri Sep 21 10:40:54 2007
@@ -412,7 +412,10 @@
"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
Modified: cfe/trunk/include/clang/Parse/Action.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Action.h?rev=42191&r1=42190&r2=42191&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Action.h (original)
+++ cfe/trunk/include/clang/Parse/Action.h Fri Sep 21 10:40:54 2007
@@ -502,6 +502,14 @@
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 @@
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,
Added: cfe/trunk/test/Sema/protocol-test-2.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/protocol-test-2.m?rev=42191&view=auto
==============================================================================
--- cfe/trunk/test/Sema/protocol-test-2.m (added)
+++ cfe/trunk/test/Sema/protocol-test-2.m Fri Sep 21 10:40:54 2007
@@ -0,0 +1,29 @@
+ at interface INTF1 @end
+
+ at protocol p1,p2,p3;
+
+ at protocol p1;
+
+ at protocol PROTO1
+- (INTF1<p1>*) meth;
+ at end
+
+ at protocol PROTO2<p1> // expected-error {{cannot find protocol definition for 'p1', referenced by 'PROTO2'}}
+ at end
+
+ at protocol p1 @end
+
+ at protocol PROTO<p1>
+ at end
+
+ at protocol PROTO<p1> // expected-error {{duplicate protocol declaration of 'PROTO'}}
+ at end
+
+ at protocol PROTO3<p1, p1>
+ at end
+
+ at protocol p2 <p1>
+ at end
+
+ at protocol PROTO4 <p1, p2, PROTO, PROTO3, p3> // expected-error {{cannot find protocol definition for 'p3', referenced by 'PROTO4'}}
+ at end
More information about the cfe-commits
mailing list