[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