This is a large/messy diff that unifies the ObjC AST's with DeclContext.

- ObjCContainerDecl's (ObjCInterfaceDecl/ObjCCategoryDecl/ObjCProtocolDecl), ObjCCategoryImpl, & ObjCImplementation are all DeclContexts.
- ObjCMethodDecl is now a ScopedDecl (so it can play nicely with DeclContext).
- ObjCContainerDecl now does iteration/lookup using DeclContext infrastructure (no more linear search:-)
- Removed ASTContext argument to DeclContext::lookup(). It wasn't being used and complicated it's use from an ObjC AST perspective.
- Added Sema::ProcessPropertyDecl() and removed Sema::diagnosePropertySetterGetterMismatch().
- Simplified Sema::ActOnAtEnd() considerably. Still more work to do.
- Fixed an incorrect casting assumption in Sema::getCurFunctionOrMethodDecl(), now that ObjCMethodDecl is a ScopedDecl.
- Removed addPropertyMethods from ObjCInterfaceDecl/ObjCCategoryDecl/ObjCProtocolDecl.

This passes all the tests on my machine. Since many of the changes are central to the way ObjC finds it's methods, I expect some fallout (and there are still a handful of FIXME's). Nevertheless, this should be a step in the right direction.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@61929 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/IdentifierResolver.cpp b/lib/Sema/IdentifierResolver.cpp
index 08c9bde..90906e7 100644
--- a/lib/Sema/IdentifierResolver.cpp
+++ b/lib/Sema/IdentifierResolver.cpp
@@ -161,7 +161,7 @@
     return false;
   }
 
-  return LookupContext(D) == LookupContext(Ctx->getPrimaryContext(Context));
+  return LookupContext(D) == LookupContext(Ctx->getPrimaryContext());
 }
 
 /// AddDecl - Link the decl to its shadowed decl chain.
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp
index 2957583..41285c4 100644
--- a/lib/Sema/Sema.cpp
+++ b/lib/Sema/Sema.cpp
@@ -223,7 +223,7 @@
   while (isa<BlockDecl>(DC))
     DC = DC->getParent();
   if (isa<ObjCMethodDecl>(DC) || isa<FunctionDecl>(DC))
-    return cast<NamedDecl>(DC);
+    return cast<ScopedDecl>(DC);
   return 0;
 }
 
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index cdec1e6..765dfe5 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -67,6 +67,7 @@
   class ObjCIvarDecl;
   class ObjCMethodDecl;
   class ObjCPropertyDecl;
+  class ObjCContainerDecl;
   struct BlockSemaInfo;
   class BasePaths;
 
@@ -1166,9 +1167,7 @@
   void CheckObjCPropertyAttributes(QualType PropertyTy, 
                                    SourceLocation Loc,
                                    unsigned &Attributes);
-  void diagnosePropertySetterGetterMismatch(ObjCPropertyDecl *property,
-                                            const ObjCMethodDecl *GetterMethod,
-                                            const ObjCMethodDecl *SetterMethod);
+  void ProcessPropertyDecl(ObjCPropertyDecl *property, ObjCContainerDecl *DC);
   void DiagnosePropertyMismatch(ObjCPropertyDecl *Property, 
                                 ObjCPropertyDecl *SuperProperty,
                                 const IdentifierInfo *Name);
