//===--- SemaDeclObjC.cpp - Semantic Analysis for ObjC Declarations -------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file implements semantic analysis for Objective C declarations.
//
//===----------------------------------------------------------------------===//

#include "Sema.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclObjC.h"
#include "clang/Parse/Scope.h"

using namespace clang;

/// ObjCActOnStartOfMethodDef - This routine sets up parameters; invisible
/// and user declared, in the method definition's AST.
void Sema::ObjCActOnStartOfMethodDef(Scope *FnBodyScope, DeclTy *D) {
  assert(CurFunctionDecl == 0 && "Method parsing confused");
  ObjCMethodDecl *MDecl = dyn_cast<ObjCMethodDecl>(static_cast<Decl *>(D));
  assert(MDecl != 0 && "Not a method declarator!");

  // Allow the rest of sema to find private method decl implementations.
  if (MDecl->isInstance())
    AddInstanceMethodToGlobalPool(MDecl);
  else
    AddFactoryMethodToGlobalPool(MDecl);
  
  // Allow all of Sema to see that we are entering a method definition.
  CurMethodDecl = MDecl;
  PushDeclContext(MDecl);

  // Create Decl objects for each parameter, entrring them in the scope for
  // binding to their use.
  struct DeclaratorChunk::ParamInfo PI;

  // Insert the invisible arguments, self and _cmd!
  PI.Ident = &Context.Idents.get("self");
  PI.IdentLoc = SourceLocation(); // synthesized vars have a null location.
  QualType selfTy = Context.getObjCIdType();
  if (MDecl->isInstance()) {
    if (ObjCInterfaceDecl *OID = MDecl->getClassInterface()) {
      // There may be no interface context due to error in declaration of the 
      // interface (which has been reported). Recover gracefully
      selfTy = Context.getObjCInterfaceType(OID);
      selfTy = Context.getPointerType(selfTy);
    }
  }
  CurMethodDecl->setSelfDecl(CreateImplicitParameter(FnBodyScope, PI.Ident, 
                                                     PI.IdentLoc, selfTy));
  
  PI.Ident = &Context.Idents.get("_cmd");
  CreateImplicitParameter(FnBodyScope, PI.Ident, PI.IdentLoc, 
                          Context.getObjCSelType());

  // Introduce all of the other parameters into this scope.
  for (unsigned i = 0, e = MDecl->getNumParams(); i != e; ++i) {
    ParmVarDecl *PDecl = MDecl->getParamDecl(i);
    IdentifierInfo *II = PDecl->getIdentifier();
    if (II) {
      IdResolver.AddDecl(PDecl, FnBodyScope);
      FnBodyScope->AddDecl(PDecl);
    }
  }
}

Sema::DeclTy *Sema::ActOnStartClassInterface(
                    SourceLocation AtInterfaceLoc,
                    IdentifierInfo *ClassName, SourceLocation ClassLoc,
                    IdentifierInfo *SuperName, SourceLocation SuperLoc,
                    IdentifierInfo **ProtocolNames, unsigned NumProtocols,
                    SourceLocation EndProtoLoc, AttributeList *AttrList) {
  assert(ClassName && "Missing class identifier");
  
  // Check for another declaration kind with the same name.
  Decl *PrevDecl = LookupDecl(ClassName, Decl::IDNS_Ordinary, TUScope);
  if (PrevDecl && !isa<ObjCInterfaceDecl>(PrevDecl)) {
    Diag(ClassLoc, diag::err_redefinition_different_kind,
         ClassName->getName());
    Diag(PrevDecl->getLocation(), diag::err_previous_definition);
  }
  
  ObjCInterfaceDecl* IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl);
  if (IDecl) {
    // Class already seen. Is it a forward declaration?
    if (!IDecl->isForwardDecl())
      Diag(AtInterfaceLoc, diag::err_duplicate_class_def, IDecl->getName());
    else {
      IDecl->setLocation(AtInterfaceLoc);
      IDecl->setForwardDecl(false);
      IDecl->AllocIntfRefProtocols(NumProtocols);
    }
  }
  else {
    IDecl = ObjCInterfaceDecl::Create(Context, AtInterfaceLoc, NumProtocols,
                                      ClassName, ClassLoc);
  
    ObjCInterfaceDecls[ClassName] = IDecl;
    // Remember that this needs to be removed when the scope is popped.
    TUScope->AddDecl(IDecl);
  }
  
  if (SuperName) {
    ObjCInterfaceDecl* SuperClassEntry = 0;
    // Check if a different kind of symbol declared in this scope.
    PrevDecl = LookupDecl(SuperName, Decl::IDNS_Ordinary, TUScope);
    if (PrevDecl && !isa<ObjCInterfaceDecl>(PrevDecl)) {
      Diag(SuperLoc, diag::err_redefinition_different_kind,
           SuperName->getName());
      Diag(PrevDecl->getLocation(), diag::err_previous_definition);
    }
    else {
      // Check that super class is previously defined
      SuperClassEntry = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl); 
                              
      if (!SuperClassEntry || SuperClassEntry->isForwardDecl()) {
        Diag(AtInterfaceLoc, diag::err_undef_superclass, 
             SuperClassEntry ? SuperClassEntry->getName() 
                             : SuperName->getName(),
             ClassName->getName()); 
      }
    }
    IDecl->setSuperClass(SuperClassEntry);
    IDecl->setSuperClassLoc(SuperLoc);
    IDecl->setLocEnd(SuperLoc);
  } else { // we have a root class.
    IDecl->setLocEnd(ClassLoc);
  }
  
  /// Check then save referenced protocols
  if (NumProtocols) {
    for (unsigned int i = 0; i != NumProtocols; i++) {
      ObjCProtocolDecl* RefPDecl = ObjCProtocols[ProtocolNames[i]];
      if (!RefPDecl || RefPDecl->isForwardDecl())
        Diag(ClassLoc, diag::warn_undef_protocolref,
             ProtocolNames[i]->getName(),
             ClassName->getName());
      IDecl->setIntfRefProtocols(i, RefPDecl);
    }
    IDecl->setLocEnd(EndProtoLoc);
  }
  return IDecl;
}

