Ensure that we have completed a type before attempting initialization

on that type. Fixes several problems in Boost.Interprocess.

llvm-svn: 102339
This commit is contained in:
Douglas Gregor 2010-04-26 14:36:57 +00:00
parent 6171c4489d
commit d984815ed9
2 changed files with 66 additions and 39 deletions

View File

@ -2620,6 +2620,12 @@ static void TryConstructorInitialization(Sema &S,
bool AllowExplicit = (Kind.getKind() == InitializationKind::IK_Direct ||
Kind.getKind() == InitializationKind::IK_Value ||
Kind.getKind() == InitializationKind::IK_Default);
// The type we're constructing needs to be complete.
if (S.RequireCompleteType(Kind.getLocation(), DestType, 0)) {
Sequence.SetFailed(InitializationSequence::FK_ConversionFailed);
return;
}
// The type we're converting to is a class type. Enumerate its constructors
// to see if one is suitable.
@ -2806,48 +2812,51 @@ static void TryUserDefinedConversion(Sema &S,
CXXRecordDecl *DestRecordDecl
= cast<CXXRecordDecl>(DestRecordType->getDecl());
DeclarationName ConstructorName
= S.Context.DeclarationNames.getCXXConstructorName(
// Try to complete the type we're converting to.
if (!S.RequireCompleteType(Kind.getLocation(), DestType, 0)) {
DeclarationName ConstructorName
= S.Context.DeclarationNames.getCXXConstructorName(
S.Context.getCanonicalType(DestType).getUnqualifiedType());
DeclContext::lookup_iterator Con, ConEnd;
for (llvm::tie(Con, ConEnd) = DestRecordDecl->lookup(ConstructorName);
Con != ConEnd; ++Con) {
NamedDecl *D = *Con;
DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess());
bool SuppressUserConversions = false;
// Find the constructor (which may be a template).
CXXConstructorDecl *Constructor = 0;
FunctionTemplateDecl *ConstructorTmpl
= dyn_cast<FunctionTemplateDecl>(D);
if (ConstructorTmpl)
Constructor = cast<CXXConstructorDecl>(
ConstructorTmpl->getTemplatedDecl());
else {
Constructor = cast<CXXConstructorDecl>(D);
DeclContext::lookup_iterator Con, ConEnd;
for (llvm::tie(Con, ConEnd) = DestRecordDecl->lookup(ConstructorName);
Con != ConEnd; ++Con) {
NamedDecl *D = *Con;
DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess());
bool SuppressUserConversions = false;
// If we're performing copy initialization using a copy constructor, we
// suppress user-defined conversions on the arguments.
// FIXME: Move constructors?
if (Kind.getKind() == InitializationKind::IK_Copy &&
Constructor->isCopyConstructor())
SuppressUserConversions = true;
}
if (!Constructor->isInvalidDecl() &&
Constructor->isConvertingConstructor(AllowExplicit)) {
// Find the constructor (which may be a template).
CXXConstructorDecl *Constructor = 0;
FunctionTemplateDecl *ConstructorTmpl
= dyn_cast<FunctionTemplateDecl>(D);
if (ConstructorTmpl)
S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl,
/*ExplicitArgs*/ 0,
&Initializer, 1, CandidateSet,
SuppressUserConversions);
else
S.AddOverloadCandidate(Constructor, FoundDecl,
&Initializer, 1, CandidateSet,
SuppressUserConversions);
}
}
Constructor = cast<CXXConstructorDecl>(
ConstructorTmpl->getTemplatedDecl());
else {
Constructor = cast<CXXConstructorDecl>(D);
// If we're performing copy initialization using a copy constructor,
// we suppress user-defined conversions on the arguments.
// FIXME: Move constructors?
if (Kind.getKind() == InitializationKind::IK_Copy &&
Constructor->isCopyConstructor())
SuppressUserConversions = true;
}
if (!Constructor->isInvalidDecl() &&
Constructor->isConvertingConstructor(AllowExplicit)) {
if (ConstructorTmpl)
S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl,
/*ExplicitArgs*/ 0,
&Initializer, 1, CandidateSet,
SuppressUserConversions);
else
S.AddOverloadCandidate(Constructor, FoundDecl,
&Initializer, 1, CandidateSet,
SuppressUserConversions);
}
}
}
}
SourceLocation DeclLoc = Initializer->getLocStart();

View File

@ -188,3 +188,21 @@ template<> void f4<int>(int, int);
void f4_test(int i) {
f4(i);
}
// Instantiate for initialization
namespace InstForInit {
template<typename T>
struct Ptr {
typedef T* type;
Ptr(type);
};
template<typename T>
struct Holder {
Holder(int i, Ptr<T> ptr = 0);
};
void test_holder(int i) {
Holder<int> h(i);
}
};