diff --git a/lib/Sema/SemaCXXScopeSpec.cpp b/lib/Sema/SemaCXXScopeSpec.cpp
index f023fbf..5fb2740 100644
--- a/lib/Sema/SemaCXXScopeSpec.cpp
+++ b/lib/Sema/SemaCXXScopeSpec.cpp
@@ -26,7 +26,7 @@
     if (LookupCtx && !LookInParentCtx) {

       IdIsUndeclared = true;

       DeclContext::lookup_const_iterator I, E;

-      for (llvm::tie(I, E) = LookupCtx->lookup(Context, Name); I != E; ++I) {

+      for (llvm::tie(I, E) = LookupCtx->lookup(Name); I != E; ++I) {

        IdIsUndeclared = false;

        if (((*I)->getIdentifierNamespace() & Decl::IDNS_Tag) || 

            isa<TypedefDecl>(*I))

diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 351694c..6585733 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -287,7 +287,7 @@
     // Perform qualified name lookup into the LookupCtx.
     // FIXME: Will need to look into base classes and such.
     DeclContext::lookup_const_iterator I, E;
-    for (llvm::tie(I, E) = LookupCtx->lookup(Context, Name); I != E; ++I)
+    for (llvm::tie(I, E) = LookupCtx->lookup(Name); I != E; ++I)
       if ((*I)->isInIdentifierNamespace(NS)) {
         // Ignore non-namespace names if we're only looking for namespaces.
         if (NamespaceNameOnly && !isa<NamespaceDecl>(*I)) continue;
@@ -334,7 +334,7 @@
       while (Ctx && (Ctx->isNamespace() || Ctx->isRecord())) {
         // Look for declarations of this name in this scope.
         DeclContext::lookup_const_iterator I, E;
-        for (llvm::tie(I, E) = Ctx->lookup(Context, Name); I != E; ++I) {
+        for (llvm::tie(I, E) = Ctx->lookup(Name); I != E; ++I) {
           // FIXME: Cache this result in the IdResolver
           if ((*I)->isInIdentifierNamespace(NS)) {
             if (NamespaceNameOnly && !isa<NamespaceDecl>(*I))
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index c5e5aa2..edc3a28 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -681,7 +681,7 @@
   //   using a qualified name. ]
   // Look for a member, first.
   FieldDecl *Member = 0;
-  DeclContext::lookup_result Result = ClassDecl->lookup(Context, MemberOrBase);
+  DeclContext::lookup_result Result = ClassDecl->lookup(MemberOrBase);
   if (Result.first != Result.second)
     Member = dyn_cast<FieldDecl>(*Result.first);
 
@@ -1590,7 +1590,7 @@
     = Context.DeclarationNames.getCXXConstructorName(
                        Context.getCanonicalType(ClassType.getUnqualifiedType()));
   DeclContext::lookup_const_iterator Con, ConEnd;
-  for (llvm::tie(Con, ConEnd) = ClassDecl->lookup(Context, ConstructorName);
+  for (llvm::tie(Con, ConEnd) = ClassDecl->lookup(ConstructorName);
        Con != ConEnd; ++Con) {
     CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*Con);
     if ((Kind == IK_Direct) ||
diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp
index 68e7744..69c45e9 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -1001,14 +1001,18 @@
   }
 }
 
-/// diagnosePropertySetterGetterMismatch - Make sure that use-defined
-/// setter/getter methods have the property type and issue diagnostics
-/// if they don't.
-///
-void
-Sema::diagnosePropertySetterGetterMismatch(ObjCPropertyDecl *property,
-                                           const ObjCMethodDecl *GetterMethod,
-                                           const ObjCMethodDecl *SetterMethod) {
+/// ProcessPropertyDecl - Make sure that any user-defined setter/getter methods 
+/// have the property type and issue diagnostics if they don't.
+/// Also synthesize a getter/setter method if none exist (and update the
+/// appropriate lookup tables. FIXME: Should reconsider if adding synthesized
+/// methods is the "right" thing to do.
+void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property, 
+                               ObjCContainerDecl *CD) {
+  ObjCMethodDecl *GetterMethod, *SetterMethod;
+  
+  GetterMethod = CD->getInstanceMethod(property->getGetterName());  
+  SetterMethod = CD->getInstanceMethod(property->getSetterName());
+  
   if (GetterMethod &&
       GetterMethod->getResultType() != property->getType()) {
     Diag(property->getLocation(), 
@@ -1031,6 +1035,29 @@
       Diag(SetterMethod->getLocation(), diag::note_declared_at);
     }
   }
+
+  // Synthesize getter/setter methods if none exist.
+  // Add any synthesized methods to the global pool. This allows us to 
+  // handle the following, which is supported by GCC (and part of the design).
+  //
+  // @interface Foo
+  // @property double bar;
+  // @end
+  //
+  // void thisIsUnfortunate() {
+  //   id foo;
+  //   double bar = [foo bar];
+  // }
+  //
+  CD->getPropertyMethods(Context, property, GetterMethod, SetterMethod);
+  if (GetterMethod) {
+    CD->addDecl(Context, GetterMethod);
+    AddInstanceMethodToGlobalPool(GetterMethod);  
+  }
+  if (SetterMethod) {
+    CD->addDecl(Context, SetterMethod);
+    AddInstanceMethodToGlobalPool(SetterMethod);     
+  }
 }
 
 // Note: For class/category implemenations, allMethods/allProperties is
@@ -1046,17 +1073,12 @@
   if (!ClassDecl)
     return;
     
-  llvm::SmallVector<ObjCMethodDecl*, 32> insMethods;
-  llvm::SmallVector<ObjCMethodDecl*, 16> clsMethods;
-  
-  llvm::DenseMap<Selector, const ObjCMethodDecl*> InsMap;
-  llvm::DenseMap<Selector, const ObjCMethodDecl*> ClsMap;
-  
   bool isInterfaceDeclKind = 
         isa<ObjCInterfaceDecl>(ClassDecl) || isa<ObjCCategoryDecl>(ClassDecl)
          || isa<ObjCProtocolDecl>(ClassDecl);
   bool checkIdenticalMethods = isa<ObjCImplementationDecl>(ClassDecl);
   
+  
   if (pNum != 0) {
     if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(ClassDecl))
       IDecl->addProperties((ObjCPropertyDecl**)allProperties, pNum);
@@ -1067,7 +1089,14 @@
     else
       assert(false && "ActOnAtEnd - property declaration misplaced");
   }
-  
+
+  DeclContext *DC = dyn_cast<DeclContext>(ClassDecl);
+  assert(DC && "Missing DeclContext");
+
+  // FIXME: Remove these and use the ObjCContainerDecl/DeclContext.
+  llvm::DenseMap<Selector, const ObjCMethodDecl*> InsMap;
+  llvm::DenseMap<Selector, const ObjCMethodDecl*> ClsMap;
+
   for (unsigned i = 0; i < allNum; i++ ) {
     ObjCMethodDecl *Method =
       cast_or_null<ObjCMethodDecl>(static_cast<Decl*>(allMethods[i]));
@@ -1084,7 +1113,7 @@
             << Method->getDeclName();
           Diag(PrevMethod->getLocation(), diag::note_previous_declaration);
       } else {
-        insMethods.push_back(Method);
+        DC->addDecl(Context, Method);
         InsMap[Method->getSelector()] = Method;
         /// The following allows us to typecheck messages to "id".
         AddInstanceMethodToGlobalPool(Method);
@@ -1101,17 +1130,13 @@
           << Method->getDeclName();
         Diag(PrevMethod->getLocation(), diag::note_previous_declaration);
       } else {
-        clsMethods.push_back(Method);
+        DC->addDecl(Context, Method);
         ClsMap[Method->getSelector()] = Method;
         /// The following allows us to typecheck messages to "Class".
         AddFactoryMethodToGlobalPool(Method);
       }
     }
   }
-  // Save the size so we can detect if we've added any property methods.
-  unsigned int insMethodsSizePriorToPropAdds = insMethods.size();
-  unsigned int clsMethodsSizePriorToPropAdds = clsMethods.size();
-  
   if (ObjCInterfaceDecl *I = dyn_cast<ObjCInterfaceDecl>(ClassDecl)) {
     // Compares properties declared in this class to those of its 
     // super class.
@@ -1119,22 +1144,15 @@
     MergeProtocolPropertiesIntoClass(I, I);
     for (ObjCInterfaceDecl::classprop_iterator i = I->classprop_begin(),
          e = I->classprop_end(); i != e; ++i) {
-      diagnosePropertySetterGetterMismatch((*i), InsMap[(*i)->getGetterName()],
-                                           InsMap[(*i)->getSetterName()]);
-      I->addPropertyMethods(Context, *i, insMethods, InsMap);
+      ProcessPropertyDecl((*i), I);
     }
-    I->addMethods(&insMethods[0], insMethods.size(),
-                  &clsMethods[0], clsMethods.size(), AtEndLoc);
-    
+    I->setAtEndLoc(AtEndLoc);
   } else if (ObjCProtocolDecl *P = dyn_cast<ObjCProtocolDecl>(ClassDecl)) {
     for (ObjCProtocolDecl::classprop_iterator i = P->classprop_begin(),
          e = P->classprop_end(); i != e; ++i) {
-      diagnosePropertySetterGetterMismatch((*i), InsMap[(*i)->getGetterName()],
-                                           InsMap[(*i)->getSetterName()]);
-      P->addPropertyMethods(Context, *i, insMethods, InsMap);
+      ProcessPropertyDecl((*i), P);
     }
-    P->addMethods(&insMethods[0], insMethods.size(),
-                  &clsMethods[0], clsMethods.size(), AtEndLoc);
+    P->setAtEndLoc(AtEndLoc);
   }
   else if (ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(ClassDecl)) {
     // Categories are used to extend the class by declaring new methods.
@@ -1145,12 +1163,9 @@
     MergeProtocolPropertiesIntoClass(C, C);
     for (ObjCCategoryDecl::classprop_iterator i = C->classprop_begin(),
          e = C->classprop_end(); i != e; ++i) {
-      diagnosePropertySetterGetterMismatch((*i), InsMap[(*i)->getGetterName()],
-                                           InsMap[(*i)->getSetterName()]);
-      C->addPropertyMethods(Context, *i, insMethods, InsMap);
+      ProcessPropertyDecl((*i), C);
     }
-    C->addMethods(&insMethods[0], insMethods.size(),
-                  &clsMethods[0], clsMethods.size(), AtEndLoc);
+    C->setAtEndLoc(AtEndLoc);
   }
   else if (ObjCImplementationDecl *IC = 
                 dyn_cast<ObjCImplementationDecl>(ClassDecl)) {
@@ -1173,24 +1188,6 @@
       }
     }
   }
-  // Add any synthesized methods to the global pool. This allows us to 
-  // handle the following, which is supported by GCC (and part of the design).
-  //
-  // @interface Foo
-  // @property double bar;
-  // @end
-  //
-  // void thisIsUnfortunate() {
-  //   id foo;
-  //   double bar = [foo bar];
-  // }
-  //
-  if (insMethodsSizePriorToPropAdds < insMethods.size())
-    for (unsigned i = insMethodsSizePriorToPropAdds; i < insMethods.size(); i++)
-      AddInstanceMethodToGlobalPool(insMethods[i]);     
-  if (clsMethodsSizePriorToPropAdds < clsMethods.size())
-    for (unsigned i = clsMethodsSizePriorToPropAdds; i < clsMethods.size(); i++)
-      AddFactoryMethodToGlobalPool(clsMethods[i]);     
 }
 
 
@@ -1241,7 +1238,7 @@
   
   ObjCMethodDecl* ObjCMethod = 
     ObjCMethodDecl::Create(Context, MethodLoc, EndLoc, Sel, resultDeclType,
-                           ClassDecl, 
+                           dyn_cast<DeclContext>(ClassDecl), 
                            MethodType == tok::minus, isVariadic,
                            false,
                            MethodDeclKind == tok::objc_optional ? 
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 3510b5d..111dca4 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -414,7 +414,7 @@
                                   FunctionDecl *&Operator)
 {
   DeclContext::lookup_iterator Alloc, AllocEnd;
-  llvm::tie(Alloc, AllocEnd) = Ctx->lookup(Context, Name);
+  llvm::tie(Alloc, AllocEnd) = Ctx->lookup(Name);
   if (Alloc == AllocEnd) {
     if (AllowMissing)
       return false;
@@ -517,7 +517,7 @@
   // Check if this function is already declared.
   {
     DeclContext::lookup_iterator Alloc, AllocEnd;
-    for (llvm::tie(Alloc, AllocEnd) = GlobalCtx->lookup(Context, Name);
+    for (llvm::tie(Alloc, AllocEnd) = GlobalCtx->lookup(Name);
          Alloc != AllocEnd; ++Alloc) {
       // FIXME: Do we need to check for default arguments here?
       FunctionDecl *Func = cast<FunctionDecl>(*Alloc);
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 704334d..26ef1bd 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -1117,7 +1117,7 @@
       = Context.DeclarationNames.getCXXConstructorName(
                                              Context.getCanonicalType(ToType));
     DeclContext::lookup_iterator Con, ConEnd;
-    for (llvm::tie(Con, ConEnd) = ToRecordDecl->lookup(Context, ConstructorName);
+    for (llvm::tie(Con, ConEnd) = ToRecordDecl->lookup(ConstructorName);
          Con != ConEnd; ++Con) {
       CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*Con);
       if (Constructor->isConvertingConstructor())
@@ -2141,7 +2141,7 @@
   //        empty.
   if (const RecordType *T1Rec = T1->getAsRecordType()) {
     DeclContext::lookup_const_iterator Oper, OperEnd;
-    for (llvm::tie(Oper, OperEnd) = T1Rec->getDecl()->lookup(Context, OpName);
+    for (llvm::tie(Oper, OperEnd) = T1Rec->getDecl()->lookup(OpName);
          Oper != OperEnd; ++Oper)
       AddMethodCandidate(cast<CXXMethodDecl>(*Oper), Args[0], 
                          Args+1, NumArgs - 1, CandidateSet,
@@ -3392,7 +3392,7 @@
   OverloadCandidateSet CandidateSet;
   DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(OO_Call);
   DeclContext::lookup_const_iterator Oper, OperEnd;
-  for (llvm::tie(Oper, OperEnd) = Record->getDecl()->lookup(Context, OpName);
+  for (llvm::tie(Oper, OperEnd) = Record->getDecl()->lookup(OpName);
        Oper != OperEnd; ++Oper)
     AddMethodCandidate(cast<CXXMethodDecl>(*Oper), Object, Args, NumArgs, 
                        CandidateSet, /*SuppressUserConversions=*/false);
@@ -3577,7 +3577,7 @@
   const RecordType *BaseRecord = Base->getType()->getAsRecordType();
   
   DeclContext::lookup_const_iterator Oper, OperEnd;
-  for (llvm::tie(Oper, OperEnd) = BaseRecord->getDecl()->lookup(Context, OpName);
+  for (llvm::tie(Oper, OperEnd) = BaseRecord->getDecl()->lookup(OpName);
        Oper != OperEnd; ++Oper)
     AddMethodCandidate(cast<CXXMethodDecl>(*Oper), Base, 0, 0, CandidateSet,
                        /*SuppressUserConversions=*/false);