/// ActOnCompatiblityAlias - this action is called after complete parsing of
/// @compaatibility_alias declaration. It sets up the alias relationships.
Sema::DeclTy *Sema::ActOnCompatiblityAlias(SourceLocation AtLoc,
                                           IdentifierInfo *AliasName, 
                                           SourceLocation AliasLocation,
                                           IdentifierInfo *ClassName,
                                           SourceLocation ClassLocation) {
  // Look for previous declaration of alias name
  Decl *ADecl = LookupDecl(AliasName, Decl::IDNS_Ordinary, TUScope);
  if (ADecl) {
    if (isa<ObjCCompatibleAliasDecl>(ADecl)) {
      Diag(AliasLocation, diag::warn_previous_alias_decl);
      Diag(ADecl->getLocation(), diag::warn_previous_declaration);
    }
    else {
      Diag(AliasLocation, diag::err_conflicting_aliasing_type,
           AliasName->getName());
      Diag(ADecl->getLocation(), diag::err_previous_declaration);
    }
    return 0;
  }
  // Check for class declaration
  Decl *CDeclU = LookupDecl(ClassName, Decl::IDNS_Ordinary, TUScope);
  ObjCInterfaceDecl *CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(CDeclU);
  if (CDecl == 0) {
    Diag(ClassLocation, diag::warn_undef_interface, ClassName->getName());
    if (CDeclU)
      Diag(CDeclU->getLocation(), diag::warn_previous_declaration);
    return 0;
  }
  
  // Everything checked out, instantiate a new alias declaration AST.
  ObjCCompatibleAliasDecl *AliasDecl = 
    ObjCCompatibleAliasDecl::Create(Context, AtLoc, AliasName, CDecl);
  
  ObjCAliasDecls[AliasName] = AliasDecl;
  TUScope->AddDecl(AliasDecl);
  return AliasDecl;
}

Sema::DeclTy *Sema::ActOnStartProtocolInterface(
                SourceLocation AtProtoInterfaceLoc,
                IdentifierInfo *ProtocolName, SourceLocation ProtocolLoc,
                IdentifierInfo **ProtoRefNames, unsigned NumProtoRefs,
                SourceLocation EndProtoLoc) {
  assert(ProtocolName && "Missing protocol identifier");
  ObjCProtocolDecl *PDecl = ObjCProtocols[ProtocolName];
  if (PDecl) {
    // Protocol already seen. Better be a forward protocol declaration
    if (!PDecl->isForwardDecl()) {
      Diag(ProtocolLoc, diag::err_duplicate_protocol_def, 
           ProtocolName->getName());
      // Just return the protocol we already had.
      // FIXME: don't leak the objects passed in!
      return PDecl;
    }
    
    PDecl->setForwardDecl(false);
    PDecl->AllocReferencedProtocols(NumProtoRefs);
  } else {
    PDecl = ObjCProtocolDecl::Create(Context, AtProtoInterfaceLoc, NumProtoRefs, 
                                     ProtocolName);
    PDecl->setForwardDecl(false);
    ObjCProtocols[ProtocolName] = PDecl;
  }
  
  if (NumProtoRefs) {
    /// Check then save referenced protocols.
    for (unsigned int i = 0; i != NumProtoRefs; i++) {
      ObjCProtocolDecl* RefPDecl = ObjCProtocols[ProtoRefNames[i]];
      if (!RefPDecl || RefPDecl->isForwardDecl())
        Diag(ProtocolLoc, diag::warn_undef_protocolref,
             ProtoRefNames[i]->getName(),
             ProtocolName->getName());
      PDecl->setReferencedProtocols(i, RefPDecl);
    }
    PDecl->setLocEnd(EndProtoLoc);
  }
  return PDecl;
}

/// FindProtocolDeclaration - This routine looks up protocols and
/// issuer error if they are not declared. It returns list of protocol
/// declarations in its 'Protocols' argument.
void
Sema::FindProtocolDeclaration(SourceLocation TypeLoc,
                              IdentifierInfo **ProtocolId,
                              unsigned NumProtocols,
                              llvm::SmallVector<DeclTy *,8> &Protocols) {
  for (unsigned i = 0; i != NumProtocols; ++i) {
    ObjCProtocolDecl *PDecl = ObjCProtocols[ProtocolId[i]];
    if (!PDecl)
      Diag(TypeLoc, diag::err_undeclared_protocol, 
           ProtocolId[i]->getName());
    else
      Protocols.push_back(PDecl); 
  }
}

/// ActOnForwardProtocolDeclaration - 
Action::DeclTy *
Sema::ActOnForwardProtocolDeclaration(SourceLocation AtProtocolLoc,
        IdentifierInfo **IdentList, unsigned NumElts) {
  llvm::SmallVector<ObjCProtocolDecl*, 32> Protocols;
  
  for (unsigned i = 0; i != NumElts; ++i) {
    IdentifierInfo *Ident = IdentList[i];
    ObjCProtocolDecl *&PDecl = ObjCProtocols[Ident];
    if (PDecl == 0)  { // Not already seen?
      // FIXME: Pass in the location of the identifier!
      PDecl = ObjCProtocolDecl::Create(Context, AtProtocolLoc, 0, Ident);
    }
    
    Protocols.push_back(PDecl);
  }
  return ObjCForwardProtocolDecl::Create(Context, AtProtocolLoc,
                                         &Protocols[0], Protocols.size());
}

