forked from OSchip/llvm-project
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:
parent
6171c4489d
commit
d984815ed9
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue