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.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@42218 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/Sema/SemaDecl.cpp b/Sema/SemaDecl.cpp
index a82aea9..ff76203 100644
--- a/Sema/SemaDecl.cpp
+++ b/Sema/SemaDecl.cpp
@@ -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");
+  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);
+    // 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);