Ambiguous.construct();
}
- void setAsIdentityConversion(QualType T) {
- setStandard();
- Standard.setAsIdentityConversion();
- Standard.setFromType(T);
- Standard.setAllToTypes(T);
- }
-
/// \brief Whether the target is really a std::initializer_list, and the
/// sequence only represents the worst element conversion.
bool isStdInitializerListElement() const {
ovl_fail_ext_disabled,
};
- /// A list of implicit conversion sequences for the arguments of an
- /// OverloadCandidate.
- typedef llvm::MutableArrayRef<ImplicitConversionSequence>
- ConversionSequenceList;
-
/// OverloadCandidate - A single candidate in an overload set (C++ 13.3).
struct OverloadCandidate {
/// Function - The actual function that this candidate
/// is a surrogate, but only if IsSurrogate is true.
CXXConversionDecl *Surrogate;
- /// The conversion sequences used to convert the function arguments
- /// to the function parameters.
- ConversionSequenceList Conversions;
+ /// Conversions - The conversion sequences used to convert the
+ /// function arguments to the function parameters, the pointer points to a
+ /// fixed size array with NumConversions elements. The memory is owned by
+ /// the OverloadCandidateSet.
+ ImplicitConversionSequence *Conversions;
/// The FixIt hints which can be used to fix the Bad candidate.
ConversionFixItGenerator Fix;
+ /// NumConversions - The number of elements in the Conversions array.
+ unsigned NumConversions;
+
/// Viable - True to indicate that this overload candidate is viable.
bool Viable;
/// hasAmbiguousConversion - Returns whether this overload
/// candidate requires an ambiguous conversion or not.
bool hasAmbiguousConversion() const {
- for (auto &C : Conversions) {
- if (!C.isInitialized()) return false;
- if (C.isAmbiguous()) return true;
+ for (unsigned i = 0, e = NumConversions; i != e; ++i) {
+ if (!Conversions[i].isInitialized()) return false;
+ if (Conversions[i].isAmbiguous()) return true;
}
return false;
}
SmallVector<OverloadCandidate, 16> Candidates;
llvm::SmallPtrSet<Decl *, 16> Functions;
- // Allocator for ConversionSequenceLists. We store the first few
+ // Allocator for OverloadCandidate::Conversions. We store the first few
// elements inline to avoid allocation for small sets.
llvm::BumpPtrAllocator ConversionSequenceAllocator;
size_t size() const { return Candidates.size(); }
bool empty() const { return Candidates.empty(); }
- /// \brief Allocate storage for conversion sequences for NumConversions
- /// conversions.
- ConversionSequenceList
- allocateConversionSequences(unsigned NumConversions) {
- ImplicitConversionSequence *Conversions;
+ /// \brief Add a new candidate with NumConversions conversion sequence slots
+ /// to the overload set.
+ OverloadCandidate &addCandidate(unsigned NumConversions = 0) {
+ Candidates.push_back(OverloadCandidate());
+ OverloadCandidate &C = Candidates.back();
// Assign space from the inline array if there are enough free slots
// available.
if (NumConversions + NumInlineSequences <= 16) {
ImplicitConversionSequence *I =
(ImplicitConversionSequence *)InlineSpace.buffer;
- Conversions = &I[NumInlineSequences];
+ C.Conversions = &I[NumInlineSequences];
NumInlineSequences += NumConversions;
} else {
// Otherwise get memory from the allocator.
- Conversions =
- ConversionSequenceAllocator.Allocate<ImplicitConversionSequence>(
- NumConversions);
+ C.Conversions = ConversionSequenceAllocator
+ .Allocate<ImplicitConversionSequence>(NumConversions);
}
// Construct the new objects.
- for (unsigned I = 0; I != NumConversions; ++I)
- new (&Conversions[I]) ImplicitConversionSequence();
-
- return ConversionSequenceList(Conversions, NumConversions);
- }
-
- /// \brief Add a new candidate with NumConversions conversion sequence slots
- /// to the overload set.
- OverloadCandidate &addCandidate(unsigned NumConversions = 0,
- ConversionSequenceList Conversions = None) {
- assert((Conversions.empty() || Conversions.size() == NumConversions) &&
- "preallocated conversion sequence has wrong length");
+ for (unsigned i = 0; i != NumConversions; ++i)
+ new (&C.Conversions[i]) ImplicitConversionSequence();
- Candidates.push_back(OverloadCandidate());
- OverloadCandidate &C = Candidates.back();
- C.Conversions = Conversions.empty()
- ? allocateConversionSequences(NumConversions)
- : Conversions;
+ C.NumConversions = NumConversions;
return C;
}
class FunctionProtoType;
class FunctionTemplateDecl;
class ImplicitConversionSequence;
- typedef MutableArrayRef<ImplicitConversionSequence> ConversionSequenceList;
class InitListExpr;
class InitializationKind;
class InitializationSequence;
void AddOverloadCandidate(FunctionDecl *Function,
DeclAccessPair FoundDecl,
ArrayRef<Expr *> Args,
- OverloadCandidateSet &CandidateSet,
+ OverloadCandidateSet& CandidateSet,
bool SuppressUserConversions = false,
bool PartialOverloading = false,
- bool AllowExplicit = false,
- ConversionSequenceList EarlyConversions = None);
+ bool AllowExplicit = false);
void AddFunctionCandidates(const UnresolvedSetImpl &Functions,
ArrayRef<Expr *> Args,
OverloadCandidateSet &CandidateSet,
ArrayRef<Expr *> Args,
OverloadCandidateSet& CandidateSet,
bool SuppressUserConversions = false,
- bool PartialOverloading = false,
- ConversionSequenceList EarlyConversions = None);
+ bool PartialOverloading = false);
void AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl,
DeclAccessPair FoundDecl,
CXXRecordDecl *ActingContext,
OverloadCandidateSet& CandidateSet,
bool SuppressUserConversions = false,
bool PartialOverloading = false);
- bool CheckNonDependentConversions(FunctionTemplateDecl *FunctionTemplate,
- ArrayRef<Expr *> Args,
- OverloadCandidateSet &CandidateSet,
- ConversionSequenceList &Conversions,
- bool SuppressUserConversions,
- CXXRecordDecl *ActingContext = nullptr,
- QualType ObjectType = QualType(),
- Expr::Classification
- ObjectClassification = {});
void AddConversionCandidate(CXXConversionDecl *Conversion,
DeclAccessPair FoundDecl,
CXXRecordDecl *ActingContext,
/// \brief The arguments included an overloaded function name that could
/// not be resolved to a suitable function.
TDK_FailedOverloadResolution,
- /// \brief Checking non-dependent argument conversions failed.
- TDK_NonDependentConversionFailure,
/// \brief Deduction failed; that's all we know.
TDK_MiscellaneousDeductionFailure,
/// \brief CUDA Target attributes do not match.
QualType OriginalArgType;
};
- TemplateDeductionResult FinishTemplateArgumentDeduction(
- FunctionTemplateDecl *FunctionTemplate,
- SmallVectorImpl<DeducedTemplateArgument> &Deduced,
- unsigned NumExplicitlySpecified, FunctionDecl *&Specialization,
- sema::TemplateDeductionInfo &Info,
- SmallVectorImpl<OriginalCallArg> const *OriginalCallArgs = nullptr,
- bool PartialOverloading = false,
- llvm::function_ref<bool()> CheckNonDependent = []{ return false; });
+ TemplateDeductionResult
+ FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
+ SmallVectorImpl<DeducedTemplateArgument> &Deduced,
+ unsigned NumExplicitlySpecified,
+ FunctionDecl *&Specialization,
+ sema::TemplateDeductionInfo &Info,
+ SmallVectorImpl<OriginalCallArg> const *OriginalCallArgs = nullptr,
+ bool PartialOverloading = false);
TemplateDeductionResult
DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
ArrayRef<Expr *> Args,
FunctionDecl *&Specialization,
sema::TemplateDeductionInfo &Info,
- bool PartialOverloading,
- llvm::function_ref<bool()> CheckNonDependent);
+ bool PartialOverloading = false);
TemplateDeductionResult
DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
Result.Result = static_cast<unsigned>(TDK);
Result.HasDiagnostic = false;
switch (TDK) {
+ case Sema::TDK_Success:
case Sema::TDK_Invalid:
case Sema::TDK_InstantiationDepth:
case Sema::TDK_TooManyArguments:
case Sema::TDK_FailedOverloadResolution:
Result.Data = Info.Expression;
break;
-
- case Sema::TDK_Success:
- case Sema::TDK_NonDependentConversionFailure:
- llvm_unreachable("not a deduction failure");
}
return Result;
case Sema::TDK_InvalidExplicitArguments:
case Sema::TDK_FailedOverloadResolution:
case Sema::TDK_CUDATargetMismatch:
- case Sema::TDK_NonDependentConversionFailure:
break;
case Sema::TDK_Inconsistent:
case Sema::TDK_NonDeducedMismatch:
case Sema::TDK_FailedOverloadResolution:
case Sema::TDK_CUDATargetMismatch:
- case Sema::TDK_NonDependentConversionFailure:
return TemplateParameter();
case Sema::TDK_Incomplete:
case Sema::TDK_NonDeducedMismatch:
case Sema::TDK_FailedOverloadResolution:
case Sema::TDK_CUDATargetMismatch:
- case Sema::TDK_NonDependentConversionFailure:
return nullptr;
case Sema::TDK_DeducedMismatch:
case Sema::TDK_SubstitutionFailure:
case Sema::TDK_FailedOverloadResolution:
case Sema::TDK_CUDATargetMismatch:
- case Sema::TDK_NonDependentConversionFailure:
return nullptr;
case Sema::TDK_Inconsistent:
case Sema::TDK_SubstitutionFailure:
case Sema::TDK_FailedOverloadResolution:
case Sema::TDK_CUDATargetMismatch:
- case Sema::TDK_NonDependentConversionFailure:
return nullptr;
case Sema::TDK_Inconsistent:
void OverloadCandidateSet::destroyCandidates() {
for (iterator i = begin(), e = end(); i != e; ++i) {
- for (auto &C : i->Conversions)
- C.~ImplicitConversionSequence();
+ for (unsigned ii = 0, ie = i->NumConversions; ii != ie; ++ii)
+ i->Conversions[ii].~ImplicitConversionSequence();
if (!i->Viable && i->FailureKind == ovl_fail_bad_deduction)
i->DeductionFailure.Destroy();
}
OverloadCandidateSet &CandidateSet,
bool SuppressUserConversions,
bool PartialOverloading,
- bool AllowExplicit,
- ConversionSequenceList EarlyConversions) {
+ bool AllowExplicit) {
const FunctionProtoType *Proto
= dyn_cast<FunctionProtoType>(Function->getType()->getAs<FunctionType>());
assert(Proto && "Functions without a prototype cannot be overloaded");
AddMethodCandidate(Method, FoundDecl, Method->getParent(),
QualType(), Expr::Classification::makeSimpleLValue(),
Args, CandidateSet, SuppressUserConversions,
- PartialOverloading, EarlyConversions);
+ PartialOverloading);
return;
}
// We treat a constructor like a non-member function, since its object
EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated);
// Add this candidate
- OverloadCandidate &Candidate =
- CandidateSet.addCandidate(Args.size(), EarlyConversions);
+ OverloadCandidate &Candidate = CandidateSet.addCandidate(Args.size());
Candidate.FoundDecl = FoundDecl;
Candidate.Function = Function;
Candidate.Viable = true;
// Determine the implicit conversion sequences for each of the
// arguments.
for (unsigned ArgIdx = 0; ArgIdx < Args.size(); ++ArgIdx) {
- if (Candidate.Conversions[ArgIdx].isInitialized()) {
- // We already formed a conversion sequence for this parameter during
- // template argument deduction.
- } else if (ArgIdx < NumParams) {
+ if (ArgIdx < NumParams) {
// (C++ 13.3.2p3): for F to be a viable function, there shall
// exist for each argument an implicit conversion sequence
// (13.3.3.1) that converts that argument to the corresponding
ArrayRef<Expr *> Args,
OverloadCandidateSet &CandidateSet,
bool SuppressUserConversions,
- bool PartialOverloading,
- ConversionSequenceList EarlyConversions) {
+ bool PartialOverloading) {
const FunctionProtoType *Proto
= dyn_cast<FunctionProtoType>(Method->getType()->getAs<FunctionType>());
assert(Proto && "Methods without a prototype cannot be overloaded");
EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated);
// Add this candidate
- OverloadCandidate &Candidate =
- CandidateSet.addCandidate(Args.size() + 1, EarlyConversions);
+ OverloadCandidate &Candidate = CandidateSet.addCandidate(Args.size() + 1);
Candidate.FoundDecl = FoundDecl;
Candidate.Function = Method;
Candidate.IsSurrogate = false;
// Determine the implicit conversion sequences for each of the
// arguments.
for (unsigned ArgIdx = 0; ArgIdx < Args.size(); ++ArgIdx) {
- if (Candidate.Conversions[ArgIdx + 1].isInitialized()) {
- // We already formed a conversion sequence for this parameter during
- // template argument deduction.
- } else if (ArgIdx < NumParams) {
+ if (ArgIdx < NumParams) {
// (C++ 13.3.2p3): for F to be a viable function, there shall
// exist for each argument an implicit conversion sequence
// (13.3.3.1) that converts that argument to the corresponding
// functions.
TemplateDeductionInfo Info(CandidateSet.getLocation());
FunctionDecl *Specialization = nullptr;
- ConversionSequenceList Conversions;
- if (TemplateDeductionResult Result = DeduceTemplateArguments(
- MethodTmpl, ExplicitTemplateArgs, Args, Specialization, Info,
- PartialOverloading, [&]() {
- return CheckNonDependentConversions(
- MethodTmpl, Args, CandidateSet, Conversions,
- SuppressUserConversions, ActingContext, ObjectType,
- ObjectClassification);
- })) {
- OverloadCandidate &Candidate =
- CandidateSet.addCandidate(Conversions.size(), Conversions);
+ if (TemplateDeductionResult Result
+ = DeduceTemplateArguments(MethodTmpl, ExplicitTemplateArgs, Args,
+ Specialization, Info, PartialOverloading)) {
+ OverloadCandidate &Candidate = CandidateSet.addCandidate();
Candidate.FoundDecl = FoundDecl;
Candidate.Function = MethodTmpl->getTemplatedDecl();
Candidate.Viable = false;
+ Candidate.FailureKind = ovl_fail_bad_deduction;
Candidate.IsSurrogate = false;
Candidate.IgnoreObjectArgument = false;
Candidate.ExplicitCallArguments = Args.size();
- if (Result == TDK_NonDependentConversionFailure)
- Candidate.FailureKind = ovl_fail_bad_conversion;
- else {
- Candidate.FailureKind = ovl_fail_bad_deduction;
- Candidate.DeductionFailure = MakeDeductionFailureInfo(Context, Result,
- Info);
- }
+ Candidate.DeductionFailure = MakeDeductionFailureInfo(Context, Result,
+ Info);
return;
}
"Specialization is not a member function?");
AddMethodCandidate(cast<CXXMethodDecl>(Specialization), FoundDecl,
ActingContext, ObjectType, ObjectClassification, Args,
- CandidateSet, SuppressUserConversions, PartialOverloading,
- Conversions);
+ CandidateSet, SuppressUserConversions, PartialOverloading);
}
/// \brief Add a C++ function template specialization as a candidate
// functions.
TemplateDeductionInfo Info(CandidateSet.getLocation());
FunctionDecl *Specialization = nullptr;
- ConversionSequenceList Conversions;
- if (TemplateDeductionResult Result = DeduceTemplateArguments(
- FunctionTemplate, ExplicitTemplateArgs, Args, Specialization, Info,
- PartialOverloading, [&]() {
- return CheckNonDependentConversions(FunctionTemplate, Args,
- CandidateSet, Conversions,
- SuppressUserConversions);
- })) {
- OverloadCandidate &Candidate =
- CandidateSet.addCandidate(Conversions.size(), Conversions);
+ if (TemplateDeductionResult Result
+ = DeduceTemplateArguments(FunctionTemplate, ExplicitTemplateArgs, Args,
+ Specialization, Info, PartialOverloading)) {
+ OverloadCandidate &Candidate = CandidateSet.addCandidate();
Candidate.FoundDecl = FoundDecl;
Candidate.Function = FunctionTemplate->getTemplatedDecl();
Candidate.Viable = false;
+ Candidate.FailureKind = ovl_fail_bad_deduction;
Candidate.IsSurrogate = false;
Candidate.IgnoreObjectArgument = false;
Candidate.ExplicitCallArguments = Args.size();
- if (Result == TDK_NonDependentConversionFailure)
- Candidate.FailureKind = ovl_fail_bad_conversion;
- else {
- Candidate.FailureKind = ovl_fail_bad_deduction;
- Candidate.DeductionFailure = MakeDeductionFailureInfo(Context, Result,
- Info);
- }
+ Candidate.DeductionFailure = MakeDeductionFailureInfo(Context, Result,
+ Info);
return;
}
// deduction as a candidate.
assert(Specialization && "Missing function template specialization?");
AddOverloadCandidate(Specialization, FoundDecl, Args, CandidateSet,
- SuppressUserConversions, PartialOverloading,
- /*AllowExplicit*/false, Conversions);
-}
-
-/// Check that implicit conversion sequences can be formed for each argument
-/// whose corresponding parameter has a non-dependent type, per DR1391's
-/// [temp.deduct.call]p10.
-bool Sema::CheckNonDependentConversions(
- FunctionTemplateDecl *FunctionTemplate, ArrayRef<Expr *> Args,
- OverloadCandidateSet &CandidateSet, ConversionSequenceList &Conversions,
- bool SuppressUserConversions, CXXRecordDecl *ActingContext,
- QualType ObjectType, Expr::Classification ObjectClassification) {
- // FIXME: The cases in which we allow explicit conversions for constructor
- // arguments never consider calling a constructor template. It's not clear
- // that is correct.
- const bool AllowExplicit = false;
-
- auto *FD = FunctionTemplate->getTemplatedDecl();
- auto *Method = dyn_cast<CXXMethodDecl>(FD);
- bool HasThisConversion = Method && !isa<CXXConstructorDecl>(Method);
- unsigned ThisConversions = HasThisConversion ? 1 : 0;
-
- Conversions =
- CandidateSet.allocateConversionSequences(ThisConversions + Args.size());
-
- // Overload resolution is always an unevaluated context.
- EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated);
-
- // For a method call, check the 'this' conversion here too. DR1391 doesn't
- // require that, but this check should never result in a hard error, and
- // overload resolution is permitted to sidestep instantiations.
- if (HasThisConversion && !cast<CXXMethodDecl>(FD)->isStatic() &&
- !ObjectType.isNull()) {
- Conversions[0] = TryObjectArgumentInitialization(
- *this, CandidateSet.getLocation(), ObjectType, ObjectClassification,
- Method, ActingContext);
- if (Conversions[0].isBad())
- return true;
- }
-
-
- for (unsigned I = 0, N = std::min<unsigned>(FD->getNumParams(), Args.size());
- I != N; ++I) {
- QualType ParamType = FD->getParamDecl(I)->getType();
- if (!ParamType->isDependentType()) {
- Conversions[ThisConversions + I]
- = TryCopyInitialization(*this, Args[I], ParamType,
- SuppressUserConversions,
- /*InOverloadResolution=*/true,
- /*AllowObjCWritebackConversion=*/
- getLangOpts().ObjCAutoRefCount,
- AllowExplicit);
- if (Conversions[ThisConversions + I].isBad())
- return true;
- }
- }
-
- return false;
+ SuppressUserConversions, PartialOverloading);
}
/// Determine whether this is an allowable conversion from the result
// Define functions that don't require ill-formed conversions for a given
// argument to be better candidates than functions that do.
- unsigned NumArgs = Cand1.Conversions.size();
- assert(Cand2.Conversions.size() == NumArgs && "Overload candidate mismatch");
+ unsigned NumArgs = Cand1.NumConversions;
+ assert(Cand2.NumConversions == NumArgs && "Overload candidate mismatch");
bool HasBetterConversion = false;
for (unsigned ArgIdx = StartArg; ArgIdx < NumArgs; ++ArgIdx) {
bool Cand1Bad = IsIllFormedConversion(Cand1.Conversions[ArgIdx]);
case ovl_fail_bad_conversion: {
unsigned I = (Cand->IgnoreObjectArgument ? 1 : 0);
- for (unsigned N = Cand->Conversions.size(); I != N; ++I)
+ for (unsigned N = Cand->NumConversions; I != N; ++I)
if (Cand->Conversions[I].isBad())
return DiagnoseBadConversion(S, Cand, I, TakingCandidateAddress);
static void NoteBuiltinOperatorCandidate(Sema &S, StringRef Opc,
SourceLocation OpLoc,
OverloadCandidate *Cand) {
- assert(Cand->Conversions.size() <= 2 && "builtin operator is not binary");
+ assert(Cand->NumConversions <= 2 && "builtin operator is not binary");
std::string TypeStr("operator");
TypeStr += Opc;
TypeStr += "(";
TypeStr += Cand->BuiltinTypes.ParamTypes[0].getAsString();
- if (Cand->Conversions.size() == 1) {
+ if (Cand->NumConversions == 1) {
TypeStr += ")";
S.Diag(OpLoc, diag::note_ovl_builtin_unary_candidate) << TypeStr;
} else {
static void NoteAmbiguousUserConversions(Sema &S, SourceLocation OpLoc,
OverloadCandidate *Cand) {
- for (const ImplicitConversionSequence &ICS : Cand->Conversions) {
+ unsigned NoOperands = Cand->NumConversions;
+ for (unsigned ArgIdx = 0; ArgIdx < NoOperands; ++ArgIdx) {
+ const ImplicitConversionSequence &ICS = Cand->Conversions[ArgIdx];
if (ICS.isBad()) break; // all meaningless after first invalid
if (!ICS.isAmbiguous()) continue;
static unsigned RankDeductionFailure(const DeductionFailureInfo &DFI) {
switch ((Sema::TemplateDeductionResult)DFI.Result) {
case Sema::TDK_Success:
- case Sema::TDK_NonDependentConversionFailure:
- llvm_unreachable("non-deduction failure while diagnosing bad deduction");
+ llvm_unreachable("TDK_success while diagnosing bad deduction");
case Sema::TDK_Invalid:
case Sema::TDK_Incomplete:
// If there's any ordering between the defined conversions...
// FIXME: this might not be transitive.
- assert(L->Conversions.size() == R->Conversions.size());
+ assert(L->NumConversions == R->NumConversions);
int leftBetter = 0;
unsigned I = (L->IgnoreObjectArgument || R->IgnoreObjectArgument);
- for (unsigned E = L->Conversions.size(); I != E; ++I) {
+ for (unsigned E = L->NumConversions; I != E; ++I) {
switch (CompareImplicitConversionSequences(S, Loc,
L->Conversions[I],
R->Conversions[I])) {
}
/// CompleteNonViableCandidate - Normally, overload resolution only
-/// computes up to the first bad conversion. Produces the FixIt set if
-/// possible.
+/// computes up to the first. Produces the FixIt set if possible.
static void CompleteNonViableCandidate(Sema &S, OverloadCandidate *Cand,
ArrayRef<Expr *> Args) {
assert(!Cand->Viable);
// Use a implicit copy initialization to check conversion fixes.
Cand->Fix.setConversionChecker(TryCopyInitialization);
- // Attempt to fix the bad conversion.
- unsigned ConvCount = Cand->Conversions.size();
- for (unsigned ConvIdx = (Cand->IgnoreObjectArgument ? 1 : 0); /**/;
- ++ConvIdx) {
+ // Skip forward to the first bad conversion.
+ unsigned ConvIdx = (Cand->IgnoreObjectArgument ? 1 : 0);
+ unsigned ConvCount = Cand->NumConversions;
+ while (true) {
assert(ConvIdx != ConvCount && "no bad conversion in candidate");
- if (Cand->Conversions[ConvIdx].isInitialized() &&
- Cand->Conversions[ConvIdx].isBad()) {
- Unfixable = !Cand->TryToFixBadConversion(ConvIdx, S);
+ ConvIdx++;
+ if (Cand->Conversions[ConvIdx - 1].isBad()) {
+ Unfixable = !Cand->TryToFixBadConversion(ConvIdx - 1, S);
break;
}
}
+ if (ConvIdx == ConvCount)
+ return;
+
+ assert(!Cand->Conversions[ConvIdx].isInitialized() &&
+ "remaining conversion is initialized?");
+
// FIXME: this should probably be preserved from the overload
// operation somehow.
bool SuppressUserConversions = false;
- const FunctionProtoType *Proto;
- unsigned ArgIdx = 0;
+ const FunctionProtoType* Proto;
+ unsigned ArgIdx = ConvIdx;
if (Cand->IsSurrogate) {
QualType ConvType
if (const PointerType *ConvPtrType = ConvType->getAs<PointerType>())
ConvType = ConvPtrType->getPointeeType();
Proto = ConvType->getAs<FunctionProtoType>();
- ArgIdx = 1;
+ ArgIdx--;
} else if (Cand->Function) {
Proto = Cand->Function->getType()->getAs<FunctionProtoType>();
if (isa<CXXMethodDecl>(Cand->Function) &&
!isa<CXXConstructorDecl>(Cand->Function))
- ArgIdx = 1;
+ ArgIdx--;
} else {
// Builtin binary operator with a bad first conversion.
assert(ConvCount <= 3);
- for (unsigned ConvIdx = (Cand->IgnoreObjectArgument ? 1 : 0);
- ConvIdx != ConvCount; ++ConvIdx) {
- if (Cand->Conversions[ConvIdx].isInitialized())
- continue;
- if (Cand->BuiltinTypes.ParamTypes[ConvIdx]->isDependentType())
- Cand->Conversions[ConvIdx].setAsIdentityConversion(
- Args[ConvIdx]->getType());
- else
- Cand->Conversions[ConvIdx] = TryCopyInitialization(
- S, Args[ConvIdx], Cand->BuiltinTypes.ParamTypes[ConvIdx],
- SuppressUserConversions,
- /*InOverloadResolution*/ true,
- /*AllowObjCWritebackConversion=*/
- S.getLangOpts().ObjCAutoRefCount);
- // FIXME: If the conversion is bad, try to fix it.
- }
+ for (; ConvIdx != ConvCount; ++ConvIdx)
+ Cand->Conversions[ConvIdx]
+ = TryCopyInitialization(S, Args[ConvIdx],
+ Cand->BuiltinTypes.ParamTypes[ConvIdx],
+ SuppressUserConversions,
+ /*InOverloadResolution*/ true,
+ /*AllowObjCWritebackConversion=*/
+ S.getLangOpts().ObjCAutoRefCount);
return;
}
// Fill in the rest of the conversions.
unsigned NumParams = Proto->getNumParams();
- for (unsigned ConvIdx = (Cand->IgnoreObjectArgument ? 1 : 0);
- ConvIdx != ConvCount; ++ConvIdx, ++ArgIdx) {
- if (Cand->Conversions[ConvIdx].isInitialized()) {
- // Found the bad conversion.
- } else if (ArgIdx < NumParams) {
- if (Proto->getParamType(ArgIdx)->isDependentType())
- Cand->Conversions[ConvIdx].setAsIdentityConversion(
- Args[ArgIdx]->getType());
- else {
- Cand->Conversions[ConvIdx] =
- TryCopyInitialization(S, Args[ArgIdx], Proto->getParamType(ArgIdx),
- SuppressUserConversions,
- /*InOverloadResolution=*/true,
- /*AllowObjCWritebackConversion=*/
- S.getLangOpts().ObjCAutoRefCount);
- // Store the FixIt in the candidate if it exists.
- if (!Unfixable && Cand->Conversions[ConvIdx].isBad())
- Unfixable = !Cand->TryToFixBadConversion(ConvIdx, S);
- }
- } else
+ for (; ConvIdx != ConvCount; ++ConvIdx, ++ArgIdx) {
+ if (ArgIdx < NumParams) {
+ Cand->Conversions[ConvIdx] = TryCopyInitialization(
+ S, Args[ArgIdx], Proto->getParamType(ArgIdx), SuppressUserConversions,
+ /*InOverloadResolution=*/true,
+ /*AllowObjCWritebackConversion=*/
+ S.getLangOpts().ObjCAutoRefCount);
+ // Store the FixIt in the candidate if it exists.
+ if (!Unfixable && Cand->Conversions[ConvIdx].isBad())
+ Unfixable = !Cand->TryToFixBadConversion(ConvIdx, S);
+ }
+ else
Cand->Conversions[ConvIdx].setEllipsis();
}
}