[cfe-commits] r42218 - in /cfe/trunk: Sema/SemaDecl.cpp include/clang/AST/Decl.h include/clang/Basic/DiagnosticKinds.def test/Sema/category-1.m test/Sema/class-proto-1.m
Fariborz Jahanian
fjahanian at apple.com
Fri Sep 21 17:01:36 PDT 2007
Author: fjahanian
Date: Fri Sep 21 19:01:35 2007
New Revision: 42218
URL: http://llvm.org/viewvc/llvm-project?rev=42218&view=rev
Log:
This patch adds to new things to clang:
1. Handles saving and checking on protocols used in an @interface declaration
2. Checks and saves class's super class.
3. Adds semantic check to category declarations.
Added:
cfe/trunk/test/Sema/category-1.m
cfe/trunk/test/Sema/class-proto-1.m
Modified:
cfe/trunk/Sema/SemaDecl.cpp
cfe/trunk/include/clang/AST/Decl.h
cfe/trunk/include/clang/Basic/DiagnosticKinds.def
Modified: cfe/trunk/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Sema/SemaDecl.cpp?rev=42218&r1=42217&r2=42218&view=diff
==============================================================================
--- cfe/trunk/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/Sema/SemaDecl.cpp Fri Sep 21 19:01:35 2007
@@ -875,11 +875,13 @@
// Class already seen. Is it a forward declaration?
if (!IDecl->getIsForwardDecl())
Diag(AtInterfaceLoc, diag::err_duplicate_class_def, ClassName->getName());
- else
+ else {
IDecl->setIsForwardDecl(false);
+ IDecl->AllocIntfRefProtocols(NumProtocols);
+ }
}
else {
- IDecl = new ObjcInterfaceDecl(AtInterfaceLoc, ClassName);
+ IDecl = new ObjcInterfaceDecl(AtInterfaceLoc, NumProtocols, ClassName);
// Chain & install the interface decl into the identifier.
IDecl->setNext(ClassName->getFETokenInfo<ScopedDecl>());
@@ -887,15 +889,28 @@
}
if (SuperName) {
- const ObjcInterfaceDecl* SuperClassEntry =
- Context.getObjCInterfaceDecl(SuperName);
+ ObjcInterfaceDecl* SuperClassEntry =
+ Context.getObjCInterfaceDecl(SuperName);
if (!SuperClassEntry || SuperClassEntry->getIsForwardDecl()) {
Diag(AtInterfaceLoc, diag::err_undef_superclass, SuperName->getName(),
ClassName->getName());
}
+ else
+ IDecl->setSuperClass(SuperClassEntry);
}
+ /// Check then save referenced protocols
+ for (unsigned int i = 0; i != NumProtocols; i++) {
+ ObjcProtocolDecl* RefPDecl = Context.getObjCProtocolDecl(ProtocolNames[i]);
+ if (!RefPDecl || RefPDecl->getIsForwardProtoDecl())
+ Diag(ClassLoc, diag::err_undef_protocolref,
+ ProtocolNames[i]->getName(),
+ ClassName->getName());
+ IDecl->setIntfRefProtocols((int)i, RefPDecl);
+ }
+
+
Context.setObjCInterfaceDecl(ClassName, IDecl);
return IDecl;
@@ -970,15 +985,50 @@
IdentifierInfo *CategoryName, SourceLocation CategoryLoc,
IdentifierInfo **ProtoRefNames, unsigned NumProtoRefs) {
ObjcCategoryDecl *CDecl;
- CDecl = new ObjcCategoryDecl(AtInterfaceLoc, ClassName);
- assert (ClassName->getFETokenInfo<ScopedDecl>() && "Missing @interface decl");
- Decl *D = static_cast<Decl *>(ClassName->getFETokenInfo<ScopedDecl>());
- assert(isa<ObjcInterfaceDecl>(D) && "Missing @interface decl");
-
- // Chain & install the category decl into the identifier.
- // Note that head of the chain is the @interface class type and follow up
- // nodes in the chain are the protocol decl nodes.
- cast<ObjcInterfaceDecl>(D)->setNext(CDecl);
+ ObjcInterfaceDecl* IDecl = Context.getObjCInterfaceDecl(ClassName);
+ CDecl = new ObjcCategoryDecl(AtInterfaceLoc, NumProtoRefs, ClassName);
+ if (IDecl) {
+ assert (ClassName->getFETokenInfo<ScopedDecl>() && "Missing @interface decl");
+ Decl *D = static_cast<Decl *>(ClassName->getFETokenInfo<ScopedDecl>());
+ assert(isa<ObjcInterfaceDecl>(D) && "Missing @interface decl");
+
+ // Chain & install the category decl into the identifier.
+ // Note that head of the chain is the @interface class type and follow up
+ // nodes in the chain are the protocol decl nodes.
+ cast<ObjcInterfaceDecl>(D)->setNext(CDecl);
+ }
+
+ CDecl->setClassInterface(IDecl);
+ /// Check that class of this category is already completely declared.
+ if (!IDecl || IDecl->getIsForwardDecl())
+ Diag(ClassLoc, diag::err_undef_interface, ClassName->getName());
+ else {
+ /// Check for duplicate interface declaration for this category
+ ObjcCategoryDecl *CDeclChain;
+ for (CDeclChain = IDecl->getListCategories(); CDeclChain;
+ CDeclChain = CDeclChain->getNextClassCategory()) {
+ if (CDeclChain->getCatName() == CategoryName) {
+ Diag(CategoryLoc, diag::err_dup_category_def, ClassName->getName(),
+ CategoryName->getName());
+ break;
+ }
+ }
+ if (!CDeclChain) {
+ CDecl->setCatName(CategoryName);
+ CDecl->insertNextClassCategory();
+ }
+ }
+
+ /// Check then save referenced protocols
+ for (unsigned int i = 0; i != NumProtoRefs; i++) {
+ ObjcProtocolDecl* RefPDecl = Context.getObjCProtocolDecl(ProtoRefNames[i]);
+ if (!RefPDecl || RefPDecl->getIsForwardProtoDecl())
+ Diag(CategoryLoc, diag::err_undef_protocolref,
+ ProtoRefNames[i]->getName(),
+ CategoryName->getName());
+ CDecl->setCatReferencedProtocols((int)i, RefPDecl);
+ }
+
return CDecl;
}
@@ -993,7 +1043,7 @@
ObjcInterfaceDecl *IDecl;
IDecl = Context.getObjCInterfaceDecl(IdentList[i]);
if (!IDecl) {// Already seen?
- IDecl = new ObjcInterfaceDecl(SourceLocation(), IdentList[i], true);
+ IDecl = new ObjcInterfaceDecl(SourceLocation(), 0, IdentList[i], true);
// Chain & install the interface decl into the identifier.
IDecl->setNext(IdentList[i]->getFETokenInfo<ScopedDecl>());
IdentList[i]->setFETokenInfo(IDecl);
Modified: cfe/trunk/include/clang/AST/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=42218&r1=42217&r2=42218&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Fri Sep 21 19:01:35 2007
@@ -26,6 +26,8 @@
class AttributeList;
class ObjcIvarDecl;
class ObjcMethodDecl;
+class ObjcProtocolDecl;
+class ObjcCategoryDecl;
/// Decl - This represents one declaration (or definition), e.g. a variable,
@@ -539,6 +541,14 @@
};
class ObjcInterfaceDecl : public TypeDecl {
+
+ /// Class's super class.
+ ObjcInterfaceDecl *SuperClass;
+
+ /// Protocols referenced in interface header declaration
+ ObjcProtocolDecl **IntfRefProtocols; // Null if none
+ int NumIntfRefProtocols; // -1 if none
+
/// Ivars/NumIvars - This is a new[]'d array of pointers to Decls.
ObjcIvarDecl **Ivars; // Null if not defined.
int NumIvars; // -1 if not defined.
@@ -551,13 +561,31 @@
ObjcMethodDecl **ClsMethods; // Null if not defined
int NumClsMethods; // -1 if not defined
+ /// List of categories defined for this class.
+ ObjcCategoryDecl *ListCategories;
+
bool isForwardDecl; // declared with @class.
public:
- ObjcInterfaceDecl(SourceLocation L, IdentifierInfo *Id, bool FD = false)
- : TypeDecl(ObjcInterface, L, Id, 0), Ivars(0), NumIvars(-1),
+ ObjcInterfaceDecl(SourceLocation L, unsigned numRefProtos,
+ IdentifierInfo *Id, bool FD = false)
+ : TypeDecl(ObjcInterface, L, Id, 0),
+ SuperClass(0),
+ IntfRefProtocols(0), NumIntfRefProtocols(-1),
+ Ivars(0), NumIvars(-1),
InsMethods(0), NumInsMethods(-1), ClsMethods(0), NumClsMethods(-1),
- isForwardDecl(FD) { }
-
+ ListCategories(0),
+ isForwardDecl(FD) {
+ AllocIntfRefProtocols(numRefProtos);
+ }
+
+ void AllocIntfRefProtocols(unsigned numRefProtos) {
+ if (numRefProtos) {
+ IntfRefProtocols = new ObjcProtocolDecl*[numRefProtos];
+ memset(IntfRefProtocols, '\0',
+ numRefProtos*sizeof(ObjcProtocolDecl*));
+ NumIntfRefProtocols = numRefProtos;
+ }
+ }
void ObjcAddInstanceVariablesToClass(ObjcIvarDecl **ivars,
unsigned numIvars);
@@ -567,6 +595,19 @@
bool getIsForwardDecl() const { return isForwardDecl; }
void setIsForwardDecl(bool val) { isForwardDecl = val; }
+ void setIntfRefProtocols(int idx, ObjcProtocolDecl *OID) {
+ assert((idx < NumIntfRefProtocols) && "index out of range");
+ IntfRefProtocols[idx] = OID;
+ }
+
+ ObjcInterfaceDecl *getSuperClass() const { return SuperClass; }
+ void setSuperClass(ObjcInterfaceDecl * superCls) { SuperClass = superCls; }
+
+ ObjcCategoryDecl* getListCategories() const { return ListCategories; }
+ void setListCategories(ObjcCategoryDecl *category) {
+ ListCategories = category;
+ }
+
static bool classof(const Decl *D) {
return D->getKind() == ObjcInterface;
}
@@ -752,6 +793,16 @@
};
class ObjcCategoryDecl : public ScopedDecl {
+ /// Interface belonging to this category
+ ObjcInterfaceDecl *ClassInterface;
+
+ /// Category name
+ IdentifierInfo *ObjcCatName;
+
+ /// referenced protocols in this category
+ ObjcProtocolDecl **CatReferencedProtocols; // Null if none
+ int NumCatReferencedProtocols; // -1 if none
+
/// category instance methods
ObjcMethodDecl **CatInsMethods; // Null if not defined
int NumCatInsMethods; // -1 if not defined
@@ -760,21 +811,45 @@
ObjcMethodDecl **CatClsMethods; // Null if not defined
int NumCatClsMethods; // -1 if not defined
- /// Category name
- IdentifierInfo *ObjcCatName;
+ /// Next category belonging to this class
+ ObjcCategoryDecl *NextClassCategory;
public:
- ObjcCategoryDecl(SourceLocation L, IdentifierInfo *Id)
+ ObjcCategoryDecl(SourceLocation L, unsigned numRefProtocol,
+ IdentifierInfo *Id)
: ScopedDecl(ObjcCategory, L, Id, 0),
+ ClassInterface(0), ObjcCatName(0),
+ CatReferencedProtocols(0), NumCatReferencedProtocols(-1),
CatInsMethods(0), NumCatInsMethods(-1),
CatClsMethods(0), NumCatClsMethods(-1),
- ObjcCatName(0) {}
+ NextClassCategory(0) {
+ if (numRefProtocol) {
+ CatReferencedProtocols = new ObjcProtocolDecl*[numRefProtocol];
+ memset(CatReferencedProtocols, '\0',
+ numRefProtocol*sizeof(ObjcProtocolDecl*));
+ NumCatReferencedProtocols = numRefProtocol;
+ }
+ }
+ ObjcInterfaceDecl *getClassInterface() const { return ClassInterface; }
+ void setClassInterface(ObjcInterfaceDecl *IDecl) { ClassInterface = IDecl; }
+
+ void setCatReferencedProtocols(int idx, ObjcProtocolDecl *OID) {
+ assert((idx < NumCatReferencedProtocols) && "index out of range");
+ CatReferencedProtocols[idx] = OID;
+ }
+
void ObjcAddCatMethods(ObjcMethodDecl **insMethods, unsigned numInsMembers,
ObjcMethodDecl **clsMethods, unsigned numClsMembers);
IdentifierInfo *getCatName() const { return ObjcCatName; }
void setCatName(IdentifierInfo *catName) { ObjcCatName = catName; }
+
+ ObjcCategoryDecl *getNextClassCategory() const { return NextClassCategory; }
+ void insertNextClassCategory() {
+ NextClassCategory = ClassInterface->getListCategories();
+ ClassInterface->setListCategories(this);
+ }
static bool classof(const Decl *D) {
return D->getKind() == ObjcCategory;
Modified: cfe/trunk/include/clang/Basic/DiagnosticKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticKinds.def?rev=42218&r1=42217&r2=42218&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticKinds.def Fri Sep 21 19:01:35 2007
@@ -416,6 +416,10 @@
"cannot find protocol definition for '%0', referenced by '%1'")
DIAG(err_duplicate_protocol_def, ERROR,
"duplicate protocol declaration of '%0'")
+DIAG(err_undef_interface, ERROR,
+ "cannot find interface declaration for '%0'")
+DIAG(err_dup_category_def, ERROR,
+ "duplicate interface declaration for category '%0(%1)'")
//===----------------------------------------------------------------------===//
// Semantic Analysis
Added: cfe/trunk/test/Sema/category-1.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/category-1.m?rev=42218&view=auto
==============================================================================
--- cfe/trunk/test/Sema/category-1.m (added)
+++ cfe/trunk/test/Sema/category-1.m Fri Sep 21 19:01:35 2007
@@ -0,0 +1,36 @@
+ at interface MyClass1 @end
+
+ at protocol p1,p2,p3;
+
+ at interface MyClass1 (Category1) <p1> // expected-error {{cannot find protocol definition for 'p1', referenced by 'Category1'}}
+ at end
+
+ at interface MyClass1 (Category1) // expected-error {{duplicate interface declaration for category 'MyClass1(Category1)'}}
+ at end
+
+ at interface MyClass1 (Category3)
+ at end
+
+ at interface MyClass1 (Category4) @end
+ at interface MyClass1 (Category5) @end
+ at interface MyClass1 (Category6) @end
+ at interface MyClass1 (Category7) @end
+ at interface MyClass1 (Category8) @end
+
+
+ at interface MyClass1 (Category4) @end // expected-error {{duplicate interface declaration for category 'MyClass1(Category4)'}}
+ at interface MyClass1 (Category7) @end // expected-error {{duplicate interface declaration for category 'MyClass1(Category7)'}}
+ at interface MyClass1 (Category8) @end // expected-error {{duplicate interface declaration for category 'MyClass1(Category8)'}}
+
+
+ at protocol p3 @end
+
+ at interface MyClass1 (Category) <p2, p3> @end // expected-error {{cannot find protocol definition for 'p2', referenced by 'Category'}}
+
+ at interface MyClass (Category) @end // expected-error {{cannot find interface declaration for 'MyClass'}}
+
+ at class MyClass2;
+
+ at interface MyClass2 (Category) @end // expected-error {{cannot find interface declaration for 'MyClass2'}}
+
+
Added: cfe/trunk/test/Sema/class-proto-1.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/class-proto-1.m?rev=42218&view=auto
==============================================================================
--- cfe/trunk/test/Sema/class-proto-1.m (added)
+++ cfe/trunk/test/Sema/class-proto-1.m Fri Sep 21 19:01:35 2007
@@ -0,0 +1,34 @@
+ at interface INTF1 @end
+
+ at protocol p1,p2,p3;
+
+ at protocol p1;
+
+ at protocol PROTO1
+- (INTF1<p1>*) meth;
+ at end
+
+ at protocol p1 @end
+
+ at interface I1 <p1> @end
+
+ at interface E1 <p2> @end // expected-error {{cannot find protocol definition for 'p2', referenced by 'E1'}}
+
+ at protocol p2 @end
+
+
+ at interface I2 <p1,p2> @end
+
+ at interface E2 <p1,p2,p3> @end // expected-error {{cannot find protocol definition for 'p3', referenced by 'E2'}}
+
+ at class U1, U2;
+
+ at interface E3 : U1 @end // expected-error {{cannot find interface declaration for 'U1', superclass of 'E3'}}
+
+
+ at interface I3 : E3 @end
+
+ at interface U2 @end
+
+ at interface I4 : U2 <p1,p2>
+ at end
More information about the cfe-commits
mailing list