From: Nico Weber Date: Wed, 27 Apr 2016 17:26:08 +0000 (+0000) Subject: Revert r267691, it caused PR27535. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=13781e37814559a2c9c04b9a11b2b4a730438936;p=clang Revert r267691, it caused PR27535. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@267744 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h index 26cbd3802f..f7ddb5bd64 100644 --- a/include/clang/AST/DeclBase.h +++ b/include/clang/AST/DeclBase.h @@ -518,8 +518,8 @@ public: bool isImplicit() const { return Implicit; } void setImplicit(bool I = true) { Implicit = I; } - /// \brief Whether *any* (re-)declaration of the entity was used, meaning that - /// a definition is required. + /// \brief Whether this declaration was used, meaning that a definition + /// is required. /// /// \param CheckUsedAttr When true, also consider the "used" attribute /// (in addition to the "used" bit set by \c setUsed()) when determining @@ -529,8 +529,7 @@ public: /// \brief Set whether the declaration is used, in the sense of odr-use. /// /// This should only be used immediately after creating a declaration. - /// It intentionally doesn't notify any listeners. - void setIsUsed() { getCanonicalDecl()->Used = true; } + void setIsUsed() { Used = true; } /// \brief Mark the declaration used, in the sense of odr-use. /// diff --git a/include/clang/Serialization/ASTWriter.h b/include/clang/Serialization/ASTWriter.h index bf53cf09be..72af48c272 100644 --- a/include/clang/Serialization/ASTWriter.h +++ b/include/clang/Serialization/ASTWriter.h @@ -565,17 +565,6 @@ public: /// decl. const Decl *getFirstLocalDecl(const Decl *D); - /// \brief Is this a local declaration (that is, one that will be written to - /// our AST file)? This is the case for declarations that are neither imported - /// from another AST file nor predefined. - bool IsLocalDecl(const Decl *D) { - if (D->isFromASTFile()) - return false; - auto I = DeclIDs.find(D); - return (I == DeclIDs.end() || - I->second >= serialization::NUM_PREDEF_DECL_IDS); - }; - /// \brief Emit a reference to a declaration. void AddDeclRef(const Decl *D, RecordDataImpl &Record); diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp index 338b059e53..aec3b7cd3b 100644 --- a/lib/AST/DeclBase.cpp +++ b/lib/AST/DeclBase.cpp @@ -340,29 +340,25 @@ unsigned Decl::getMaxAlignment() const { return Align; } -bool Decl::isUsed(bool CheckUsedAttr) const { - const Decl *CanonD = getCanonicalDecl(); - if (CanonD->Used) +bool Decl::isUsed(bool CheckUsedAttr) const { + if (Used) return true; - + // Check for used attribute. - // Ask the most recent decl, since attributes accumulate in the redecl chain. - if (CheckUsedAttr && getMostRecentDecl()->hasAttr()) + if (CheckUsedAttr && hasAttr()) return true; - // The information may have not been deserialized yet. Force deserialization - // to complete the needed information. - return getMostRecentDecl()->getCanonicalDecl()->Used; + return false; } void Decl::markUsed(ASTContext &C) { - if (isUsed()) + if (Used) return; if (C.getASTMutationListener()) C.getASTMutationListener()->DeclarationMarkedUsed(this); - setIsUsed(); + Used = true; } bool Decl::isReferenced() const { diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 065c236d6c..0f47e9e099 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -13011,7 +13011,17 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func, UndefinedButUsed.insert(std::make_pair(Func->getCanonicalDecl(), Loc)); } - Func->markUsed(Context); + // Normally the most current decl is marked used while processing the use and + // any subsequent decls are marked used by decl merging. This fails with + // template instantiation since marking can happen at the end of the file + // and, because of the two phase lookup, this function is called with at + // decl in the middle of a decl chain. We loop to maintain the invariant + // that once a decl is used, all decls after it are also used. + for (FunctionDecl *F = Func->getMostRecentDecl();; F = F->getPreviousDecl()) { + F->markUsed(Context); + if (F == Func) + break; + } } static void diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index a6e993885a..d81d73d4ba 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -51,11 +51,6 @@ namespace clang { bool HasPendingBody; - ///\brief A flag to carry the information for a decl from the entity is - /// used. We use it to delay the marking of the canonical decl as used until - /// the entire declaration is deserialized and merged. - bool IsDeclMarkedUsed; - uint64_t GetCurrentCursorOffset(); uint64_t ReadLocalOffset(const RecordData &R, unsigned &I) { @@ -222,8 +217,7 @@ namespace clang { : Reader(Reader), F(*Loc.F), Offset(Loc.Offset), ThisDeclID(thisDeclID), ThisDeclLoc(ThisDeclLoc), Record(Record), Idx(Idx), TypeIDForTypeDecl(0), NamedDeclForTagDecl(0), - TypedefNameForLinkage(nullptr), HasPendingBody(false), - IsDeclMarkedUsed(false) {} + TypedefNameForLinkage(nullptr), HasPendingBody(false) {} template static Decl *getMostRecentDeclImpl(Redeclarable *D); @@ -450,11 +444,6 @@ uint64_t ASTDeclReader::GetCurrentCursorOffset() { void ASTDeclReader::Visit(Decl *D) { DeclVisitor::Visit(D); - // At this point we have deserialized and merged the decl and it is safe to - // update its canonical decl to signal that the entire entity is used. - D->getCanonicalDecl()->Used |= IsDeclMarkedUsed; - IsDeclMarkedUsed = false; - if (DeclaratorDecl *DD = dyn_cast(D)) { if (DD->DeclInfo) { DeclaratorDecl::ExtInfo *Info = @@ -535,7 +524,6 @@ void ASTDeclReader::VisitDecl(Decl *D) { } D->setImplicit(Record[Idx++]); D->Used = Record[Idx++]; - IsDeclMarkedUsed |= D->Used; D->setReferenced(Record[Idx++]); D->setTopLevelDeclInObjCContainer(Record[Idx++]); D->setAccess((AccessSpecifier)Record[Idx++]); @@ -560,7 +548,7 @@ void ASTDeclReader::VisitDecl(Decl *D) { if (Owner->NameVisibility != Module::AllVisible) { // The owning module is not visible. Mark this declaration as hidden. D->Hidden = true; - + // Note that this declaration was hidden because its owning module is // not yet visible. Reader.HiddenNamesMap[Owner].push_back(D); @@ -2367,8 +2355,6 @@ void ASTDeclReader::mergeRedeclarable(Redeclarable *DBase, T *Existing, // appropriate canonical declaration. D->RedeclLink = Redeclarable::PreviousDeclLink(ExistingCanon); D->First = ExistingCanon; - ExistingCanon->Used |= D->Used; - D->Used = false; // When we merge a namespace, update its pointer to the first namespace. // We cannot have loaded any redeclarations of this declaration yet, so @@ -3126,6 +3112,11 @@ void ASTDeclReader::attachPreviousDecl(ASTReader &Reader, Decl *D, Previous->IdentifierNamespace & (Decl::IDNS_Ordinary | Decl::IDNS_Tag | Decl::IDNS_Type); + // If the previous declaration is marked as used, then this declaration should + // be too. + if (Previous->Used) + D->Used = true; + // If the declaration declares a template, it may inherit default arguments // from the previous declaration. if (TemplateDecl *TD = dyn_cast(D)) @@ -3874,7 +3865,7 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile, // ASTMutationListeners other than an ASTWriter. // Maintain AST consistency: any later redeclarations are used too. - D->setIsUsed(); + forAllLaterRedecls(D, [](Decl *D) { D->Used = true; }); break; } diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index 32c9c4787c..073ed67474 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -5784,13 +5784,8 @@ void ASTWriter::AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD, void ASTWriter::DeclarationMarkedUsed(const Decl *D) { assert(!WritingAST && "Already writing the AST!"); - - // If there is *any* declaration of the entity that's not from an AST file, - // we can skip writing the update record. We make sure that isUsed() triggers - // completion of the redeclaration chain of the entity. - for (auto Prev = D->getMostRecentDecl(); Prev; Prev = Prev->getPreviousDecl()) - if (IsLocalDecl(Prev)) - return; + if (!D->isFromASTFile()) + return; DeclUpdates[D].push_back(DeclUpdate(UPD_DECL_MARKED_USED)); } diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp index 1e26f0f9c0..e2b03ba98e 100644 --- a/lib/Serialization/ASTWriterDecl.cpp +++ b/lib/Serialization/ASTWriterDecl.cpp @@ -1541,6 +1541,16 @@ void ASTDeclWriter::VisitDeclContext(DeclContext *DC) { } const Decl *ASTWriter::getFirstLocalDecl(const Decl *D) { + /// \brief Is this a local declaration (that is, one that will be written to + /// our AST file)? This is the case for declarations that are neither imported + /// from another AST file nor predefined. + auto IsLocalDecl = [&](const Decl *D) -> bool { + if (D->isFromASTFile()) + return false; + auto I = DeclIDs.find(D); + return (I == DeclIDs.end() || I->second >= NUM_PREDEF_DECL_IDS); + }; + assert(IsLocalDecl(D) && "expected a local declaration"); const Decl *Canon = D->getCanonicalDecl(); diff --git a/test/Modules/Inputs/PR27401/a.h b/test/Modules/Inputs/PR27401/a.h deleted file mode 100644 index 63d6b707f4..0000000000 --- a/test/Modules/Inputs/PR27401/a.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef _LIBCPP_ALGORITHM -#define _LIBCPP_ALGORITHM -template -struct integral_constant { - static const _Tp value = _Tp(); -}; - -template -struct is_nothrow_default_constructible - : integral_constant {}; - -template -struct is_nothrow_move_constructible - : integral_constant {}; - -class allocator {}; -#endif diff --git a/test/Modules/Inputs/PR27401/b.h b/test/Modules/Inputs/PR27401/b.h deleted file mode 100644 index 2b4e7f14fb..0000000000 --- a/test/Modules/Inputs/PR27401/b.h +++ /dev/null @@ -1,21 +0,0 @@ -#include "a.h" -#ifndef _LIBCPP_VECTOR -template -class __vector_base { -protected: - _Allocator __alloc() const; - __vector_base(_Allocator); -}; - -template -class vector : __vector_base<_Tp, _Allocator> { -public: - vector() noexcept(is_nothrow_default_constructible<_Allocator>::value); - vector(const vector &); - vector(vector &&) - noexcept(is_nothrow_move_constructible<_Allocator>::value); -}; - -#endif -void GetUniquePtrType() { vector v; } - diff --git a/test/Modules/Inputs/PR27401/module.modulemap b/test/Modules/Inputs/PR27401/module.modulemap deleted file mode 100644 index a0efadaa0e..0000000000 --- a/test/Modules/Inputs/PR27401/module.modulemap +++ /dev/null @@ -1 +0,0 @@ -module "b" { header "b.h" export * } diff --git a/test/Modules/pr27401.cpp b/test/Modules/pr27401.cpp deleted file mode 100644 index 7d5479cb92..0000000000 --- a/test/Modules/pr27401.cpp +++ /dev/null @@ -1,38 +0,0 @@ -// RUN: rm -rf %t -// RUN: %clang_cc1 -std=c++11 -I%S/Inputs/PR27401 -verify %s -// RUN: %clang_cc1 -std=c++11 -fmodules -fmodule-map-file=%S/Inputs/PR27401/module.modulemap -fmodules-cache-path=%t -I%S/Inputs/PR27401 -verify %s - -#include "a.h" -#define _LIBCPP_VECTOR -template -class __vector_base { -protected: - _Allocator __alloc() const; - __vector_base(_Allocator); -}; - -template -class vector : __vector_base<_Tp, _Allocator> { -public: - vector() noexcept(is_nothrow_default_constructible<_Allocator>::value); - vector(const vector &); - vector(vector &&) - noexcept(is_nothrow_move_constructible<_Allocator>::value); -}; - -template -vector<_Tp, _Allocator>::vector(const vector &__x) : __vector_base<_Tp, _Allocator>(__x.__alloc()) {} - - struct CommentOptions { - vector ParseAllComments; - CommentOptions() {} - }; - struct PrintingPolicy { - PrintingPolicy(CommentOptions LO) : LangOpts(LO) {} - CommentOptions LangOpts; - }; - -#include "b.h" -CommentOptions fn1() { return fn1(); } - -// expected-no-diagnostics