diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/ASTImporter.cpp | 4 | ||||
-rw-r--r-- | clang/lib/AST/DeclBase.cpp | 32 | ||||
-rw-r--r-- | clang/lib/AST/DeclCXX.cpp | 28 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 156 | ||||
-rw-r--r-- | clang/lib/Sema/SemaLookup.cpp | 6 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTReaderDecl.cpp | 46 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTWriterDecl.cpp | 9 |
7 files changed, 149 insertions, 132 deletions
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 82307e8e980..10f5a206d5b 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -2083,8 +2083,10 @@ Decl *ASTNodeImporter::VisitNamespaceDecl(NamespaceDecl *D) { NamespaceDecl *ToNamespace = MergeWithNamespace; if (!ToNamespace) { ToNamespace = NamespaceDecl::Create(Importer.getToContext(), DC, + D->isInline(), Importer.Import(D->getLocStart()), - Loc, Name.getAsIdentifierInfo()); + Loc, Name.getAsIdentifierInfo(), + /*PrevDecl=*/0); ToNamespace->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToNamespace); diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp index 3fc507ebdb9..0312cfbc4ab 100644 --- a/clang/lib/AST/DeclBase.cpp +++ b/clang/lib/AST/DeclBase.cpp @@ -839,15 +839,21 @@ DeclContext *DeclContext::getPrimaryContext() { } } -DeclContext *DeclContext::getNextContext() { - switch (DeclKind) { - case Decl::Namespace: - // Return the next namespace - return static_cast<NamespaceDecl*>(this)->getNextNamespace(); - - default: - return 0; +void +DeclContext::collectAllContexts(llvm::SmallVectorImpl<DeclContext *> &Contexts){ + Contexts.clear(); + + if (DeclKind != Decl::Namespace) { + Contexts.push_back(this); + return; } + + NamespaceDecl *Self = static_cast<NamespaceDecl *>(this); + for (NamespaceDecl *N = Self->getMostRecentDeclaration(); N; + N = N->getPreviousDeclaration()) + Contexts.push_back(N); + + std::reverse(Contexts.begin(), Contexts.end()); } std::pair<Decl *, Decl *> @@ -1067,15 +1073,17 @@ void DeclContext::addDeclInternal(Decl *D) { /// declarations in DCtx (and any other contexts linked to it or /// transparent contexts nested within it). void DeclContext::buildLookup(DeclContext *DCtx) { - for (; DCtx; DCtx = DCtx->getNextContext()) { - for (decl_iterator D = DCtx->decls_begin(), - DEnd = DCtx->decls_end(); + llvm::SmallVector<DeclContext *, 2> Contexts; + DCtx->collectAllContexts(Contexts); + for (unsigned I = 0, N = Contexts.size(); I != N; ++I) { + for (decl_iterator D = Contexts[I]->decls_begin(), + DEnd = Contexts[I]->decls_end(); D != DEnd; ++D) { // Insert this declaration into the lookup structure, but only // if it's semantically in its decl context. During non-lazy // lookup building, this is implicitly enforced by addDecl. if (NamedDecl *ND = dyn_cast<NamedDecl>(*D)) - if (D->getDeclContext() == DCtx) + if (D->getDeclContext() == Contexts[I]) makeDeclVisibleInContextImpl(ND, false); // If this declaration is itself a transparent declaration context or diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index ba369bbe99e..f820e9b57ff 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -1767,20 +1767,30 @@ NamespaceDecl *UsingDirectiveDecl::getNominatedNamespace() { void NamespaceDecl::anchor() { } +NamespaceDecl::NamespaceDecl(DeclContext *DC, bool Inline, + SourceLocation StartLoc, + SourceLocation IdLoc, IdentifierInfo *Id, + NamespaceDecl *PrevDecl) + : NamedDecl(Namespace, DC, IdLoc, Id), DeclContext(Namespace), + LocStart(StartLoc), RBraceLoc(), AnonOrFirstNamespaceAndInline(0, Inline) +{ + setPreviousDeclaration(PrevDecl); + + if (PrevDecl) + AnonOrFirstNamespaceAndInline.setPointer(PrevDecl->getOriginalNamespace()); +} + NamespaceDecl *NamespaceDecl::Create(ASTContext &C, DeclContext *DC, - SourceLocation StartLoc, - SourceLocation IdLoc, IdentifierInfo *Id) { - return new (C) NamespaceDecl(DC, StartLoc, IdLoc, Id); + bool Inline, SourceLocation StartLoc, + SourceLocation IdLoc, IdentifierInfo *Id, + NamespaceDecl *PrevDecl) { + return new (C) NamespaceDecl(DC, Inline, StartLoc, IdLoc, Id, PrevDecl); } NamespaceDecl *NamespaceDecl::CreateDeserialized(ASTContext &C, unsigned ID) { void *Mem = AllocateDeserializedDecl(C, ID, sizeof(NamespaceDecl)); - return new (Mem) NamespaceDecl(0, SourceLocation(), SourceLocation(), 0); -} - -NamespaceDecl *NamespaceDecl::getNextNamespace() { - return dyn_cast_or_null<NamespaceDecl>( - NextNamespace.get(getASTContext().getExternalSource())); + return new (Mem) NamespaceDecl(0, false, SourceLocation(), SourceLocation(), + 0, 0); } void NamespaceAliasDecl::anchor() { } diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 56b526b1d7e..44c84f3679f 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -5531,17 +5531,13 @@ Decl *Sema::ActOnStartNamespaceDef(Scope *NamespcScope, SourceLocation StartLoc = InlineLoc.isValid() ? InlineLoc : NamespaceLoc; // For anonymous namespace, take the location of the left brace. SourceLocation Loc = II ? IdentLoc : LBrace; - NamespaceDecl *Namespc = NamespaceDecl::Create(Context, CurContext, - StartLoc, Loc, II); - Namespc->setInline(InlineLoc.isValid()); - + bool IsInline = InlineLoc.isValid(); + bool IsInvalid = false; + bool IsStd = false; + bool AddToKnown = false; Scope *DeclRegionScope = NamespcScope->getParent(); - ProcessDeclAttributeList(DeclRegionScope, Namespc, AttrList); - - if (const VisibilityAttr *Attr = Namespc->getAttr<VisibilityAttr>()) - PushNamespaceVisibilityAttr(Attr); - + NamespaceDecl *PrevNS = 0; if (II) { // C++ [namespace.def]p2: // The identifier in an original-namespace-definition shall not @@ -5555,11 +5551,11 @@ Decl *Sema::ActOnStartNamespaceDef(Scope *NamespcScope, // look through using directives, just look for any ordinary names. const unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_Member | - Decl::IDNS_Type | Decl::IDNS_Using | Decl::IDNS_Tag | - Decl::IDNS_Namespace; + Decl::IDNS_Type | Decl::IDNS_Using | Decl::IDNS_Tag | + Decl::IDNS_Namespace; NamedDecl *PrevDecl = 0; for (DeclContext::lookup_result R - = CurContext->getRedeclContext()->lookup(II); + = CurContext->getRedeclContext()->lookup(II); R.first != R.second; ++R.first) { if ((*R.first)->getIdentifierNamespace() & IDNS) { PrevDecl = *R.first; @@ -5567,100 +5563,90 @@ Decl *Sema::ActOnStartNamespaceDef(Scope *NamespcScope, } } - if (NamespaceDecl *OrigNS = dyn_cast_or_null<NamespaceDecl>(PrevDecl)) { + PrevNS = dyn_cast_or_null<NamespaceDecl>(PrevDecl); + + if (PrevNS) { // This is an extended namespace definition. - if (Namespc->isInline() != OrigNS->isInline()) { + if (IsInline != PrevNS->isInline()) { // inline-ness must match - if (OrigNS->isInline()) { + if (PrevNS->isInline()) { // The user probably just forgot the 'inline', so suggest that it // be added back. - Diag(Namespc->getLocation(), - diag::warn_inline_namespace_reopened_noninline) + Diag(Loc, diag::warn_inline_namespace_reopened_noninline) << FixItHint::CreateInsertion(NamespaceLoc, "inline "); } else { - Diag(Namespc->getLocation(), diag::err_inline_namespace_mismatch) - << Namespc->isInline(); + Diag(Loc, diag::err_inline_namespace_mismatch) + << IsInline; } - Diag(OrigNS->getLocation(), diag::note_previous_definition); - - // Recover by ignoring the new namespace's inline status. - Namespc->setInline(OrigNS->isInline()); - } - - // 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); - } + Diag(PrevNS->getLocation(), diag::note_previous_definition); + + IsInline = PrevNS->isInline(); + } } else if (PrevDecl) { // This is an invalid name redefinition. - Diag(Namespc->getLocation(), diag::err_redefinition_different_kind) - << Namespc->getDeclName(); + Diag(Loc, diag::err_redefinition_different_kind) + << II; Diag(PrevDecl->getLocation(), diag::note_previous_definition); - Namespc->setInvalidDecl(); + IsInvalid = true; // Continue on to push Namespc as current DeclContext and return it. - } else if (II->isStr("std") && + } else if (II->isStr("std") && CurContext->getRedeclContext()->isTranslationUnit()) { // This is the first "real" definition of the namespace "std", so update // our cache of the "std" namespace to point at this definition. - if (NamespaceDecl *StdNS = getStdNamespace()) { - // We had already defined a dummy namespace "std". Link this new - // namespace definition to the dummy namespace "std". - StdNS->setNextNamespace(Namespc); - StdNS->setLocation(IdentLoc); - Namespc->setOriginalNamespace(StdNS->getOriginalNamespace()); - } - - // Make our StdNamespace cache point at the first real definition of the - // "std" namespace. - StdNamespace = Namespc; - - // Add this instance of "std" to the set of known namespaces - KnownNamespaces[Namespc] = false; - } else if (!Namespc->isInline()) { - // Since this is an "original" namespace, add it to the known set of - // namespaces if it is not an inline namespace. - KnownNamespaces[Namespc] = false; + PrevNS = getStdNamespace(); + IsStd = true; + AddToKnown = !IsInline; + } else { + // We've seen this namespace for the first time. + AddToKnown = !IsInline; } - - PushOnScopeChains(Namespc, DeclRegionScope); } else { // Anonymous namespaces. - assert(Namespc->isAnonymousNamespace()); - - // Link the anonymous namespace into its parent. - NamespaceDecl *PrevDecl; + + // Determine whether the parent already has an anonymous namespace. DeclContext *Parent = CurContext->getRedeclContext(); if (TranslationUnitDecl *TU = dyn_cast<TranslationUnitDecl>(Parent)) { - PrevDecl = TU->getAnonymousNamespace(); - TU->setAnonymousNamespace(Namespc); + PrevNS = TU->getAnonymousNamespace(); } else { NamespaceDecl *ND = cast<NamespaceDecl>(Parent); - PrevDecl = ND->getAnonymousNamespace(); - ND->setAnonymousNamespace(Namespc); + PrevNS = ND->getAnonymousNamespace(); } - // Link the anonymous namespace with its previous declaration. - if (PrevDecl) { - assert(PrevDecl->isAnonymousNamespace()); - assert(!PrevDecl->getNextNamespace()); - Namespc->setOriginalNamespace(PrevDecl->getOriginalNamespace()); - PrevDecl->setNextNamespace(Namespc); + if (PrevNS && IsInline != PrevNS->isInline()) { + // inline-ness must match + Diag(Loc, diag::err_inline_namespace_mismatch) + << IsInline; + Diag(PrevNS->getLocation(), diag::note_previous_definition); + IsInvalid = true; + + // Recover by ignoring the new namespace's inline status. + IsInline = PrevNS->isInline(); + } + } + + NamespaceDecl *Namespc = NamespaceDecl::Create(Context, CurContext, IsInline, + StartLoc, Loc, II, PrevNS); + + ProcessDeclAttributeList(DeclRegionScope, Namespc, AttrList); - if (Namespc->isInline() != PrevDecl->isInline()) { - // inline-ness must match - Diag(Namespc->getLocation(), diag::err_inline_namespace_mismatch) - << Namespc->isInline(); - Diag(PrevDecl->getLocation(), diag::note_previous_definition); - Namespc->setInvalidDecl(); - // Recover by ignoring the new namespace's inline status. - Namespc->setInline(PrevDecl->isInline()); - } + // FIXME: Should we be merging attributes? + if (const VisibilityAttr *Attr = Namespc->getAttr<VisibilityAttr>()) + PushNamespaceVisibilityAttr(Attr); + + if (IsStd) + StdNamespace = Namespc; + if (AddToKnown) + KnownNamespaces[Namespc] = false; + + if (II) { + PushOnScopeChains(Namespc, DeclRegionScope); + } else { + // Link the anonymous namespace into its parent. + DeclContext *Parent = CurContext->getRedeclContext(); + if (TranslationUnitDecl *TU = dyn_cast<TranslationUnitDecl>(Parent)) { + TU->setAnonymousNamespace(Namespc); + } else { + cast<NamespaceDecl>(Parent)->setAnonymousNamespace(Namespc); } CurContext->addDecl(Namespc); @@ -5681,7 +5667,7 @@ Decl *Sema::ActOnStartNamespaceDef(Scope *NamespcScope, // declarations semantically contained within an anonymous // namespace internal linkage. - if (!PrevDecl) { + if (!PrevNS) { UsingDirectiveDecl* UD = UsingDirectiveDecl::Create(Context, CurContext, /* 'using' */ LBrace, @@ -5740,8 +5726,10 @@ NamespaceDecl *Sema::getOrCreateStdNamespace() { // The "std" namespace has not yet been defined, so build one implicitly. StdNamespace = NamespaceDecl::Create(Context, Context.getTranslationUnitDecl(), + /*Inline=*/false, SourceLocation(), SourceLocation(), - &PP.getIdentifierTable().get("std")); + &PP.getIdentifierTable().get("std"), + /*PrevDecl=*/0); getStdNamespace()->setImplicit(true); } diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index 984184b9c98..eab1517b650 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -2740,8 +2740,10 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result, Result.getSema().ForceDeclarationOfImplicitMembers(Class); // Enumerate all of the results in this context. - for (DeclContext *CurCtx = Ctx->getPrimaryContext(); CurCtx; - CurCtx = CurCtx->getNextContext()) { + llvm::SmallVector<DeclContext *, 2> Contexts; + Ctx->collectAllContexts(Contexts); + for (unsigned I = 0, N = Contexts.size(); I != N; ++I) { + DeclContext *CurCtx = Contexts[I]; for (DeclContext::decl_iterator D = CurCtx->decls_begin(), DEnd = CurCtx->decls_end(); D != DEnd; ++D) { diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index 24ac976c108..6e73388da16 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -967,17 +967,22 @@ void ASTDeclReader::VisitLabelDecl(LabelDecl *D) { void ASTDeclReader::VisitNamespaceDecl(NamespaceDecl *D) { + RedeclarableResult Redecl = VisitRedeclarable(D); VisitNamedDecl(D); - D->IsInline = Record[Idx++]; + D->setInline(Record[Idx++]); D->LocStart = ReadSourceLocation(Record, Idx); D->RBraceLoc = ReadSourceLocation(Record, Idx); - D->NextNamespace = Record[Idx++]; - - bool IsOriginal = Record[Idx++]; - // FIXME: Modules will likely have trouble with pointing directly at - // the original namespace. - D->OrigOrAnonNamespace.setInt(IsOriginal); - D->OrigOrAnonNamespace.setPointer(ReadDeclAs<NamespaceDecl>(Record, Idx)); + + if (Redecl.getFirstID() == ThisDeclID) { + // FIXME: If there's already an anonymous namespace, do we merge it with + // this one? Or do we, when loading modules, just forget about anonymous + // namespace entirely? + D->setAnonymousNamespace(ReadDeclAs<NamespaceDecl>(Record, Idx)); + } else { + // Link this namespace back to the first declaration, which has already + // been deserialized. + D->AnonOrFirstNamespaceAndInline.setPointer(D->getFirstDeclaration()); + } } void ASTDeclReader::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) { @@ -1772,6 +1777,8 @@ void ASTDeclReader::attachPreviousDecl(Decl *D, Decl *previous) { ID->RedeclLink.setPointer(cast<ObjCInterfaceDecl>(previous)); } else if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) { PD->RedeclLink.setPointer(cast<ObjCProtocolDecl>(previous)); + } else if (NamespaceDecl *ND = dyn_cast<NamespaceDecl>(D)) { + ND->RedeclLink.setPointer(cast<NamespaceDecl>(previous)); } else { RedeclarableTemplateDecl *TD = cast<RedeclarableTemplateDecl>(D); TD->CommonOrPrev = cast<RedeclarableTemplateDecl>(previous); @@ -1801,6 +1808,10 @@ void ASTDeclReader::attachLatestDecl(Decl *D, Decl *Latest) { PD->RedeclLink = Redeclarable<ObjCProtocolDecl>::LatestDeclLink( cast<ObjCProtocolDecl>(Latest)); + } else if (NamespaceDecl *ND = dyn_cast<NamespaceDecl>(D)) { + ND->RedeclLink + = Redeclarable<NamespaceDecl>::LatestDeclLink( + cast<NamespaceDecl>(Latest)); } else { RedeclarableTemplateDecl *TD = cast<RedeclarableTemplateDecl>(D); TD->getCommonPtr()->Latest = cast<RedeclarableTemplateDecl>(Latest); @@ -2216,6 +2227,8 @@ static Decl *getPreviousDecl(Decl *D) { return ID->getPreviousDeclaration(); if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) return PD->getPreviousDeclaration(); + if (NamespaceDecl *ND = dyn_cast<NamespaceDecl>(D)) + return ND->getPreviousDeclaration(); return cast<RedeclarableTemplateDecl>(D)->getPreviousDeclaration(); } @@ -2234,7 +2247,9 @@ static Decl *getMostRecentDecl(Decl *D) { return ID->getMostRecentDeclaration(); if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) return PD->getMostRecentDeclaration(); - + if (NamespaceDecl *ND = dyn_cast<NamespaceDecl>(D)) + return ND->getMostRecentDeclaration(); + return cast<RedeclarableTemplateDecl>(D)->getMostRecentDeclaration(); } @@ -2446,15 +2461,10 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile, case UPD_CXX_ADDED_ANONYMOUS_NAMESPACE: { NamespaceDecl *Anon = Reader.ReadDeclAs<NamespaceDecl>(ModuleFile, Record, Idx); - // Guard against these being loaded out of original order. Don't use - // getNextNamespace(), since it tries to access the context and can't in - // the middle of deserialization. - if (!Anon->NextNamespace) { - if (TranslationUnitDecl *TU = dyn_cast<TranslationUnitDecl>(D)) - TU->setAnonymousNamespace(Anon); - else - cast<NamespaceDecl>(D)->OrigOrAnonNamespace.setPointer(Anon); - } + if (TranslationUnitDecl *TU = dyn_cast<TranslationUnitDecl>(D)) + TU->setAnonymousNamespace(Anon); + else + cast<NamespaceDecl>(D)->setAnonymousNamespace(Anon); break; } diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp index 7ff1d5aab06..45ce7799fa3 100644 --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -802,18 +802,14 @@ void ASTDeclWriter::VisitLabelDecl(LabelDecl *D) { void ASTDeclWriter::VisitNamespaceDecl(NamespaceDecl *D) { + VisitRedeclarable(D); VisitNamedDecl(D); Record.push_back(D->isInline()); Writer.AddSourceLocation(D->getLocStart(), Record); Writer.AddSourceLocation(D->getRBraceLoc(), Record); - Writer.AddDeclRef(D->getNextNamespace(), Record); - // Only write one reference--original or anonymous - Record.push_back(D->isOriginalNamespace()); if (D->isOriginalNamespace()) Writer.AddDeclRef(D->getAnonymousNamespace(), Record); - else - Writer.AddDeclRef(D->getOriginalNamespace(), Record); Code = serialization::DECL_NAMESPACE; if (Writer.hasChain() && !D->isOriginalNamespace() && @@ -836,7 +832,8 @@ void ASTDeclWriter::VisitNamespaceDecl(NamespaceDecl *D) { } } - if (Writer.hasChain() && D->isAnonymousNamespace() && !D->getNextNamespace()){ + if (Writer.hasChain() && D->isAnonymousNamespace() && + D == D->getMostRecentDeclaration()) { // This is a most recent reopening of the anonymous namespace. If its parent // is in a previous PCH (or is the TU), mark that parent for update, because // the original namespace always points to the latest re-opening of its |