Sema::DeclTy *Sema::ActOnStartCategoryInterface(
                      SourceLocation AtInterfaceLoc,
                      IdentifierInfo *ClassName, SourceLocation ClassLoc,
                      IdentifierInfo *CategoryName, SourceLocation CategoryLoc,
                      IdentifierInfo **ProtoRefNames, unsigned NumProtoRefs,
                      SourceLocation EndProtoLoc) {
  ObjCInterfaceDecl *IDecl = getObjCInterfaceDecl(ClassName);
  
  ObjCCategoryDecl *CDecl = 
    ObjCCategoryDecl::Create(Context, AtInterfaceLoc, CategoryName);
  CDecl->setClassInterface(IDecl);
  
  /// Check that class of this category is already completely declared.
  if (!IDecl || IDecl->isForwardDecl())
    Diag(ClassLoc, diag::err_undef_interface, ClassName->getName());
  else {
    /// Check for duplicate interface declaration for this category
    ObjCCategoryDecl *CDeclChain;
    for (CDeclChain = IDecl->getCategoryList(); CDeclChain;
         CDeclChain = CDeclChain->getNextClassCategory()) {
      if (CDeclChain->getIdentifier() == CategoryName) {
        Diag(CategoryLoc, diag::err_dup_category_def, ClassName->getName(),
             CategoryName->getName());
        break;
      }
    }
  if (!CDeclChain)
    CDecl->insertNextClassCategory();
  }

  if (NumProtoRefs) {
    llvm::SmallVector<ObjCProtocolDecl*, 32> RefProtocols;
    /// Check and then save the referenced protocols.
    for (unsigned int i = 0; i != NumProtoRefs; i++) {
      ObjCProtocolDecl* RefPDecl = ObjCProtocols[ProtoRefNames[i]];
      if (!RefPDecl || RefPDecl->isForwardDecl()) {
        Diag(CategoryLoc, diag::warn_undef_protocolref,
             ProtoRefNames[i]->getName(),
             CategoryName->getName());
      }
      if (RefPDecl)
        RefProtocols.push_back(RefPDecl);
    }
    if (!RefProtocols.empty())
      CDecl->setReferencedProtocolList(&RefProtocols[0], RefProtocols.size());
  }
  CDecl->setLocEnd(EndProtoLoc);
  return CDecl;
}

/// ActOnStartCategoryImplementation - Perform semantic checks on the
/// category implementation declaration and build an ObjCCategoryImplDecl
/// object.
Sema::DeclTy *Sema::ActOnStartCategoryImplementation(
                      SourceLocation AtCatImplLoc,
                      IdentifierInfo *ClassName, SourceLocation ClassLoc,
                      IdentifierInfo *CatName, SourceLocation CatLoc) {
  ObjCInterfaceDecl *IDecl = getObjCInterfaceDecl(ClassName);
  ObjCCategoryImplDecl *CDecl = 
    ObjCCategoryImplDecl::Create(Context, AtCatImplLoc, CatName, IDecl);
  /// Check that class of this category is already completely declared.
  if (!IDecl || IDecl->isForwardDecl())
    Diag(ClassLoc, diag::err_undef_interface, ClassName->getName());

  /// TODO: Check that CatName, category name, is not used in another
  // implementation.
  return CDecl;
}

Sema::DeclTy *Sema::ActOnStartClassImplementation(
                      SourceLocation AtClassImplLoc,
                      IdentifierInfo *ClassName, SourceLocation ClassLoc,
                      IdentifierInfo *SuperClassname, 
                      SourceLocation SuperClassLoc) {
  ObjCInterfaceDecl* IDecl = 0;
  // Check for another declaration kind with the same name.
  Decl *PrevDecl = LookupDecl(ClassName, Decl::IDNS_Ordinary, TUScope);
  if (PrevDecl && !isa<ObjCInterfaceDecl>(PrevDecl)) {
    Diag(ClassLoc, diag::err_redefinition_different_kind,
         ClassName->getName());
    Diag(PrevDecl->getLocation(), diag::err_previous_definition);
  }
  else {
    // Is there an interface declaration of this class; if not, warn!
    IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl); 
    if (!IDecl)
      Diag(ClassLoc, diag::warn_undef_interface, ClassName->getName());
  }
  
  // Check that super class name is valid class name
  ObjCInterfaceDecl* SDecl = 0;
  if (SuperClassname) {
    // Check if a different kind of symbol declared in this scope.
    PrevDecl = LookupDecl(SuperClassname, Decl::IDNS_Ordinary, TUScope);
    if (PrevDecl && !isa<ObjCInterfaceDecl>(PrevDecl)) {
      Diag(SuperClassLoc, diag::err_redefinition_different_kind,
           SuperClassname->getName());
      Diag(PrevDecl->getLocation(), diag::err_previous_definition);
    }
    else {
      SDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl); 
      if (!SDecl)
        Diag(SuperClassLoc, diag::err_undef_superclass, 
             SuperClassname->getName(), ClassName->getName());
      else if (IDecl && IDecl->getSuperClass() != SDecl) {
        // This implementation and its interface do not have the same
        // super class.
        Diag(SuperClassLoc, diag::err_conflicting_super_class, 
             SDecl->getName());
        Diag(SDecl->getLocation(), diag::err_previous_definition);
      }
    }
  }
  
  if (!IDecl) {
    // Legacy case of @implementation with no corresponding @interface.
    // Build, chain & install the interface decl into the identifier.
    IDecl = ObjCInterfaceDecl::Create(Context, AtClassImplLoc, 0, ClassName, 
                                      ClassLoc, false, true);
    ObjCInterfaceDecls[ClassName] = IDecl;
    IDecl->setSuperClass(SDecl);
    IDecl->setLocEnd(ClassLoc);
    
    // Remember that this needs to be removed when the scope is popped.
    TUScope->AddDecl(IDecl);
  }
  
  ObjCImplementationDecl* IMPDecl = 
    ObjCImplementationDecl::Create(Context, AtClassImplLoc, ClassName, 
                                   IDecl, SDecl);
  
  // Check that there is no duplicate implementation of this class.
  if (ObjCImplementations[ClassName])
    // FIXME: Don't leak everything!
    Diag(ClassLoc, diag::err_dup_implementation_class, ClassName->getName());
  else // add it to the list.
    ObjCImplementations[ClassName] = IMPDecl;
  return IMPDecl;
}

