]> granicus.if.org Git - clang/commitdiff
Eliminate Sema::ObjCImplementations, relying instead on name lookup. What's good...
authorDouglas Gregor <dgregor@apple.com>
Fri, 24 Apr 2009 00:11:27 +0000 (00:11 +0000)
committerDouglas Gregor <dgregor@apple.com>
Fri, 24 Apr 2009 00:11:27 +0000 (00:11 +0000)
As part of this, make ObjCImplDecl inherit from NamedDecl (since
ObjCImplementationDecls now need to have names so that they can be
found). This brings ObjCImplDecl very, very close to
ObjCContainerDecl; we may be able to merge them soon.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@69941 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/DeclBase.h
include/clang/AST/DeclObjC.h
lib/AST/DeclBase.cpp
lib/Frontend/PCHReader.cpp
lib/Frontend/PCHWriter.cpp
lib/Sema/Sema.h
lib/Sema/SemaDeclObjC.cpp
lib/Sema/SemaExpr.cpp
lib/Sema/SemaExprObjC.cpp
lib/Sema/SemaLookup.cpp

index c525be996e67ac41566fb95eecc8719712501670..f9bb7a4450618f02400e9040c2d5621ec56569f5 100644 (file)
@@ -74,16 +74,19 @@ public:
 #include "clang/AST/DeclNodes.def"
   };
 
-  /// IdentifierNamespace - According to C99 6.2.3, there are four namespaces,
-  /// labels, tags, members and ordinary identifiers. These are meant
-  /// as bitmasks, so that searches in C++ can look into the "tag" namespace
-  /// during ordinary lookup.
+  /// IdentifierNamespace - According to C99 6.2.3, there are four
+  /// namespaces, labels, tags, members and ordinary
+  /// identifiers. These are meant as bitmasks, so that searches in
+  /// C++ can look into the "tag" namespace during ordinary lookup. We
+  /// use additional namespaces for Objective-C entities.
   enum IdentifierNamespace {
     IDNS_Label = 0x1,
     IDNS_Tag = 0x2,
     IDNS_Member = 0x4,
     IDNS_Ordinary = 0x8,
-    IDNS_Protocol = 0x10
+    IDNS_ObjCProtocol = 0x10,
+    IDNS_ObjCImplementation = 0x20,
+    IDNS_ObjCCategoryImpl = 0x40
   };
   
   /// ObjCDeclQualifier - Qualifier used on types in method declarations
@@ -154,7 +157,7 @@ private:
   bool Implicit : 1;
 
   /// IdentifierNamespace - This specifies what IDNS_* namespace this lives in.
-  unsigned IdentifierNamespace : 5;
+  unsigned IdentifierNamespace : 8;
   
 #ifndef NDEBUG
   void CheckAccessDeclContext() const;
index 816de41e43367bebecbbd452b126cb1ccded596a..d457760118ce53a8c5635d991d7698d14bd4af08 100644 (file)
@@ -793,7 +793,7 @@ public:
   static bool classof(const ObjCCategoryDecl *D) { return true; }
 };
 
