From: Douglas Gregor Date: Thu, 25 Aug 2011 15:28:26 +0000 (+0000) Subject: Remove a bogus assertion from the AST reader, which assumed that X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=1b59e9c3e1780567e30e5ead2b3512f0aa21fcb6;p=clang Remove a bogus assertion from the AST reader, which assumed that redeclarations of a particular entity would occur in source order. Friend declarations that occur within class templates (or member classes thereof) do not follow this, nor would modules. Big thanks to Erik Verbruggen for reducing this problem from the Very Large Qt preamble testcase he found. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@138557 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index ab46e0a096..6e7cbbf9b0 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -123,8 +123,8 @@ namespace clang { ClassTemplateSpecializationDecl *D); void VisitClassTemplatePartialSpecializationDecl( ClassTemplatePartialSpecializationDecl *D); - void VisitClassScopeFunctionSpecializationDecl( - ClassScopeFunctionSpecializationDecl *D); + void VisitClassScopeFunctionSpecializationDecl( + ClassScopeFunctionSpecializationDecl *D); void VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D); void VisitValueDecl(ValueDecl *VD); void VisitEnumConstantDecl(EnumConstantDecl *ECD); @@ -1087,14 +1087,8 @@ void ASTDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) { ASTReader::FirstLatestDeclIDMap::iterator I = Reader.FirstLatestDeclIDs.find(ThisDeclID); if (I != Reader.FirstLatestDeclIDs.end()) { - Decl *NewLatest = Reader.GetDecl(I->second); - assert((LatestDecl->getLocation().isInvalid() || - NewLatest->getLocation().isInvalid() || - !Reader.SourceMgr.isBeforeInTranslationUnit( - NewLatest->getLocation(), - LatestDecl->getLocation())) && - "The new latest is supposed to come after the previous latest"); - LatestDecl = cast(NewLatest); + if (Decl *NewLatest = Reader.GetDecl(I->second)) + LatestDecl = cast(NewLatest); } assert(LatestDecl->getKind() == D->getKind() && "Latest kind mismatch"); @@ -1217,8 +1211,8 @@ void ASTDeclReader::VisitClassTemplatePartialSpecializationDecl( } } -void ASTDeclReader::VisitClassScopeFunctionSpecializationDecl( - ClassScopeFunctionSpecializationDecl *D) { +void ASTDeclReader::VisitClassScopeFunctionSpecializationDecl( + ClassScopeFunctionSpecializationDecl *D) { VisitDecl(D); D->Specialization = ReadDeclAs(Record, Idx); } diff --git a/test/PCH/chain-friend-instantiation.cpp b/test/PCH/chain-friend-instantiation.cpp new file mode 100644 index 0000000000..294d979112 --- /dev/null +++ b/test/PCH/chain-friend-instantiation.cpp @@ -0,0 +1,61 @@ +// RUN: %clang_cc1 %s -ast-print -o - -chain-include %s -chain-include %s + +#if !defined(PASS1) +#define PASS1 + +template class TClass; + +namespace NS { + template TClass problematic(X * ptr, const TClass &src); + + template + class TBaseClass + { + protected: + template friend TClass problematic(X * ptr, const TClass &src); + }; +} + +template +class TClass: public NS::TBaseClass +{ +public: + inline TClass() { } +}; + + +namespace NS { + template + TClass problematic(X *ptr, const TClass &src); +} + +template +TClass unconst(const TClass &src); + +#elif !defined(PASS2) +#define PASS2 + +namespace std { +class s {}; +} + + +typedef TClass TStr; + +struct crash { + TStr str; + + crash(const TClass p) + { + unconst(p); + } +}; + +#else + +void f() { + const TStr p; + crash c(p); +} + +#endif