void Sema::CheckImplementationIvars(ObjCImplementationDecl *ImpDecl,
                                    ObjCIvarDecl **ivars, unsigned numIvars,
                                    SourceLocation RBrace) {
  assert(ImpDecl && "missing implementation decl");
  ObjCInterfaceDecl* IDecl = getObjCInterfaceDecl(ImpDecl->getIdentifier());
  if (!IDecl)
    return;
  /// Check case of non-existing @interface decl.
  /// (legacy objective-c @implementation decl without an @interface decl).
  /// Add implementations's ivar to the synthesize class's ivar list.
  if (IDecl->ImplicitInterfaceDecl()) {
    IDecl->addInstanceVariablesToClass(ivars, numIvars, RBrace);
    return;
  }
  // If implementation has empty ivar list, just return.
  if (numIvars == 0)
    return;
  
  assert(ivars && "missing @implementation ivars");
  
  // Check interface's Ivar list against those in the implementation.
  // names and types must match.
  //
  unsigned j = 0;
  ObjCInterfaceDecl::ivar_iterator 
    IVI = IDecl->ivar_begin(), IVE = IDecl->ivar_end();
  for (; numIvars > 0 && IVI != IVE; ++IVI) {
    ObjCIvarDecl* ImplIvar = ivars[j++];
    ObjCIvarDecl* ClsIvar = *IVI;
    assert (ImplIvar && "missing implementation ivar");
    assert (ClsIvar && "missing class ivar");
    if (ImplIvar->getCanonicalType() != ClsIvar->getCanonicalType()) {
      Diag(ImplIvar->getLocation(), diag::err_conflicting_ivar_type,
           ImplIvar->getIdentifier()->getName());
      Diag(ClsIvar->getLocation(), diag::err_previous_definition,
           ClsIvar->getIdentifier()->getName());
    }
    // TODO: Two mismatched (unequal width) Ivar bitfields should be diagnosed 
    // as error.
    else if (ImplIvar->getIdentifier() != ClsIvar->getIdentifier()) {
      Diag(ImplIvar->getLocation(), diag::err_conflicting_ivar_name,
           ImplIvar->getIdentifier()->getName());
      Diag(ClsIvar->getLocation(), diag::err_previous_definition,
           ClsIvar->getIdentifier()->getName());
      return;
    }
    --numIvars;
  }
  
  if (numIvars > 0)
    Diag(ivars[j]->getLocation(), diag::err_inconsistant_ivar_count);
  else if (IVI != IVE)
    Diag((*IVI)->getLocation(), diag::err_inconsistant_ivar_count);
}

void Sema::WarnUndefinedMethod(SourceLocation ImpLoc, ObjCMethodDecl *method,
                               bool &IncompleteImpl) {
  if (!IncompleteImpl) {
    Diag(ImpLoc, diag::warn_incomplete_impl);
    IncompleteImpl = true;
  }
  Diag(ImpLoc, diag::warn_undef_method_impl, method->getSelector().getName());
}

/// CheckProtocolMethodDefs - This routine checks unimplemented methods
/// Declared in protocol, and those referenced by it.
void Sema::CheckProtocolMethodDefs(SourceLocation ImpLoc,
                                   ObjCProtocolDecl *PDecl,
                                   bool& IncompleteImpl,
                                   const llvm::DenseSet<Selector> &InsMap,
                                   const llvm::DenseSet<Selector> &ClsMap) {
  // check unimplemented instance methods.
  for (ObjCProtocolDecl::instmeth_iterator I = PDecl->instmeth_begin(), 
       E = PDecl->instmeth_end(); I != E; ++I) {
    ObjCMethodDecl *method = *I;
    if (!InsMap.count(method->getSelector()) && 
        method->getImplementationControl() != ObjCMethodDecl::Optional)
      WarnUndefinedMethod(ImpLoc, method, IncompleteImpl);
  }
  // check unimplemented class methods
  for (ObjCProtocolDecl::classmeth_iterator I = PDecl->classmeth_begin(), 
       E = PDecl->classmeth_end(); I != E; ++I) {
    ObjCMethodDecl *method = *I;
    if (!ClsMap.count(method->getSelector()) &&
        method->getImplementationControl() != ObjCMethodDecl::Optional)
      WarnUndefinedMethod(ImpLoc, method, IncompleteImpl);
  }
  // Check on this protocols's referenced protocols, recursively
  ObjCProtocolDecl** RefPDecl = PDecl->getReferencedProtocols();
  for (unsigned i = 0; i < PDecl->getNumReferencedProtocols(); i++)
    CheckProtocolMethodDefs(ImpLoc, RefPDecl[i], IncompleteImpl, InsMap, ClsMap);
}

