diff options
Diffstat (limited to 'clang/lib')
31 files changed, 825 insertions, 371 deletions
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 044106300cb..3455504fdb1 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -539,7 +539,7 @@ const ASTRecordLayout &ASTContext::getASTRecordLayout(const RecordDecl *D) {    ASTRecordLayout *NewEntry = new ASTRecordLayout();    Entry = NewEntry; -  NewEntry->InitializeLayout(D->getNumMembers()); +  NewEntry->InitializeLayout(std::distance(D->field_begin(), D->field_end()));    bool IsUnion = D->isUnion();    unsigned StructPacking = 0; @@ -552,10 +552,11 @@ const ASTRecordLayout &ASTContext::getASTRecordLayout(const RecordDecl *D) {    // Layout each field, for now, just sequentially, respecting alignment.  In    // the future, this will need to be tweakable by targets. -  for (unsigned i = 0, e = D->getNumMembers(); i != e; ++i) { -    const FieldDecl *FD = D->getMember(i); -    NewEntry->LayoutField(FD, i, IsUnion, StructPacking, *this); -  } +  unsigned FieldIdx = 0; +  for (RecordDecl::field_iterator Field = D->field_begin(), +                               FieldEnd = D->field_end(); +       Field != FieldEnd; (void)++Field, ++FieldIdx) +    NewEntry->LayoutField(*Field, FieldIdx, IsUnion, StructPacking, *this);    // Finally, round the size of the total struct up to the alignment of the    // struct itself. @@ -996,12 +997,16 @@ QualType ASTContext::getTypeDeclType(TypeDecl *Decl, TypeDecl* PrevDecl) {    return QualType(Decl->TypeForDecl, 0);  } -/// setTagDefinition - Used by RecordDecl::defineBody to inform ASTContext -///  about which RecordDecl serves as the definition of a particular -///  struct/union/class.  This will eventually be used by enums as well. +/// setTagDefinition - Used by RecordDecl::completeDefinition and +/// EnumDecl::completeDefinition to inform about which +/// RecordDecl/EnumDecl serves as the definition of a particular +/// struct/union/class/enum.  void ASTContext::setTagDefinition(TagDecl* D) {    assert (D->isDefinition()); -  cast<TagType>(D->TypeForDecl)->decl = D;   +  if (!D->TypeForDecl) +    getTypeDeclType(D); +  else +    cast<TagType>(D->TypeForDecl)->decl = D;    }  /// getTypedefType - Return the unique reference to the type for the @@ -1460,14 +1465,17 @@ QualType ASTContext::getCFConstantStringType() {      FieldTypes[2] = getPointerType(CharTy.getQualifiedType(QualType::Const));        // long length;      FieldTypes[3] = LongTy;   -    // Create fields -    FieldDecl *FieldDecls[4]; -   -    for (unsigned i = 0; i < 4; ++i) -      FieldDecls[i] = FieldDecl::Create(*this, SourceLocation(), 0, -                                        FieldTypes[i]); -    CFConstantStringTypeDecl->defineBody(*this, FieldDecls, 4); +    // Create fields +    for (unsigned i = 0; i < 4; ++i) { +      FieldDecl *Field = FieldDecl::Create(*this, CFConstantStringTypeDecl,  +                                           SourceLocation(), 0, +                                           FieldTypes[i], /*BitWidth=*/0,  +                                           /*Mutable=*/false, /*PrevDecl=*/0); +      CFConstantStringTypeDecl->addDecl(*this, Field, true); +    } + +    CFConstantStringTypeDecl->completeDefinition(*this);    }    return getTagDeclType(CFConstantStringTypeDecl); @@ -1476,6 +1484,10 @@ QualType ASTContext::getCFConstantStringType() {  QualType ASTContext::getObjCFastEnumerationStateType()  {    if (!ObjCFastEnumerationStateTypeDecl) { +    ObjCFastEnumerationStateTypeDecl = +      RecordDecl::Create(*this, TagDecl::TK_struct, TUDecl, SourceLocation(), +                         &Idents.get("__objcFastEnumerationState")); +          QualType FieldTypes[] = {        UnsignedLongTy,        getPointerType(ObjCIdType), @@ -1484,16 +1496,16 @@ QualType ASTContext::getObjCFastEnumerationStateType()                             llvm::APInt(32, 5), ArrayType::Normal, 0)      }; -    FieldDecl *FieldDecls[4]; -    for (size_t i = 0; i < 4; ++i) -      FieldDecls[i] = FieldDecl::Create(*this, SourceLocation(), 0,  -                                        FieldTypes[i]); -     -    ObjCFastEnumerationStateTypeDecl = -      RecordDecl::Create(*this, TagDecl::TK_struct, TUDecl, SourceLocation(), -                         &Idents.get("__objcFastEnumerationState")); +    for (size_t i = 0; i < 4; ++i) { +      FieldDecl *Field = FieldDecl::Create(*this,  +                                           ObjCFastEnumerationStateTypeDecl,  +                                           SourceLocation(), 0,  +                                           FieldTypes[i], /*BitWidth=*/0,  +                                           /*Mutable=*/false, /*PrevDecl=*/0); +      ObjCFastEnumerationStateTypeDecl->addDecl(*this, Field, true); +    } -    ObjCFastEnumerationStateTypeDecl->defineBody(*this, FieldDecls, 4); +    ObjCFastEnumerationStateTypeDecl->completeDefinition(*this);    }    return getTagDeclType(ObjCFastEnumerationStateTypeDecl); @@ -1745,16 +1757,17 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,      }      if (ExpandStructures) {        S += '='; -      for (int i = 0; i < RDecl->getNumMembers(); i++) { -        FieldDecl *FD = RDecl->getMember(i); +      for (RecordDecl::field_iterator Field = RDecl->field_begin(), +                                   FieldEnd = RDecl->field_end(); +           Field != FieldEnd; ++Field) {          if (NameFields) {            S += '"'; -          S += FD->getNameAsString(); +          S += Field->getNameAsString();            S += '"';          }          // Special case bit-fields. -        if (const Expr *E = FD->getBitWidth()) { +        if (const Expr *E = Field->getBitWidth()) {            // FIXME: Fix constness.            ASTContext *Ctx = const_cast<ASTContext*>(this);            unsigned N = E->getIntegerConstantExprValue(*Ctx).getZExtValue(); @@ -1763,7 +1776,8 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,            S += 'b';            S += llvm::utostr(N);          } else { -          getObjCEncodingForTypeImpl(FD->getType(), S, false, true, NameFields); +          getObjCEncodingForTypeImpl(Field->getType(), S, false, true,  +                                     NameFields);          }        }      } diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 194f47f96c4..7643e4eda87 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -81,10 +81,11 @@ BlockDecl *BlockDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L) {    return new (Mem) BlockDecl(DC, L);  } -FieldDecl *FieldDecl::Create(ASTContext &C, SourceLocation L, -                             IdentifierInfo *Id, QualType T, Expr *BW) { +FieldDecl *FieldDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, +                             IdentifierInfo *Id, QualType T, Expr *BW, +                             bool Mutable, ScopedDecl *PrevDecl) {    void *Mem = C.getAllocator().Allocate<FieldDecl>(); -  return new (Mem) FieldDecl(L, Id, T, BW); +  return new (Mem) FieldDecl(Decl::Field, DC, L, Id, T, BW, Mutable, PrevDecl);  } @@ -118,10 +119,21 @@ EnumDecl *EnumDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L,  }  void EnumDecl::Destroy(ASTContext& C) { -  if (getEnumConstantList()) getEnumConstantList()->Destroy(C); +  DeclContext::DestroyDecls(C);    Decl::Destroy(C);  } +void EnumDecl::completeDefinition(ASTContext &C, QualType NewType) { +  assert(!isDefinition() && "Cannot redefine enums!"); +  setDefinition(true); + +  IntegerType = NewType; + +  // Let ASTContext know that this is the defining EnumDecl for this +  // type. +  C.setTagDefinition(this); +} +  FileScopeAsmDecl *FileScopeAsmDecl::Create(ASTContext &C,                                             SourceLocation L,                                             StringLiteral *Str) { @@ -248,12 +260,10 @@ TagDecl* TagDecl::getDefinition(ASTContext& C) const {  RecordDecl::RecordDecl(Kind DK, TagKind TK, DeclContext *DC, SourceLocation L,                         IdentifierInfo *Id) -: TagDecl(DK, TK, DC, L, Id, 0) { +  : TagDecl(DK, TK, DC, L, Id, 0), DeclContext(DK) {    HasFlexibleArrayMember = false;    assert(classof(static_cast<Decl*>(this)) && "Invalid Kind!"); -  Members = 0; -  NumMembers = -1;    }  RecordDecl *RecordDecl::Create(ASTContext &C, TagKind TK, DeclContext *DC, @@ -267,46 +277,25 @@ RecordDecl *RecordDecl::Create(ASTContext &C, TagKind TK, DeclContext *DC,  }  RecordDecl::~RecordDecl() { -  delete[] Members;  }  void RecordDecl::Destroy(ASTContext& C) { -  if (isDefinition()) -    for (field_iterator I=field_begin(), E=field_end(); I!=E; ++I) -      (*I)->Destroy(C); - +  DeclContext::DestroyDecls(C);    TagDecl::Destroy(C);  } -/// defineBody - When created, RecordDecl's correspond to a forward declared -/// record.  This method is used to mark the decl as being defined, with the -/// specified contents. -void RecordDecl::defineBody(ASTContext& C, FieldDecl **members, -                            unsigned numMembers) { +/// completeDefinition - Notes that the definition of this type is now +/// complete. +void RecordDecl::completeDefinition(ASTContext& C) {    assert(!isDefinition() && "Cannot redefine record!"); +    setDefinition(true); -  NumMembers = numMembers; -  if (numMembers) { -    Members = new FieldDecl*[numMembers]; -    memcpy(Members, members, numMembers*sizeof(Decl*)); -  } -  // Let ASTContext know that this is the defining RecordDecl this type. +  // Let ASTContext know that this is the defining RecordDecl for this +  // type.    C.setTagDefinition(this);  } - -FieldDecl *RecordDecl::getMember(IdentifierInfo *II) { -  if (Members == 0 || NumMembers < 0) -    return 0; -   -  // Linear search.  When C++ classes come along, will likely need to revisit. -  for (int i = 0; i != NumMembers; ++i) -    if (Members[i]->getIdentifier() == II) -      return Members[i]; -  return 0; -} -  //===----------------------------------------------------------------------===//  // BlockDecl Implementation  //===----------------------------------------------------------------------===// diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp index 7b5df1c1945..3e0f158cbe1 100644 --- a/clang/lib/AST/DeclBase.cpp +++ b/clang/lib/AST/DeclBase.cpp @@ -15,6 +15,7 @@  #include "clang/AST/DeclObjC.h"  #include "clang/AST/DeclCXX.h"  #include "clang/AST/ASTContext.h" +#include "clang/AST/Type.h"  #include "llvm/ADT/DenseMap.h"  using namespace clang; @@ -34,7 +35,6 @@ static unsigned nNamespaces = 0;  static unsigned nOverFuncs = 0;  static unsigned nTypedef = 0;  static unsigned nFieldDecls = 0; -static unsigned nCXXFieldDecls = 0;  static unsigned nInterfaceDecls = 0;  static unsigned nClassDecls = 0;  static unsigned nMethodDecls = 0; @@ -95,7 +95,7 @@ bool Decl::CollectingStats(bool Enable) {  void Decl::PrintStats() {    fprintf(stderr, "*** Decl Stats:\n");    fprintf(stderr, "  %d decls total.\n",  -          int(nFuncs+nVars+nParmVars+nFieldDecls+nSUC+nCXXFieldDecls+nCXXSUC+ +          int(nFuncs+nVars+nParmVars+nFieldDecls+nSUC+nCXXSUC+                nEnumDecls+nEnumConst+nTypedef+nInterfaceDecls+nClassDecls+                nMethodDecls+nProtocolDecls+nCategoryDecls+nIvarDecls+                nAtDefsFieldDecls+nNamespaces+nOverFuncs)); @@ -122,9 +122,6 @@ void Decl::PrintStats() {    fprintf(stderr, "    %d struct/union/class decls, %d each (%d bytes)\n",             nSUC, (int)sizeof(RecordDecl),            int(nSUC*sizeof(RecordDecl))); -  fprintf(stderr, "    %d C++ field decls, %d each (%d bytes)\n",  -          nCXXFieldDecls, (int)sizeof(CXXFieldDecl), -          int(nCXXFieldDecls*sizeof(CXXFieldDecl)));    fprintf(stderr, "    %d C++ struct/union/class decls, %d each (%d bytes)\n",             nCXXSUC, (int)sizeof(CXXRecordDecl),            int(nCXXSUC*sizeof(CXXRecordDecl))); @@ -183,7 +180,7 @@ void Decl::PrintStats() {            int(nFuncs*sizeof(FunctionDecl)+                nVars*sizeof(VarDecl)+nParmVars*sizeof(ParmVarDecl)+                nFieldDecls*sizeof(FieldDecl)+nSUC*sizeof(RecordDecl)+ -              nCXXFieldDecls*sizeof(CXXFieldDecl)+nCXXSUC*sizeof(CXXRecordDecl)+ +              nCXXSUC*sizeof(CXXRecordDecl)+                nEnumDecls*sizeof(EnumDecl)+nEnumConst*sizeof(EnumConstantDecl)+                nTypedef*sizeof(TypedefDecl)+                nInterfaceDecls*sizeof(ObjCInterfaceDecl)+ @@ -236,7 +233,6 @@ void Decl::addDeclKind(Kind k) {    case ImplicitParam:    case TranslationUnit:     break; -  case CXXField:            nCXXFieldDecls++; break;    case CXXRecord:           nCXXSUC++; break;    // FIXME: Statistics for C++ decls.    case TemplateTypeParm: @@ -372,3 +368,269 @@ const DeclContext *DeclContext::getLexicalParent() const {      return SD->getLexicalDeclContext();    return getParent();  } + +/// TwoNamedDecls - Stores up to two NamedDecls. The first +/// declaration, if any, is in the ordinary identifier namespace, and +/// corresponds to values (functions, variables, etc.). The second +/// declaration, if any, is in the tag identifier namespace, and +/// corresponds to tag types (classes, enums). +struct TwoNamedDecls { +  NamedDecl* Decls[2]; +}; + +// FIXME: We really want to use a DenseSet here to eliminate the +// redundant storage of the declaration names, but (1) it doesn't give +// us the ability to search based on DeclarationName, (2) we really +// need something more like a DenseMultiSet, and (3) it's +// implemented in terms of DenseMap anyway. +typedef llvm::DenseMap<DeclarationName, TwoNamedDecls> StoredDeclsMap; + +DeclContext::~DeclContext() { +  unsigned Size = LookupPtr.getInt(); +  if (Size == LookupIsMap) { +    StoredDeclsMap *Map = static_cast<StoredDeclsMap*>(LookupPtr.getPointer()); +    delete Map; +  } else { +    NamedDecl **Array = static_cast<NamedDecl**>(LookupPtr.getPointer()); +    delete [] Array; +  } +} + +void DeclContext::DestroyDecls(ASTContext &C) { +  for (decl_iterator D = Decls.begin(); D != Decls.end(); ++D) { +    if ((*D)->getLexicalDeclContext() == this) +      (*D)->Destroy(C); +  } +} + +DeclContext *DeclContext::getPrimaryContext(ASTContext &Context) { +  switch (DeclKind) { +  case Decl::Block: +  case Decl::TranslationUnit: +    // There is only one DeclContext for these entities. +    return this; + +  case Decl::Namespace: +    // The original namespace is our primary context. +    return static_cast<NamespaceDecl*>(this)->getOriginalNamespace(); + +  case Decl::Enum: +    // The declaration associated with the enumeration type is our +    // primary context. +    return Context.getTypeDeclType(static_cast<EnumDecl*>(this)) +             ->getAsEnumType()->getDecl(); + +  case Decl::Record: +  case Decl::CXXRecord: { +    // The declaration associated with the type is be our primary +    // context.  +#if 0 +    // FIXME: This is what we expect to do. However, it doesn't work +    // because ASTContext::setTagDefinition changes the result of +    // Context.getTypeDeclType, meaning that our "primary" declaration +    // of a RecordDecl/CXXRecordDecl will change, and we won't be able +    // to find any values inserted into the earlier "primary" +    // declaration. We need better tracking of redeclarations and +    // definitions. +    QualType Type = Context.getTypeDeclType(static_cast<RecordDecl*>(this)); +    return Type->getAsRecordType()->getDecl(); +#else +    // FIXME: This hack will work for now, because the declaration we +    // create when we're defining the record is the one we'll use as +    // the definition later. +    return this; +#endif +  } + +  case Decl::ObjCMethod: +    return this; + +  case Decl::ObjCInterface: +    // FIXME: Can Objective-C interfaces be forward-declared? +    return this; + +  default: +    assert(DeclKind >= Decl::FunctionFirst && DeclKind <= Decl::FunctionLast && +          "Unknown DeclContext kind"); +    return this; +  } +} + +DeclContext *DeclContext::getNextContext() { +  switch (DeclKind) { +  case Decl::Block: +  case Decl::TranslationUnit: +  case Decl::Enum: +  case Decl::Record: +  case Decl::CXXRecord: +  case Decl::ObjCMethod: +  case Decl::ObjCInterface: +    // There is only one DeclContext for these entities. +    return 0; + +  case Decl::Namespace: +    // Return the next namespace +    return static_cast<NamespaceDecl*>(this)->getNextNamespace(); + +  default: +    assert(DeclKind >= Decl::FunctionFirst && DeclKind <= Decl::FunctionLast && +          "Unknown DeclContext kind"); +    return 0; +  } +} + +void DeclContext::addDecl(ASTContext &Context, ScopedDecl *D, bool AllowLookup) { +  Decls.push_back(D); +  if (AllowLookup) +    D->getDeclContext()->insert(Context, D); +} + +DeclContext::lookup_result  +DeclContext::lookup(ASTContext &Context, DeclarationName Name) { +  DeclContext *PrimaryContext = getPrimaryContext(Context); +  if (PrimaryContext != this) +    return PrimaryContext->lookup(Context, Name); + +  /// If there is no lookup data structure, build one now by talking +  /// all of the linked DeclContexts (in declaration order!) and +  /// inserting their values. +  if (LookupPtr.getPointer() == 0) { +    for (DeclContext *DCtx = this; DCtx; DCtx = DCtx->getNextContext()) +      for (decl_iterator D = DCtx->decls_begin(); D != DCtx->decls_end(); ++D) +        insertImpl(*D); +  } + +  lookup_result Result(0, 0); +  if (isLookupMap()) { +    StoredDeclsMap *Map = static_cast<StoredDeclsMap*>(LookupPtr.getPointer()); +    StoredDeclsMap::iterator Pos = Map->find(Name); +    if (Pos != Map->end()) { +      Result.first = Pos->second.Decls[0]? &Pos->second.Decls[0]  +                                        : &Pos->second.Decls[1]; +      Result.second = Pos->second.Decls[1]? &Pos->second.Decls[2] +                                         : &Pos->second.Decls[1]; +    } +    return Result; +  }  + +  // We have a small array. Look into it. +  unsigned Size = LookupPtr.getInt(); +  NamedDecl **Array = static_cast<NamedDecl**>(LookupPtr.getPointer()); +  for (unsigned Idx = 0; Idx < Size; ++Idx) +    if (Array[Idx]->getDeclName() == Name) { +      Result.first = &Array[Idx]; +      Result.second = Result.first + 1; +      if (Idx + 1 < Size && Array[Idx + 1]->getDeclName() == Name) +        ++Result.second; +      break; +    } + +  return Result; +} + +DeclContext::lookup_const_result  +DeclContext::lookup(ASTContext &Context, DeclarationName Name) const { +  return const_cast<DeclContext*>(this)->lookup(Context, Name); +} + +void DeclContext::insert(ASTContext &Context, NamedDecl *D) { +  DeclContext *PrimaryContext = getPrimaryContext(Context); +  if (PrimaryContext != this) { +    PrimaryContext->insert(Context, D); +    return; +  } + +  // If we already have a lookup data structure, perform the insertion +  // into it. Otherwise, be lazy and don't build that structure until +  // someone asks for it. +  if (LookupPtr.getPointer()) +    insertImpl(D); +} + +void DeclContext::insertImpl(NamedDecl *D) { +  if (!isLookupMap()) { +    unsigned Size = LookupPtr.getInt(); + +    // The lookup data is stored as an array. Search through the array +    // to find the insertion location. +    NamedDecl **Array; +    if (Size == 0) { +      Array = new NamedDecl*[LookupIsMap - 1]; +      LookupPtr.setPointer(Array); +    } else { +      Array = static_cast<NamedDecl **>(LookupPtr.getPointer()); +    } + +    // We always keep declarations of the same name next to each other +    // in the array, so that it is easy to return multiple results +    // from lookup(). There will be zero, one, or two declarations of +    // the same name. +    unsigned Match; +    for (Match = 0; Match < Size; ++Match) { +      if (Array[Match]->getDeclName() == D->getDeclName()) +       break; +    } + +    if (Match < Size) { +      // We found another declaration with the same name. If it's also +      // in the same identifier namespace, update the declaration in +      // place. +      Decl::IdentifierNamespace NS = D->getIdentifierNamespace(); +      if (Array[Match]->getIdentifierNamespace() == NS) { +       Array[Match] = D; +       return; +      } +      if (Match + 1 < Size && Array[Match + 1]->getIdentifierNamespace() == NS) { +       Array[Match + 1] = D; +       return; +      } + +      // If there is an existing declaration in the namespace of +      // ordinary identifiers, then it must precede the tag +      // declaration for C++ name lookup to operate properly. Therefore, +      // if our match is an ordinary name and the new name is in the +      // tag namespace, we'll insert the new declaration after it.  +      if (Match < Size && (NS == Decl::IDNS_Tag) &&  +         (Array[Match]->getIdentifierNamespace() & Decl::IDNS_Ordinary)) +       ++Match; +    } +        +    if (Size < LookupIsMap - 1) { +      // The new declaration will fit in the array. Insert the new +      // declaration at the position Match in the array.  +      for (unsigned Idx = Size; Idx > Match; --Idx) +       Array[Idx] = Array[Idx-1]; +       +      Array[Match] = D; +      LookupPtr.setInt(Size + 1); +      return; +    } + +    // We've reached capacity in this array. Create a map and copy in +    // all of the declarations that were stored in the array. +    StoredDeclsMap *Map = new StoredDeclsMap(16); +    LookupPtr.setPointer(Map); +    LookupPtr.setInt(LookupIsMap); +    for (unsigned Idx = 0; Idx < LookupIsMap - 1; ++Idx)  +      insertImpl(Array[Idx]); +    delete [] Array; + +    // Fall through to perform insertion into the map. +  }  + +  // Insert this declaration into the map. +  StoredDeclsMap *Map = static_cast<StoredDeclsMap*>(LookupPtr.getPointer()); +  StoredDeclsMap::iterator Pos = Map->find(D->getDeclName()); +  unsigned IndexOfD = D->getIdentifierNamespace() & Decl::IDNS_Ordinary? 0 : 1; + +  if (Pos == Map->end()) { +    // Put this declaration into the appropriate slot. +    TwoNamedDecls Val; +    Val.Decls[0] = 0; +    Val.Decls[1] = 0; +    Val.Decls[IndexOfD] = D; +    Pos = Map->insert(std::make_pair(D->getDeclName(),Val)).first; +  } else { +    Pos->second.Decls[IndexOfD] = D; +  } +} diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index a26803caecb..3eaf301d7a8 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -36,16 +36,9 @@ NonTypeTemplateParmDecl::Create(ASTContext &C, DeclContext *DC,    return new (Mem) NonTypeTemplateParmDecl(DC, L, Id, T, TypeSpecStartLoc);  } -CXXFieldDecl *CXXFieldDecl::Create(ASTContext &C, CXXRecordDecl *RD, -                                   SourceLocation L, IdentifierInfo *Id, -                                   QualType T, bool Mut, Expr *BW) { -  void *Mem = C.getAllocator().Allocate<CXXFieldDecl>(); -  return new (Mem) CXXFieldDecl(RD, L, Id, T, Mut, BW); -} -  CXXRecordDecl::CXXRecordDecl(TagKind TK, DeclContext *DC,                               SourceLocation L, IdentifierInfo *Id)  -  : RecordDecl(CXXRecord, TK, DC, L, Id), DeclContext(CXXRecord), +  : RecordDecl(CXXRecord, TK, DC, L, Id),      UserDeclaredConstructor(false), UserDeclaredCopyConstructor(false),      Aggregate(true), Polymorphic(false), Bases(0), NumBases(0),      Constructors(DC, DeclarationName()), @@ -74,11 +67,6 @@ void CXXRecordDecl::Destroy(ASTContext &C) {    if (isDefinition())      Destructor->Destroy(C); -  for (OverloadedFunctionDecl::function_iterator func  -         = Conversions.function_begin(); -       func != Conversions.function_end(); ++func) -    (*func)->Destroy(C); -    RecordDecl::Destroy(C);  } @@ -176,7 +164,7 @@ CXXBaseOrMemberInitializer(QualType BaseType, Expr **Args, unsigned NumArgs)  }  CXXBaseOrMemberInitializer:: -CXXBaseOrMemberInitializer(CXXFieldDecl *Member, Expr **Args, unsigned NumArgs) +CXXBaseOrMemberInitializer(FieldDecl *Member, Expr **Args, unsigned NumArgs)    : Args(0), NumArgs(0) {    BaseOrMember = reinterpret_cast<uintptr_t>(Member);    assert((BaseOrMember & 0x01) == 0 && "Invalid member pointer");   diff --git a/clang/lib/AST/DeclObjC.cpp b/clang/lib/AST/DeclObjC.cpp index 84f0d98bf2e..b9226318e39 100644 --- a/clang/lib/AST/DeclObjC.cpp +++ b/clang/lib/AST/DeclObjC.cpp @@ -95,10 +95,10 @@ ObjCIvarDecl *ObjCIvarDecl::Create(ASTContext &C, SourceLocation L,  ObjCAtDefsFieldDecl -*ObjCAtDefsFieldDecl::Create(ASTContext &C, SourceLocation L, +*ObjCAtDefsFieldDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L,                               IdentifierInfo *Id, QualType T, Expr *BW) {    void *Mem = C.getAllocator().Allocate<ObjCAtDefsFieldDecl>(); -  return new (Mem) ObjCAtDefsFieldDecl(L, Id, T, BW); +  return new (Mem) ObjCAtDefsFieldDecl(DC, L, Id, T, BW);  }  void ObjCAtDefsFieldDecl::Destroy(ASTContext& C) { diff --git a/clang/lib/AST/DeclSerialization.cpp b/clang/lib/AST/DeclSerialization.cpp index 29714c0125c..c0ffb0c4234 100644 --- a/clang/lib/AST/DeclSerialization.cpp +++ b/clang/lib/AST/DeclSerialization.cpp @@ -120,11 +120,29 @@ void Decl::ReadInRec(Deserializer& D, ASTContext& C) {  //===----------------------------------------------------------------------===//  void DeclContext::EmitOutRec(Serializer& S) const { -  S.EmitPtr(DeclChain); +  S.EmitInt(Decls.size()); +  for (decl_iterator D = decls_begin(); D != decls_end(); ++D) { +    bool Owned = ((*D)->getLexicalDeclContext() == this && +                  DeclKind != Decl::TranslationUnit && +                  !isFunctionOrMethod()); +    S.EmitBool(Owned); +    if (Owned) +      S.EmitOwnedPtr(*D); +    else +      S.EmitPtr(*D); +  }  }  void DeclContext::ReadOutRec(Deserializer& D, ASTContext& C) { -  D.ReadPtr(DeclChain); +  unsigned NumDecls = D.ReadInt(); +  Decls.resize(NumDecls); +  for (unsigned Idx = 0; Idx < NumDecls; ++Idx) { +    bool Owned = D.ReadBool(); +    if (Owned) +      Decls[Idx] = cast_or_null<ScopedDecl>(D.ReadOwnedPtr<Decl>(C)); +    else +      D.ReadPtr<ScopedDecl>(Decls[Idx]); +  }  }  //===----------------------------------------------------------------------===// @@ -205,14 +223,12 @@ void NamedDecl::ReadInRec(Deserializer& D, ASTContext& C) {  void ScopedDecl::EmitInRec(Serializer& S) const {    NamedDecl::EmitInRec(S); -  S.EmitPtr(getNext());                     // From ScopedDecl.      S.EmitPtr(cast_or_null<Decl>(getDeclContext()));  // From ScopedDecl.    S.EmitPtr(cast_or_null<Decl>(getLexicalDeclContext()));  // From ScopedDecl.  }  void ScopedDecl::ReadInRec(Deserializer& D, ASTContext& C) {    NamedDecl::ReadInRec(D, C); -  D.ReadPtr(Next);                                  // From ScopedDecl.    assert(DeclCtx == 0); @@ -394,8 +410,8 @@ ParmVarDecl* ParmVarDecl::CreateImpl(Deserializer& D, ASTContext& C) {  void EnumDecl::EmitImpl(Serializer& S) const {    ScopedDecl::EmitInRec(S);    S.EmitBool(isDefinition()); -  S.Emit(IntegerType);   -  S.BatchEmitOwnedPtrs(getEnumConstantList(),getNextDeclarator()); +  S.Emit(IntegerType); +  S.EmitOwnedPtr(getNextDeclarator());  }  EnumDecl* EnumDecl::CreateImpl(Deserializer& D, ASTContext& C) { @@ -406,12 +422,7 @@ EnumDecl* EnumDecl::CreateImpl(Deserializer& D, ASTContext& C) {    decl->setDefinition(D.ReadBool());    decl->IntegerType = QualType::ReadVal(D); -  Decl* next_declarator; -  Decl* Elist; -   -  D.BatchReadOwnedPtrs(Elist, next_declarator, C); -   -  decl->setDeclChain(cast_or_null<EnumConstantDecl>(Elist)); +  Decl* next_declarator = D.ReadOwnedPtr<Decl>(C);    decl->setNextDeclarator(cast_or_null<ScopedDecl>(next_declarator));    return decl; @@ -451,14 +462,17 @@ EnumConstantDecl* EnumConstantDecl::CreateImpl(Deserializer& D, ASTContext& C) {  //===----------------------------------------------------------------------===//  void FieldDecl::EmitImpl(Serializer& S) const { +  S.EmitBool(Mutable);    S.Emit(getType()); -  NamedDecl::EmitInRec(S); +  ScopedDecl::EmitInRec(S);    S.EmitOwnedPtr(BitWidth);    }  FieldDecl* FieldDecl::CreateImpl(Deserializer& D, ASTContext& C) {    void *Mem = C.getAllocator().Allocate<FieldDecl>(); -  FieldDecl* decl = new (Mem) FieldDecl(SourceLocation(), NULL, QualType(), 0); +  FieldDecl* decl = new (Mem) FieldDecl(Field, 0, SourceLocation(), NULL,  +                                        QualType(), 0, false, 0); +  decl->Mutable = D.ReadBool();    decl->DeclType.ReadBackpatch(D);      decl->ReadInRec(D, C);    decl->BitWidth = D.ReadOwnedPtr<Expr>(C); @@ -579,13 +593,7 @@ void RecordDecl::EmitImpl(Serializer& S) const {    ScopedDecl::EmitInRec(S);    S.EmitBool(isDefinition());    S.EmitBool(hasFlexibleArrayMember()); -  S.EmitSInt(getNumMembers()); -  if (getNumMembers() > 0) { -    assert (Members); -    S.BatchEmitOwnedPtrs((unsigned) getNumMembers(), (Decl**) &Members[0]); -  } -  else -    ScopedDecl::EmitOutRec(S); +  ScopedDecl::EmitOutRec(S);  }  RecordDecl* RecordDecl::CreateImpl(Deserializer& D, ASTContext& C) { @@ -597,17 +605,8 @@ RecordDecl* RecordDecl::CreateImpl(Deserializer& D, ASTContext& C) {    decl->ScopedDecl::ReadInRec(D, C);    decl->setDefinition(D.ReadBool());    decl->setHasFlexibleArrayMember(D.ReadBool()); -  decl->NumMembers = D.ReadSInt(); -   -  if (decl->getNumMembers() > 0) { -    decl->Members = new FieldDecl*[(unsigned) decl->getNumMembers()]; -                               -    D.BatchReadOwnedPtrs((unsigned) decl->getNumMembers(), -                         (Decl**) &decl->Members[0], C); -  } -  else -    decl->ScopedDecl::ReadOutRec(D, C); -   +  decl->ScopedDecl::ReadOutRec(D, C); +        return decl;  } diff --git a/clang/lib/AST/DeclarationName.cpp b/clang/lib/AST/DeclarationName.cpp index 649b092db01..af983feed1e 100644 --- a/clang/lib/AST/DeclarationName.cpp +++ b/clang/lib/AST/DeclarationName.cpp @@ -311,3 +311,9 @@ DeclarationNameTable::getCXXOperatorName(OverloadedOperatorKind Op) {    return DeclarationName(&CXXOperatorNames[(unsigned)Op]);  } +unsigned  +llvm::DenseMapInfo<clang::DeclarationName>:: +getHashValue(clang::DeclarationName N) { +  return DenseMapInfo<void*>::getHashValue(N.getAsOpaquePtr()); +} + diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index 14db18c1345..b5f966d8621 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -353,7 +353,7 @@ static bool DeclCanBeLvalue(const NamedDecl *Decl, ASTContext &Ctx) {          = dyn_cast<NonTypeTemplateParmDecl>(Decl))      return NTTParm->getType()->isReferenceType(); -  return isa<VarDecl>(Decl) || isa<CXXFieldDecl>(Decl) || +  return isa<VarDecl>(Decl) || isa<FieldDecl>(Decl) ||      // C++ 3.10p2: An lvalue refers to an object or function.      (Ctx.getLangOptions().CPlusPlus &&       (isa<FunctionDecl>(Decl) || isa<OverloadedFunctionDecl>(Decl))); @@ -1222,10 +1222,15 @@ static int64_t evaluateOffsetOf(ASTContext& C, const Expr *E)      const ASTRecordLayout &RL = C.getASTRecordLayout(RD);      FieldDecl *FD = ME->getMemberDecl(); -    // FIXME: This is linear time. -    unsigned i = 0, e = 0; -    for (i = 0, e = RD->getNumMembers(); i != e; i++) { -      if (RD->getMember(i) == FD) +    // FIXME: This is linear time. And the fact that we're indexing +    // into the layout by position in the record means that we're +    // either stuck numbering the fields in the AST or we have to keep +    // the linear search (yuck and yuck). +    unsigned i = 0; +    for (RecordDecl::field_iterator Field = RD->field_begin(), +                                 FieldEnd = RD->field_end(); +         Field != FieldEnd; (void)++Field, ++i) { +      if (*Field == FD)          break;      } diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 341baeab85b..7a83d6c063d 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -156,9 +156,11 @@ APValue LValueExprEvaluator::VisitMemberExpr(MemberExpr *E) {    FieldDecl *FD = E->getMemberDecl();    // FIXME: This is linear time. -  unsigned i = 0, e = 0; -  for (i = 0, e = RD->getNumMembers(); i != e; i++) { -    if (RD->getMember(i) == FD) +  unsigned i = 0; +  for (RecordDecl::field_iterator Field = RD->field_begin(), +                               FieldEnd = RD->field_end(); +       Field != FieldEnd; (void)++Field, ++i) { +    if (*Field == FD)        break;    } diff --git a/clang/lib/Analysis/RegionStore.cpp b/clang/lib/Analysis/RegionStore.cpp index 563a1fe9b75..f8fc88612ed 100644 --- a/clang/lib/Analysis/RegionStore.cpp +++ b/clang/lib/Analysis/RegionStore.cpp @@ -433,8 +433,13 @@ SVal RegionStoreManager::RetrieveStruct(Store store, const TypedRegion* R) {    llvm::ImmutableList<SVal> StructVal = getBasicVals().getEmptySValList(); -  for (int i = RD->getNumMembers() - 1; i >= 0; --i) { -    FieldRegion* FR = MRMgr.getFieldRegion(RD->getMember(i), R); +  for (DeclContext::reverse_decl_iterator Mem = RD->decls_rbegin(); +       Mem != RD->decls_rend(); ++Mem) { +    FieldDecl *FD = dyn_cast<FieldDecl>(*Mem); +    if (!FD) +      continue; + +    FieldRegion* FR = MRMgr.getFieldRegion(FD, R);      RegionBindingsTy B(static_cast<const RegionBindingsTy::TreeTy*>(store));      RegionBindingsTy::data_type* data = B.lookup(FR); diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index d93bccd2ff2..67c60aae07c 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -289,10 +289,11 @@ llvm::DIType CGDebugInfo::CreateType(const EnumType *Ty,    llvm::SmallVector<llvm::DIDescriptor, 32> Enumerators;    // Create DIEnumerator elements for each enumerator. -  for (EnumConstantDecl *Elt = Decl->getEnumConstantList(); Elt; -       Elt = dyn_cast_or_null<EnumConstantDecl>(Elt->getNextDeclarator())) { -    Enumerators.push_back(DebugFactory.CreateEnumerator(Elt->getNameAsString(), -                                            Elt->getInitVal().getZExtValue())); +  for (EnumDecl::enumerator_iterator Enum = Decl->enumerator_begin(), +                                  EnumEnd = Decl->enumerator_end(); +       Enum != EnumEnd; ++Enum) { +    Enumerators.push_back(DebugFactory.CreateEnumerator(Enum->getNameAsString(), +                                            Enum->getInitVal().getZExtValue()));    }    // Return a CompositeType for the enum itself. diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp index 65f8a1a2e41..834d7483baf 100644 --- a/clang/lib/CodeGen/CGExprAgg.cpp +++ b/clang/lib/CodeGen/CGExprAgg.cpp @@ -434,20 +434,24 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) {    // the optimizer, especially with bitfields.    unsigned NumInitElements = E->getNumInits();    RecordDecl *SD = E->getType()->getAsRecordType()->getDecl(); -  unsigned NumMembers = SD->getNumMembers() - SD->hasFlexibleArrayMember();    unsigned CurInitVal = 0;    bool isUnion = E->getType()->isUnionType();    // Here we iterate over the fields; this makes it simpler to both    // default-initialize fields and skip over unnamed fields. -  for (unsigned CurFieldNo = 0; CurFieldNo != NumMembers; ++CurFieldNo) { -    FieldDecl *CurField = SD->getMember(CurFieldNo); -    if (CurField->getIdentifier() == 0) { +  for (RecordDecl::field_iterator Field = SD->field_begin(), +                               FieldEnd = SD->field_end(); +       Field != FieldEnd; ++Field) { +    // We're done once we hit the flexible array member +    if (Field->getType()->isIncompleteArrayType()) +      break; + +    if (Field->getIdentifier() == 0) {        // Initializers can't initialize unnamed fields, e.g. "int : 20;"        continue;      }      // FIXME: volatility -    LValue FieldLoc = CGF.EmitLValueForField(DestPtr, CurField, isUnion,0); +    LValue FieldLoc = CGF.EmitLValueForField(DestPtr, *Field, isUnion,0);      if (CurInitVal < NumInitElements) {        // Store the initializer into the field        // This will probably have to get a bit smarter when we support @@ -455,7 +459,7 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) {        EmitInitializationToLValue(E->getInit(CurInitVal++), FieldLoc);      } else {        // We're out of initalizers; default-initialize to null -      EmitNullInitializationToLValue(FieldLoc, CurField->getType()); +      EmitNullInitializationToLValue(FieldLoc, Field->getType());      }      // Unions only initialize one field. diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp index 7f294e29965..52d99dc60e6 100644 --- a/clang/lib/CodeGen/CGExprConstant.cpp +++ b/clang/lib/CodeGen/CGExprConstant.cpp @@ -187,16 +187,17 @@ public:      unsigned EltNo = 0;  // Element no in ILE      int FieldNo = 0; // Field no in RecordDecl      bool RewriteType = false; -    while (EltNo < ILE->getNumInits() && FieldNo < RD->getNumMembers()) { -      FieldDecl* curField = RD->getMember(FieldNo); +    for (RecordDecl::field_iterator Field = RD->field_begin(), +                                 FieldEnd = RD->field_end(); +         EltNo < ILE->getNumInits() && Field != FieldEnd; ++Field) {        FieldNo++; -      if (!curField->getIdentifier()) +      if (!Field->getIdentifier())          continue; -      if (curField->isBitField()) { -        InsertBitfieldIntoStruct(Elts, curField, ILE->getInit(EltNo)); +      if (Field->isBitField()) { +        InsertBitfieldIntoStruct(Elts, *Field, ILE->getInit(EltNo));        } else { -        unsigned FieldNo = CGM.getTypes().getLLVMFieldNo(curField); +        unsigned FieldNo = CGM.getTypes().getLLVMFieldNo(*Field);          llvm::Constant *C = CGM.EmitConstantExpr(ILE->getInit(EltNo), CGF);          RewriteType |= (C->getType() != Elts[FieldNo]->getType());          Elts[FieldNo] = C; @@ -223,8 +224,10 @@ public:      // Find the field decl we're initializing, if any      int FieldNo = 0; // Field no in RecordDecl      FieldDecl* curField = 0; -    while (FieldNo < RD->getNumMembers()) { -      curField = RD->getMember(FieldNo); +    for (RecordDecl::field_iterator Field = RD->field_begin(), +                                 FieldEnd = RD->field_end(); +         Field != FieldEnd; ++Field) { +      curField = *Field;        FieldNo++;        if (curField->getIdentifier())          break; diff --git a/clang/lib/CodeGen/CGObjCMac.cpp b/clang/lib/CodeGen/CGObjCMac.cpp index 013b0f9cc3e..201f53e34d0 100644 --- a/clang/lib/CodeGen/CGObjCMac.cpp +++ b/clang/lib/CodeGen/CGObjCMac.cpp @@ -2373,12 +2373,15 @@ ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm)    RecordDecl *RD = RecordDecl::Create(Ctx, TagDecl::TK_struct, 0,                                        SourceLocation(),                                        &Ctx.Idents.get("_objc_super"));   -  FieldDecl *FieldDecls[2]; -  FieldDecls[0] = FieldDecl::Create(Ctx, SourceLocation(), 0,  -                                    Ctx.getObjCIdType()); -  FieldDecls[1] = FieldDecl::Create(Ctx, SourceLocation(), 0, -                                    Ctx.getObjCClassType()); -  RD->defineBody(Ctx, FieldDecls, 2); +  RD->addDecl(Ctx,  +              FieldDecl::Create(Ctx, RD, SourceLocation(), 0,  +                                Ctx.getObjCIdType(), 0, false, 0),  +              true); +  RD->addDecl(Ctx,  +              FieldDecl::Create(Ctx, RD, SourceLocation(), 0, +                                Ctx.getObjCClassType(), 0, false, 0),  +              true); +  RD->completeDefinition(Ctx);    SuperCTy = Ctx.getTagDeclType(RD);    SuperPtrCTy = Ctx.getPointerType(SuperCTy); diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 82e732163bd..e83d2cd2930 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -775,21 +775,20 @@ llvm::Function *CodeGenModule::getMemSetFn() {  static void appendFieldAndPadding(CodeGenModule &CGM,                                    std::vector<llvm::Constant*>& Fields, -                                  int FieldNo, llvm::Constant* Field, +                                  FieldDecl *FieldD, FieldDecl *NextFieldD, +                                  llvm::Constant* Field,                                    RecordDecl* RD, const llvm::StructType *STy)  {    // Append the field.    Fields.push_back(Field); -  int StructFieldNo =  -    CGM.getTypes().getLLVMFieldNo(RD->getMember(FieldNo)); +  int StructFieldNo = CGM.getTypes().getLLVMFieldNo(FieldD);    int NextStructFieldNo; -  if (FieldNo + 1 == RD->getNumMembers()) { +  if (!NextFieldD) {      NextStructFieldNo = STy->getNumElements();    } else { -    NextStructFieldNo =  -      CGM.getTypes().getLLVMFieldNo(RD->getMember(FieldNo + 1)); +    NextStructFieldNo = CGM.getTypes().getLLVMFieldNo(NextFieldD);    }    // Append padding @@ -841,29 +840,38 @@ GetAddrOfConstantCFString(const std::string &str) {      cast<llvm::StructType>(getTypes().ConvertType(CFTy));    std::vector<llvm::Constant*> Fields; -   -   +  RecordDecl::field_iterator Field = CFRD->field_begin(); +    // Class pointer. -  appendFieldAndPadding(*this, Fields, 0, CFConstantStringClassRef, CFRD, STy); +  FieldDecl *CurField = *Field++; +  FieldDecl *NextField = *Field++; +  appendFieldAndPadding(*this, Fields, CurField, NextField, +                        CFConstantStringClassRef, CFRD, STy);    // Flags. +  CurField = NextField; +  NextField = *Field++;    const llvm::Type *Ty = getTypes().ConvertType(getContext().UnsignedIntTy); -  appendFieldAndPadding(*this, Fields, 1, llvm::ConstantInt::get(Ty, 0x07C8),  -                        CFRD, STy); +  appendFieldAndPadding(*this, Fields, CurField, NextField, +                        llvm::ConstantInt::get(Ty, 0x07C8), CFRD, STy);    // String pointer. +  CurField = NextField; +  NextField = *Field++;    llvm::Constant *C = llvm::ConstantArray::get(str);    C = new llvm::GlobalVariable(C->getType(), true,                                  llvm::GlobalValue::InternalLinkage,                                 C, ".str", &getModule()); -  appendFieldAndPadding(*this, Fields, 2,  +  appendFieldAndPadding(*this, Fields, CurField, NextField,                          llvm::ConstantExpr::getGetElementPtr(C, Zeros, 2),                          CFRD, STy);    // String length. +  CurField = NextField; +  NextField = 0;    Ty = getTypes().ConvertType(getContext().LongTy); -  appendFieldAndPadding(*this, Fields, 3, llvm::ConstantInt::get(Ty, str.length()), -                        CFRD, STy); +  appendFieldAndPadding(*this, Fields, CurField, NextField, +                        llvm::ConstantInt::get(Ty, str.length()), CFRD, STy);    // The struct.    C = llvm::ConstantStruct::get(STy, Fields); diff --git a/clang/lib/CodeGen/CodeGenTypes.cpp b/clang/lib/CodeGen/CodeGenTypes.cpp index 85b10399a41..8918671332d 100644 --- a/clang/lib/CodeGen/CodeGenTypes.cpp +++ b/clang/lib/CodeGen/CodeGenTypes.cpp @@ -392,7 +392,7 @@ const llvm::Type *CodeGenTypes::ConvertTagDeclType(const TagDecl *TD) {    } else if (TD->isUnion()) {      // Just use the largest element of the union, breaking ties with the      // highest aligned member. -    if (RD->getNumMembers() != 0) { +    if (RD->field_begin() != RD->field_end()) {        RecordOrganizer RO(*this, *RD);        RO.layoutUnionFields(Context.getASTRecordLayout(RD)); @@ -478,16 +478,17 @@ void RecordOrganizer::layoutStructFields(const ASTRecordLayout &RL) {    uint64_t llvmSize = 0;    // FIXME: Make this a SmallVector    std::vector<const llvm::Type*> LLVMFields; -  int NumMembers = RD.getNumMembers(); -  for (int curField = 0; curField < NumMembers; curField++) { -    const FieldDecl *FD = RD.getMember(curField); +  unsigned curField = 0; +  for (RecordDecl::field_iterator Field = RD.field_begin(), +                               FieldEnd = RD.field_end(); +       Field != FieldEnd; ++Field) {      uint64_t offset = RL.getFieldOffset(curField); -    const llvm::Type *Ty = CGT.ConvertTypeRecursive(FD->getType()); +    const llvm::Type *Ty = CGT.ConvertTypeRecursive(Field->getType());      uint64_t size = CGT.getTargetData().getABITypeSizeInBits(Ty); -    if (FD->isBitField()) { -      Expr *BitWidth = FD->getBitWidth(); +    if (Field->isBitField()) { +      Expr *BitWidth = Field->getBitWidth();        llvm::APSInt FieldSize(32);        bool isBitField =          BitWidth->isIntegerConstantExpr(FieldSize, CGT.getContext()); @@ -498,8 +499,8 @@ void RecordOrganizer::layoutStructFields(const ASTRecordLayout &RL) {        // Bitfield field info is different from other field info;        // it actually ignores the underlying LLVM struct because        // there isn't any convenient mapping. -      CGT.addFieldInfo(FD, offset / size); -      CGT.addBitFieldInfo(FD, offset % size, BitFieldSize); +      CGT.addFieldInfo(*Field, offset / size); +      CGT.addBitFieldInfo(*Field, offset % size, BitFieldSize);      } else {        // Put the element into the struct. This would be simpler        // if we didn't bother, but it seems a bit too strange to @@ -510,9 +511,10 @@ void RecordOrganizer::layoutStructFields(const ASTRecordLayout &RL) {        }        llvmSize += size; -      CGT.addFieldInfo(FD, LLVMFields.size()); +      CGT.addFieldInfo(*Field, LLVMFields.size());        LLVMFields.push_back(Ty);      } +    ++curField;    }    while (llvmSize < RL.getSize()) { @@ -528,21 +530,24 @@ void RecordOrganizer::layoutStructFields(const ASTRecordLayout &RL) {  /// corresponding llvm struct type.  This should be invoked only after  /// all fields are added.  void RecordOrganizer::layoutUnionFields(const ASTRecordLayout &RL) { -  for (int curField = 0; curField < RD.getNumMembers(); curField++) { -    const FieldDecl *FD = RD.getMember(curField); +  unsigned curField = 0; +  for (RecordDecl::field_iterator Field = RD.field_begin(), +                               FieldEnd = RD.field_end(); +       Field != FieldEnd; ++Field) {      // The offset should usually be zero, but bitfields could be strange      uint64_t offset = RL.getFieldOffset(curField); -    if (FD->isBitField()) { -      Expr *BitWidth = FD->getBitWidth(); +    if (Field->isBitField()) { +      Expr *BitWidth = Field->getBitWidth();        uint64_t BitFieldSize =            BitWidth->getIntegerConstantExprValue(CGT.getContext()).getZExtValue(); -      CGT.addFieldInfo(FD, 0); -      CGT.addBitFieldInfo(FD, offset, BitFieldSize); +      CGT.addFieldInfo(*Field, 0); +      CGT.addBitFieldInfo(*Field, offset, BitFieldSize);      } else { -      CGT.addFieldInfo(FD, 0); +      CGT.addFieldInfo(*Field, 0);      } +    ++curField;    }    // This looks stupid, but it is correct in the sense that diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 572ca613e01..5ae629a6c0e 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -914,7 +914,7 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc,        for (unsigned i = 0, e = FieldDeclarators.size(); i != e; ++i) {          FieldDeclarator &FD = FieldDeclarators[i];          // Install the declarator into the current TagDecl. -        DeclTy *Field = Actions.ActOnField(CurScope, +        DeclTy *Field = Actions.ActOnField(CurScope, TagDecl,                                             DS.getSourceRange().getBegin(),                                             FD.D, FD.BitfieldSize);          FieldDecls.push_back(Field); @@ -934,8 +934,8 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc,          continue;        }        llvm::SmallVector<DeclTy*, 16> Fields; -      Actions.ActOnDefs(CurScope, Tok.getLocation(), Tok.getIdentifierInfo(), -          Fields); +      Actions.ActOnDefs(CurScope, TagDecl, Tok.getLocation(),  +                        Tok.getIdentifierInfo(), Fields);        FieldDecls.insert(FieldDecls.end(), Fields.begin(), Fields.end());        ConsumeToken();        ExpectAndConsume(tok::r_paren, diag::err_expected_rparen); diff --git a/clang/lib/Sema/CXXFieldCollector.h b/clang/lib/Sema/CXXFieldCollector.h index 44d482692b7..69d13515fa6 100644 --- a/clang/lib/Sema/CXXFieldCollector.h +++ b/clang/lib/Sema/CXXFieldCollector.h @@ -18,15 +18,15 @@  #include "llvm/ADT/SmallVector.h"  namespace clang { -  class CXXFieldDecl; +  class FieldDecl;  /// CXXFieldCollector - Used to keep track of CXXFieldDecls during parsing of  /// C++ classes.  class CXXFieldCollector { -  /// Fields - Contains all CXXFieldDecls collected during parsing of a C++ +  /// Fields - Contains all FieldDecls collected during parsing of a C++    /// class. When a nested class is entered, its fields are appended to the    /// fields of its parent class, when it is exited its fields are removed. -  llvm::SmallVector<CXXFieldDecl*, 32> Fields; +  llvm::SmallVector<FieldDecl*, 32> Fields;    /// FieldCount - Each entry represents the number of fields collected during    /// the parsing of a C++ class. When a nested class is entered, a new field @@ -52,7 +52,7 @@ public:    void StartClass() { FieldCount.push_back(0); }    /// Add - Called by Sema::ActOnCXXMemberDeclarator. -  void Add(CXXFieldDecl *D) { +  void Add(FieldDecl *D) {      Fields.push_back(D);      ++FieldCount.back();    } @@ -62,7 +62,7 @@ public:    /// getCurFields - Pointer to array of fields added to the currently parsed    /// class. -  CXXFieldDecl **getCurFields() { return &*(Fields.end() - getCurNumFields()); } +  FieldDecl **getCurFields() { return &*(Fields.end() - getCurNumFields()); }    /// FinishClass - Called by Sema::ActOnFinishCXXClassDef.    void FinishClass() { diff --git a/clang/lib/Sema/IdentifierResolver.cpp b/clang/lib/Sema/IdentifierResolver.cpp index 5fb18f6cef4..4441503528a 100644 --- a/clang/lib/Sema/IdentifierResolver.cpp +++ b/clang/lib/Sema/IdentifierResolver.cpp @@ -51,9 +51,6 @@ public:  DeclContext *IdentifierResolver::LookupContext::getContext(Decl *D) {    DeclContext *Ctx; -  if (CXXFieldDecl *FD = dyn_cast<CXXFieldDecl>(D)) -    return FD->getParent(); -    if (EnumConstantDecl *EnumD = dyn_cast<EnumConstantDecl>(D)) {      Ctx = EnumD->getDeclContext()->getParent();    } else if (ScopedDecl *SD = dyn_cast<ScopedDecl>(D)) @@ -149,7 +146,7 @@ IdentifierResolver::~IdentifierResolver() {  /// if 'D' is in Scope 'S', otherwise 'S' is ignored and isDeclInScope returns  /// true if 'D' belongs to the given declaration context.  bool IdentifierResolver::isDeclInScope(Decl *D, DeclContext *Ctx, -                                       Scope *S) const { +                                       ASTContext &Context, Scope *S) const {    if (Ctx->isFunctionOrMethod()) {      if (S->isDeclScope(D))        return true; @@ -169,7 +166,7 @@ bool IdentifierResolver::isDeclInScope(Decl *D, DeclContext *Ctx,      return false;    } -  return LookupContext(D) == LookupContext(Ctx); +  return LookupContext(D) == LookupContext(Ctx->getPrimaryContext(Context));  }  /// AddDecl - Link the decl to its shadowed decl chain. diff --git a/clang/lib/Sema/IdentifierResolver.h b/clang/lib/Sema/IdentifierResolver.h index 9d785133957..bc9da6126d0 100644 --- a/clang/lib/Sema/IdentifierResolver.h +++ b/clang/lib/Sema/IdentifierResolver.h @@ -208,7 +208,8 @@ public:    /// isDeclInScope - If 'Ctx' is a function/method, isDeclInScope returns true    /// if 'D' is in Scope 'S', otherwise 'S' is ignored and isDeclInScope returns    /// true if 'D' belongs to the given declaration context. -  bool isDeclInScope(Decl *D, DeclContext *Ctx, Scope *S = 0) const; +  bool isDeclInScope(Decl *D, DeclContext *Ctx, ASTContext &Context, +                     Scope *S = 0) const;    /// AddDecl - Link the decl to its shadowed decl chain.    void AddDecl(NamedDecl *D); diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index 13226c0b0ea..650b8d7d7dd 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -68,7 +68,7 @@ static inline RecordDecl *CreateStructDecl(ASTContext &C, const char *Name) {  void Sema::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) {    TUScope = S; -  PushDeclContext(Context.getTranslationUnitDecl()); +  PushDeclContext(S, Context.getTranslationUnitDecl());    if (!PP.getLangOptions().ObjC1) return;    // Synthesize "typedef struct objc_selector *SEL;" diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index 4a8f83084dd..97e8507e9b3 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -300,10 +300,10 @@ public:                           IdentifierInfo *Name, SourceLocation NameLoc,                           AttributeList *Attr);   -  virtual void ActOnDefs(Scope *S, SourceLocation DeclStart, +  virtual void ActOnDefs(Scope *S, DeclTy *TagD, SourceLocation DeclStart,                           IdentifierInfo *ClassName,                           llvm::SmallVectorImpl<DeclTy*> &Decls); -  virtual DeclTy *ActOnField(Scope *S, SourceLocation DeclStart, +  virtual DeclTy *ActOnField(Scope *S, DeclTy *TagD, SourceLocation DeclStart,                               Declarator &D, ExprTy *BitfieldWidth);    virtual DeclTy *ActOnIvar(Scope *S, SourceLocation DeclStart, @@ -326,7 +326,7 @@ public:    DeclContext *getContainingDC(DeclContext *DC);    /// Set the current declaration context until it gets popped. -  void PushDeclContext(DeclContext *DC); +  void PushDeclContext(Scope *S, DeclContext *DC);    void PopDeclContext();    /// getCurFunctionDecl - If inside of a function body, this returns a pointer @@ -351,7 +351,7 @@ public:    /// if 'D' is in Scope 'S', otherwise 'S' is ignored and isDeclInScope returns    /// true if 'D' belongs to the given declaration context.    bool isDeclInScope(Decl *D, DeclContext *Ctx, Scope *S = 0) { -    return IdResolver.isDeclInScope(D, Ctx, S); +    return IdResolver.isDeclInScope(D, Ctx, Context, S);    }    /// Subroutines of ActOnDeclarator(). @@ -478,7 +478,8 @@ public:    /// More parsing and symbol table subroutines...    Decl *LookupDecl(DeclarationName Name, unsigned NSI, Scope *S,                     const DeclContext *LookupCtx = 0, -                   bool enableLazyBuiltinCreation = true); +                   bool enableLazyBuiltinCreation = true, +                  bool LookInParent = true);    ObjCInterfaceDecl *getObjCInterfaceDecl(IdentifierInfo *Id);    ScopedDecl *LazilyCreateBuiltin(IdentifierInfo *II, unsigned ID,                                     Scope *S); diff --git a/clang/lib/Sema/SemaCXXScopeSpec.cpp b/clang/lib/Sema/SemaCXXScopeSpec.cpp index 1f92b6f6aab..d01552c373b 100644 --- a/clang/lib/Sema/SemaCXXScopeSpec.cpp +++ b/clang/lib/Sema/SemaCXXScopeSpec.cpp @@ -20,7 +20,25 @@ using namespace clang;  namespace {
    Decl *LookupNestedName(DeclContext *LookupCtx, bool LookInParentCtx,
 -                         DeclarationName Name, bool &IdIsUndeclared) {
 +                         DeclarationName Name, bool &IdIsUndeclared,
 +                        ASTContext &Context) {
 +    if (LookupCtx && !LookInParentCtx) {
 +      IdIsUndeclared = true;
 +      for (DeclContext::lookup_const_result I = LookupCtx->lookup(Context, Name);
 +          I.first != I.second; ++I.first) {
 +       IdIsUndeclared = false;
 +       if (((*I.first)->getIdentifierNamespace() & Decl::IDNS_Tag) &&
 +           !isa<EnumDecl>(*I.first))
 +         return *I.first;
 +      }
 +
 +      return 0;
 +    }
 +
 +    // FIXME: Decouple this from the IdentifierResolver so that we can
 +    // deal with lookups into the semantic parent contexts that aren't
 +    // lexical parent contexts.
 +
      IdentifierResolver::iterator
        I = IdentifierResolver::begin(Name, LookupCtx, LookInParentCtx),
        E = IdentifierResolver::end();
 @@ -73,10 +91,11 @@ Sema::CXXScopeTy *Sema::ActOnCXXNestedNameSpecifier(Scope *S,    bool IdIsUndeclared;
    if (DC)
 -    SD = LookupNestedName(DC, false/*LookInParentCtx*/, &II, IdIsUndeclared);
 +    SD = LookupNestedName(DC, false/*LookInParentCtx*/, &II, IdIsUndeclared,
 +                         Context);
    else
      SD = LookupNestedName(CurContext, true/*LookInParent*/, &II, 
 -                          IdIsUndeclared);
 +                          IdIsUndeclared, Context);
    if (SD) {
      if (TypedefDecl *TD = dyn_cast<TypedefDecl>(SD)) {
 diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 41587c5aee6..b541f59a223 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -74,14 +74,16 @@ DeclContext *Sema::getContainingDC(DeclContext *DC) {    return DC->getLexicalParent();  } -void Sema::PushDeclContext(DeclContext *DC) { +void Sema::PushDeclContext(Scope *S, DeclContext *DC) {    assert(getContainingDC(DC) == CurContext &&        "The next DeclContext should be lexically contained in the current one.");    CurContext = DC; +  S->setEntity(DC);  }  void Sema::PopDeclContext() {    assert(CurContext && "DeclContext imbalance!"); +    CurContext = getContainingDC(CurContext);  } @@ -97,53 +99,90 @@ void Sema::PushOnScopeChains(NamedDecl *D, Scope *S) {    //   in this case the class name or enumeration name is hidden.    if (TagDecl *TD = dyn_cast<TagDecl>(D)) {      // We are pushing the name of a tag (enum or class). -    IdentifierResolver::iterator -        I = IdResolver.begin(TD->getIdentifier(), -                             TD->getDeclContext(), false/*LookInParentCtx*/); -    if (I != IdResolver.end() && isDeclInScope(*I, TD->getDeclContext(), S)) { -      // There is already a declaration with the same name in the same -      // scope. It must be found before we find the new declaration, -      // so swap the order on the shadowed declaration chain. - -      IdResolver.AddShadowedDecl(TD, *I); -      return; +    if (CurContext == TD->getDeclContext()) { +      // We're pushing the tag into the current context, which might +      // require some reshuffling in the identifier resolver. +      IdentifierResolver::iterator +        I = IdResolver.begin(TD->getIdentifier(), CurContext,  +                            false/*LookInParentCtx*/); +      if (I != IdResolver.end()) { +       // There is already a declaration with the same name in the same +       // scope. It must be found before we find the new declaration, +       // so swap the order on the shadowed declaration chain. +       IdResolver.AddShadowedDecl(TD, *I); + +       // Add this declaration to the current context. +       CurContext->addDecl(Context, TD); +        +       return; +      }      }    } else if (getLangOptions().CPlusPlus && isa<FunctionDecl>(D)) { -    FunctionDecl *FD = cast<FunctionDecl>(D);      // We are pushing the name of a function, which might be an      // overloaded name. -    IdentifierResolver::iterator -        I = IdResolver.begin(FD->getDeclName(), -                             FD->getDeclContext(), false/*LookInParentCtx*/); -    if (I != IdResolver.end() && -        IdResolver.isDeclInScope(*I, FD->getDeclContext(), S) && -        (isa<OverloadedFunctionDecl>(*I) || isa<FunctionDecl>(*I))) { -      // There is already a declaration with the same name in the same -      // scope. It must be a function or an overloaded function. -      OverloadedFunctionDecl* Ovl = dyn_cast<OverloadedFunctionDecl>(*I); +    FunctionDecl *FD = cast<FunctionDecl>(D); +    Decl *Prev = LookupDecl(FD->getDeclName(), Decl::IDNS_Ordinary, S, +                           FD->getDeclContext(), false, false); +    if (Prev && (isa<OverloadedFunctionDecl>(Prev) || isa<FunctionDecl>(Prev))) { +      // There is already a declaration with the same name in +      // the same scope. It must be a function or an overloaded +      // function. +      OverloadedFunctionDecl* Ovl = dyn_cast<OverloadedFunctionDecl>(Prev);        if (!Ovl) {          // We haven't yet overloaded this function. Take the existing          // FunctionDecl and put it into an OverloadedFunctionDecl.          Ovl = OverloadedFunctionDecl::Create(Context,                                                FD->getDeclContext(),                                               FD->getDeclName()); -        Ovl->addOverload(dyn_cast<FunctionDecl>(*I)); +        Ovl->addOverload(dyn_cast<FunctionDecl>(Prev)); -        // Remove the name binding to the existing FunctionDecl... -        IdResolver.RemoveDecl(*I); - -        // ... and put the OverloadedFunctionDecl in its place. +       // If there is an name binding for the existing FunctionDecl, +       // remove it. +       for (IdentifierResolver::iterator I  +              = IdResolver.begin(FD->getDeclName(), FD->getDeclContext(),  +                                 false/*LookInParentCtx*/); +            I != IdResolver.end(); ++I) { +         if (*I == Prev) { +           IdResolver.RemoveDecl(*I); +           S->RemoveDecl(*I); +           break; +         } +       } +        +       // Add the name binding for the OverloadedFunctionDecl.          IdResolver.AddDecl(Ovl); + +        // Update the context with the newly-created overloaded +        // function set. +        FD->getDeclContext()->insert(Context, Ovl); + +       S->AddDecl(Ovl);        } +      // We added this function declaration to the scope earlier, but +      // we don't want it there because it is part of the overloaded +      // function declaration. +      S->RemoveDecl(FD); +        // We have an OverloadedFunctionDecl. Add the new FunctionDecl        // to its list of overloads.        Ovl->addOverload(FD); -      return; +      // Add this new function declaration to the declaration context. +      CurContext->addDecl(Context, FD, false); + +      return;            }    } +  if (ScopedDecl *SD = dyn_cast<ScopedDecl>(D)) +    CurContext->addDecl(Context, SD); +  else { +    // Other kinds of declarations don't currently have a context +    // where they need to be inserted. +  } + +    IdResolver.AddDecl(D);  } @@ -157,25 +196,13 @@ void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) {      Decl *TmpD = static_cast<Decl*>(*I);      assert(TmpD && "This decl didn't get pushed??"); -    if (isa<CXXFieldDecl>(TmpD)) continue; +    assert(isa<NamedDecl>(TmpD) && "Decl isn't NamedDecl?"); +    NamedDecl *D = cast<NamedDecl>(TmpD); -    assert(isa<ScopedDecl>(TmpD) && "Decl isn't ScopedDecl?"); -    ScopedDecl *D = cast<ScopedDecl>(TmpD); -     -    IdentifierInfo *II = D->getIdentifier(); -    if (!II) continue; -     -    // We only want to remove the decls from the identifier decl chains for -    // local scopes, when inside a function/method. -    // However, we *always* remove template parameters, since they are -    // purely lexically scoped (and can never be found by qualified -    // name lookup). -    if (S->getFnParent() != 0 || isa<TemplateTypeParmDecl>(D)) -      IdResolver.RemoveDecl(D); - -    // Chain this decl to the containing DeclContext. -    D->setNext(CurContext->getDeclChain()); -    CurContext->setDeclChain(D); +    if (!D->getDeclName()) continue; + +    // Remove this name from our lexical scope. +    IdResolver.RemoveDecl(D);    }  } @@ -193,21 +220,76 @@ ObjCInterfaceDecl *Sema::getObjCInterfaceDecl(IdentifierInfo *Id) {  /// namespace.  Decl *Sema::LookupDecl(DeclarationName Name, unsigned NSI, Scope *S,                         const DeclContext *LookupCtx, -                       bool enableLazyBuiltinCreation) { +                       bool enableLazyBuiltinCreation, +                      bool LookInParent) {    if (!Name) return 0;    unsigned NS = NSI;    if (getLangOptions().CPlusPlus && (NS & Decl::IDNS_Ordinary))      NS |= Decl::IDNS_Tag; -  IdentifierResolver::iterator  -    I = LookupCtx ? IdResolver.begin(Name, LookupCtx, false/*LookInParentCtx*/) -                  : IdResolver.begin(Name, CurContext, true/*LookInParentCtx*/); -  // Scan up the scope chain looking for a decl that matches this identifier -  // that is in the appropriate namespace.  This search should not take long, as -  // shadowing of names is uncommon, and deep shadowing is extremely uncommon. -  for (; I != IdResolver.end(); ++I) -    if ((*I)->getIdentifierNamespace() & NS) -      return *I; +  if (LookupCtx) { +    assert(getLangOptions().CPlusPlus && "No qualified name lookup in C"); + +    // Perform qualified name lookup into the LookupCtx. +    // FIXME: Will need to look into base classes and such. +    for (DeclContext::lookup_const_result I = LookupCtx->lookup(Context, Name); +        I.first != I.second; ++I.first) +      if ((*I.first)->getIdentifierNamespace() & NS) +       return *I.first; +  } else if (getLangOptions().CPlusPlus &&  +               (NS & (Decl::IDNS_Ordinary | Decl::IDNS_Tag))) { +    // Name lookup for ordinary names and tag names in C++ requires +    // looking into scopes that aren't strictly lexical, and +    // therefore we walk through the context as well as walking +    // through the scopes. +    IdentifierResolver::iterator  +      I = IdResolver.begin(Name, CurContext, true/*LookInParentCtx*/), +      IEnd = IdResolver.end(); +    for (; S; S = S->getParent()) { +      // Check whether the IdResolver has anything in this scope. +      // FIXME: The isDeclScope check could be expensive. Can we do better? +      for (; I != IEnd && S->isDeclScope(*I); ++I) +        if ((*I)->getIdentifierNamespace() & NS) +          return *I; +       +      // If there is an entity associated with this scope, it's a +      // DeclContext. We might need to perform qualified lookup into +      // it. +      DeclContext *Ctx = static_cast<DeclContext *>(S->getEntity()); +      while (Ctx && Ctx->isFunctionOrMethod()) +        Ctx = Ctx->getParent(); +      while (Ctx && (Ctx->isNamespace() || Ctx->isCXXRecord())) { +        // Look for declarations of this name in this scope. +        for (DeclContext::lookup_const_result I = Ctx->lookup(Context, Name); +             I.first != I.second; ++I.first) { +          // FIXME: Cache this result in the IdResolver +          if ((*I.first)->getIdentifierNamespace() & NS) +            return  *I.first; +        } +         +        Ctx = Ctx->getParent(); +      } +       +      if (!LookInParent) +        return 0; +    } +  } else { +    // Unqualified name lookup for names in our lexical scope. This +    // name lookup suffices when all of the potential names are known +    // to have been pushed onto the IdResolver, as happens in C +    // (always) and in C++ for names in the "label" namespace. +    assert(!LookupCtx && "Can't perform qualified name lookup here"); +    IdentifierResolver::iterator I +      = IdResolver.begin(Name, CurContext, LookInParent); +     +    // Scan up the scope chain looking for a decl that matches this +    // identifier that is in the appropriate namespace.  This search +    // should not take long, as shadowing of names is uncommon, and +    // deep shadowing is extremely uncommon. +    for (; I != IdResolver.end(); ++I) +      if ((*I)->getIdentifierNamespace() & NS) +         return *I; +  }    // If we didn't find a use of this identifier, and if the identifier    // corresponds to a compiler builtin, create the decl object for the builtin @@ -826,7 +908,8 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl) {    // The scope passed in may not be a decl scope.  Zip up the scope tree until    // we find one that is. -  while ((S->getFlags() & Scope::DeclScope) == 0) +  while ((S->getFlags() & Scope::DeclScope) == 0 || +        (S->getFlags() & Scope::TemplateParamScope) != 0)      S = S->getParent();    DeclContext *DC; @@ -854,6 +937,7 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl) {        // No previous declaration in the qualifying scope.        Diag(D.getIdentifierLoc(), diag::err_typecheck_no_member)          << Name << D.getCXXScopeSpec().getRange(); +      InvalidDecl = true;      } else if (!CurContext->Encloses(DC)) {        // The qualifying scope doesn't enclose the original declaration.        // Emit diagnostic based on current scope. @@ -865,6 +949,7 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl) {          Diag(L, diag::err_invalid_declarator_scope)            << Name << cast<NamedDecl>(DC)->getDeclName() << R;        } +      InvalidDecl = true;      }    } @@ -1127,23 +1212,42 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl) {            if (OldDecl == PrevDecl) {              // Remove the name binding for the previous -            // declaration. We'll add the binding back later, but then -            // it will refer to the new declaration (which will -            // contain more information). -            IdResolver.RemoveDecl(cast<NamedDecl>(PrevDecl)); +            // declaration. +           if (S->isDeclScope(PrevDecl)) { +             IdResolver.RemoveDecl(cast<NamedDecl>(PrevDecl)); +             S->RemoveDecl(PrevDecl); +           } + +           // Introduce the new binding for this declaration. +           IdResolver.AddDecl(NewFD); +           if (getLangOptions().CPlusPlus && NewFD->getParent()) +             NewFD->getParent()->insert(Context, NewFD); + +           // Add the redeclaration to the current scope, since we'll +           // be skipping PushOnScopeChains. +           S->AddDecl(NewFD);            } else {              // We need to update the OverloadedFunctionDecl with the              // latest declaration of this function, so that name              // lookup will always refer to the latest declaration of              // this function.              *MatchedDecl = NewFD; +         } -            // Add the redeclaration to the current scope, since we'll -            // be skipping PushOnScopeChains. -            S->AddDecl(NewFD); +          if (getLangOptions().CPlusPlus) { +            // Add this declaration to the current context. +            CurContext->addDecl(Context, NewFD, false); -            return NewFD; +            // Check default arguments now that we have merged decls. +            CheckCXXDefaultArguments(NewFD);            } + +         // Set the lexical context. If the declarator has a C++ +         // scope specifier, the lexical context will be different +         // from the semantic context. +         NewFD->setLexicalDeclContext(CurContext); + +         return NewFD;          }        }      } @@ -2071,7 +2175,7 @@ Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {      parmDeclType = Context.getArrayDecayedType(parmDeclType);    } else if (parmDeclType->isFunctionType())      parmDeclType = Context.getPointerType(parmDeclType); -   +    ParmVarDecl *New = ParmVarDecl::Create(Context, CurContext,                                            D.getIdentifierLoc(), II,                                           parmDeclType, StorageClass,  @@ -2079,9 +2183,11 @@ Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {    if (D.getInvalidType())      New->setInvalidDecl(); -     + +  // Add the parameter declaration into this scope. +  S->AddDecl(New);    if (II) -    PushOnScopeChains(New, S); +    IdResolver.AddDecl(New);    ProcessDeclAttributes(New, D);    return New; @@ -2133,7 +2239,7 @@ Sema::DeclTy *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, DeclTy *D) {      Diag(Definition->getLocation(), diag::note_previous_definition);    } -  PushDeclContext(FD); +  PushDeclContext(FnBodyScope, FD);    // Check the validity of our function parameters    CheckParmsForFunctionDef(FD); @@ -2573,17 +2679,19 @@ Sema::DeclTy *Sema::ActOnTagStruct(Scope *S, TagDecl::TagKind Kind, TagKind TK,  /// Collect the instance variables declared in an Objective-C object.  Used in  /// the creation of structures from objects using the @defs directive. -static void CollectIvars(ObjCInterfaceDecl *Class, ASTContext& Ctx, +static void CollectIvars(ObjCInterfaceDecl *Class, RecordDecl *Record, +                         ASTContext& Ctx,                           llvm::SmallVectorImpl<Sema::DeclTy*> &ivars) {    if (Class->getSuperClass()) -    CollectIvars(Class->getSuperClass(), Ctx, ivars); +    CollectIvars(Class->getSuperClass(), Record, Ctx, ivars);    // For each ivar, create a fresh ObjCAtDefsFieldDecl.    for (ObjCInterfaceDecl::ivar_iterator          I=Class->ivar_begin(), E=Class->ivar_end(); I!=E; ++I) {      ObjCIvarDecl* ID = *I; -    ivars.push_back(ObjCAtDefsFieldDecl::Create(Ctx, ID->getLocation(), +    ivars.push_back(ObjCAtDefsFieldDecl::Create(Ctx, Record, +                                                ID->getLocation(),                                                  ID->getIdentifier(),                                                  ID->getType(),                                                  ID->getBitWidth())); @@ -2592,7 +2700,7 @@ static void CollectIvars(ObjCInterfaceDecl *Class, ASTContext& Ctx,  /// Called whenever @defs(ClassName) is encountered in the source.  Inserts the  /// instance variables of ClassName into Decls. -void Sema::ActOnDefs(Scope *S, SourceLocation DeclStart,  +void Sema::ActOnDefs(Scope *S, DeclTy *TagD, SourceLocation DeclStart,                        IdentifierInfo *ClassName,                       llvm::SmallVectorImpl<DeclTy*> &Decls) {    // Check that ClassName is a valid class @@ -2602,7 +2710,17 @@ void Sema::ActOnDefs(Scope *S, SourceLocation DeclStart,      return;    }    // Collect the instance variables -  CollectIvars(Class, Context, Decls); +  CollectIvars(Class, dyn_cast<RecordDecl>((Decl*)TagD), Context, Decls); + +  // Introduce all of these fields into the appropriate scope. +  for (llvm::SmallVectorImpl<DeclTy*>::iterator D = Decls.begin(); +       D != Decls.end(); ++D) { +    FieldDecl *FD = cast<FieldDecl>((Decl*)*D); +    if (getLangOptions().CPlusPlus) +      PushOnScopeChains(cast<FieldDecl>(FD), S); +    else if (RecordDecl *Record = dyn_cast<RecordDecl>((Decl*)TagD)) +      Record->addDecl(Context, FD); +  }  }  /// TryToFixInvalidVariablyModifiedType - Helper method to turn variable array @@ -2657,12 +2775,13 @@ bool Sema::VerifyBitField(SourceLocation FieldLoc, IdentifierInfo *FieldName,  /// ActOnField - Each field of a struct/union/class is passed into this in order  /// to create a FieldDecl object for it. -Sema::DeclTy *Sema::ActOnField(Scope *S, +Sema::DeclTy *Sema::ActOnField(Scope *S, DeclTy *TagD,                                 SourceLocation DeclStart,                                  Declarator &D, ExprTy *BitfieldWidth) {    IdentifierInfo *II = D.getIdentifier();    Expr *BitWidth = (Expr*)BitfieldWidth;    SourceLocation Loc = DeclStart; +  RecordDecl *Record = (RecordDecl *)TagD;    if (II) Loc = D.getIdentifierLoc();    // FIXME: Unnamed fields can be handled in various different ways, for @@ -2699,22 +2818,24 @@ Sema::DeclTy *Sema::ActOnField(Scope *S,    // FIXME: Chain fielddecls together.    FieldDecl *NewFD; -  if (getLangOptions().CPlusPlus) { -    // FIXME: Replace CXXFieldDecls with FieldDecls for simple structs. -    NewFD = CXXFieldDecl::Create(Context, cast<CXXRecordDecl>(CurContext), -                                 Loc, II, T, -                                 D.getDeclSpec().getStorageClassSpec() == -                                   DeclSpec::SCS_mutable, BitWidth); -    if (II) -      PushOnScopeChains(NewFD, S); -  } -  else -    NewFD = FieldDecl::Create(Context, Loc, II, T, BitWidth); -   +  // FIXME: We don't want CurContext for C, do we? No, we'll need some +  // other way to determine the current RecordDecl. +  NewFD = FieldDecl::Create(Context, Record, +                            Loc, II, T, BitWidth, +                            D.getDeclSpec().getStorageClassSpec() == +                              DeclSpec::SCS_mutable, +                            /*PrevDecl=*/0); +    ProcessDeclAttributes(NewFD, D);    if (D.getInvalidType() || InvalidDecl)      NewFD->setInvalidDecl(); + +  if (II && getLangOptions().CPlusPlus) +    PushOnScopeChains(NewFD, S); +  else +    Record->addDecl(Context, NewFD); +    return NewFD;  } @@ -2921,7 +3042,7 @@ void Sema::ActOnFields(Scope* S,    // Okay, we successfully defined 'Record'.    if (Record) { -    Record->defineBody(Context, &RecFields[0], RecFields.size()); +    Record->completeDefinition(Context);      // If this is a C++ record, HandleTagDeclDefinition will be invoked in      // Sema::ActOnFinishCXXClassDef.      if (!isa<CXXRecordDecl>(Record)) @@ -3189,7 +3310,7 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, DeclTy *EnumDeclX,      ECD->setType(NewTy);    } -  Enum->defineElements(EltList, BestType); +  Enum->completeDefinition(Context, BestType);    Consumer.HandleTagDeclDefinition(Enum);  } diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index bff650db5fe..5c2b49472b1 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -904,8 +904,10 @@ static void HandleTransparentUnionAttr(Decl *d, const AttributeList &Attr,    // FIXME: This isn't supposed to be restricted to pointers, but otherwise    // we might silently generate incorrect code; see following code -  for (int i = 0; i < RD->getNumMembers(); i++) { -    if (!RD->getMember(i)->getType()->isPointerType()) { +  for (RecordDecl::field_iterator Field = RD->field_begin(), +                               FieldEnd = RD->field_end(); +       Field != FieldEnd; ++Field) { +    if (!Field->getType()->isPointerType()) {        S.Diag(Attr.getLoc(), diag::warn_transparent_union_nonpointer);        return;      } diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index bedf3f7d6b6..31ecfbabd29 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -382,7 +382,7 @@ void Sema::ActOnBaseSpecifiers(DeclTy *ClassDecl, BaseTy **Bases,  /// definition, when on C++.  void Sema::ActOnStartCXXClassDef(Scope *S, DeclTy *D, SourceLocation LBrace) {    CXXRecordDecl *Dcl = cast<CXXRecordDecl>(static_cast<Decl *>(D)); -  PushDeclContext(Dcl); +  PushDeclContext(S, Dcl);    FieldCollector->StartClass();    if (Dcl->getIdentifier()) { @@ -486,7 +486,8 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,    bool InvalidDecl = false;    if (isInstField) -    Member = static_cast<Decl*>(ActOnField(S, Loc, D, BitWidth)); +    Member = static_cast<Decl*>(ActOnField(S, cast<CXXRecordDecl>(CurContext),  +                                           Loc, D, BitWidth));    else      Member = static_cast<Decl*>(ActOnDeclarator(S, D, LastInGroup)); @@ -593,7 +594,7 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,      Member->setInvalidDecl();    if (isInstField) { -    FieldCollector->Add(cast<CXXFieldDecl>(Member)); +    FieldCollector->Add(cast<FieldDecl>(Member));      return LastInGroup;    }    return Member; @@ -632,7 +633,10 @@ Sema::ActOnMemInitializer(DeclTy *ConstructorD,    //   mem-initializer-id for the hidden base class may be specified    //   using a qualified name. ]    // Look for a member, first. -  CXXFieldDecl *Member = ClassDecl->getMember(MemberOrBase); +  FieldDecl *Member = 0; +  DeclContext::lookup_result Result = ClassDecl->lookup(Context, MemberOrBase); +  if (Result.first != Result.second) +    Member = dyn_cast<FieldDecl>(*Result.first);    // FIXME: Handle members of an anonymous union. @@ -1251,43 +1255,42 @@ Sema::DeclTy *Sema::ActOnStartNamespaceDef(Scope *NamespcScope,      // in that declarative region, it is treated as an original-namespace-name.      Decl *PrevDecl = -        LookupDecl(II, Decl::IDNS_Tag | Decl::IDNS_Ordinary, DeclRegionScope, 0, -                   /*enableLazyBuiltinCreation=*/false); - -    if (PrevDecl && isDeclInScope(PrevDecl, CurContext, DeclRegionScope)) { -      if (NamespaceDecl *OrigNS = dyn_cast<NamespaceDecl>(PrevDecl)) { -        // This is an extended namespace definition. -        // Attach this namespace decl to the chain of extended namespace -        // definitions. -        NamespaceDecl *NextNS = OrigNS; -        while (NextNS->getNextNamespace()) -          NextNS = NextNS->getNextNamespace(); - -        NextNS->setNextNamespace(Namespc); -        Namespc->setOriginalNamespace(OrigNS); - -        // We won't add this decl to the current scope. We want the namespace -        // name to return the original namespace decl during a name lookup. -      } else { -        // This is an invalid name redefinition. -        Diag(Namespc->getLocation(), diag::err_redefinition_different_kind) -          << Namespc->getDeclName(); -        Diag(PrevDecl->getLocation(), diag::note_previous_definition); -        Namespc->setInvalidDecl(); -        // Continue on to push Namespc as current DeclContext and return it. +      LookupDecl(II, Decl::IDNS_Tag | Decl::IDNS_Ordinary, DeclRegionScope, 0, +                /*enableLazyBuiltinCreation=*/false,  +                /*LookupInParent=*/false); +     +    if (NamespaceDecl *OrigNS = dyn_cast_or_null<NamespaceDecl>(PrevDecl)) { +      // This is an extended namespace definition. +      // Attach this namespace decl to the chain of extended namespace +      // definitions. +      OrigNS->setNextNamespace(Namespc); +      Namespc->setOriginalNamespace(OrigNS->getOriginalNamespace()); + +      // Remove the previous declaration from the scope.       +      if (DeclRegionScope->isDeclScope(OrigNS)) { +       IdResolver.RemoveDecl(OrigNS); +       DeclRegionScope->RemoveDecl(OrigNS);        } -    } else { -      // This namespace name is declared for the first time. -      PushOnScopeChains(Namespc, DeclRegionScope); -    } -  } -  else { +    } else if (PrevDecl) { +      // This is an invalid name redefinition. +      Diag(Namespc->getLocation(), diag::err_redefinition_different_kind) +       << Namespc->getDeclName(); +      Diag(PrevDecl->getLocation(), diag::note_previous_definition); +      Namespc->setInvalidDecl(); +      // Continue on to push Namespc as current DeclContext and return it. +    }  + +    PushOnScopeChains(Namespc, DeclRegionScope); +  } else {      // FIXME: Handle anonymous namespaces    }    // Although we could have an invalid decl (i.e. the namespace name is a    // redefinition), push it as current DeclContext and try to continue parsing. -  PushDeclContext(Namespc->getOriginalNamespace()); +  // FIXME: We should be able to push Namespc here, so that the +  // each DeclContext for the namespace has the declarations +  // that showed up in that particular namespace definition. +  PushDeclContext(NamespcScope, Namespc);    return Namespc;  } diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp index fa73bcf2591..d1357247709 100644 --- a/clang/lib/Sema/SemaDeclObjC.cpp +++ b/clang/lib/Sema/SemaDeclObjC.cpp @@ -36,7 +36,7 @@ void Sema::ObjCActOnStartOfMethodDef(Scope *FnBodyScope, DeclTy *D) {      AddFactoryMethodToGlobalPool(MDecl);    // Allow all of Sema to see that we are entering a method definition. -  PushDeclContext(MDecl); +  PushDeclContext(FnBodyScope, MDecl);    // Create Decl objects for each parameter, entrring them in the scope for    // binding to their use. diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index b2542542417..ba5d28a6334 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -453,13 +453,13 @@ Sema::ExprResult Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc,      }    } -  if (CXXFieldDecl *FD = dyn_cast<CXXFieldDecl>(D)) { +  if (FieldDecl *FD = dyn_cast<FieldDecl>(D)) {      if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(CurContext)) {        if (MD->isStatic())          // "invalid use of member 'x' in static member function"          return Diag(Loc, diag::err_invalid_member_use_in_static_method)             << FD->getDeclName(); -      if (cast<CXXRecordDecl>(MD->getParent()) != FD->getParent()) +      if (MD->getParent() != FD->getDeclContext())          // "invalid use of nonstatic data member 'x'"          return Diag(Loc, diag::err_invalid_non_static_member_use)            << FD->getDeclName(); @@ -1231,20 +1231,28 @@ ActOnMemberReferenceExpr(ExprTy *Base, SourceLocation OpLoc,        return Diag(OpLoc, diag::err_typecheck_incomplete_tag)                 << RDecl->getDeclName() << BaseExpr->getSourceRange();      // The record definition is complete, now make sure the member is valid. -    FieldDecl *MemberDecl = RDecl->getMember(&Member); -    if (!MemberDecl) +    // FIXME: Qualified name lookup for C++ is a bit more complicated +    // than this. +    DeclContext::lookup_result Lookup = RDecl->lookup(Context, &Member); +    if (Lookup.first == Lookup.second) {        return Diag(MemberLoc, diag::err_typecheck_no_member)                 << &Member << BaseExpr->getSourceRange(); +    }  + +    FieldDecl *MemberDecl = dyn_cast<FieldDecl>(*Lookup.first); +    if (!MemberDecl) { +      unsigned DiagID = PP.getDiagnostics().getCustomDiagID(Diagnostic::Error, +                          "Clang only supports references to members"); +      return Diag(MemberLoc, DiagID); +    }      // Figure out the type of the member; see C99 6.5.2.3p3      // FIXME: Handle address space modifiers      QualType MemberType = MemberDecl->getType();      unsigned combinedQualifiers =          MemberType.getCVRQualifiers() | BaseType.getCVRQualifiers(); -    if (CXXFieldDecl *CXXMember = dyn_cast<CXXFieldDecl>(MemberDecl)) { -      if (CXXMember->isMutable()) -        combinedQualifiers &= ~QualType::Const; -    } +    if (MemberDecl->isMutable()) +      combinedQualifiers &= ~QualType::Const;      MemberType = MemberType.getQualifiedType(combinedQualifiers);      return new MemberExpr(BaseExpr, OpKind == tok::arrow, MemberDecl, @@ -3484,7 +3492,11 @@ Sema::ExprResult Sema::ActOnBuiltinOffsetOf(SourceLocation BuiltinLoc,      // Get the decl corresponding to this.      RecordDecl *RD = RC->getDecl(); -    FieldDecl *MemberDecl = RD->getMember(OC.U.IdentInfo); +    FieldDecl *MemberDecl = 0; +    DeclContext::lookup_result Lookup = RD->lookup(Context, OC.U.IdentInfo); +    if (Lookup.first != Lookup.second) +      MemberDecl = dyn_cast<FieldDecl>(*Lookup.first); +      if (!MemberDecl)        return Diag(BuiltinLoc, diag::err_typecheck_no_member)         << OC.U.IdentInfo << SourceRange(OC.LocStart, OC.LocEnd); @@ -3552,7 +3564,7 @@ void Sema::ActOnBlockStart(SourceLocation CaretLoc, Scope *BlockScope) {    BSI->TheScope = BlockScope;    BSI->TheDecl = BlockDecl::Create(Context, CurContext, CaretLoc); -  PushDeclContext(BSI->TheDecl); +  PushDeclContext(BlockScope, BSI->TheDecl);  }  void Sema::ActOnBlockArguments(Declarator &ParamInfo) { diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 27b0ba34d19..a32a6f68fad 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -412,9 +412,8 @@ bool Sema::FindAllocationOverload(SourceLocation StartLoc, DeclarationName Name,                                    DeclContext *Ctx, bool AllowMissing,                                    FunctionDecl *&Operator)  { -  IdentifierResolver::iterator I = -    IdResolver.begin(Name, Ctx, /*LookInParentCtx=*/false); -  if (I == IdResolver.end()) { +  DeclContext::lookup_result Lookup = Ctx->lookup(Context, Name); +  if (Lookup.first == Lookup.second) {      if (AllowMissing)        return false;      // FIXME: Bad location information. @@ -423,7 +422,7 @@ bool Sema::FindAllocationOverload(SourceLocation StartLoc, DeclarationName Name,    }    OverloadCandidateSet Candidates; -  NamedDecl *Decl = *I; +  NamedDecl *Decl = *Lookup.first;    // Even member operator new/delete are implicitly treated as static, so don't    // use AddMemberCandidate.    if (FunctionDecl *Fn = dyn_cast_or_null<FunctionDecl>(Decl)) diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 42f9b14085e..f36d3a504fc 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -15,6 +15,8 @@  #include "clang/AST/ASTContext.h"  #include "clang/AST/Expr.h"  #include "clang/Basic/Diagnostic.h" +#include <algorithm> // for std::count_if +#include <functional> // for std::mem_fun  namespace clang { @@ -39,10 +41,9 @@ int InitListChecker::numArrayElements(QualType DeclType) {  int InitListChecker::numStructUnionElements(QualType DeclType) {    RecordDecl *structDecl = DeclType->getAsRecordType()->getDecl(); -  int InitializableMembers = 0; -  for (int i = 0; i < structDecl->getNumMembers(); i++) -    if (structDecl->getMember(i)->getIdentifier()) -      ++InitializableMembers; +  int InitializableMembers  +    = std::count_if(structDecl->field_begin(), structDecl->field_end(), +                    std::mem_fun(&FieldDecl::getDeclName));    if (structDecl->isUnion())      return std::min(InitializableMembers, 1);    return InitializableMembers - structDecl->hasFlexibleArrayMember(); @@ -286,21 +287,28 @@ void InitListChecker::CheckStructUnionTypes(InitListExpr *IList,    // If structDecl is a forward declaration, this loop won't do anything;    // That's okay, because an error should get printed out elsewhere. It    // might be worthwhile to skip over the rest of the initializer, though. -  int numMembers = DeclType->getAsRecordType()->getDecl()->getNumMembers() - -                   structDecl->hasFlexibleArrayMember(); -  for (int i = 0; i < numMembers; i++) { +  RecordDecl *RD = DeclType->getAsRecordType()->getDecl(); +  for (RecordDecl::field_iterator Field = RD->field_begin(), +                               FieldEnd = RD->field_end(); +       Field != FieldEnd; ++Field) { +    // If we've hit the flexible array member at the end, we're done. +    if (Field->getType()->isIncompleteArrayType()) +      break; +      // Don't attempt to go past the end of the init list      if (Index >= IList->getNumInits())        break; -    FieldDecl * curField = structDecl->getMember(i); -    if (!curField->getIdentifier()) { + +    if (!Field->getIdentifier()) {        // Don't initialize unnamed fields, e.g. "int : 20;"        continue;      } -    CheckSubElementType(IList, curField->getType(), Index); + +    CheckSubElementType(IList, Field->getType(), Index);      if (DeclType->isUnionType())        break;    } +    // FIXME: Implement flexible array initialization GCC extension (it's a     // really messy extension to implement, unfortunately...the necessary    // information isn't actually even here!) diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 8a68d5be5c3..307abe3ac95 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -1955,10 +1955,9 @@ void Sema::AddOperatorCandidates(OverloadedOperatorKind Op, Scope *S,    //        (13.3.1.1.1); otherwise, the set of member candidates is    //        empty.    if (const RecordType *T1Rec = T1->getAsRecordType()) { -    IdentifierResolver::iterator I  -      = IdResolver.begin(OpName, cast<CXXRecordType>(T1Rec)->getDecl(),  -                         /*LookInParentCtx=*/false); -    NamedDecl *MemberOps = (I == IdResolver.end())? 0 : *I; +    DeclContext::lookup_const_result Lookup  +      = cast<CXXRecordType>(T1Rec)->getDecl()->lookup(Context, OpName); +    NamedDecl *MemberOps = (Lookup.first == Lookup.second)? 0 : *Lookup.first;      if (CXXMethodDecl *Method = dyn_cast_or_null<CXXMethodDecl>(MemberOps))        AddMethodCandidate(Method, Args[0], Args+1, NumArgs - 1, CandidateSet,                           /*SuppressUserConversions=*/false); @@ -3118,11 +3117,10 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,    //  ordinary lookup of the name operator() in the context of    //  (E).operator().    OverloadCandidateSet CandidateSet; -  IdentifierResolver::iterator I  -    = IdResolver.begin(Context.DeclarationNames.getCXXOperatorName(OO_Call),  -                       cast<CXXRecordType>(Record)->getDecl(),  -                       /*LookInParentCtx=*/false); -  NamedDecl *MemberOps = (I == IdResolver.end())? 0 : *I; +  DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(OO_Call); +  DeclContext::lookup_const_result Lookup  +    = cast<CXXRecordType>(Record)->getDecl()->lookup(Context, OpName); +  NamedDecl *MemberOps = (Lookup.first == Lookup.second)? 0 : *Lookup.first;    if (CXXMethodDecl *Method = dyn_cast_or_null<CXXMethodDecl>(MemberOps))      AddMethodCandidate(Method, Object, Args, NumArgs, CandidateSet,                         /*SuppressUserConversions=*/false); @@ -3315,10 +3313,9 @@ Sema::BuildOverloadedArrowExpr(Expr *Base, SourceLocation OpLoc,    DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(OO_Arrow);    OverloadCandidateSet CandidateSet;    const RecordType *BaseRecord = Base->getType()->getAsRecordType(); -  IdentifierResolver::iterator I -    = IdResolver.begin(OpName, cast<CXXRecordType>(BaseRecord)->getDecl(), -                       /*LookInParentCtx=*/false); -  NamedDecl *MemberOps = (I == IdResolver.end())? 0 : *I; +  DeclContext::lookup_const_result Lookup  +    = cast<CXXRecordType>(BaseRecord)->getDecl()->lookup(Context, OpName); +  NamedDecl *MemberOps = (Lookup.first == Lookup.second)? 0 : *Lookup.first;    if (CXXMethodDecl *Method = dyn_cast_or_null<CXXMethodDecl>(MemberOps))      AddMethodCandidate(Method, Base, 0, 0, CandidateSet,                         /*SuppressUserConversions=*/false);  | 

