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 | 07665a69e88334ced1648b5e4bcc2dbe2b90e366 (patch) | |
tree | afcb47baaf692b09480bbe21c541f2c86df4cd98 /clang/lib/Sema | |
parent | 07ebf302e5086323ddaf824427606d67ffe3b112 (diff) | |
download | bcm5719-llvm-07665a69e88334ced1648b5e4bcc2dbe2b90e366.tar.gz bcm5719-llvm-07665a69e88334ced1648b5e4bcc2dbe2b90e366.zip |
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.
llvm-svn: 61735
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r-- | clang/lib/Sema/IdentifierResolver.cpp | 61 | ||||
-rw-r--r-- | clang/lib/Sema/IdentifierResolver.h | 17 | ||||
-rw-r--r-- | clang/lib/Sema/Sema.h | 21 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 53 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 59 |
5 files changed, 97 insertions, 114 deletions
diff --git a/clang/lib/Sema/IdentifierResolver.cpp b/clang/lib/Sema/IdentifierResolver.cpp index 027beede491..18e78a0d170 100644 --- a/clang/lib/Sema/IdentifierResolver.cpp +++ b/clang/lib/Sema/IdentifierResolver.cpp @@ -60,6 +60,9 @@ DeclContext *IdentifierResolver::LookupContext::getContext(Decl *D) { else return TUCtx(); + while (Ctx->isTransparentContext()) + Ctx = Ctx->getParent(); + if (isa<TranslationUnitDecl>(Ctx)) return TUCtx(); @@ -83,30 +86,12 @@ bool IdentifierResolver::LookupContext::isEqOrContainedBy( // IdDeclInfo Implementation //===----------------------------------------------------------------------===// -/// FindContext - Returns an iterator pointing just after the decl that is -/// in the given context or in a parent of it. The search is in reverse -/// order, from end to begin. -IdentifierResolver::IdDeclInfo::DeclsTy::iterator -IdentifierResolver::IdDeclInfo::FindDeclVisibleInContext( - const LookupContext &Ctx, - const DeclsTy::iterator &Start) { - for (DeclsTy::iterator I = Start; I != Decls.begin(); --I) { - if (Ctx.isEqOrContainedBy(LookupContext(*(I-1)))) - return I; - } - - return Decls.begin(); -} - /// AddShadowed - Add a decl by putting it directly above the 'Shadow' decl. /// Later lookups will find the 'Shadow' decl first. The 'Shadow' decl must /// be already added to the scope chain and must be in the same context as /// the decl that we want to add. void IdentifierResolver::IdDeclInfo::AddShadowed(NamedDecl *D, NamedDecl *Shadow) { - assert(LookupContext(D) == LookupContext(Shadow) && - "Decl and Shadow not in same context!"); - for (DeclsTy::iterator I = Decls.end(); I != Decls.begin(); --I) { if (Shadow == *(I-1)) { Decls.insert(I-1, D); @@ -147,7 +132,15 @@ IdentifierResolver::~IdentifierResolver() { /// true if 'D' belongs to the given declaration context. bool IdentifierResolver::isDeclInScope(Decl *D, DeclContext *Ctx, ASTContext &Context, Scope *S) const { + while (Ctx->isTransparentContext()) + Ctx = Ctx->getParent(); + if (Ctx->isFunctionOrMethod()) { + // Ignore the scopes associated within transparent declaration contexts. + while (S->getEntity() && + ((DeclContext *)S->getEntity())->isTransparentContext()) + S = S->getParent(); + if (S->isDeclScope(D)) return true; if (LangOpt.CPlusPlus) { @@ -201,7 +194,6 @@ void IdentifierResolver::AddDecl(NamedDecl *D) { /// encountered before the 'D' decl. void IdentifierResolver::AddShadowedDecl(NamedDecl *D, NamedDecl *Shadow) { assert(D->getDeclName() == Shadow->getDeclName() && "Different ids!"); - assert(LookupContext(D) == LookupContext(Shadow) && "Different context!"); DeclarationName Name = D->getDeclName(); void *Ptr = Name.getFETokenInfo<void>(); @@ -252,30 +244,14 @@ IdentifierResolver::begin(DeclarationName Name, const DeclContext *Ctx, void *Ptr = Name.getFETokenInfo<void>(); if (!Ptr) return end(); - LookupContext LC(Ctx); - if (isDeclPtr(Ptr)) { NamedDecl *D = static_cast<NamedDecl*>(Ptr); - LookupContext DC(D); - - if (( LookInParentCtx && LC.isEqOrContainedBy(DC)) || - (!LookInParentCtx && LC == DC)) - return iterator(D); - else - return end(); + return iterator(D); } IdDeclInfo *IDI = toIdDeclInfo(Ptr); - IdDeclInfo::DeclsTy::iterator I; - if (LookInParentCtx) - I = IDI->FindDeclVisibleInContext(LC); - else { - for (I = IDI->decls_end(); I != IDI->decls_begin(); --I) - if (LookupContext(*(I-1)) == LC) - break; - } - + IdDeclInfo::DeclsTy::iterator I = IDI->decls_end(); if (I != IDI->decls_begin()) return iterator(I-1, LookInParentCtx); else // No decls found. @@ -285,22 +261,11 @@ IdentifierResolver::begin(DeclarationName Name, const DeclContext *Ctx, /// PreIncIter - Do a preincrement when 'Ptr' is a BaseIter. void IdentifierResolver::iterator::PreIncIter() { NamedDecl *D = **this; - LookupContext Ctx(D); void *InfoPtr = D->getDeclName().getFETokenInfo<void>(); assert(!isDeclPtr(InfoPtr) && "Decl with wrong id ?"); IdDeclInfo *Info = toIdDeclInfo(InfoPtr); BaseIter I = getIterator(); - if (LookInParentCtx()) - I = Info->FindDeclVisibleInContext(Ctx, I); - else { - if (I != Info->decls_begin() && LookupContext(*(I-1)) != Ctx) { - // The next decl is in different declaration context. - // Skip remaining decls and set the iterator to the end. - I = Info->decls_begin(); - } - } - if (I != Info->decls_begin()) *this = iterator(I-1, LookInParentCtx()); else // No more decls. diff --git a/clang/lib/Sema/IdentifierResolver.h b/clang/lib/Sema/IdentifierResolver.h index 30846dcd174..3dab1b53a75 100644 --- a/clang/lib/Sema/IdentifierResolver.h +++ b/clang/lib/Sema/IdentifierResolver.h @@ -91,22 +91,7 @@ class IdentifierResolver { inline DeclsTy::iterator decls_begin() { return Decls.begin(); } inline DeclsTy::iterator decls_end() { return Decls.end(); } - /// FindContext - Returns an iterator pointing just after the decl that is - /// in the given context or in a parent of it. The search is in reverse - /// order, from end to begin. - DeclsTy::iterator FindDeclVisibleInContext(const LookupContext &Ctx) { - return FindDeclVisibleInContext(Ctx, Decls.end()); - } - - /// FindContext - Returns an iterator pointing just after the decl that is - /// in the given context or in a parent of it. The search is in reverse - /// order, from end to begin. - DeclsTy::iterator FindDeclVisibleInContext(const LookupContext &Ctx, - const DeclsTy::iterator &Start); - - void AddDecl(NamedDecl *D) { - Decls.insert(FindDeclVisibleInContext(LookupContext(D)), D); - } + void AddDecl(NamedDecl *D) { Decls.push_back(D); } /// AddShadowed - Add a decl by putting it directly above the 'Shadow' decl. /// Later lookups will find the 'Shadow' decl first. The 'Shadow' decl must diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index ca151760c59..d3f373f4949 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -288,12 +288,6 @@ public: virtual void ObjCActOnStartOfMethodDef(Scope *S, DeclTy *D); virtual DeclTy *ActOnFinishFunctionBody(DeclTy *Decl, StmtArg Body); - virtual DeclTy *ActOnLinkageSpec(SourceLocation Loc, SourceLocation LBrace, - SourceLocation RBrace, const char *Lang, - unsigned StrSize, - DeclTy **Decls, unsigned NumDecls); - virtual DeclTy *ActOnLinkageSpec(SourceLocation Loc, const char *Lang, - unsigned StrSize, DeclTy *D); virtual DeclTy *ActOnFileScopeAsmDecl(SourceLocation Loc, ExprArg expr); /// Scope actions. @@ -326,6 +320,7 @@ public: DeclTy **Fields, unsigned NumFields, SourceLocation LBrac, SourceLocation RBrac, AttributeList *AttrList); + virtual void ActOnEnumStartDefinition(Scope *S, DeclTy *EnumDecl); virtual DeclTy *ActOnEnumConstant(Scope *S, DeclTy *EnumDecl, DeclTy *LastEnumConstant, SourceLocation IdLoc, IdentifierInfo *Id, @@ -980,6 +975,20 @@ public: SourceLocation RParenLoc); //===--------------------------------------------------------------------===// + // C++ Declarations + // + virtual DeclTy *ActOnStartLinkageSpecification(Scope *S, + SourceLocation ExternLoc, + SourceLocation LangLoc, + const char *Lang, + unsigned StrSize, + SourceLocation LBraceLoc); + virtual DeclTy *ActOnFinishLinkageSpecification(Scope *S, + DeclTy *LinkageSpec, + SourceLocation RBraceLoc); + + + //===--------------------------------------------------------------------===// // C++ Classes // virtual bool isCurrentClassName(const IdentifierInfo &II, Scope *S, diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 21d3ad68a0e..f4677f03f41 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -93,6 +93,13 @@ void Sema::PopDeclContext() { /// Add this decl to the scope shadowed decl chains. void Sema::PushOnScopeChains(NamedDecl *D, Scope *S) { + // Move up the scope chain until we find the nearest enclosing + // non-transparent context. The declaration will be introduced into this + // scope. + while (S->getEntity() && + ((DeclContext *)S->getEntity())->isTransparentContext()) + S = S->getParent(); + S->AddDecl(D); // Add scoped declarations into their context, so that they can be @@ -149,8 +156,11 @@ void Sema::PushOnScopeChains(NamedDecl *D, Scope *S) { // We are pushing the name of a function, which might be an // overloaded name. FunctionDecl *FD = cast<FunctionDecl>(D); + DeclContext *DC = FD->getDeclContext(); + while (DC->isTransparentContext()) + DC = DC->getParent(); IdentifierResolver::iterator Redecl - = std::find_if(IdResolver.begin(FD->getDeclName(), CurContext, + = std::find_if(IdResolver.begin(FD->getDeclName(), DC, false/*LookInParentCtx*/), IdResolver.end(), std::bind1st(std::mem_fun(&ScopedDecl::declarationReplaces), @@ -337,7 +347,7 @@ Decl *Sema::LookupDecl(DeclarationName Name, unsigned NSI, Scope *S, Ctx = Ctx->getParent(); } - if (!LookInParent) + if (!LookInParent && !Ctx->isTransparentContext()) return 0; } } @@ -3117,6 +3127,15 @@ void Sema::ActOnFields(Scope* S, ProcessDeclAttributeList(Record, Attr); } +void Sema::ActOnEnumStartDefinition(Scope *S, DeclTy *EnumD) { + EnumDecl *Enum = cast_or_null<EnumDecl>((Decl *)EnumD); + + if (Enum) { + // Enter the enumeration context. + PushDeclContext(S, Enum); + } +} + Sema::DeclTy *Sema::ActOnEnumConstant(Scope *S, DeclTy *theEnumDecl, DeclTy *lastEnumConst, SourceLocation IdLoc, IdentifierInfo *Id, @@ -3212,20 +3231,22 @@ Sema::DeclTy *Sema::ActOnEnumConstant(Scope *S, DeclTy *theEnumDecl, void Sema::ActOnEnumBody(SourceLocation EnumLoc, DeclTy *EnumDeclX, DeclTy **Elements, unsigned NumElements) { EnumDecl *Enum = cast<EnumDecl>(static_cast<Decl*>(EnumDeclX)); + QualType EnumType = Context.getTypeDeclType(Enum); - if (Enum) { - if (EnumDecl *Def = cast_or_null<EnumDecl>(Enum->getDefinition(Context))) { - // Diagnose code like: - // enum e0 { - // E0 = sizeof(enum e0 { E1 }) - // }; - Diag(Def->getLocation(), diag::err_nested_redefinition) - << Enum->getDeclName(); - Diag(Enum->getLocation(), diag::note_previous_definition); - Enum->setInvalidDecl(); - return; - } + if (EnumType->getAsEnumType()->getDecl()->isDefinition()) { + EnumDecl *Def = EnumType->getAsEnumType()->getDecl(); + // Diagnose code like: + // enum e0 { + // E0 = sizeof(enum e0 { E1 }) + // }; + Diag(Def->getLocation(), diag::err_nested_redefinition) + << Enum->getDeclName(); + Diag(Enum->getLocation(), diag::note_previous_definition); + Enum->setInvalidDecl(); + PopDeclContext(); + return; } + // TODO: If the result value doesn't fit in an int, it must be a long or long // long value. ISO C does not support this, but GCC does as an extension, // emit a warning. @@ -3239,7 +3260,6 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, DeclTy *EnumDeclX, // Keep track of whether all elements have type int. bool AllElementsInt = true; - QualType EnumType = Context.getTypeDeclType(Enum); EnumConstantDecl *EltList = 0; for (unsigned i = 0; i != NumElements; ++i) { EnumConstantDecl *ECD = @@ -3392,6 +3412,9 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, DeclTy *EnumDeclX, Enum->completeDefinition(Context, BestType); Consumer.HandleTagDeclDefinition(Enum); + + // Leave the context of the enumeration. + PopDeclContext(); } Sema::DeclTy *Sema::ActOnFileScopeAsmDecl(SourceLocation Loc, diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index e3c8373723e..7c05f6b4970 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -2003,48 +2003,49 @@ bool Sema::CheckOverloadedOperatorDeclaration(FunctionDecl *FnDecl) { return false; } -/// ActOnLinkageSpec - Parsed a C++ linkage-specification that -/// contained braces. Lang/StrSize contains the language string that -/// was parsed at location Loc. Decls/NumDecls provides the -/// declarations parsed inside the linkage specification. -Sema::DeclTy *Sema::ActOnLinkageSpec(SourceLocation Loc, - SourceLocation LBrace, - SourceLocation RBrace, - const char *Lang, - unsigned StrSize, - DeclTy **Decls, unsigned NumDecls) { +/// ActOnStartLinkageSpecification - Parsed the beginning of a C++ +/// linkage specification, including the language and (if present) +/// the '{'. ExternLoc is the location of the 'extern', LangLoc is +/// the location of the language string literal, which is provided +/// by Lang/StrSize. LBraceLoc, if valid, provides the location of +/// the '{' brace. Otherwise, this linkage specification does not +/// have any braces. +Sema::DeclTy *Sema::ActOnStartLinkageSpecification(Scope *S, + SourceLocation ExternLoc, + SourceLocation LangLoc, + const char *Lang, + unsigned StrSize, + SourceLocation LBraceLoc) { LinkageSpecDecl::LanguageIDs Language; if (strncmp(Lang, "\"C\"", StrSize) == 0) Language = LinkageSpecDecl::lang_c; else if (strncmp(Lang, "\"C++\"", StrSize) == 0) Language = LinkageSpecDecl::lang_cxx; else { - Diag(Loc, diag::err_bad_language); + Diag(LangLoc, diag::err_bad_language); return 0; } // FIXME: Add all the various semantics of linkage specifications - return LinkageSpecDecl::Create(Context, Loc, Language, - (Decl **)Decls, NumDecls); + LinkageSpecDecl *D = LinkageSpecDecl::Create(Context, CurContext, + LangLoc, Language, + LBraceLoc.isValid()); + CurContext->addDecl(Context, D); + PushDeclContext(S, D); + return D; } -Sema::DeclTy *Sema::ActOnLinkageSpec(SourceLocation Loc, - const char *Lang, unsigned StrSize, - DeclTy *D) { - LinkageSpecDecl::LanguageIDs Language; - Decl *dcl = static_cast<Decl *>(D); - if (strncmp(Lang, "\"C\"", StrSize) == 0) - Language = LinkageSpecDecl::lang_c; - else if (strncmp(Lang, "\"C++\"", StrSize) == 0) - Language = LinkageSpecDecl::lang_cxx; - else { - Diag(Loc, diag::err_bad_language); - return 0; - } - - // FIXME: Add all the various semantics of linkage specifications - return LinkageSpecDecl::Create(Context, Loc, Language, dcl); +/// ActOnFinishLinkageSpecification - Completely the definition of +/// the C++ linkage specification LinkageSpec. If RBraceLoc is +/// valid, it's the position of the closing '}' brace in a linkage +/// specification that uses braces. +Sema::DeclTy *Sema::ActOnFinishLinkageSpecification(Scope *S, + DeclTy *LinkageSpec, + SourceLocation RBraceLoc) { + if (LinkageSpec) + PopDeclContext(); + return LinkageSpec; } /// ActOnExceptionDeclarator - Parsed the exception-declarator in a C++ catch |