diff options
author | Douglas Gregor <dgregor@apple.com> | 2008-12-11 16:49:14 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2008-12-11 16:49:14 +0000 |
commit | 91f84216f78f52f9aae422a2a034c1c7eaa098ce (patch) | |
tree | fc0c4c5b68ca37cab2115e3d2564ed36cb016b69 /clang/lib | |
parent | 32bfb5de3408728c5da5101db863098a8f854848 (diff) | |
download | bcm5719-llvm-91f84216f78f52f9aae422a2a034c1c7eaa098ce.tar.gz bcm5719-llvm-91f84216f78f52f9aae422a2a034c1c7eaa098ce.zip |
Unifies the name-lookup mechanisms used in various parts of the AST
and separates lexical name lookup from qualified name lookup. In
particular:
* Make DeclContext the central data structure for storing and
looking up declarations within existing declarations, e.g., members
of structs/unions/classes, enumerators in C++0x enums, members of
C++ namespaces, and (later) members of Objective-C
interfaces/implementations. DeclContext uses a lazily-constructed
data structure optimized for fast lookup (array for small contexts,
hash table for larger contexts).
* Implement C++ qualified name lookup in terms of lookup into
DeclContext.
* Implement C++ unqualified name lookup in terms of
qualified+unqualified name lookup (since unqualified lookup is not
purely lexical in C++!)
* Limit the use of the chains of declarations stored in
IdentifierInfo to those names declared lexically.
* Eliminate CXXFieldDecl, collapsing its behavior into
FieldDecl. (FieldDecl is now a ScopedDecl).
* Make RecordDecl into a DeclContext and eliminates its
Members/NumMembers fields (since one can just iterate through the
DeclContext to get the fields).
llvm-svn: 60878
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); |