[cfe-commits] r76508 - in /cfe/trunk: include/clang/AST/ASTContext.h include/clang/AST/DeclObjC.h include/clang/Basic/DiagnosticSemaKinds.td lib/AST/ASTContext.cpp lib/AST/DeclObjC.cpp lib/Sema/SemaDeclObjC.cpp test/SemaObjC/category-1.m

Argiris Kirtzidis akyrtzi at gmail.com
Mon Jul 20 17:05:53 PDT 2009


Author: akirtzidis
Date: Mon Jul 20 19:05:53 2009
New Revision: 76508

URL: http://llvm.org/viewvc/llvm-project?rev=76508&view=rev
Log:
- 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.

Modified:
    cfe/trunk/include/clang/AST/ASTContext.h
    cfe/trunk/include/clang/AST/DeclObjC.h
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/AST/ASTContext.cpp
    cfe/trunk/lib/AST/DeclObjC.cpp
    cfe/trunk/lib/Sema/SemaDeclObjC.cpp
    cfe/trunk/test/SemaObjC/category-1.m

Modified: cfe/trunk/include/clang/AST/ASTContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=76508&r1=76507&r2=76508&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Mon Jul 20 19:05:53 2009
@@ -97,6 +97,9 @@
   llvm::DenseMap<const RecordDecl*, const ASTRecordLayout*> ASTRecordLayouts;
   llvm::DenseMap<const ObjCContainerDecl*, const ASTRecordLayout*> ObjCLayouts;
 
+  /// \brief Mapping from ObjCContainers to their ObjCImplementations.
+  llvm::DenseMap<ObjCContainerDecl*, ObjCImplDecl*> ObjCImpls;
+
   llvm::DenseMap<unsigned, FixedWidthIntType*> SignedFixedWidthIntTypes;
   llvm::DenseMap<unsigned, FixedWidthIntType*> UnsignedFixedWidthIntTypes;
   
@@ -804,6 +807,18 @@
     return Res;
   }
 
+  /// \brief Get the implementation of ObjCInterfaceDecl,or NULL if none exists.
+  ObjCImplementationDecl *getObjCImplementation(ObjCInterfaceDecl *D);
+  /// \brief Get the implementation of ObjCCategoryDecl, or NULL if none exists.
+  ObjCCategoryImplDecl   *getObjCImplementation(ObjCCategoryDecl *D);
+
+  /// \brief Set the implementation of ObjCInterfaceDecl.
+  void setObjCImplementation(ObjCInterfaceDecl *IFaceD,
+                             ObjCImplementationDecl *ImplD);
+  /// \brief Set the implementation of ObjCCategoryDecl.
+  void setObjCImplementation(ObjCCategoryDecl *CatD,
+                             ObjCCategoryImplDecl *ImplD);
+
 private:
   ASTContext(const ASTContext&); // DO NOT IMPLEMENT
   void operator=(const ASTContext&); // DO NOT IMPLEMENT

Modified: cfe/trunk/include/clang/AST/DeclObjC.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclObjC.h?rev=76508&r1=76507&r2=76508&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/DeclObjC.h (original)
+++ cfe/trunk/include/clang/AST/DeclObjC.h Mon Jul 20 19:05:53 2009
@@ -427,7 +427,10 @@
   const ObjCList<ObjCProtocolDecl> &getReferencedProtocols() const { 
     return ReferencedProtocols; 
   }
-  
+
+  ObjCImplementationDecl *getImplementation() const;
+  void setImplementation(ObjCImplementationDecl *ImplD);
+
   ObjCCategoryDecl *FindCategoryDeclaration(IdentifierInfo *CategoryId) const;
 
   typedef ObjCList<ObjCProtocolDecl>::iterator protocol_iterator;
@@ -775,7 +778,10 @@
   ObjCInterfaceDecl *getClassInterface() { return ClassInterface; }
   const ObjCInterfaceDecl *getClassInterface() const { return ClassInterface; }
   void setClassInterface(ObjCInterfaceDecl *IDecl) { ClassInterface = IDecl; }
