aboutsummaryrefslogtreecommitdiff
path: root/lib/AST
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2009-01-05 19:45:36 +0000
committerDouglas Gregor <dgregor@apple.com>2009-01-05 19:45:36 +0000
commit074149e11baf5f7db12f84efd5c34ba6e35d5cdf (patch)
treea02b3f87f914315d7ac21bc25fddf46250229d59 /lib/AST
parente1dccaefe2d44a9f83f8c3f087438a3297254cac (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.cpp59
-rw-r--r--lib/AST/DeclCXX.cpp38
-rw-r--r--lib/AST/DeclSerialization.cpp17
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);
- }
}
//===----------------------------------------------------------------------===//