Factor out the actual overload resolution from TryConstructorInitialization, since it needs to be used again for list constructor resolution.

llvm-svn: 149791
This commit is contained in:
Sebastian Redl 2012-02-04 21:27:39 +00:00
parent 88e4d4933a
commit ab3f7a4e3d
1 changed files with 70 additions and 53 deletions

View File

@ -2761,6 +2761,57 @@ static bool TryListConstructionSpecialCases(Sema &S,
return false;
}
static OverloadingResult
ResolveConstructorOverload(Sema &S, SourceLocation DeclLoc,
Expr **Args, unsigned NumArgs,
OverloadCandidateSet &CandidateSet,
DeclContext::lookup_iterator Con,
DeclContext::lookup_iterator ConEnd,
OverloadCandidateSet::iterator &Best,
bool CopyInitializing, bool AllowExplicit,
bool OnlyListConstructors) {
CandidateSet.clear();
for (; 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);
// If we're performing copy initialization using a copy constructor, we
// suppress user-defined conversions on the arguments.
// FIXME: Move constructors?
if (CopyInitializing && Constructor->isCopyConstructor())
SuppressUserConversions = true;
}
if (!Constructor->isInvalidDecl() &&
(AllowExplicit || !Constructor->isExplicit()) &&
(!OnlyListConstructors || !S.isInitListConstructor(Constructor))) {
if (ConstructorTmpl)
S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl,
/*ExplicitArgs*/ 0,
Args, NumArgs, CandidateSet,
SuppressUserConversions);
else
S.AddOverloadCandidate(Constructor, FoundDecl,
Args, NumArgs, CandidateSet,
SuppressUserConversions);
}
}
// Perform overload resolution and return the result.
return CandidateSet.BestViableFunction(S, DeclLoc, Best);
}
/// \brief Attempt initialization by constructor (C++ [dcl.init]), which
/// enumerates the constructors of the initialized entity and performs overload
/// resolution to select the best.
@ -2784,20 +2835,10 @@ static void TryConstructorInitialization(Sema &S,
for (unsigned i = 0; i < NumArgs; ++i)
S.CheckSelfReference(DD, Args[i]);
// Build the candidate set directly in the initialization sequence
// structure, so that it will persist if we fail.
OverloadCandidateSet &CandidateSet = Sequence.getFailedCandidateSet();
CandidateSet.clear();
// Determine whether we are allowed to call explicit constructors or
// explicit conversion operators.
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_Incomplete);
return;
}
const RecordType *DestRecordType = DestType->getAs<RecordType>();
@ -2810,6 +2851,16 @@ static void TryConstructorInitialization(Sema &S,
DestRecordDecl, DestType, Sequence))
return;
// Build the candidate set directly in the initialization sequence
// structure, so that it will persist if we fail.
OverloadCandidateSet &CandidateSet = Sequence.getFailedCandidateSet();
// Determine whether we are allowed to call explicit constructors or
// explicit conversion operators.
bool AllowExplicit = (Kind.getKind() == InitializationKind::IK_Direct ||
Kind.getKind() == InitializationKind::IK_Value ||
Kind.getKind() == InitializationKind::IK_Default);
if (InitListSyntax) {
// Time to unwrap the init list.
InitListExpr *ILE = cast<InitListExpr>(Args[0]);
@ -2820,50 +2871,16 @@ static void TryConstructorInitialization(Sema &S,
// - Otherwise, if T is a class type, constructors are considered. The
// applicable constructors are enumerated, and the best one is chosen
// through overload resolution.
DeclContext::lookup_iterator Con, ConEnd;
for (llvm::tie(Con, ConEnd) = S.LookupConstructors(DestRecordDecl);
Con != ConEnd; ++Con) {
NamedDecl *D = *Con;
DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess());
bool SuppressUserConversions = false;
DeclContext::lookup_iterator ConStart, ConEnd;
llvm::tie(ConStart, ConEnd) = S.LookupConstructors(DestRecordDecl);
// 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);
// 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() &&
(AllowExplicit || !Constructor->isExplicit())) {
if (ConstructorTmpl)
S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl,
/*ExplicitArgs*/ 0,
Args, NumArgs, CandidateSet,
SuppressUserConversions);
else
S.AddOverloadCandidate(Constructor, FoundDecl,
Args, NumArgs, CandidateSet,
SuppressUserConversions);
}
}
SourceLocation DeclLoc = Kind.getLocation();
// Perform overload resolution. If it fails, return the failed result.
OverloadCandidateSet::iterator Best;
if (OverloadingResult Result
= CandidateSet.BestViableFunction(S, DeclLoc, Best)) {
if (OverloadingResult Result =
ResolveConstructorOverload(S, Kind.getLocation(), Args, NumArgs,
CandidateSet, ConStart, ConEnd, Best,
Kind.getKind() == InitializationKind::IK_Copy,
AllowExplicit,
/*OnlyListConstructors=*/false)) {
Sequence.SetOverloadFailure(InitListSyntax ?
InitializationSequence::FK_ListConstructorOverloadFailed :
InitializationSequence::FK_ConstructorOverloadFailed,