void Sema::ImplMethodsVsClassMethods(ObjCImplementationDecl* IMPDecl, 
                                     ObjCInterfaceDecl* IDecl) {
  llvm::DenseSet<Selector> InsMap;
  // Check and see if instance methods in class interface have been
  // implemented in the implementation class.
  for (ObjCImplementationDecl::instmeth_iterator I = IMPDecl->instmeth_begin(),
       E = IMPDecl->instmeth_end(); I != E; ++I)
    InsMap.insert((*I)->getSelector());
  
  bool IncompleteImpl = false;
  for (ObjCInterfaceDecl::instmeth_iterator I = IDecl->instmeth_begin(),
       E = IDecl->instmeth_end(); I != E; ++I)
    if (!InsMap.count((*I)->getSelector()))
      WarnUndefinedMethod(IMPDecl->getLocation(), *I, IncompleteImpl);
      
  llvm::DenseSet<Selector> ClsMap;
  // Check and see if class methods in class interface have been
  // implemented in the implementation class.
  for (ObjCImplementationDecl::classmeth_iterator I =IMPDecl->classmeth_begin(),
       E = IMPDecl->classmeth_end(); I != E; ++I)
    ClsMap.insert((*I)->getSelector());
  
  for (ObjCInterfaceDecl::classmeth_iterator I = IDecl->classmeth_begin(),
       E = IDecl->classmeth_end(); I != E; ++I)
    if (!ClsMap.count((*I)->getSelector()))
      WarnUndefinedMethod(IMPDecl->getLocation(), *I, IncompleteImpl);
  
  // Check the protocol list for unimplemented methods in the @implementation
  // class.
  ObjCProtocolDecl** protocols = IDecl->getReferencedProtocols();
  for (unsigned i = 0; i < IDecl->getNumIntfRefProtocols(); i++)
    CheckProtocolMethodDefs(IMPDecl->getLocation(), protocols[i], 
                            IncompleteImpl, InsMap, ClsMap);
}

/// ImplCategoryMethodsVsIntfMethods - Checks that methods declared in the
/// category interface is implemented in the category @implementation.
void Sema::ImplCategoryMethodsVsIntfMethods(ObjCCategoryImplDecl *CatImplDecl,
                                            ObjCCategoryDecl *CatClassDecl) {
  llvm::DenseSet<Selector> InsMap;
  // Check and see if instance methods in category interface have been
  // implemented in its implementation class.
  for (ObjCCategoryImplDecl::instmeth_iterator I =CatImplDecl->instmeth_begin(),
       E = CatImplDecl->instmeth_end(); I != E; ++I)
    InsMap.insert((*I)->getSelector());
  
  bool IncompleteImpl = false;
  for (ObjCCategoryDecl::instmeth_iterator I = CatClassDecl->instmeth_begin(),
       E = CatClassDecl->instmeth_end(); I != E; ++I)
    if (!InsMap.count((*I)->getSelector()))
      WarnUndefinedMethod(CatImplDecl->getLocation(), *I, IncompleteImpl);

  llvm::DenseSet<Selector> ClsMap;
  // Check and see if class methods in category interface have been
  // implemented in its implementation class.
  for (ObjCCategoryImplDecl::classmeth_iterator
       I = CatImplDecl->classmeth_begin(), E = CatImplDecl->classmeth_end();
       I != E; ++I)
    ClsMap.insert((*I)->getSelector());
  
  for (ObjCCategoryDecl::classmeth_iterator I = CatClassDecl->classmeth_begin(),
       E = CatClassDecl->classmeth_end(); I != E; ++I)
    if (!ClsMap.count((*I)->getSelector()))
      WarnUndefinedMethod(CatImplDecl->getLocation(), *I, IncompleteImpl);
  
  // Check the protocol list for unimplemented methods in the @implementation
  // class.
  ObjCProtocolDecl** protocols = CatClassDecl->getReferencedProtocols();
  for (unsigned i = 0; i < CatClassDecl->getNumReferencedProtocols(); i++) {
    ObjCProtocolDecl* PDecl = protocols[i];
    CheckProtocolMethodDefs(CatImplDecl->getLocation(), PDecl, IncompleteImpl, 
                            InsMap, ClsMap);
  }
}

/// ActOnForwardClassDeclaration - 
Action::DeclTy *
Sema::ActOnForwardClassDeclaration(SourceLocation AtClassLoc,
                                   IdentifierInfo **IdentList, unsigned NumElts) 
{
  llvm::SmallVector<ObjCInterfaceDecl*, 32> Interfaces;
  
  for (unsigned i = 0; i != NumElts; ++i) {
    // Check for another declaration kind with the same name.
    Decl *PrevDecl = LookupDecl(IdentList[i], Decl::IDNS_Ordinary, TUScope);
    if (PrevDecl && !isa<ObjCInterfaceDecl>(PrevDecl)) {
      Diag(AtClassLoc, diag::err_redefinition_different_kind,
           IdentList[i]->getName());
      Diag(PrevDecl->getLocation(), diag::err_previous_definition);
    }
    ObjCInterfaceDecl *IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl); 
    if (!IDecl) {  // Not already seen?  Make a forward decl.
      IDecl = ObjCInterfaceDecl::Create(Context, AtClassLoc, 0, IdentList[i],
                                        SourceLocation(), true);
      ObjCInterfaceDecls[IdentList[i]] = IDecl;

      // Remember that this needs to be removed when the scope is popped.
      TUScope->AddDecl(IDecl);
    }

    Interfaces.push_back(IDecl);
  }
  
  return ObjCClassDecl::Create(Context, AtClassLoc,
                               &Interfaces[0], Interfaces.size());
}


/// MatchTwoMethodDeclarations - Checks that two methods have matching type and
/// returns true, or false, accordingly.
/// TODO: Handle protocol list; such as id<p1,p2> in type comparisons
bool Sema::MatchTwoMethodDeclarations(const ObjCMethodDecl *Method, 
                                      const ObjCMethodDecl *PrevMethod) {
  if (Method->getResultType().getCanonicalType() !=
      PrevMethod->getResultType().getCanonicalType())
    return false;
  for (unsigned i = 0, e = Method->getNumParams(); i != e; ++i) {
    ParmVarDecl *ParamDecl = Method->getParamDecl(i);
    ParmVarDecl *PrevParamDecl = PrevMethod->getParamDecl(i);
    if (Context.getCanonicalType(ParamDecl->getType()) !=
        Context.getCanonicalType(PrevParamDecl->getType()))
      return false;
  }
  return true;
}

