- Introduce ASTContext::getObjCImplementation() and ASTContext::setObjCImplementation() which use a DenseMap to associate
  an interface/category with its implementation (if one exists).

- Introduce ObjCInterfaceDecl::get/setImplementation() and ObjCCategoryDecl::get/setImplementation() that use the above methods.

- Add a compiler error for when a category is reimplemented.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@76508 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp
index 8dc14ee..440b0fb 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -605,6 +605,19 @@
                       IdentifierInfo *ClassName, SourceLocation ClassLoc,
                       IdentifierInfo *CatName, SourceLocation CatLoc) {
   ObjCInterfaceDecl *IDecl = getObjCInterfaceDecl(ClassName);
+  ObjCCategoryDecl *CatIDecl = 0;
+  if (IDecl) {
+    CatIDecl = IDecl->FindCategoryDeclaration(CatName);
+    if (!CatIDecl) {
+      // Category @implementation with no corresponding @interface.
+      // Create and install one.
+      CatIDecl = ObjCCategoryDecl::Create(Context, CurContext, SourceLocation(),
+                                          CatName);
+      CatIDecl->setClassInterface(IDecl);
+      CatIDecl->insertNextClassCategory();
+    }
+  }
+
   ObjCCategoryImplDecl *CDecl = 
     ObjCCategoryImplDecl::Create(Context, CurContext, AtCatImplLoc, CatName,
                                  IDecl);
@@ -615,8 +628,17 @@
   // FIXME: PushOnScopeChains?
   CurContext->addDecl(CDecl);
 
-  /// TODO: Check that CatName, category name, is not used in another
-  // implementation.
+  /// Check that CatName, category name, is not used in another implementation.
+  if (CatIDecl) {
+    if (CatIDecl->getImplementation()) {
+      Diag(ClassLoc, diag::err_dup_implementation_category) << ClassName
+        << CatName;
+      Diag(CatIDecl->getImplementation()->getLocation(),
+           diag::note_previous_definition);
+    } else
+      CatIDecl->setImplementation(CDecl);
+  }
+
   ObjCCategoryImpls.push_back(CDecl);
   
   CheckObjCDeclScope(CDecl);
@@ -697,8 +719,10 @@
   if (LookupObjCImplementation(ClassName))
     // FIXME: Don't leak everything!
     Diag(ClassLoc, diag::err_dup_implementation_class) << ClassName;
-  else // add it to the list.
+  else { // add it to the list.
+    IDecl->setImplementation(IMPDecl);
     PushOnScopeChains(IMPDecl, TUScope);
+  }
   return DeclPtrTy::make(IMPDecl);
 }