-class ObjCImplDecl : public Decl, public DeclContext {
+class ObjCImplDecl : public NamedDecl, public DeclContext {
   /// Class interface for this category implementation
   ObjCInterfaceDecl *ClassInterface;
   
@@ -802,8 +802,10 @@ class ObjCImplDecl : public Decl, public DeclContext {
 protected:
   ObjCImplDecl(Kind DK, DeclContext *DC, SourceLocation L,
                ObjCInterfaceDecl *classInterface)
-      : Decl(DK, DC, L), DeclContext(DK),
-        ClassInterface(classInterface) {}
+    : NamedDecl(DK, DC, L, 
+                classInterface? classInterface->getDeclName() 
+                              : DeclarationName()), 
+      DeclContext(DK), ClassInterface(classInterface) {}
   
 public:
   virtual ~ObjCImplDecl() {}
index 62783b140f91363075852bd0aa0882b808be40cd..010dc677afe0005ad457ea459b33cf12a1ff34c2 100644 (file)
@@ -165,14 +165,19 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
     case ObjCContainer:
     case ObjCCategory:
     case ObjCInterface:
-    case ObjCCategoryImpl:
     case ObjCProperty:
     case ObjCCompatibleAlias:
       return IDNS_Ordinary;
       
     case ObjCProtocol:
-      return IDNS_Protocol;
+      return IDNS_ObjCProtocol;
       
+    case ObjCImplementation:
+      return IDNS_ObjCImplementation;
+
+    case ObjCCategoryImpl:
+      return IDNS_ObjCCategoryImpl;
+
     case Field:
     case ObjCAtDefsField:
     case ObjCIvar:
@@ -197,7 +202,6 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
     case FileScopeAsm:
     case StaticAssert:
     case ObjCClass:
-    case ObjCImplementation:
     case ObjCPropertyImpl:
     case ObjCForwardProtocol:
     case Block:
index eef1029724fc4dbb0f1e0ed841f66bd50e8ccf45..06a7258cda6161bae003468e046b0b98caf45e89 100644 (file)
@@ -327,7 +327,7 @@ void PCHDeclReader::VisitObjCPropertyDecl(ObjCPropertyDecl *D) {
 }
 
 void PCHDeclReader::VisitObjCImplDecl(ObjCImplDecl *D) {
-  VisitDecl(D);
+  VisitNamedDecl(D);
   D->setClassInterface(
               cast_or_null<ObjCInterfaceDecl>(Reader.GetDecl(Record[Idx++])));
   D->setLocEnd(SourceLocation::getFromRawEncoding(Record[Idx++]));
index 985d297be15e1d7c81eaa4b49d28bebcbd404cd9..1af093a1cc7d47f9ec09a8f7d5fd67f2026b81f5 100644 (file)
@@ -498,7 +498,7 @@ void PCHDeclWriter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) {
 }
 
 void PCHDeclWriter::VisitObjCImplDecl(ObjCImplDecl *D) {
-  VisitDecl(D);
+  VisitNamedDecl(D);
   Writer.AddDeclRef(D->getClassInterface(), Record);
   Writer.AddSourceLocation(D->getLocEnd(), Record);
   // Abstract class (no need to define a stable pch::DECL code).
index 8cf2af057796f64a76b9cdd0c9d462bd5816be6b..b5f4e0bc9e0482900624ac385454250ae5470306 100644 (file)
@@ -168,10 +168,6 @@ public:
   /// This is only necessary for issuing pretty diagnostics.
   llvm::SmallVector<TypedefDecl*, 24> ExtVectorDecls;
 
-  /// ObjCImplementations - Keep track of all class @implementations
-  /// so we can emit errors on duplicates.
-  llvm::DenseMap<IdentifierInfo*, ObjCImplementationDecl*> ObjCImplementations;
-  
   /// ObjCCategoryImpls - Maintain a list of category implementations so 
   /// we can check for duplicates and find local method declarations.
   llvm::SmallVector<ObjCCategoryImplDecl*, 8> ObjCCategoryImpls;
@@ -770,7 +766,11 @@ public:
     /// C99 6.2.2p4-5 and C++ [basic.link]p6.
     LookupRedeclarationWithLinkage,
     /// Look up the name of an Objective-C protocol.
-    LookupProtocolName
+    LookupObjCProtocolName,
+    /// Look up the name of an Objective-C implementation
+    LookupObjCImplementationName,
+    /// Look up the name of an Objective-C category implementation
+    LookupObjCCategoryImplName
   };
 
   /// @brief Represents the results of name lookup.
@@ -1022,7 +1022,9 @@ public:
     case Sema::LookupTagName:
     case Sema::LookupMemberName:
     case Sema::LookupRedeclarationWithLinkage: // FIXME: check linkage, scoping
-    case Sema::LookupProtocolName:
+    case Sema::LookupObjCProtocolName:
+    case Sema::LookupObjCImplementationName:
+    case Sema::LookupObjCCategoryImplName:
       return D->isInIdentifierNamespace(IDNS);
       
     case Sema::LookupOperatorName:
@@ -1057,6 +1059,8 @@ public:
                                 SourceLocation Loc = SourceLocation());
 
   ObjCProtocolDecl *LookupProtocol(IdentifierInfo *II);
+  ObjCImplementationDecl *LookupObjCImplementation(IdentifierInfo *II);
+  ObjCCategoryImplDecl *LookupObjCCategoryImpl(IdentifierInfo *II);
 
   void LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S,
                                     QualType T1, QualType T2, 
index 7badaa313049f9c1d37944f2c37e0a714806bc29..e0cbdce7e0d5265acf9cfb2b0d7cbeae11c7f880 100644 (file)
@@ -677,18 +677,15 @@ Sema::DeclPtrTy Sema::ActOnStartClassImplementation(
     ObjCImplementationDecl::Create(Context, CurContext, AtClassImplLoc, 
                                    IDecl, SDecl);
   
-  // FIXME: PushOnScopeChains?
-  CurContext->addDecl(Context, IMPDecl);
-
   if (CheckObjCDeclScope(IMPDecl))
     return DeclPtrTy::make(IMPDecl);
   
   // Check that there is no duplicate implementation of this class.
-  if (ObjCImplementations[ClassName])
+  if (LookupObjCImplementation(ClassName))
     // FIXME: Don't leak everything!
     Diag(ClassLoc, diag::err_dup_implementation_class) << ClassName;
   else // add it to the list.
-    ObjCImplementations[ClassName] = IMPDecl;
+    PushOnScopeChains(IMPDecl, TUScope);
   return DeclPtrTy::make(IMPDecl);
 }
 
@@ -832,8 +829,8 @@ bool Sema::isPropertyReadonly(ObjCPropertyDecl *PDecl,
     }
   }
   // Lastly, look through the implementation (if one is in scope).
-  if (ObjCImplementationDecl *ImpDecl 
-        ObjCImplementations[IDecl->getIdentifier()])
+  if (ObjCImplementationDecl *ImpDecl 
+      = LookupObjCImplementation(IDecl->getIdentifier()))
     if (ImpDecl->getInstanceMethod(Context, PDecl->getSetterName()))
       return false;
   // If all fails, look at the super class.
index 8490672f4bfe28a35538999bb965616d9542ccdb..89f834cf5aebe1f0702487905f31172f30eabf43 100644 (file)
@@ -1807,8 +1807,8 @@ ObjCMethodDecl *Sema::FindMethodInNestedImplementations(
                                               const ObjCInterfaceDecl *IFace,
                                               const Selector &Sel) {
   ObjCMethodDecl *Method = 0;
-  if (ObjCImplementationDecl *ImpDecl =
-      Sema::ObjCImplementations[IFace->getIdentifier()])
+  if (ObjCImplementationDecl *ImpDecl 
+        = LookupObjCImplementation(IFace->getIdentifier()))
     Method = ImpDecl->getInstanceMethod(Context, Sel);
   
   if (!Method && IFace->getSuperClass())
index 1df7f3dcc913509319b1422da5d0e59ad0c37a2e..d48ba4470c47f18cefac36dc07dd0231e3e81cdd 100644 (file)
@@ -222,8 +222,8 @@ ObjCMethodDecl *Sema::LookupPrivateClassMethod(Selector Sel,
   ObjCMethodDecl *Method = 0;
   // lookup in class and all superclasses
   while (ClassDecl && !Method) {
-    if (ObjCImplementationDecl *ImpDecl 
-        ObjCImplementations[ClassDecl->getIdentifier()])
+    if (ObjCImplementationDecl *ImpDecl 
+          = LookupObjCImplementation(ClassDecl->getIdentifier()))
       Method = ImpDecl->getClassMethod(Context, Sel);
     
     // Look through local category implementations associated with the class.
@@ -255,8 +255,8 @@ ObjCMethodDecl *Sema::LookupPrivateInstanceMethod(Selector Sel,
   ObjCMethodDecl *Method = 0;
   while (ClassDecl && !Method) {
     // If we have implementations in scope, check "private" methods.
-    if (ObjCImplementationDecl *ImpDecl = 
-        ObjCImplementations[ClassDecl->getIdentifier()])
+    if (ObjCImplementationDecl *ImpDecl
+          = LookupObjCImplementation(ClassDecl->getIdentifier()))
       Method = ImpDecl->getInstanceMethod(Context, Sel);
     
     // Look through local category implementations associated with the class.
@@ -288,8 +288,8 @@ Action::OwningExprResult Sema::ActOnClassPropertyRefExpr(
   if (!Getter)
     if (ObjCMethodDecl *CurMeth = getCurMethodDecl())
       if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface())
-        if (ObjCImplementationDecl *ImpDecl =
-            ObjCImplementations[ClassDecl->getIdentifier()])
+        if (ObjCImplementationDecl *ImpDecl
+              = LookupObjCImplementation(ClassDecl->getIdentifier()))
           Getter = ImpDecl->getClassMethod(Context, Sel);
 
   if (Getter) {
@@ -310,8 +310,8 @@ Action::OwningExprResult Sema::ActOnClassPropertyRefExpr(
     // methods.
     if (ObjCMethodDecl *CurMeth = getCurMethodDecl())
       if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface())
-        if (ObjCImplementationDecl *ImpDecl =
-              ObjCImplementations[ClassDecl->getIdentifier()])
+        if (ObjCImplementationDecl *ImpDecl 
+              = LookupObjCImplementation(ClassDecl->getIdentifier()))
           Setter = ImpDecl->getClassMethod(Context, SetterSel);
   }
   // Look through local category implementations associated with the class.
index 613c30bc0cb7af1418492b65f82b68f0de84fb90..4b5a04b450fdf02c5fbdda9549a6379c44088476 100644 (file)
@@ -294,8 +294,16 @@ getIdentifierNamespacesFromLookupNameKind(Sema::LookupNameKind NameKind,
     IDNS = Decl::IDNS_Ordinary | Decl::IDNS_Tag | Decl::IDNS_Member;
     break;
 
-  case Sema::LookupProtocolName:
-    IDNS = Decl::IDNS_Protocol;
+  case Sema::LookupObjCProtocolName:
+    IDNS = Decl::IDNS_ObjCProtocol;
+    break;
+
+  case Sema::LookupObjCImplementationName:
+    IDNS = Decl::IDNS_ObjCImplementation;
+    break;
+
+  case Sema::LookupObjCCategoryImplName:
+    IDNS = Decl::IDNS_ObjCCategoryImpl;
     break;
   }
   return IDNS;
@@ -836,8 +844,16 @@ Sema::LookupName(Scope *S, DeclarationName Name, LookupNameKind NameKind,
       IDNS = Decl::IDNS_Ordinary;
       break;
 
-    case Sema::LookupProtocolName:
-      IDNS = Decl::IDNS_Protocol;
+    case Sema::LookupObjCProtocolName:
+      IDNS = Decl::IDNS_ObjCProtocol;
+      break;
+
+    case Sema::LookupObjCImplementationName:
+      IDNS = Decl::IDNS_ObjCImplementation;
+      break;
+      
+    case Sema::LookupObjCCategoryImplName:
+      IDNS = Decl::IDNS_ObjCCategoryImpl;
       break;
     }
 
@@ -1490,10 +1506,24 @@ IsAcceptableNonMemberOperatorCandidate(FunctionDecl *Fn,
 
 /// \brief Find the protocol with the given name, if any.
 ObjCProtocolDecl *Sema::LookupProtocol(IdentifierInfo *II) {
-  Decl *D = LookupName(TUScope, II, LookupProtocolName).getAsDecl();
+  Decl *D = LookupName(TUScope, II, LookupObjCProtocolName).getAsDecl();
   return cast_or_null<ObjCProtocolDecl>(D);
 }
 
+/// \brief Find the Objective-C implementation with the given name, if
+/// any.
+ObjCImplementationDecl *Sema::LookupObjCImplementation(IdentifierInfo *II) {
+  Decl *D = LookupName(TUScope, II, LookupObjCImplementationName).getAsDecl();
+  return cast_or_null<ObjCImplementationDecl>(D);
+}
+
+/// \brief Find the Objective-C category implementation with the given
+/// name, if any.
+ObjCCategoryImplDecl *Sema::LookupObjCCategoryImpl(IdentifierInfo *II) {
+  Decl *D = LookupName(TUScope, II, LookupObjCCategoryImplName).getAsDecl();
+  return cast_or_null<ObjCCategoryImplDecl>(D);
+}
+
 void Sema::LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S,
                                         QualType T1, QualType T2, 
                                         FunctionSet &Functions) {