Make instantiating initializers for classes with a dependent base type
work correctly. The change in lib/AST/DeclCXX.cpp is mostly a large reindentation; I couldn't figure out a good way to avoid it. llvm-svn: 80446
This commit is contained in:
parent
ca73326f56
commit
15e05261d4
|
@ -595,66 +595,81 @@ CXXConstructorDecl::setBaseOrMemberInitializers(
|
|||
CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(getDeclContext());
|
||||
llvm::SmallVector<CXXBaseOrMemberInitializer*, 32> AllToInit;
|
||||
llvm::DenseMap<const void *, CXXBaseOrMemberInitializer*> AllBaseFields;
|
||||
bool HasDependentBaseInit = false;
|
||||
|
||||
for (unsigned i = 0; i < NumInitializers; i++) {
|
||||
CXXBaseOrMemberInitializer *Member = Initializers[i];
|
||||
if (Member->isBaseInitializer())
|
||||
if (Member->isBaseInitializer()) {
|
||||
if (Member->getBaseClass()->isDependentType())
|
||||
HasDependentBaseInit = true;
|
||||
AllBaseFields[Member->getBaseClass()->getAs<RecordType>()] = Member;
|
||||
else
|
||||
} else {
|
||||
AllBaseFields[Member->getMember()] = Member;
|
||||
}
|
||||
}
|
||||
|
||||
if (HasDependentBaseInit) {
|
||||
// If we have a dependent base initialization, we can't determine the
|
||||
// association between initializers and bases; just dump the known
|
||||
// initializers into the list, and don't try to deal with other bases.
|
||||
for (unsigned i = 0; i < NumInitializers; i++) {
|
||||
CXXBaseOrMemberInitializer *Member = Initializers[i];
|
||||
if (Member->isBaseInitializer())
|
||||
AllToInit.push_back(Member);
|
||||
}
|
||||
} else {
|
||||
// Push virtual bases before others.
|
||||
for (CXXRecordDecl::base_class_iterator VBase =
|
||||
ClassDecl->vbases_begin(),
|
||||
E = ClassDecl->vbases_end(); VBase != E; ++VBase) {
|
||||
if (VBase->getType()->isDependentType())
|
||||
continue;
|
||||
if (CXXBaseOrMemberInitializer *Value =
|
||||
AllBaseFields.lookup(VBase->getType()->getAs<RecordType>()))
|
||||
AllToInit.push_back(Value);
|
||||
else {
|
||||
CXXRecordDecl *VBaseDecl =
|
||||
cast<CXXRecordDecl>(VBase->getType()->getAs<RecordType>()->getDecl());
|
||||
assert(VBaseDecl && "setBaseOrMemberInitializers - VBaseDecl null");
|
||||
if (!VBaseDecl->getDefaultConstructor(C))
|
||||
Bases.push_back(VBase);
|
||||
CXXBaseOrMemberInitializer *Member =
|
||||
new (C) CXXBaseOrMemberInitializer(VBase->getType(), 0, 0,
|
||||
VBaseDecl->getDefaultConstructor(C),
|
||||
SourceLocation(),
|
||||
SourceLocation());
|
||||
AllToInit.push_back(Member);
|
||||
}
|
||||
}
|
||||
|
||||
// Push virtual bases before others.
|
||||
for (CXXRecordDecl::base_class_iterator VBase =
|
||||
ClassDecl->vbases_begin(),
|
||||
E = ClassDecl->vbases_end(); VBase != E; ++VBase) {
|
||||
if (VBase->getType()->isDependentType())
|
||||
continue;
|
||||
if (CXXBaseOrMemberInitializer *Value =
|
||||
AllBaseFields.lookup(VBase->getType()->getAs<RecordType>()))
|
||||
AllToInit.push_back(Value);
|
||||
else {
|
||||
CXXRecordDecl *VBaseDecl =
|
||||
cast<CXXRecordDecl>(VBase->getType()->getAs<RecordType>()->getDecl());
|
||||
assert(VBaseDecl && "setBaseOrMemberInitializers - VBaseDecl null");
|
||||
if (!VBaseDecl->getDefaultConstructor(C))
|
||||
Bases.push_back(VBase);
|
||||
CXXBaseOrMemberInitializer *Member =
|
||||
new (C) CXXBaseOrMemberInitializer(VBase->getType(), 0, 0,
|
||||
VBaseDecl->getDefaultConstructor(C),
|
||||
for (CXXRecordDecl::base_class_iterator Base =
|
||||
ClassDecl->bases_begin(),
|
||||
E = ClassDecl->bases_end(); Base != E; ++Base) {
|
||||
// Virtuals are in the virtual base list and already constructed.
|
||||
if (Base->isVirtual())
|
||||
continue;
|
||||
// Skip dependent types.
|
||||
if (Base->getType()->isDependentType())
|
||||
continue;
|
||||
if (CXXBaseOrMemberInitializer *Value =
|
||||
AllBaseFields.lookup(Base->getType()->getAs<RecordType>()))
|
||||
AllToInit.push_back(Value);
|
||||
else {
|
||||
CXXRecordDecl *BaseDecl =
|
||||
cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
|
||||
assert(BaseDecl && "setBaseOrMemberInitializers - BaseDecl null");
|
||||
if (!BaseDecl->getDefaultConstructor(C))
|
||||
Bases.push_back(Base);
|
||||
CXXBaseOrMemberInitializer *Member =
|
||||
new (C) CXXBaseOrMemberInitializer(Base->getType(), 0, 0,
|
||||
BaseDecl->getDefaultConstructor(C),
|
||||
SourceLocation(),
|
||||
SourceLocation());
|
||||
AllToInit.push_back(Member);
|
||||
AllToInit.push_back(Member);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (CXXRecordDecl::base_class_iterator Base =
|
||||
ClassDecl->bases_begin(),
|
||||
E = ClassDecl->bases_end(); Base != E; ++Base) {
|
||||
// Virtuals are in the virtual base list and already constructed.
|
||||
if (Base->isVirtual())
|
||||
continue;
|
||||
// Skip dependent types.
|
||||
if (Base->getType()->isDependentType())
|
||||
continue;
|
||||
if (CXXBaseOrMemberInitializer *Value =
|
||||
AllBaseFields.lookup(Base->getType()->getAs<RecordType>()))
|
||||
AllToInit.push_back(Value);
|
||||
else {
|
||||
CXXRecordDecl *BaseDecl =
|
||||
cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
|
||||
assert(BaseDecl && "setBaseOrMemberInitializers - BaseDecl null");
|
||||
if (!BaseDecl->getDefaultConstructor(C))
|
||||
Bases.push_back(Base);
|
||||
CXXBaseOrMemberInitializer *Member =
|
||||
new (C) CXXBaseOrMemberInitializer(Base->getType(), 0, 0,
|
||||
BaseDecl->getDefaultConstructor(C),
|
||||
SourceLocation(),
|
||||
SourceLocation());
|
||||
AllToInit.push_back(Member);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// non-static data members.
|
||||
for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
|
||||
E = ClassDecl->field_end(); Field != E; ++Field) {
|
||||
|
|
|
@ -1134,9 +1134,9 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New,
|
|||
MemInitResult NewInit;
|
||||
|
||||
if (Init->isBaseInitializer()) {
|
||||
// FIXME: Type needs to be instantiated.
|
||||
QualType BaseType =
|
||||
Context.getCanonicalType(QualType(Init->getBaseClass(), 0));
|
||||
QualType BaseType(Init->getBaseClass(), 0);
|
||||
BaseType = SubstType(BaseType, TemplateArgs, Init->getSourceLocation(),
|
||||
New->getDeclName());
|
||||
|
||||
NewInit = BuildBaseInitializer(BaseType,
|
||||
(Expr **)NewArgs.data(),
|
||||
|
|
|
@ -18,3 +18,9 @@ template<typename T> struct B {
|
|||
};
|
||||
|
||||
B<int> b0;
|
||||
|
||||
template <class T> struct AA { AA(int); };
|
||||
template <class T> class BB : public AA<T> {
|
||||
BB() : AA<T>(1) {}
|
||||
};
|
||||
BB<int> x;
|
||||
|
|
Loading…
Reference in New Issue