void Sema::AddInstanceMethodToGlobalPool(ObjCMethodDecl *Method) {
  ObjCMethodList &FirstMethod = InstanceMethodPool[Method->getSelector()];
  if (!FirstMethod.Method) {
    // Haven't seen a method with this selector name yet - add it.
    FirstMethod.Method = Method;
    FirstMethod.Next = 0;
  } else {
    // We've seen a method with this name, now check the type signature(s).
    bool match = MatchTwoMethodDeclarations(Method, FirstMethod.Method);
    
    for (ObjCMethodList *Next = FirstMethod.Next; !match && Next; 
         Next = Next->Next)
      match = MatchTwoMethodDeclarations(Method, Next->Method);
      
    if (!match) {
      // We have a new signature for an existing method - add it.
      // This is extremely rare. Only 1% of Cocoa selectors are "overloaded".
      struct ObjCMethodList *OMI = new ObjCMethodList(Method, FirstMethod.Next);
      FirstMethod.Next = OMI;
    }
  }
}

void Sema::AddFactoryMethodToGlobalPool(ObjCMethodDecl *Method) {
  ObjCMethodList &FirstMethod = FactoryMethodPool[Method->getSelector()];
  if (!FirstMethod.Method) {
    // Haven't seen a method with this selector name yet - add it.
    FirstMethod.Method = Method;
    FirstMethod.Next = 0;
  } else {
    // We've seen a method with this name, now check the type signature(s).
    bool match = MatchTwoMethodDeclarations(Method, FirstMethod.Method);
    
    for (ObjCMethodList *Next = FirstMethod.Next; !match && Next; 
         Next = Next->Next)
      match = MatchTwoMethodDeclarations(Method, Next->Method);
      
    if (!match) {
      // We have a new signature for an existing method - add it.
      // This is extremely rare. Only 1% of Cocoa selectors are "overloaded".
      struct ObjCMethodList *OMI = new ObjCMethodList(Method, FirstMethod.Next);
      FirstMethod.Next = OMI;
    }
  }
}

// Note: For class/category implemenations, allMethods/allProperties is
// always null.
void Sema::ActOnAtEnd(SourceLocation AtEndLoc, DeclTy *classDecl,
                      DeclTy **allMethods, unsigned allNum,
                      DeclTy **allProperties, unsigned pNum) {
  Decl *ClassDecl = static_cast<Decl *>(classDecl);

  // FIXME: If we don't have a ClassDecl, we have an error. We should consider
  // always passing in a decl. If the decl has an error, isInvalidDecl()
  // should be true.
  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);
    else if (ObjCCategoryDecl *CDecl = dyn_cast<ObjCCategoryDecl>(ClassDecl))
      CDecl->addProperties((ObjCPropertyDecl**)allProperties, pNum);
    else if (ObjCProtocolDecl *PDecl = dyn_cast<ObjCProtocolDecl>(ClassDecl))
          PDecl->addProperties((ObjCPropertyDecl**)allProperties, pNum);
    else
      assert(false && "ActOnAtEnd - property declaration misplaced");
  
  for (unsigned i = 0; i < allNum; i++ ) {
    ObjCMethodDecl *Method =
      cast_or_null<ObjCMethodDecl>(static_cast<Decl*>(allMethods[i]));

    if (!Method) continue;  // Already issued a diagnostic.
    if (Method->isInstance()) {
      /// Check for instance method of the same name with incompatible types
      const ObjCMethodDecl *&PrevMethod = InsMap[Method->getSelector()];
      bool match = PrevMethod ? MatchTwoMethodDeclarations(Method, PrevMethod) 
                              : false;
      if (isInterfaceDeclKind && PrevMethod && !match 
          || checkIdenticalMethods && match) {
          Diag(Method->getLocation(), diag::error_duplicate_method_decl,
               Method->getSelector().getName());
          Diag(PrevMethod->getLocation(), diag::err_previous_declaration);
      } else {
        insMethods.push_back(Method);
        InsMap[Method->getSelector()] = Method;
        /// The following allows us to typecheck messages to "id".
        AddInstanceMethodToGlobalPool(Method);
      }
    }
    else {
      /// Check for class method of the same name with incompatible types
      const ObjCMethodDecl *&PrevMethod = ClsMap[Method->getSelector()];
      bool match = PrevMethod ? MatchTwoMethodDeclarations(Method, PrevMethod) 
                              : false;
      if (isInterfaceDeclKind && PrevMethod && !match 
          || checkIdenticalMethods && match) {
        Diag(Method->getLocation(), diag::error_duplicate_method_decl,
             Method->getSelector().getName());
        Diag(PrevMethod->getLocation(), diag::err_previous_declaration);
      } else {
        clsMethods.push_back(Method);
        ClsMap[Method->getSelector()] = Method;
        /// The following allows us to typecheck messages to "Class".
        AddFactoryMethodToGlobalPool(Method);
      }
    }
  }
  
  if (ObjCInterfaceDecl *I = dyn_cast<ObjCInterfaceDecl>(ClassDecl)) {
    I->addMethods(&insMethods[0], insMethods.size(),
                  &clsMethods[0], clsMethods.size(), AtEndLoc);
  } else if (ObjCProtocolDecl *P = dyn_cast<ObjCProtocolDecl>(ClassDecl)) {
    P->addMethods(&insMethods[0], insMethods.size(),
                  &clsMethods[0], clsMethods.size(), AtEndLoc);
  }
  else if (ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(ClassDecl)) {
    C->addMethods(&insMethods[0], insMethods.size(),
                  &clsMethods[0], clsMethods.size(), AtEndLoc);
  }
  else if (ObjCImplementationDecl *IC = 
                dyn_cast<ObjCImplementationDecl>(ClassDecl)) {
    IC->setLocEnd(AtEndLoc);
    if (ObjCInterfaceDecl* IDecl = getObjCInterfaceDecl(IC->getIdentifier()))
      ImplMethodsVsClassMethods(IC, IDecl);
  } else {
    ObjCCategoryImplDecl* CatImplClass = cast<ObjCCategoryImplDecl>(ClassDecl);
    CatImplClass->setLocEnd(AtEndLoc);
    ObjCInterfaceDecl* IDecl = CatImplClass->getClassInterface();
    // Find category interface decl and then check that all methods declared
    // in this interface is implemented in the category @implementation.
    if (IDecl) {
      for (ObjCCategoryDecl *Categories = IDecl->getCategoryList();
           Categories; Categories = Categories->getNextClassCategory()) {
        if (Categories->getIdentifier() == CatImplClass->getIdentifier()) {
          ImplCategoryMethodsVsIntfMethods(CatImplClass, Categories);
          break;
        }
      }
    }
  }
}


