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).
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@60878 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 0441063..3455504 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -539,7 +539,7 @@
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 @@
// 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 @@
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 @@
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);
+ 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::getObjCFastEnumerationStateType()
{
if (!ObjCFastEnumerationStateTypeDecl) {
+ ObjCFastEnumerationStateTypeDecl =
+ RecordDecl::Create(*this, TagDecl::TK_struct, TUDecl, SourceLocation(),
+ &Idents.get("__objcFastEnumerationState"));
+
QualType FieldTypes[] = {
UnsignedLongTy,
getPointerType(ObjCIdType),
@@ -1484,16 +1496,16 @@
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]);
+ 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 =
- RecordDecl::Create(*this, TagDecl::TK_struct, TUDecl, SourceLocation(),
- &Idents.get("__objcFastEnumerationState"));
-
- ObjCFastEnumerationStateTypeDecl->defineBody(*this, FieldDecls, 4);
+ ObjCFastEnumerationStateTypeDecl->completeDefinition(*this);
}
return getTagDeclType(ObjCFastEnumerationStateTypeDecl);
@@ -1745,16 +1757,17 @@
}
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 @@
S += 'b';
S += llvm::utostr(N);
} else {
- getObjCEncodingForTypeImpl(FD->getType(), S, false, true, NameFields);
+ getObjCEncodingForTypeImpl(Field->getType(), S, false, true,
+ NameFields);
}
}
}
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 194f47f..7643e4e 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -81,10 +81,11 @@
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 @@
}
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 @@
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() {
- 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/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp
index 7b5df1c..3e0f158 100644
--- a/lib/AST/DeclBase.cpp
+++ b/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 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 @@
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 @@
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 @@
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 @@
case ImplicitParam:
case TranslationUnit: break;
- case CXXField: nCXXFieldDecls++; break;
case CXXRecord: nCXXSUC++; break;
// FIXME: Statistics for C++ decls.
case TemplateTypeParm:
@@ -372,3 +368,269 @@
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/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index a26803c..3eaf301 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -36,16 +36,9 @@
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 @@
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::
-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/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp
index 84f0d98..b922631 100644
--- a/lib/AST/DeclObjC.cpp
+++ b/lib/AST/DeclObjC.cpp
@@ -95,10 +95,10 @@
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/lib/AST/DeclSerialization.cpp b/lib/AST/DeclSerialization.cpp
index 29714c0..c0ffb0c 100644
--- a/lib/AST/DeclSerialization.cpp
+++ b/lib/AST/DeclSerialization.cpp
@@ -120,11 +120,29 @@
//===----------------------------------------------------------------------===//
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 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 @@
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 @@
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 @@
//===----------------------------------------------------------------------===//
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 @@
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 @@
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/lib/AST/DeclarationName.cpp b/lib/AST/DeclarationName.cpp
index 649b092..af983fe 100644
--- a/lib/AST/DeclarationName.cpp
+++ b/lib/AST/DeclarationName.cpp
@@ -311,3 +311,9 @@
return DeclarationName(&CXXOperatorNames[(unsigned)Op]);
}
+unsigned
+llvm::DenseMapInfo<clang::DeclarationName>::
+getHashValue(clang::DeclarationName N) {
+ return DenseMapInfo<void*>::getHashValue(N.getAsOpaquePtr());
+}
+
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index 14db18c..b5f966d 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -353,7 +353,7 @@
= 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 @@
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/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp
index 341baea..7a83d6c 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/lib/AST/ExprConstant.cpp
@@ -156,9 +156,11 @@
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;
}