From b379c0672bd63c831740bfc8bbabc2d72ee615ce Mon Sep 17 00:00:00 2001 From: Richard Smith <richard-llvm@metafoo.co.uk> Date: Tue, 30 Sep 2014 00:45:29 +0000 Subject: [PATCH] PR20399: Do not assert when adding an implicit member coming from a module at writing time. Patch by Vassil Vassilev! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@218651 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Serialization/ASTWriter.cpp | 11 ++--- test/Modules/Inputs/PR20399/FirstHeader.h | 17 +++++++ test/Modules/Inputs/PR20399/SecondHeader.h | 13 +++++ test/Modules/Inputs/PR20399/module.modulemap | 18 +++++++ test/Modules/Inputs/PR20399/stl_map.h | 25 ++++++++++ test/Modules/Inputs/PR20399/vector | 51 ++++++++++++++++++++ test/Modules/pr20399.cpp | 2 + 7 files changed, 131 insertions(+), 6 deletions(-) create mode 100644 test/Modules/Inputs/PR20399/FirstHeader.h create mode 100644 test/Modules/Inputs/PR20399/SecondHeader.h create mode 100644 test/Modules/Inputs/PR20399/module.modulemap create mode 100644 test/Modules/Inputs/PR20399/stl_map.h create mode 100644 test/Modules/Inputs/PR20399/vector create mode 100644 test/Modules/pr20399.cpp diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index 04a39c07aaf..94eead8641f 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 00000000000..c8005227b35 --- /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 00000000000..8548cc563ab --- /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 00000000000..223434adba1 --- /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 00000000000..11da0425348 --- /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 00000000000..379e4661d35 --- /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 00000000000..4f4a02561fc --- /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 -- GitLab