diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-01-05 19:45:36 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-01-05 19:45:36 +0000 |
commit | 074149e11baf5f7db12f84efd5c34ba6e35d5cdf (patch) | |
tree | a02b3f87f914315d7ac21bc25fddf46250229d59 /lib/AST | |
parent | e1dccaefe2d44a9f83f8c3f087438a3297254cac (diff) |
Introduce support for "transparent" DeclContexts, which are
DeclContexts whose members are visible from enclosing DeclContexts up
to (and including) the innermost enclosing non-transparent
DeclContexts. Transparent DeclContexts unify the mechanism to be used
for various language features, including C enumerations, anonymous
unions, C++0x inline namespaces, and C++ linkage
specifications. Please refer to the documentation in the Clang
internals manual for more information.
Only enumerations and linkage specifications currently use transparent
DeclContexts.
Still to do: use transparent DeclContexts to implement anonymous
unions and GCC's anonymous structs extension, and, later, the C++0x
features. We also need to tighten up the DeclContext/ScopedDecl link
to ensure that every ScopedDecl is in a single DeclContext, which
will ensure that we can then enforce ownership and reduce the memory
footprint of DeclContext.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@61735 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/AST')
-rw-r--r-- | lib/AST/DeclBase.cpp | 59 | ||||
-rw-r--r-- | lib/AST/DeclCXX.cpp | 38 | ||||
-rw-r--r-- | lib/AST/DeclSerialization.cpp | 17 |
3 files changed, 55 insertions, 59 deletions
diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp index c6b3c53cc4..59d8a07bfd 100644 --- a/lib/AST/DeclBase.cpp +++ b/lib/AST/DeclBase.cpp @@ -406,10 +406,24 @@ void DeclContext::DestroyDecls(ASTContext &C) { } } +bool DeclContext::isTransparentContext() const { + if (DeclKind == Decl::Enum) + return true; // FIXME: Check for C++0x scoped enums + else if (DeclKind == Decl::LinkageSpec) + return true; + else if (DeclKind == Decl::Record || DeclKind == Decl::CXXRecord) + return false; // FIXME: need to know about anonymous unions/structs + else if (DeclKind == Decl::Namespace) + return false; // FIXME: Check for C++0x inline namespaces + + return false; +} + DeclContext *DeclContext::getPrimaryContext(ASTContext &Context) { switch (DeclKind) { - case Decl::Block: case Decl::TranslationUnit: + case Decl::LinkageSpec: + case Decl::Block: // There is only one DeclContext for these entities. return this; @@ -418,10 +432,15 @@ DeclContext *DeclContext::getPrimaryContext(ASTContext &Context) { return static_cast<NamespaceDecl*>(this)->getOriginalNamespace(); case Decl::Enum: +#if 0 + // FIXME: See the comment for CXXRecord, below. // The declaration associated with the enumeration type is our // primary context. return Context.getTypeDeclType(static_cast<EnumDecl*>(this)) ->getAsEnumType()->getDecl(); +#else + return this; +#endif case Decl::Record: case Decl::CXXRecord: { @@ -461,13 +480,14 @@ DeclContext *DeclContext::getPrimaryContext(ASTContext &Context) { 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: + case Decl::LinkageSpec: + case Decl::Block: // There is only one DeclContext for these entities. return 0; @@ -488,6 +508,24 @@ void DeclContext::addDecl(ASTContext &Context, ScopedDecl *D, bool AllowLookup) D->getDeclContext()->insert(Context, D); } +/// buildLookup - Build the lookup data structure with all of the +/// declarations in DCtx (and any other contexts linked to it or +/// transparent contexts nested within it). +void DeclContext::buildLookup(ASTContext &Context, DeclContext *DCtx) { + for (; DCtx; DCtx = DCtx->getNextContext()) { + for (decl_iterator D = DCtx->decls_begin(); D != DCtx->decls_end(); ++D) { + // Insert this declaration into the lookup structure + insertImpl(*D); + + // If this declaration is itself a transparent declaration context, + // add its members (recursively). + if (DeclContext *InnerCtx = dyn_cast<DeclContext>(*D)) + if (InnerCtx->isTransparentContext()) + buildLookup(Context, InnerCtx->getPrimaryContext(Context)); + } + } +} + DeclContext::lookup_result DeclContext::lookup(ASTContext &Context, DeclarationName Name) { DeclContext *PrimaryContext = getPrimaryContext(Context); @@ -497,11 +535,8 @@ DeclContext::lookup(ASTContext &Context, DeclarationName Name) { /// If there is no lookup data structure, build one now by walking /// 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); - } + if (LookupPtr.getPointer() == 0) + buildLookup(Context, this); if (isLookupMap()) { StoredDeclsMap *Map = static_cast<StoredDeclsMap*>(LookupPtr.getPointer()); @@ -543,9 +578,19 @@ void DeclContext::insert(ASTContext &Context, ScopedDecl *D) { // someone asks for it. if (LookupPtr.getPointer()) insertImpl(D); + + + // If we are a transparent context, insert into our parent context, + // too. This operation is recursive. + if (isTransparentContext()) + getParent()->insert(Context, D); } void DeclContext::insertImpl(ScopedDecl *D) { + // Skip unnamed declarations. + if (!D->getDeclName()) + return; + bool MayBeRedeclaration = true; if (!isLookupMap()) { diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp index 27065a75ba..66afac8524 100644 --- a/lib/AST/DeclCXX.cpp +++ b/lib/AST/DeclCXX.cpp @@ -291,42 +291,10 @@ OverloadedFunctionDecl::Create(ASTContext &C, DeclContext *DC, return new (Mem) OverloadedFunctionDecl(DC, N); } -LinkageSpecDecl::LinkageSpecDecl(SourceLocation L, LanguageIDs lang, - Decl **InDecls, unsigned InNumDecls) - : Decl(LinkageSpec, L), Language(lang), HadBraces(true), - Decls(0), NumDecls(InNumDecls) { - Decl **NewDecls = new Decl*[NumDecls]; - for (unsigned I = 0; I < NumDecls; ++I) - NewDecls[I] = InDecls[I]; - Decls = NewDecls; -} - -LinkageSpecDecl::~LinkageSpecDecl() { - if (HadBraces) - delete [] (Decl**)Decls; -} - LinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C, + DeclContext *DC, SourceLocation L, - LanguageIDs Lang, Decl *D) { + LanguageIDs Lang, bool Braces) { void *Mem = C.getAllocator().Allocate<LinkageSpecDecl>(); - return new (Mem) LinkageSpecDecl(L, Lang, D); -} - -LinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C, - SourceLocation L, - LanguageIDs Lang, - Decl **Decls, unsigned NumDecls) { - void *Mem = C.getAllocator().Allocate<LinkageSpecDecl>(); - return new (Mem) LinkageSpecDecl(L, Lang, Decls, NumDecls); -} - -LinkageSpecDecl::decl_const_iterator LinkageSpecDecl::decls_begin() const { - if (hasBraces()) return (Decl**)Decls; - else return (Decl**)&Decls; -} - -LinkageSpecDecl::decl_iterator LinkageSpecDecl::decls_end() const { - if (hasBraces()) return (Decl**)Decls + NumDecls; - else return (Decl**)&Decls + 1; + return new (Mem) LinkageSpecDecl(DC, L, Lang, Braces); } diff --git a/lib/AST/DeclSerialization.cpp b/lib/AST/DeclSerialization.cpp index 68412f968a..0a298139bd 100644 --- a/lib/AST/DeclSerialization.cpp +++ b/lib/AST/DeclSerialization.cpp @@ -686,29 +686,12 @@ void LinkageSpecDecl::EmitInRec(Serializer& S) const { Decl::EmitInRec(S); S.EmitInt(getLanguage()); S.EmitBool(HadBraces); - if (HadBraces) { - S.EmitInt(NumDecls); - for (decl_const_iterator D = decls_begin(), DEnd = decls_end(); - D != DEnd; ++D) - S.EmitPtr(*D); - } else { - S.EmitPtr((Decl*)Decls); - } } void LinkageSpecDecl::ReadInRec(Deserializer& D, ASTContext& C) { Decl::ReadInRec(D, C); Language = static_cast<LanguageIDs>(D.ReadInt()); HadBraces = D.ReadBool(); - if (HadBraces) { - NumDecls = D.ReadInt(); - Decl **NewDecls = new Decl*[NumDecls]; - Decls = NewDecls; - for (unsigned I = 0; I < NumDecls; ++I) - D.ReadPtr(NewDecls[I]); - } else { - D.ReadPtr(this->Decls); - } } //===----------------------------------------------------------------------===// |