From 79947a24e672f8b719edb2f4e7ff2474905e969c Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Fri, 24 Apr 2009 00:11:27 +0000 Subject: [PATCH] Eliminate Sema::ObjCImplementations, relying instead on name lookup. What's good for uniformity is good for PCH (or is it the other way around?). 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. llvm-svn: 69941 --- clang/include/clang/AST/DeclBase.h | 15 ++++++----- clang/include/clang/AST/DeclObjC.h | 8 +++--- clang/lib/AST/DeclBase.cpp | 10 +++++--- clang/lib/Frontend/PCHReader.cpp | 2 +- clang/lib/Frontend/PCHWriter.cpp | 2 +- clang/lib/Sema/Sema.h | 16 +++++++----- clang/lib/Sema/SemaDeclObjC.cpp | 11 +++----- clang/lib/Sema/SemaExpr.cpp | 4 +-- clang/lib/Sema/SemaExprObjC.cpp | 16 ++++++------ clang/lib/Sema/SemaLookup.cpp | 40 ++++++++++++++++++++++++++---- 10 files changed, 82 insertions(+), 42 deletions(-) diff --git a/clang/include/clang/AST/DeclBase.h b/clang/include/clang/AST/DeclBase.h index c525be996e67..f9bb7a445061 100644 --- a/clang/include/clang/AST/DeclBase.h +++ b/clang/include/clang/AST/DeclBase.h @@ -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; diff --git a/clang/include/clang/AST/DeclObjC.h b/clang/include/clang/AST/DeclObjC.h index 816de41e4336..d457760118ce 100644 --- a/clang/include/clang/AST/DeclObjC.h +++ b/clang/include/clang/AST/DeclObjC.h @@ -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() {} diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp index 62783b140f91..010dc677afe0 100644 --- a/clang/lib/AST/DeclBase.cpp +++ b/clang/lib/AST/DeclBase.cpp @@ -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: diff --git a/clang/lib/Frontend/PCHReader.cpp b/clang/lib/Frontend/PCHReader.cpp index eef1029724fc..06a7258cda61 100644 --- a/clang/lib/Frontend/PCHReader.cpp +++ b/clang/lib/Frontend/PCHReader.cpp @@ -327,7 +327,7 @@ void PCHDeclReader::VisitObjCPropertyDecl(ObjCPropertyDecl *D) { } void PCHDeclReader::VisitObjCImplDecl(ObjCImplDecl *D) { - VisitDecl(D); + VisitNamedDecl(D); D->setClassInterface( cast_or_null(Reader.GetDecl(Record[Idx++]))); D->setLocEnd(SourceLocation::getFromRawEncoding(Record[Idx++])); diff --git a/clang/lib/Frontend/PCHWriter.cpp b/clang/lib/Frontend/PCHWriter.cpp index 985d297be15e..1af093a1cc7d 100644 --- a/clang/lib/Frontend/PCHWriter.cpp +++ b/clang/lib/Frontend/PCHWriter.cpp @@ -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). diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index 8cf2af057796..b5f4e0bc9e04 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -168,10 +168,6 @@ public: /// This is only necessary for issuing pretty diagnostics. llvm::SmallVector ExtVectorDecls; - /// ObjCImplementations - Keep track of all class @implementations - /// so we can emit errors on duplicates. - llvm::DenseMap ObjCImplementations; - /// ObjCCategoryImpls - Maintain a list of category implementations so /// we can check for duplicates and find local method declarations. llvm::SmallVector 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, diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp index 7badaa313049..e0cbdce7e0d5 100644 --- a/clang/lib/Sema/SemaDeclObjC.cpp +++ b/clang/lib/Sema/SemaDeclObjC.cpp @@ -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. diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 8490672f4bfe..89f834cf5aeb 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -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()) diff --git a/clang/lib/Sema/SemaExprObjC.cpp b/clang/lib/Sema/SemaExprObjC.cpp index 1df7f3dcc913..d48ba4470c47 100644 --- a/clang/lib/Sema/SemaExprObjC.cpp +++ b/clang/lib/Sema/SemaExprObjC.cpp @@ -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. diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index 613c30bc0cb7..4b5a04b450fd 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -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(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(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(D); +} + void Sema::LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S, QualType T1, QualType T2, FunctionSet &Functions) {