diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index 04a39c07aaf08631d613f3d0473539df43544822..94eead8641f8ef40e3d7bfd9defb7790204fed98 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -5708,8 +5708,6 @@ void ASTWriter::CompletedTagDefinition(const TagDecl *D) { } void ASTWriter::AddedVisibleDecl(const DeclContext *DC, const Decl *D) { - assert(!WritingAST && "Already writing the AST!"); - // TU and namespaces are handled elsewhere. if (isa<TranslationUnitDecl>(DC) || isa<NamespaceDecl>(DC)) return; @@ -5718,12 +5716,12 @@ void ASTWriter::AddedVisibleDecl(const DeclContext *DC, const Decl *D) { return; // Not a source decl added to a DeclContext from PCH. assert(!getDefinitiveDeclContext(DC) && "DeclContext not definitive!"); + assert(!WritingAST && "Already writing the AST!"); AddUpdatedDeclContext(DC); UpdatingVisibleDecls.push_back(D); } void ASTWriter::AddedCXXImplicitMember(const CXXRecordDecl *RD, const Decl *D) { - assert(!WritingAST && "Already writing the AST!"); assert(D->isImplicit()); if (!(!D->isFromASTFile() && RD->isFromASTFile())) return; // Not a source member added to a class from PCH. @@ -5732,17 +5730,18 @@ void ASTWriter::AddedCXXImplicitMember(const CXXRecordDecl *RD, const Decl *D) { // A decl coming from PCH was modified. assert(RD->isCompleteDefinition()); + assert(!WritingAST && "Already writing the AST!"); DeclUpdates[RD].push_back(DeclUpdate(UPD_CXX_ADDED_IMPLICIT_MEMBER, D)); } void ASTWriter::AddedCXXTemplateSpecialization(const ClassTemplateDecl *TD, const ClassTemplateSpecializationDecl *D) { // The specializations set is kept in the canonical template. - assert(!WritingAST && "Already writing the AST!"); TD = TD->getCanonicalDecl(); if (!(!D->isFromASTFile() && TD->isFromASTFile())) return; // Not a source specialization added to a template from PCH. + assert(!WritingAST && "Already writing the AST!"); DeclUpdates[TD].push_back(DeclUpdate(UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION, D)); } @@ -5750,11 +5749,11 @@ void ASTWriter::AddedCXXTemplateSpecialization(const ClassTemplateDecl *TD, void ASTWriter::AddedCXXTemplateSpecialization( const VarTemplateDecl *TD, const VarTemplateSpecializationDecl *D) { // The specializations set is kept in the canonical template. - assert(!WritingAST && "Already writing the AST!"); TD = TD->getCanonicalDecl(); if (!(!D->isFromASTFile() && TD->isFromASTFile())) return; // Not a source specialization added to a template from PCH. + assert(!WritingAST && "Already writing the AST!"); DeclUpdates[TD].push_back(DeclUpdate(UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION, D)); } @@ -5762,11 +5761,11 @@ void ASTWriter::AddedCXXTemplateSpecialization( void ASTWriter::AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD, const FunctionDecl *D) { // The specializations set is kept in the canonical template. - assert(!WritingAST && "Already writing the AST!"); TD = TD->getCanonicalDecl(); if (!(!D->isFromASTFile() && TD->isFromASTFile())) return; // Not a source specialization added to a template from PCH. + assert(!WritingAST && "Already writing the AST!"); DeclUpdates[TD].push_back(DeclUpdate(UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION, D)); } diff --git a/test/Modules/Inputs/PR20399/FirstHeader.h b/test/Modules/Inputs/PR20399/FirstHeader.h new file mode 100644 index 0000000000000000000000000000000000000000..c8005227b35748fe8643461c841a6b4be2efeb1f --- /dev/null +++ b/test/Modules/Inputs/PR20399/FirstHeader.h @@ -0,0 +1,17 @@ +#ifndef FIRSTHEADER +#define FIRSTHEADER + +#include "SecondHeader.h" // Just a class which gets in the lazy deserialization chain + +#include "stl_map.h" +#include "vector" +struct A { + typedef std::map<int, int*>::iterator el; +}; + +struct B { + ~B() {} + std::vector<int> fvec; // Cannot replace with simple mockup +}; + +#endif diff --git a/test/Modules/Inputs/PR20399/SecondHeader.h b/test/Modules/Inputs/PR20399/SecondHeader.h new file mode 100644 index 0000000000000000000000000000000000000000..8548cc563abd4af8879916c63acf3520d0788deb --- /dev/null +++ b/test/Modules/Inputs/PR20399/SecondHeader.h @@ -0,0 +1,13 @@ +#ifndef SECONDHEADER +#define SECONDHEADER + +#include "vector" + +class Collection { + template <class T> struct Address { }; +}; + +template <> struct Collection::Address<std::vector<bool> > + : public Collection::Address<std::vector<bool>::iterator> { }; + +#endif diff --git a/test/Modules/Inputs/PR20399/module.modulemap b/test/Modules/Inputs/PR20399/module.modulemap new file mode 100644 index 0000000000000000000000000000000000000000..223434adba19bb04d80c2f3ea79cc564cba58983 --- /dev/null +++ b/test/Modules/Inputs/PR20399/module.modulemap @@ -0,0 +1,18 @@ +module stdlib [system] { + header "stl_map.h" + header "vector" + } + +module libCore { + header "SecondHeader.h" + use stdlib + export * +} + +module libGdml { + header "FirstHeader.h" + use libCore + use stdlib + export * +} + diff --git a/test/Modules/Inputs/PR20399/stl_map.h b/test/Modules/Inputs/PR20399/stl_map.h new file mode 100644 index 0000000000000000000000000000000000000000..11da04253483099b9ffaa28f1cba3a7a60829771 --- /dev/null +++ b/test/Modules/Inputs/PR20399/stl_map.h @@ -0,0 +1,25 @@ +namespace std +{ + template<typename _Iterator> + class reverse_iterator {}; + + template<typename _Iterator> + inline int* + operator-(const int& __x, const reverse_iterator<_Iterator>& __y) {}; + + template<typename _Tp> + struct _Rb_tree_iterator + { + typedef _Rb_tree_iterator<_Tp> _Self; + }; + + template <typename _Key, typename _Tp > + class map + { + public: + typedef _Rb_tree_iterator<int> iterator; + + template<typename _K1, typename _T1> + friend bool operator<(const map<_K1, _T1>&, const map<_K1, _T1>&); + }; +} // namespace std diff --git a/test/Modules/Inputs/PR20399/vector b/test/Modules/Inputs/PR20399/vector new file mode 100644 index 0000000000000000000000000000000000000000..379e4661d354720c46534384e27773c9b8917d0c --- /dev/null +++ b/test/Modules/Inputs/PR20399/vector @@ -0,0 +1,51 @@ +namespace std +{ + template<typename _Tp, typename _Alloc = int> + class vector + { + public: + int* _M_start; + int* _M_end_of_storage; + + ~vector() + { this->_M_end_of_storage - this->_M_start; } + }; + + struct _Bit_iterator {}; + + inline int* operator-(const _Bit_iterator& __x, const _Bit_iterator& __y) + { + return 0; + } + + struct _Bvector_base + { + struct _Bvector_impl + { + _Bit_iterator _M_start; + + _Bvector_impl() { } + }; + + public: + ~_Bvector_base() + { this->_M_deallocate(); } + + protected: + _Bvector_impl _M_impl; + + void _M_deallocate() {} + }; + + template<typename _Alloc> + class vector<bool, _Alloc> : protected _Bvector_base + { + typedef _Bvector_base _Base; + public: + typedef _Bit_iterator iterator; + + vector() + : _Base() { } + }; + +} // namespace std diff --git a/test/Modules/pr20399.cpp b/test/Modules/pr20399.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4f4a02561fc21e0239df304ef7dd8c6502880966 --- /dev/null +++ b/test/Modules/pr20399.cpp @@ -0,0 +1,2 @@ +// RUN: rm -rf %t +// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t -fmodule-name=libGdml -emit-module -x c++ -std=c++11 %S/Inputs/PR20399/module.modulemap