PR20399: Do not assert when adding an implicit member coming from a module at

writing time.

Patch by Vassil Vassilev!

llvm-svn: 218651
This commit is contained in:
Richard Smith 2014-09-30 00:45:29 +00:00
parent 0fbf3af3dc
commit e9a8bc3b69
7 changed files with 131 additions and 6 deletions

View File

@ -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));
}

View File

@ -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

View File

@ -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

View File

@ -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 *
}

View File

@ -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

View File

@ -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

View File

@ -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