]> granicus.if.org Git - clang/commitdiff
- Introduce ASTContext::getObjCImplementation() and ASTContext::setObjCImplementation...
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>
Tue, 21 Jul 2009 00:05:53 +0000 (00:05 +0000)
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>
Tue, 21 Jul 2009 00:05:53 +0000 (00:05 +0000)
  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

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

index 30f2308d12da359c613b8a4d2714519958f9f2bd..2637b68097c82b1c502f5f309caf7c870938333b 100644 (file)
@@ -97,6 +97,9 @@ class ASTContext {
   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 @@ public:
     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
index 1411c37cad4f929c39e709040174402484af79fe..b23ad3d29b27db8f8f5441a0330d0f851e540a74 100644 (file)
@@ -427,7 +427,10 @@ public:
   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 @@ public:
   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 @@ public:
   
   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.
index 2864ed2ad674a5995b454adcb8608afc6345937c..cfca62acaa4ab747ff37c063a166bd6f6f6f2aa8 100644 (file)
@@ -168,6 +168,8 @@ def warn_dup_category_def : Warning<
   "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<
index 05627b47ebe706a514e9b356bb8db538d2345a6a..304799cf91b9ff478e7ba74852128e8868c77019 100644 (file)
@@ -824,6 +824,36 @@ unsigned ASTContext::CountSynthesizedIvars(const ObjCInterfaceDecl *OI)
   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.
 ///
index 613dc58a57631513094e24280ba408a93763275a..4eee28b4682ce73ce0b4d26f1e20612ab36c7955 100644 (file)
@@ -363,6 +363,15 @@ void ObjCInterfaceDecl::Destroy(ASTContext &C) {
   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 @@ ObjCCategoryDecl *ObjCCategoryDecl::Create(ASTContext &C, DeclContext *DC,
   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 @@ void ObjCImplDecl::addPropertyImplementation(ObjCPropertyImplDecl *property) {
   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.
index 8dc14eebe452135f16aa3299d0cb67c9fd446d08..440b0fba6a7f8925a45ac607406d1632af10fcb9 100644 (file)
@@ -605,6 +605,19 @@ Sema::DeclPtrTy Sema::ActOnStartCategoryImplementation(
                       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 @@ Sema::DeclPtrTy Sema::ActOnStartCategoryImplementation(
   // 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 @@ Sema::DeclPtrTy Sema::ActOnStartClassImplementation(
   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);
 }
 
index 6ae775848e78bdf48c9e48a12d83b1c55cd4f163..077a49d2b73e2bf1b52de31882b0f8dc3ed9cd88 100644 (file)
@@ -53,4 +53,8 @@
 @implementation XCRemoteComputerManager
 @end
 
+@implementation XCRemoteComputerManager(x) // expected-note {{previous definition is here}}
+@end
 
+@implementation XCRemoteComputerManager(x) // expected-error {{reimplementation of category 'x' for class 'XCRemoteComputerManager'}}
+@end