/// CvtQTToAstBitMask - utility routine to produce an AST bitmask for
/// objective-c's type qualifier from the parser version of the same info.
static Decl::ObjCDeclQualifier 
CvtQTToAstBitMask(ObjCDeclSpec::ObjCDeclQualifier PQTVal) {
  Decl::ObjCDeclQualifier ret = Decl::OBJC_TQ_None;
  if (PQTVal & ObjCDeclSpec::DQ_In)
    ret = (Decl::ObjCDeclQualifier)(ret | Decl::OBJC_TQ_In);
  if (PQTVal & ObjCDeclSpec::DQ_Inout)
    ret = (Decl::ObjCDeclQualifier)(ret | Decl::OBJC_TQ_Inout);
  if (PQTVal & ObjCDeclSpec::DQ_Out)
    ret = (Decl::ObjCDeclQualifier)(ret | Decl::OBJC_TQ_Out);
  if (PQTVal & ObjCDeclSpec::DQ_Bycopy)
    ret = (Decl::ObjCDeclQualifier)(ret | Decl::OBJC_TQ_Bycopy);
  if (PQTVal & ObjCDeclSpec::DQ_Byref)
    ret = (Decl::ObjCDeclQualifier)(ret | Decl::OBJC_TQ_Byref);
  if (PQTVal & ObjCDeclSpec::DQ_Oneway)
    ret = (Decl::ObjCDeclQualifier)(ret | Decl::OBJC_TQ_Oneway);

  return ret;
}

Sema::DeclTy *Sema::ActOnMethodDeclaration(
    SourceLocation MethodLoc, SourceLocation EndLoc,
    tok::TokenKind MethodType, DeclTy *classDecl,
    ObjCDeclSpec &ReturnQT, TypeTy *ReturnType,
    Selector Sel,
    // optional arguments. The number of types/arguments is obtained
    // from the Sel.getNumArgs().
    ObjCDeclSpec *ArgQT, TypeTy **ArgTypes, IdentifierInfo **ArgNames,
    AttributeList *AttrList, tok::ObjCKeywordKind MethodDeclKind,
    bool isVariadic) {
  Decl *ClassDecl = static_cast<Decl*>(classDecl);

  // Make sure we can establish a context for the method.
  if (!ClassDecl) {
    Diag(MethodLoc, diag::error_missing_method_context);
    return 0;
  }
  QualType resultDeclType;
  
  if (ReturnType)
    resultDeclType = QualType::getFromOpaquePtr(ReturnType);
  else // get the type for "id".
    resultDeclType = Context.getObjCIdType();
  
  ObjCMethodDecl* ObjCMethod = 
    ObjCMethodDecl::Create(Context, MethodLoc, EndLoc, Sel, resultDeclType,
                           ClassDecl, AttrList, 
                           MethodType == tok::minus, isVariadic,
                           MethodDeclKind == tok::objc_optional ? 
                           ObjCMethodDecl::Optional : 
                           ObjCMethodDecl::Required);
  
  llvm::SmallVector<ParmVarDecl*, 16> Params;
  
  for (unsigned i = 0; i < Sel.getNumArgs(); i++) {
    // FIXME: arg->AttrList must be stored too!
    QualType argType;
    
    if (ArgTypes[i])
      argType = QualType::getFromOpaquePtr(ArgTypes[i]);
    else
      argType = Context.getObjCIdType();
    ParmVarDecl* Param = ParmVarDecl::Create(Context, ObjCMethod,
                                             SourceLocation(/*FIXME*/),
                                             ArgNames[i], argType,
                                             VarDecl::None, 0, 0);
    Param->setObjCDeclQualifier(
      CvtQTToAstBitMask(ArgQT[i].getObjCDeclQualifier()));
    Params.push_back(Param);
  }

  ObjCMethod->setMethodParams(&Params[0], Sel.getNumArgs());
  ObjCMethod->setObjCDeclQualifier(
    CvtQTToAstBitMask(ReturnQT.getObjCDeclQualifier()));
  const ObjCMethodDecl *PrevMethod = 0;
 
  // For implementations (which can be very "coarse grain"), we add the 
  // method now. This allows the AST to implement lookup methods that work 
  // incrementally (without waiting until we parse the @end). It also allows 
  // us to flag multiple declaration errors as they occur.
  if (ObjCImplementationDecl *ImpDecl = 
        dyn_cast<ObjCImplementationDecl>(ClassDecl)) {
    if (MethodType == tok::minus) {
      PrevMethod = ImpDecl->getInstanceMethod(Sel);
      ImpDecl->addInstanceMethod(ObjCMethod);
    } else {
      PrevMethod = ImpDecl->getClassMethod(Sel);
      ImpDecl->addClassMethod(ObjCMethod);
    }
  } 
  else if (ObjCCategoryImplDecl *CatImpDecl = 
            dyn_cast<ObjCCategoryImplDecl>(ClassDecl)) {
    if (MethodType == tok::minus) {
      PrevMethod = CatImpDecl->getInstanceMethod(Sel);
      CatImpDecl->addInstanceMethod(ObjCMethod);
    } else {
      PrevMethod = CatImpDecl->getClassMethod(Sel);
      CatImpDecl->addClassMethod(ObjCMethod);
    }
  }
  if (PrevMethod) {
    // You can never have two method definitions with the same name.
    Diag(ObjCMethod->getLocation(), diag::error_duplicate_method_decl,
        ObjCMethod->getSelector().getName());
    Diag(PrevMethod->getLocation(), diag::err_previous_declaration);
  } 
  return ObjCMethod;
}