-  
+
+  ObjCCategoryImplDecl *getImplementation() const;
+  void setImplementation(ObjCCategoryImplDecl *ImplD);
+
   /// setProtocolList - Set the list of protocols that this interface
   /// implements.
   void setProtocolList(ObjCProtocolDecl *const*List, unsigned Num,
@@ -828,7 +834,7 @@
   
   const ObjCInterfaceDecl *getClassInterface() const { return ClassInterface; }
   ObjCInterfaceDecl *getClassInterface() { return ClassInterface; }
-  void setClassInterface(ObjCInterfaceDecl *IFace) { ClassInterface = IFace; }
+  void setClassInterface(ObjCInterfaceDecl *IFace);
 
   void addInstanceMethod(ObjCMethodDecl *method) { 
     // FIXME: Context should be set correctly before we get here.

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=76508&r1=76507&r2=76508&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Mon Jul 20 19:05:53 2009
@@ -168,6 +168,8 @@
   "duplicate definition of category %1 on interface %0">;
 def err_conflicting_super_class : Error<"conflicting super class name %0">;
 def err_dup_implementation_class : Error<"reimplementation of class %0">;
+def err_dup_implementation_category : Error<
+  "reimplementation of category %1 for class %0">;
 def err_conflicting_ivar_type : Error<
   "instance variable %0 has conflicting type: %1 vs %2">;
 def err_conflicting_ivar_bitwidth : Error<

Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=76508&r1=76507&r2=76508&view=diff

==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Mon Jul 20 19:05:53 2009
@@ -824,6 +824,36 @@
   return count;
 }
 
+/// \brief Get the implementation of ObjCInterfaceDecl,or NULL if none exists.
+ObjCImplementationDecl *ASTContext::getObjCImplementation(ObjCInterfaceDecl *D) {
+  llvm::DenseMap<ObjCContainerDecl*, ObjCImplDecl*>::iterator
+    I = ObjCImpls.find(D);
+  if (I != ObjCImpls.end())
+    return cast<ObjCImplementationDecl>(I->second);
+  return 0;
+}
+/// \brief Get the implementation of ObjCCategoryDecl, or NULL if none exists.
+ObjCCategoryImplDecl *ASTContext::getObjCImplementation(ObjCCategoryDecl *D) {
+  llvm::DenseMap<ObjCContainerDecl*, ObjCImplDecl*>::iterator
+    I = ObjCImpls.find(D);
+  if (I != ObjCImpls.end())
+    return cast<ObjCCategoryImplDecl>(I->second);
+  return 0;
+}
+
+/// \brief Set the implementation of ObjCInterfaceDecl.
+void ASTContext::setObjCImplementation(ObjCInterfaceDecl *IFaceD,
+                           ObjCImplementationDecl *ImplD) {
+  assert(IFaceD && ImplD && "Passed null params");
+  ObjCImpls[IFaceD] = ImplD;
+}
+/// \brief Set the implementation of ObjCCategoryDecl.
+void ASTContext::setObjCImplementation(ObjCCategoryDecl *CatD,
+                           ObjCCategoryImplDecl *ImplD) {
+  assert(CatD && ImplD && "Passed null params");
+  ObjCImpls[CatD] = ImplD;
+}
+
 /// getInterfaceLayoutImpl - Get or compute information about the
 /// layout of the given interface.
 ///

Modified: cfe/trunk/lib/AST/DeclObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclObjC.cpp?rev=76508&r1=76507&r2=76508&view=diff

==============================================================================
--- cfe/trunk/lib/AST/DeclObjC.cpp (original)
+++ cfe/trunk/lib/AST/DeclObjC.cpp Mon Jul 20 19:05:53 2009
@@ -363,6 +363,15 @@
   Decl::Destroy(C);
 }
 
+ObjCImplementationDecl *ObjCInterfaceDecl::getImplementation() const {
+  return getASTContext().getObjCImplementation(
+                                          const_cast<ObjCInterfaceDecl*>(this));
+}
+
+void ObjCInterfaceDecl::setImplementation(ObjCImplementationDecl *ImplD) {
+  getASTContext().setObjCImplementation(this, ImplD);
+}
+
 
 /// FindCategoryDeclaration - Finds category declaration in the list of
 /// categories for this class and returns it. Name of the category is passed
@@ -529,6 +538,16 @@
   return new (C) ObjCCategoryDecl(DC, L, Id);
 }
 
+ObjCCategoryImplDecl *ObjCCategoryDecl::getImplementation() const {
+  return getASTContext().getObjCImplementation(
+                                           const_cast<ObjCCategoryDecl*>(this));
+}
+
+void ObjCCategoryDecl::setImplementation(ObjCCategoryImplDecl *ImplD) {
+  getASTContext().setObjCImplementation(this, ImplD);
+}
+
+
 //===----------------------------------------------------------------------===//
 // ObjCCategoryImplDecl
 //===----------------------------------------------------------------------===//
@@ -547,6 +566,23 @@
   addDecl(property);
 }
 
+void ObjCImplDecl::setClassInterface(ObjCInterfaceDecl *IFace) {
+  ASTContext &Ctx = getASTContext();
+
+  if (ObjCImplementationDecl *ImplD
+        = dyn_cast_or_null<ObjCImplementationDecl>(this))
+    if (IFace)
+      Ctx.setObjCImplementation(IFace, ImplD);
+
+  else if (ObjCCategoryImplDecl *ImplD =
+             dyn_cast_or_null<ObjCCategoryImplDecl>(this)) {
+    if (ObjCCategoryDecl *CD = IFace->FindCategoryDeclaration(getIdentifier()))
+      Ctx.setObjCImplementation(CD, ImplD);
+  }
+
+  ClassInterface = IFace;
+}
+
 /// FindPropertyImplIvarDecl - This method lookup the ivar in the list of
 /// properties implemented in this category @implementation block and returns
 /// the implemented property that uses it.

Modified: cfe/trunk/lib/Sema/SemaDeclObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclObjC.cpp?rev=76508&r1=76507&r2=76508&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclObjC.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclObjC.cpp Mon Jul 20 19:05:53 2009
@@ -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);
 }
 

Modified: cfe/trunk/test/SemaObjC/category-1.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/category-1.m?rev=76508&r1=76507&r2=76508&view=diff

==============================================================================
--- cfe/trunk/test/SemaObjC/category-1.m (original)
+++ cfe/trunk/test/SemaObjC/category-1.m Mon Jul 20 19:05:53 2009
@@ -53,4 +53,8 @@
 @implementation XCRemoteComputerManager
 @end
 
+ at implementation XCRemoteComputerManager(x) // expected-note {{previous definition is here}}
+ at end
 
+ at implementation XCRemoteComputerManager(x) // expected-error {{reimplementation of category 'x' for class 'XCRemoteComputerManager'}}
+ at end





More information about the cfe-commits mailing list