Revert "DR1391: Check for implicit conversion sequences for non-dependent function template parameters between deduction and substitution. The idea is to accept as many cases as possible, on the basis that substitution failure outside the immediate context is much more common during substitution than during implicit conversion sequence formation."

This reverts commit r290808, as it broken all ARM and AArch64 test-suite
test: MultiSource/UnitTests/C++11/frame_layout

Also, please, next time, try to write a commit message in according to
our guidelines:

http://llvm.org/docs/DeveloperPolicy.html#commit-messages

llvm-svn: 290811
This commit is contained in:
Renato Golin 2017-01-02 11:15:42 +00:00
parent 21706cbd24
commit dad96d6751
9 changed files with 124 additions and 362 deletions

View File

@ -531,13 +531,6 @@ namespace clang {
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 {
@ -610,11 +603,6 @@ namespace clang {
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
@ -639,13 +627,18 @@ namespace clang {
/// 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;
@ -684,9 +677,9 @@ namespace clang {
/// 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;
}
@ -735,7 +728,7 @@ namespace clang {
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;
@ -776,45 +769,30 @@ namespace clang {
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();
for (unsigned i = 0; i != NumConversions; ++i)
new (&C.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");
Candidates.push_back(OverloadCandidate());
OverloadCandidate &C = Candidates.back();
C.Conversions = Conversions.empty()
? allocateConversionSequences(NumConversions)
: Conversions;
C.NumConversions = NumConversions;
return C;
}

View File

@ -119,7 +119,6 @@ namespace clang {
class FunctionProtoType;
class FunctionTemplateDecl;
class ImplicitConversionSequence;
typedef MutableArrayRef<ImplicitConversionSequence> ConversionSequenceList;
class InitListExpr;
class InitializationKind;
class InitializationSequence;
@ -2511,11 +2510,10 @@ public:
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,
@ -2535,8 +2533,7 @@ public:
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,
@ -2554,15 +2551,6 @@ public:
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,
@ -6591,8 +6579,6 @@ public:
/// \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.
@ -6630,14 +6616,14 @@ public:
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,
@ -6645,8 +6631,7 @@ public:
ArrayRef<Expr *> Args,
FunctionDecl *&Specialization,
sema::TemplateDeductionInfo &Info,
bool PartialOverloading,
llvm::function_ref<bool()> CheckNonDependent);
bool PartialOverloading = false);
TemplateDeductionResult
DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,

View File

@ -589,6 +589,7 @@ clang::MakeDeductionFailureInfo(ASTContext &Context,
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:
@ -647,10 +648,6 @@ clang::MakeDeductionFailureInfo(ASTContext &Context,
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;
@ -667,7 +664,6 @@ void DeductionFailureInfo::Destroy() {
case Sema::TDK_InvalidExplicitArguments:
case Sema::TDK_FailedOverloadResolution:
case Sema::TDK_CUDATargetMismatch:
case Sema::TDK_NonDependentConversionFailure:
break;
case Sema::TDK_Inconsistent:
@ -711,7 +707,6 @@ TemplateParameter DeductionFailureInfo::getTemplateParameter() {
case Sema::TDK_NonDeducedMismatch:
case Sema::TDK_FailedOverloadResolution:
case Sema::TDK_CUDATargetMismatch:
case Sema::TDK_NonDependentConversionFailure:
return TemplateParameter();
case Sema::TDK_Incomplete:
@ -744,7 +739,6 @@ TemplateArgumentList *DeductionFailureInfo::getTemplateArgumentList() {
case Sema::TDK_NonDeducedMismatch:
case Sema::TDK_FailedOverloadResolution:
case Sema::TDK_CUDATargetMismatch:
case Sema::TDK_NonDependentConversionFailure:
return nullptr;
case Sema::TDK_DeducedMismatch:
@ -773,7 +767,6 @@ const TemplateArgument *DeductionFailureInfo::getFirstArg() {
case Sema::TDK_SubstitutionFailure:
case Sema::TDK_FailedOverloadResolution:
case Sema::TDK_CUDATargetMismatch:
case Sema::TDK_NonDependentConversionFailure:
return nullptr;
case Sema::TDK_Inconsistent:
@ -802,7 +795,6 @@ const TemplateArgument *DeductionFailureInfo::getSecondArg() {
case Sema::TDK_SubstitutionFailure:
case Sema::TDK_FailedOverloadResolution:
case Sema::TDK_CUDATargetMismatch:
case Sema::TDK_NonDependentConversionFailure:
return nullptr;
case Sema::TDK_Inconsistent:
@ -837,8 +829,8 @@ llvm::Optional<unsigned> DeductionFailureInfo::getCallArgIndex() {
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();
}
@ -5845,8 +5837,7 @@ Sema::AddOverloadCandidate(FunctionDecl *Function,
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");
@ -5865,7 +5856,7 @@ Sema::AddOverloadCandidate(FunctionDecl *Function,
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
@ -5898,8 +5889,7 @@ Sema::AddOverloadCandidate(FunctionDecl *Function,
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;
@ -5963,10 +5953,7 @@ Sema::AddOverloadCandidate(FunctionDecl *Function,
// 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
@ -6275,8 +6262,7 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl,
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");
@ -6297,8 +6283,7 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl,
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;
@ -6360,10 +6345,7 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl,
// 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
@ -6424,30 +6406,19 @@ Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl,
// 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;
}
@ -6458,8 +6429,7 @@ Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl,
"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
@ -6487,29 +6457,19 @@ Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate,
// 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;
}
@ -6517,64 +6477,7 @@ Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate,
// 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
@ -8813,8 +8716,8 @@ bool clang::isBetterOverloadCandidate(Sema &S, const OverloadCandidate &Cand1,
// 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]);
@ -10021,7 +9924,7 @@ static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand,
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);
@ -10084,12 +9987,12 @@ static void NoteSurrogateCandidate(Sema &S, OverloadCandidate *Cand) {
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 {
@ -10102,7 +10005,9 @@ static void NoteBuiltinOperatorCandidate(Sema &S, StringRef Opc,
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;
@ -10122,8 +10027,7 @@ static SourceLocation GetLocationForCandidate(const OverloadCandidate *Cand) {
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:
@ -10226,11 +10130,11 @@ struct CompareOverloadCandidatesForDisplay {
// 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])) {
@ -10279,8 +10183,7 @@ struct CompareOverloadCandidatesForDisplay {
}
/// 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);
@ -10293,24 +10196,30 @@ static void CompleteNonViableCandidate(Sema &S, OverloadCandidate *Cand,
// 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
@ -10318,56 +10227,40 @@ static void CompleteNonViableCandidate(Sema &S, OverloadCandidate *Cand,
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();
}
}

View File

@ -2849,13 +2849,14 @@ CheckOriginalCallArgDeduction(Sema &S, Sema::OriginalCallArg OriginalArg,
///
/// \param OriginalCallArgs If non-NULL, the original call arguments against
/// which the deduced argument types should be compared.
Sema::TemplateDeductionResult Sema::FinishTemplateArgumentDeduction(
FunctionTemplateDecl *FunctionTemplate,
SmallVectorImpl<DeducedTemplateArgument> &Deduced,
unsigned NumExplicitlySpecified, FunctionDecl *&Specialization,
TemplateDeductionInfo &Info,
SmallVectorImpl<OriginalCallArg> const *OriginalCallArgs,
bool PartialOverloading, llvm::function_ref<bool()> CheckNonDependent) {
Sema::TemplateDeductionResult
Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
SmallVectorImpl<DeducedTemplateArgument> &Deduced,
unsigned NumExplicitlySpecified,
FunctionDecl *&Specialization,
TemplateDeductionInfo &Info,
SmallVectorImpl<OriginalCallArg> const *OriginalCallArgs,
bool PartialOverloading) {
// Unevaluated SFINAE context.
EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated);
SFINAETrap Trap(*this);
@ -2882,18 +2883,6 @@ Sema::TemplateDeductionResult Sema::FinishTemplateArgumentDeduction(
PartialOverloading))
return Result;
// C++ [temp.deduct.call]p10: [DR1391]
// If deduction succeeds for all parameters that contain
// template-parameters that participate in template argument deduction,
// and all template arguments are explicitly specified, deduced, or
// obtained from default template arguments, remaining parameters are then
// compared with the corresponding arguments. For each remaining parameter
// P with a type that was non-dependent before substitution of any
// explicitly-specified template arguments, if the corresponding argument
// A cannot be implicitly converted to P, deduction fails.
if (CheckNonDependent())
return TDK_NonDependentConversionFailure;
// Form the template argument list from the deduced template arguments.
TemplateArgumentList *DeducedArgumentList
= TemplateArgumentList::CreateCopy(Context, Builder);
@ -3318,17 +3307,12 @@ DeduceTemplateArgumentByListElement(Sema &S,
/// \param Info the argument will be updated to provide additional information
/// about template argument deduction.
///
/// \param CheckNonDependent A callback to invoke to check conversions for
/// non-dependent parameters, between deduction and substitution, per DR1391.
/// If this returns true, substitution will be skipped and we return
/// TDK_NonDependentConversionFailure.
///
/// \returns the result of template argument deduction.
Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
FunctionTemplateDecl *FunctionTemplate,
TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef<Expr *> Args,
FunctionDecl *&Specialization, TemplateDeductionInfo &Info,
bool PartialOverloading, llvm::function_ref<bool()> CheckNonDependent) {
bool PartialOverloading) {
if (FunctionTemplate->isInvalidDecl())
return TDK_Invalid;
@ -3512,7 +3496,7 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
return FinishTemplateArgumentDeduction(FunctionTemplate, Deduced,
NumExplicitlySpecified, Specialization,
Info, &OriginalCallArgs,
PartialOverloading, CheckNonDependent);
PartialOverloading);
}
QualType Sema::adjustCCAndNoReturn(QualType ArgFunctionType,

View File

@ -174,81 +174,3 @@ namespace dr1359 { // dr1359: 3.5
constexpr Y y = Y(); // expected-error {{no matching}}
#endif
}
namespace dr1391 { // dr1391: partial
struct A {}; struct B : A {};
template<typename T> struct C { C(int); typename T::error error; }; // expected-error 2{{'::'}}
template<typename T> struct D {};
// No deduction is performed for parameters with no deducible template-parameters, therefore types do not need to match.
template<typename T> void a(T, int T::*);
void test_a(int A::*p) { a(A(), p); } // ok, type of second parameter does not need to match
namespace dr_example_1 {
template<typename T, typename U> void f(C<T>);
template<typename T> void f(D<T>);
void g(D<int> d) {
f(d); // ok, first 'f' eliminated by deduction failure
f<int>(d); // ok, first 'f' eliminated because 'U' cannot be deduced
}
}
namespace dr_example_2 {
template<typename T> typename C<T>::error f(int, T);
template<typename T> T f(T, T);
void g(A a) {
f(a, a); // ok, no conversion from A to int for first parameter of first candidate
}
}
namespace std_example {
template<typename T> struct Z {
typedef typename T::x xx;
};
template<typename T> typename Z<T>::xx f(void *, T);
template<typename T> void f(int, T);
struct A {} a;
void g() { f(1, a); }
}
template<typename T> void b(C<int> ci, T *p);
void b(...);
void test_b() {
b(0, 0); // ok, deduction fails prior to forming a conversion sequence and instantiating C<int>
// FIXME: The "while substituting" note should point at the overload candidate.
b<int>(0, 0); // expected-note {{instantiation of}} expected-note {{while substituting}}
}
template<typename T> struct Id { typedef T type; };
template<typename T> void c(T, typename Id<C<T> >::type);
void test_c() {
// Implicit conversion sequences for dependent types are checked later.
c(0.0, 0); // expected-note {{instantiation of}}
}
namespace partial_ordering {
// FIXME: Second template should be considered more specialized because non-dependent parameter is ignored.
template<typename T> int a(T, short) = delete; // expected-error 0-1{{extension}} expected-note {{candidate}}
template<typename T> int a(T*, char); // expected-note {{candidate}}
int test_a = a((int*)0, 0); // FIXME: expected-error {{ambiguous}}
// FIXME: Second template should be considered more specialized:
// deducing #1 from #2 ignores the second P/A pair, so deduction succeeds,
// deducing #2 from #1 fails to deduce T, so deduction fails.
template<typename T> int b(T, int) = delete; // expected-error 0-1{{extension}} expected-note {{candidate}}
template<typename T, typename U> int b(T*, U); // expected-note {{candidate}}
int test_b = b((int*)0, 0); // FIXME: expected-error {{ambiguous}}
// Unintended consequences: because partial ordering does not consider
// explicit template arguments, and deduction from a non-dependent type
// vacuously succeeds, a non-dependent template is less specialized than
// anything else!
// According to DR1391, this is ambiguous!
template<typename T> int c(int);
template<typename T> int c(T);
int test_c1 = c(0); // ok
int test_c2 = c<int>(0); // FIXME: apparently ambiguous
}
}

View File

@ -1401,7 +1401,7 @@ void run() {
f(1, integral_constant<bool, true>{});
}
// CHECK-ELIDE-NOTREE: error: no matching function for call to 'f'
// CHECK-ELIDE-NOTREE: note: candidate function not viable: no known conversion from 'integral_constant<[...], true>' to 'integral_constant<[...], false>' for 2nd argument
// CHECK-ELIDE-NOTREE: note: candidate function [with T = int] not viable: no known conversion from 'integral_constant<[...], true>' to 'integral_constant<[...], false>' for 2nd argument
}
namespace ZeroArgs {

View File

@ -338,7 +338,7 @@ namespace PR5756 {
// Tests the exact text used to note the candidates
namespace test1 {
template <class T> void foo(T t, unsigned N); // expected-note {{candidate function not viable: no known conversion from 'const char [6]' to 'unsigned int' for 2nd argument}}
template <class T> void foo(T t, unsigned N); // expected-note {{candidate function [with T = int] not viable: no known conversion from 'const char [6]' to 'unsigned int' for 2nd argument}}
void foo(int n, char N); // expected-note {{candidate function not viable: no known conversion from 'const char [6]' to 'char' for 2nd argument}}
void foo(int n, const char *s, int t); // expected-note {{candidate function not viable: requires 3 arguments, but 2 were provided}}
void foo(int n, const char *s, int t, ...); // expected-note {{candidate function not viable: requires at least 3 arguments, but 2 were provided}}

View File

@ -70,7 +70,7 @@ void test_X2(X2 *x2p, const X2 *cx2p) {
// Tests the exact text used to note the candidates
namespace test1 {
class A {
template <class T> void foo(T t, unsigned N); // expected-note {{candidate function not viable: no known conversion from 'const char [6]' to 'unsigned int' for 2nd argument}}
template <class T> void foo(T t, unsigned N); // expected-note {{candidate function [with T = int] not viable: no known conversion from 'const char [6]' to 'unsigned int' for 2nd argument}}
void foo(int n, char N); // expected-note {{candidate function not viable: no known conversion from 'const char [6]' to 'char' for 2nd argument}}
void foo(int n, const char *s, int t); // expected-note {{candidate function not viable: requires 3 arguments, but 2 were provided}}
void foo(int n, const char *s, int t, ...); // expected-note {{candidate function not viable: requires at least 3 arguments, but 2 were provided}}

View File

@ -8161,7 +8161,7 @@ and <I>POD class</I></td>
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1391">1391</a></td>
<td>DRWP</td>
<td>Conversions to parameter types with non-deduced template arguments</td>
<td class="partial" align="center">Partial</td>
<td class="none" align="center">Unknown</td>
</tr>
<tr id="1392">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1392">1392</a></td>