Sema::DeclTy *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc, 
                                  FieldDeclarator &FD,
                                  ObjCDeclSpec &ODS) {
  QualType T = GetTypeForDeclarator(FD.D, S);
  ObjCPropertyDecl *PDecl = ObjCPropertyDecl::Create(Context, AtLoc, 
                                                     FD.D.getIdentifier(), T);
  
  if (ODS.getPropertyAttributes() & ObjCDeclSpec::DQ_PR_readonly)
    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readonly);
  
  if (ODS.getPropertyAttributes() & ObjCDeclSpec::DQ_PR_getter) {
    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_getter);
    PDecl->setGetterName(ODS.getGetterName());
  }
  
  if (ODS.getPropertyAttributes() & ObjCDeclSpec::DQ_PR_setter) {
    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_setter);
    PDecl->setSetterName(ODS.getSetterName());
  }
  
  if (ODS.getPropertyAttributes() & ObjCDeclSpec::DQ_PR_assign)
    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_assign);
  
  if (ODS.getPropertyAttributes() & ObjCDeclSpec::DQ_PR_readwrite)
    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readwrite);
  
  if (ODS.getPropertyAttributes() & ObjCDeclSpec::DQ_PR_retain)
    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_retain);
  
  if (ODS.getPropertyAttributes() & ObjCDeclSpec::DQ_PR_copy)
    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_copy);
  
  if (ODS.getPropertyAttributes() & ObjCDeclSpec::DQ_PR_nonatomic)
    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_nonatomic);
  
  return PDecl;
}

/// ActOnPropertyImplDecl - This routine performs semantic checks and
/// builds the AST node for a property implementation declaration; declared
/// as @synthesize or @dynamic.
///
Sema::DeclTy *Sema::ActOnPropertyImplDecl(SourceLocation AtLoc, 
                                          SourceLocation PropertyLoc,
                                          bool Synthesize, 
                                          DeclTy *ClassCatImpDecl,
                                          IdentifierInfo *PropertyId,
                                          IdentifierInfo *PropertyIvar) {
  Decl *ClassImpDecl = static_cast<Decl*>(ClassCatImpDecl);
  // Make sure we have a context for the property implementation declaration.
  if (!ClassImpDecl) {
    Diag(AtLoc, diag::error_missing_property_context);
    return 0;
  }
  ObjCPropertyDecl *property = 0;
  ObjCInterfaceDecl* IDecl = 0;
  // Find the class or category class where this property must have
  // a declaration.
  if (ObjCImplementationDecl *IC = 
        dyn_cast<ObjCImplementationDecl>(ClassImpDecl)) {
    IDecl = getObjCInterfaceDecl(IC->getIdentifier());
    // We always synthesize an interface for an implementation
    // without an interface decl. So, IDecl is always non-zero.
    assert(IDecl && 
           "ActOnPropertyImplDecl - @implementation without @interface");
    
    // Look for this property declaration in the @implementation's @interface
    property = IDecl->FindPropertyDeclaration(PropertyId);
    if (!property) {
       Diag(PropertyLoc, diag::error_bad_property_decl, IDecl->getName());
      return 0;
    }
  }
  else if (ObjCCategoryImplDecl* CatImplClass = 
            dyn_cast<ObjCCategoryImplDecl>(ClassImpDecl)) {
    if (Synthesize) {
      Diag(AtLoc, diag::error_synthesize_category_decl);
      return 0;
    }    
    IDecl = CatImplClass->getClassInterface();
    if (!IDecl) {
      Diag(AtLoc, diag::error_missing_property_interface);
      return 0;
    }
    ObjCCategoryDecl *Category = 
      IDecl->FindCategoryDeclaration(CatImplClass->getIdentifier());
    
    // If category for this implementation not found, it is an error which
    // has already been reported eralier.
    if (!Category)
      return 0;
    // Look for this property declaration in @implementation's category
    property = Category->FindPropertyDeclaration(PropertyId);
    if (!property) {
      Diag(PropertyLoc, diag::error_bad_category_property_decl, 
           Category->getName());
      return 0;
    }
  }
  else {
    Diag(AtLoc, diag::error_bad_property_context);
    return 0;
  }
  
  // Check that we have a valid, previously declared ivar for @synthesize
  if (Synthesize) {
    // @synthesize
    if (!PropertyIvar)
      PropertyIvar = PropertyId;
    // Check that this is a previously declared 'ivar' in 'IDecl' interface
    ObjCIvarDecl *Ivar = IDecl->FindIvarDeclaration(PropertyIvar);
    if (!Ivar) {
      Diag(PropertyLoc, diag::error_missing_property_ivar_decl, 
           PropertyId->getName());
      return 0;
    }
    // Check that type of property and its ivar match. 
    if (Ivar->getCanonicalType() != property->getCanonicalType()) {
      Diag(PropertyLoc, diag::error_property_ivar_type, property->getName(),
           Ivar->getName());
      return 0;
    }
      
  } else if (PropertyIvar) {
    // @dynamic
    Diag(PropertyLoc, diag::error_dynamic_property_ivar_decl);
    return 0;
  }
  assert (property && "ActOnPropertyImplDecl - property declaration missing");
  // TODO: Build the property implementation AST, pushes it into its 
  // class/cateogory implementation's vector of property implementations
#if 0
  ObjCCategoryImplDecl *PIDecl = 
    ObjCCategoryImplDecl::Create(AtLoc, PropertyLoc, property, 
      Synthesize ? ObjCPropertyImplDecl::OBJC_PR_IMPL_SYNTHSIZE 
                 : ObjCPropertyImplDecl::OBJC_PR_IMPL_DYNAMIC,
                                 PropertyId, PropertyIvar);
#endif
  return 0;
}

