forked from OSchip/llvm-project
Add missing "original call argument has same type as deduced parameter type"
check for deductions from elements of a braced-init-list. llvm-svn: 291190
This commit is contained in:
parent
1594e0629d
commit
c92d206ce4
|
@ -3377,8 +3377,10 @@ def note_addrof_ovl_candidate_disabled_by_enable_if_attr : Note<
|
||||||
"candidate function made ineligible by enable_if">;
|
"candidate function made ineligible by enable_if">;
|
||||||
def note_ovl_candidate_deduced_mismatch : Note<
|
def note_ovl_candidate_deduced_mismatch : Note<
|
||||||
"candidate template ignored: deduced type "
|
"candidate template ignored: deduced type "
|
||||||
"%diff{$ of %ordinal0 parameter does not match adjusted type $ of argument"
|
"%diff{$ of %select{|element of }4%ordinal0 parameter does not match "
|
||||||
"|of %ordinal0 parameter does not match adjusted type of argument}1,2%3">;
|
"adjusted type $ of %select{|element of }4argument"
|
||||||
|
"|of %select{|element of }4%ordinal0 parameter does not match "
|
||||||
|
"adjusted type of %select{|element of }4argument}1,2%3">;
|
||||||
def note_ovl_candidate_non_deduced_mismatch : Note<
|
def note_ovl_candidate_non_deduced_mismatch : Note<
|
||||||
"candidate template ignored: could not match %diff{$ against $|types}0,1">;
|
"candidate template ignored: could not match %diff{$ against $|types}0,1">;
|
||||||
// This note is needed because the above note would sometimes print two
|
// This note is needed because the above note would sometimes print two
|
||||||
|
|
|
@ -6564,6 +6564,10 @@ public:
|
||||||
/// \brief After substituting deduced template arguments, a dependent
|
/// \brief After substituting deduced template arguments, a dependent
|
||||||
/// parameter type did not match the corresponding argument.
|
/// parameter type did not match the corresponding argument.
|
||||||
TDK_DeducedMismatch,
|
TDK_DeducedMismatch,
|
||||||
|
/// \brief After substituting deduced template arguments, an element of
|
||||||
|
/// a dependent parameter type did not match the corresponding element
|
||||||
|
/// of the corresponding argument (when deducing from an initializer list).
|
||||||
|
TDK_DeducedMismatchNested,
|
||||||
/// \brief A non-depnedent component of the parameter did not match the
|
/// \brief A non-depnedent component of the parameter did not match the
|
||||||
/// corresponding component of the argument.
|
/// corresponding component of the argument.
|
||||||
TDK_NonDeducedMismatch,
|
TDK_NonDeducedMismatch,
|
||||||
|
@ -6602,13 +6606,14 @@ public:
|
||||||
/// brief A function argument from which we performed template argument
|
/// brief A function argument from which we performed template argument
|
||||||
// deduction for a call.
|
// deduction for a call.
|
||||||
struct OriginalCallArg {
|
struct OriginalCallArg {
|
||||||
OriginalCallArg(QualType OriginalParamType,
|
OriginalCallArg(QualType OriginalParamType, bool DecomposedParam,
|
||||||
unsigned ArgIdx,
|
unsigned ArgIdx, QualType OriginalArgType)
|
||||||
QualType OriginalArgType)
|
: OriginalParamType(OriginalParamType),
|
||||||
: OriginalParamType(OriginalParamType), ArgIdx(ArgIdx),
|
DecomposedParam(DecomposedParam), ArgIdx(ArgIdx),
|
||||||
OriginalArgType(OriginalArgType) { }
|
OriginalArgType(OriginalArgType) {}
|
||||||
|
|
||||||
QualType OriginalParamType;
|
QualType OriginalParamType;
|
||||||
|
bool DecomposedParam;
|
||||||
unsigned ArgIdx;
|
unsigned ArgIdx;
|
||||||
QualType OriginalArgType;
|
QualType OriginalArgType;
|
||||||
};
|
};
|
||||||
|
|
|
@ -604,7 +604,8 @@ clang::MakeDeductionFailureInfo(ASTContext &Context,
|
||||||
Result.Data = Info.Param.getOpaqueValue();
|
Result.Data = Info.Param.getOpaqueValue();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Sema::TDK_DeducedMismatch: {
|
case Sema::TDK_DeducedMismatch:
|
||||||
|
case Sema::TDK_DeducedMismatchNested: {
|
||||||
// FIXME: Should allocate from normal heap so that we can free this later.
|
// FIXME: Should allocate from normal heap so that we can free this later.
|
||||||
auto *Saved = new (Context) DFIDeducedMismatchArgs;
|
auto *Saved = new (Context) DFIDeducedMismatchArgs;
|
||||||
Saved->FirstArg = Info.FirstArg;
|
Saved->FirstArg = Info.FirstArg;
|
||||||
|
@ -664,6 +665,7 @@ void DeductionFailureInfo::Destroy() {
|
||||||
case Sema::TDK_Inconsistent:
|
case Sema::TDK_Inconsistent:
|
||||||
case Sema::TDK_Underqualified:
|
case Sema::TDK_Underqualified:
|
||||||
case Sema::TDK_DeducedMismatch:
|
case Sema::TDK_DeducedMismatch:
|
||||||
|
case Sema::TDK_DeducedMismatchNested:
|
||||||
case Sema::TDK_NonDeducedMismatch:
|
case Sema::TDK_NonDeducedMismatch:
|
||||||
// FIXME: Destroy the data?
|
// FIXME: Destroy the data?
|
||||||
Data = nullptr;
|
Data = nullptr;
|
||||||
|
@ -699,6 +701,7 @@ TemplateParameter DeductionFailureInfo::getTemplateParameter() {
|
||||||
case Sema::TDK_TooFewArguments:
|
case Sema::TDK_TooFewArguments:
|
||||||
case Sema::TDK_SubstitutionFailure:
|
case Sema::TDK_SubstitutionFailure:
|
||||||
case Sema::TDK_DeducedMismatch:
|
case Sema::TDK_DeducedMismatch:
|
||||||
|
case Sema::TDK_DeducedMismatchNested:
|
||||||
case Sema::TDK_NonDeducedMismatch:
|
case Sema::TDK_NonDeducedMismatch:
|
||||||
case Sema::TDK_CUDATargetMismatch:
|
case Sema::TDK_CUDATargetMismatch:
|
||||||
return TemplateParameter();
|
return TemplateParameter();
|
||||||
|
@ -735,6 +738,7 @@ TemplateArgumentList *DeductionFailureInfo::getTemplateArgumentList() {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
case Sema::TDK_DeducedMismatch:
|
case Sema::TDK_DeducedMismatch:
|
||||||
|
case Sema::TDK_DeducedMismatchNested:
|
||||||
return static_cast<DFIDeducedMismatchArgs*>(Data)->TemplateArgs;
|
return static_cast<DFIDeducedMismatchArgs*>(Data)->TemplateArgs;
|
||||||
|
|
||||||
case Sema::TDK_SubstitutionFailure:
|
case Sema::TDK_SubstitutionFailure:
|
||||||
|
@ -764,6 +768,7 @@ const TemplateArgument *DeductionFailureInfo::getFirstArg() {
|
||||||
case Sema::TDK_Inconsistent:
|
case Sema::TDK_Inconsistent:
|
||||||
case Sema::TDK_Underqualified:
|
case Sema::TDK_Underqualified:
|
||||||
case Sema::TDK_DeducedMismatch:
|
case Sema::TDK_DeducedMismatch:
|
||||||
|
case Sema::TDK_DeducedMismatchNested:
|
||||||
case Sema::TDK_NonDeducedMismatch:
|
case Sema::TDK_NonDeducedMismatch:
|
||||||
return &static_cast<DFIArguments*>(Data)->FirstArg;
|
return &static_cast<DFIArguments*>(Data)->FirstArg;
|
||||||
|
|
||||||
|
@ -791,6 +796,7 @@ const TemplateArgument *DeductionFailureInfo::getSecondArg() {
|
||||||
case Sema::TDK_Inconsistent:
|
case Sema::TDK_Inconsistent:
|
||||||
case Sema::TDK_Underqualified:
|
case Sema::TDK_Underqualified:
|
||||||
case Sema::TDK_DeducedMismatch:
|
case Sema::TDK_DeducedMismatch:
|
||||||
|
case Sema::TDK_DeducedMismatchNested:
|
||||||
case Sema::TDK_NonDeducedMismatch:
|
case Sema::TDK_NonDeducedMismatch:
|
||||||
return &static_cast<DFIArguments*>(Data)->SecondArg;
|
return &static_cast<DFIArguments*>(Data)->SecondArg;
|
||||||
|
|
||||||
|
@ -803,11 +809,14 @@ const TemplateArgument *DeductionFailureInfo::getSecondArg() {
|
||||||
}
|
}
|
||||||
|
|
||||||
llvm::Optional<unsigned> DeductionFailureInfo::getCallArgIndex() {
|
llvm::Optional<unsigned> DeductionFailureInfo::getCallArgIndex() {
|
||||||
if (static_cast<Sema::TemplateDeductionResult>(Result) ==
|
switch (static_cast<Sema::TemplateDeductionResult>(Result)) {
|
||||||
Sema::TDK_DeducedMismatch)
|
case Sema::TDK_DeducedMismatch:
|
||||||
|
case Sema::TDK_DeducedMismatchNested:
|
||||||
return static_cast<DFIDeducedMismatchArgs*>(Data)->CallArgIndex;
|
return static_cast<DFIDeducedMismatchArgs*>(Data)->CallArgIndex;
|
||||||
|
|
||||||
return llvm::None;
|
default:
|
||||||
|
return llvm::None;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void OverloadCandidateSet::destroyCandidates() {
|
void OverloadCandidateSet::destroyCandidates() {
|
||||||
|
@ -9682,7 +9691,8 @@ static void DiagnoseBadDeduction(Sema &S, NamedDecl *Found, Decl *Templated,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
case Sema::TDK_DeducedMismatch: {
|
case Sema::TDK_DeducedMismatch:
|
||||||
|
case Sema::TDK_DeducedMismatchNested: {
|
||||||
// Format the template argument list into the argument string.
|
// Format the template argument list into the argument string.
|
||||||
SmallString<128> TemplateArgString;
|
SmallString<128> TemplateArgString;
|
||||||
if (TemplateArgumentList *Args =
|
if (TemplateArgumentList *Args =
|
||||||
|
@ -9695,7 +9705,8 @@ static void DiagnoseBadDeduction(Sema &S, NamedDecl *Found, Decl *Templated,
|
||||||
S.Diag(Templated->getLocation(), diag::note_ovl_candidate_deduced_mismatch)
|
S.Diag(Templated->getLocation(), diag::note_ovl_candidate_deduced_mismatch)
|
||||||
<< (*DeductionFailure.getCallArgIndex() + 1)
|
<< (*DeductionFailure.getCallArgIndex() + 1)
|
||||||
<< *DeductionFailure.getFirstArg() << *DeductionFailure.getSecondArg()
|
<< *DeductionFailure.getFirstArg() << *DeductionFailure.getSecondArg()
|
||||||
<< TemplateArgString;
|
<< TemplateArgString
|
||||||
|
<< (DeductionFailure.Result == Sema::TDK_DeducedMismatchNested);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10012,6 +10023,7 @@ static unsigned RankDeductionFailure(const DeductionFailureInfo &DFI) {
|
||||||
|
|
||||||
case Sema::TDK_SubstitutionFailure:
|
case Sema::TDK_SubstitutionFailure:
|
||||||
case Sema::TDK_DeducedMismatch:
|
case Sema::TDK_DeducedMismatch:
|
||||||
|
case Sema::TDK_DeducedMismatchNested:
|
||||||
case Sema::TDK_NonDeducedMismatch:
|
case Sema::TDK_NonDeducedMismatch:
|
||||||
case Sema::TDK_MiscellaneousDeductionFailure:
|
case Sema::TDK_MiscellaneousDeductionFailure:
|
||||||
case Sema::TDK_CUDATargetMismatch:
|
case Sema::TDK_CUDATargetMismatch:
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include "clang/AST/Expr.h"
|
#include "clang/AST/Expr.h"
|
||||||
#include "clang/AST/ExprCXX.h"
|
#include "clang/AST/ExprCXX.h"
|
||||||
#include "clang/AST/StmtVisitor.h"
|
#include "clang/AST/StmtVisitor.h"
|
||||||
|
#include "clang/AST/TypeOrdering.h"
|
||||||
#include "clang/Sema/DeclSpec.h"
|
#include "clang/Sema/DeclSpec.h"
|
||||||
#include "clang/Sema/Sema.h"
|
#include "clang/Sema/Sema.h"
|
||||||
#include "clang/Sema/Template.h"
|
#include "clang/Sema/Template.h"
|
||||||
|
@ -2856,6 +2857,36 @@ CheckOriginalCallArgDeduction(Sema &S, Sema::OriginalCallArg OriginalArg,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Find the pack index for a particular parameter index in an instantiation of
|
||||||
|
/// a function template with specific arguments.
|
||||||
|
///
|
||||||
|
/// \return The pack index for whichever pack produced this parameter, or -1
|
||||||
|
/// if this was not produced by a parameter. Intended to be used as the
|
||||||
|
/// ArgumentPackSubstitutionIndex for further substitutions.
|
||||||
|
// FIXME: We should track this in OriginalCallArgs so we don't need to
|
||||||
|
// reconstruct it here.
|
||||||
|
static unsigned getPackIndexForParam(Sema &S,
|
||||||
|
FunctionTemplateDecl *FunctionTemplate,
|
||||||
|
const MultiLevelTemplateArgumentList &Args,
|
||||||
|
unsigned ParamIdx) {
|
||||||
|
unsigned Idx = 0;
|
||||||
|
for (auto *PD : FunctionTemplate->getTemplatedDecl()->parameters()) {
|
||||||
|
if (PD->isParameterPack()) {
|
||||||
|
unsigned NumExpansions =
|
||||||
|
S.getNumArgumentsInExpansion(PD->getType(), Args).getValueOr(1);
|
||||||
|
if (Idx + NumExpansions > ParamIdx)
|
||||||
|
return ParamIdx - Idx;
|
||||||
|
Idx += NumExpansions;
|
||||||
|
} else {
|
||||||
|
if (Idx == ParamIdx)
|
||||||
|
return -1; // Not a pack expansion
|
||||||
|
++Idx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
llvm_unreachable("parameter index would not be produced from template");
|
||||||
|
}
|
||||||
|
|
||||||
/// \brief Finish template argument deduction for a function template,
|
/// \brief Finish template argument deduction for a function template,
|
||||||
/// checking the deduced template arguments for completeness and forming
|
/// checking the deduced template arguments for completeness and forming
|
||||||
/// the function template specialization.
|
/// the function template specialization.
|
||||||
|
@ -2906,9 +2937,9 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
|
||||||
DeclContext *Owner = FunctionTemplate->getDeclContext();
|
DeclContext *Owner = FunctionTemplate->getDeclContext();
|
||||||
if (FunctionTemplate->getFriendObjectKind())
|
if (FunctionTemplate->getFriendObjectKind())
|
||||||
Owner = FunctionTemplate->getLexicalDeclContext();
|
Owner = FunctionTemplate->getLexicalDeclContext();
|
||||||
|
MultiLevelTemplateArgumentList SubstArgs(*DeducedArgumentList);
|
||||||
Specialization = cast_or_null<FunctionDecl>(
|
Specialization = cast_or_null<FunctionDecl>(
|
||||||
SubstDecl(FunctionTemplate->getTemplatedDecl(), Owner,
|
SubstDecl(FunctionTemplate->getTemplatedDecl(), Owner, SubstArgs));
|
||||||
MultiLevelTemplateArgumentList(*DeducedArgumentList)));
|
|
||||||
if (!Specialization || Specialization->isInvalidDecl())
|
if (!Specialization || Specialization->isInvalidDecl())
|
||||||
return TDK_SubstitutionFailure;
|
return TDK_SubstitutionFailure;
|
||||||
|
|
||||||
|
@ -2934,19 +2965,46 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
|
||||||
// In general, the deduction process attempts to find template argument
|
// In general, the deduction process attempts to find template argument
|
||||||
// values that will make the deduced A identical to A (after the type A
|
// values that will make the deduced A identical to A (after the type A
|
||||||
// is transformed as described above). [...]
|
// is transformed as described above). [...]
|
||||||
|
llvm::SmallDenseMap<std::pair<unsigned, QualType>, QualType> DeducedATypes;
|
||||||
for (unsigned I = 0, N = OriginalCallArgs->size(); I != N; ++I) {
|
for (unsigned I = 0, N = OriginalCallArgs->size(); I != N; ++I) {
|
||||||
OriginalCallArg OriginalArg = (*OriginalCallArgs)[I];
|
OriginalCallArg OriginalArg = (*OriginalCallArgs)[I];
|
||||||
unsigned ParamIdx = OriginalArg.ArgIdx;
|
|
||||||
|
|
||||||
|
auto ParamIdx = OriginalArg.ArgIdx;
|
||||||
if (ParamIdx >= Specialization->getNumParams())
|
if (ParamIdx >= Specialization->getNumParams())
|
||||||
|
// FIXME: This presumably means a pack ended up smaller than we
|
||||||
|
// expected while deducing. Should this not result in deduction
|
||||||
|
// failure? Can it even happen?
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
QualType DeducedA = Specialization->getParamDecl(ParamIdx)->getType();
|
QualType DeducedA;
|
||||||
|
if (!OriginalArg.DecomposedParam) {
|
||||||
|
// P is one of the function parameters, just look up its substituted
|
||||||
|
// type.
|
||||||
|
DeducedA = Specialization->getParamDecl(ParamIdx)->getType();
|
||||||
|
} else {
|
||||||
|
// P is a decomposed element of a parameter corresponding to a
|
||||||
|
// braced-init-list argument. Substitute back into P to find the
|
||||||
|
// deduced A.
|
||||||
|
QualType &CacheEntry =
|
||||||
|
DeducedATypes[{ParamIdx, OriginalArg.OriginalParamType}];
|
||||||
|
if (CacheEntry.isNull()) {
|
||||||
|
ArgumentPackSubstitutionIndexRAII PackIndex(
|
||||||
|
*this, getPackIndexForParam(*this, FunctionTemplate, SubstArgs,
|
||||||
|
ParamIdx));
|
||||||
|
CacheEntry =
|
||||||
|
SubstType(OriginalArg.OriginalParamType, SubstArgs,
|
||||||
|
Specialization->getTypeSpecStartLoc(),
|
||||||
|
Specialization->getDeclName());
|
||||||
|
}
|
||||||
|
DeducedA = CacheEntry;
|
||||||
|
}
|
||||||
|
|
||||||
if (CheckOriginalCallArgDeduction(*this, OriginalArg, DeducedA)) {
|
if (CheckOriginalCallArgDeduction(*this, OriginalArg, DeducedA)) {
|
||||||
Info.FirstArg = TemplateArgument(DeducedA);
|
Info.FirstArg = TemplateArgument(DeducedA);
|
||||||
Info.SecondArg = TemplateArgument(OriginalArg.OriginalArgType);
|
Info.SecondArg = TemplateArgument(OriginalArg.OriginalArgType);
|
||||||
Info.CallArgIndex = OriginalArg.ArgIdx;
|
Info.CallArgIndex = OriginalArg.ArgIdx;
|
||||||
return TDK_DeducedMismatch;
|
return OriginalArg.DecomposedParam ? TDK_DeducedMismatchNested
|
||||||
|
: TDK_DeducedMismatch;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3203,7 +3261,7 @@ static Sema::TemplateDeductionResult DeduceTemplateArgumentsFromCallArgument(
|
||||||
Expr *Arg, TemplateDeductionInfo &Info,
|
Expr *Arg, TemplateDeductionInfo &Info,
|
||||||
SmallVectorImpl<DeducedTemplateArgument> &Deduced,
|
SmallVectorImpl<DeducedTemplateArgument> &Deduced,
|
||||||
SmallVectorImpl<Sema::OriginalCallArg> &OriginalCallArgs,
|
SmallVectorImpl<Sema::OriginalCallArg> &OriginalCallArgs,
|
||||||
Optional<unsigned> ArgIdx, unsigned TDF);
|
bool DecomposedParam, unsigned ArgIdx, unsigned TDF);
|
||||||
|
|
||||||
/// \brief Attempt template argument deduction from an initializer list
|
/// \brief Attempt template argument deduction from an initializer list
|
||||||
/// deemed to be an argument in a function call.
|
/// deemed to be an argument in a function call.
|
||||||
|
@ -3211,7 +3269,8 @@ static Sema::TemplateDeductionResult DeduceFromInitializerList(
|
||||||
Sema &S, TemplateParameterList *TemplateParams, QualType AdjustedParamType,
|
Sema &S, TemplateParameterList *TemplateParams, QualType AdjustedParamType,
|
||||||
InitListExpr *ILE, TemplateDeductionInfo &Info,
|
InitListExpr *ILE, TemplateDeductionInfo &Info,
|
||||||
SmallVectorImpl<DeducedTemplateArgument> &Deduced,
|
SmallVectorImpl<DeducedTemplateArgument> &Deduced,
|
||||||
SmallVectorImpl<Sema::OriginalCallArg> &OriginalCallArgs, unsigned TDF) {
|
SmallVectorImpl<Sema::OriginalCallArg> &OriginalCallArgs, unsigned ArgIdx,
|
||||||
|
unsigned TDF) {
|
||||||
// C++ [temp.deduct.call]p1: (CWG 1591)
|
// C++ [temp.deduct.call]p1: (CWG 1591)
|
||||||
// If removing references and cv-qualifiers from P gives
|
// If removing references and cv-qualifiers from P gives
|
||||||
// std::initializer_list<P0> or P0[N] for some P0 and N and the argument is
|
// std::initializer_list<P0> or P0[N] for some P0 and N and the argument is
|
||||||
|
@ -3237,8 +3296,8 @@ static Sema::TemplateDeductionResult DeduceFromInitializerList(
|
||||||
if (ElTy->isDependentType()) {
|
if (ElTy->isDependentType()) {
|
||||||
for (Expr *E : ILE->inits()) {
|
for (Expr *E : ILE->inits()) {
|
||||||
if (auto Result = DeduceTemplateArgumentsFromCallArgument(
|
if (auto Result = DeduceTemplateArgumentsFromCallArgument(
|
||||||
S, TemplateParams, ElTy, E, Info, Deduced, OriginalCallArgs, None,
|
S, TemplateParams, ElTy, E, Info, Deduced, OriginalCallArgs, true,
|
||||||
TDF))
|
ArgIdx, TDF))
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3270,7 +3329,7 @@ static Sema::TemplateDeductionResult DeduceTemplateArgumentsFromCallArgument(
|
||||||
Expr *Arg, TemplateDeductionInfo &Info,
|
Expr *Arg, TemplateDeductionInfo &Info,
|
||||||
SmallVectorImpl<DeducedTemplateArgument> &Deduced,
|
SmallVectorImpl<DeducedTemplateArgument> &Deduced,
|
||||||
SmallVectorImpl<Sema::OriginalCallArg> &OriginalCallArgs,
|
SmallVectorImpl<Sema::OriginalCallArg> &OriginalCallArgs,
|
||||||
Optional<unsigned> ArgIdx, unsigned TDF) {
|
bool DecomposedParam, unsigned ArgIdx, unsigned TDF) {
|
||||||
QualType ArgType = Arg->getType();
|
QualType ArgType = Arg->getType();
|
||||||
QualType OrigParamType = ParamType;
|
QualType OrigParamType = ParamType;
|
||||||
|
|
||||||
|
@ -3283,19 +3342,15 @@ static Sema::TemplateDeductionResult DeduceTemplateArgumentsFromCallArgument(
|
||||||
// If [...] the argument is a non-empty initializer list [...]
|
// If [...] the argument is a non-empty initializer list [...]
|
||||||
if (InitListExpr *ILE = dyn_cast<InitListExpr>(Arg))
|
if (InitListExpr *ILE = dyn_cast<InitListExpr>(Arg))
|
||||||
return DeduceFromInitializerList(S, TemplateParams, ParamType, ILE, Info,
|
return DeduceFromInitializerList(S, TemplateParams, ParamType, ILE, Info,
|
||||||
Deduced, OriginalCallArgs, TDF);
|
Deduced, OriginalCallArgs, ArgIdx, TDF);
|
||||||
|
|
||||||
// [...] the deduction process attempts to find template argument values
|
// [...] the deduction process attempts to find template argument values
|
||||||
// that will make the deduced A identical to A
|
// that will make the deduced A identical to A
|
||||||
//
|
//
|
||||||
// Keep track of the argument type and corresponding parameter index,
|
// Keep track of the argument type and corresponding parameter index,
|
||||||
// so we can check for compatibility between the deduced A and A.
|
// so we can check for compatibility between the deduced A and A.
|
||||||
//
|
OriginalCallArgs.push_back(
|
||||||
// FIXME: We are supposed to perform this check for the P/A pairs we extract
|
Sema::OriginalCallArg(OrigParamType, DecomposedParam, ArgIdx, ArgType));
|
||||||
// from the initializer list case too.
|
|
||||||
if (ArgIdx)
|
|
||||||
OriginalCallArgs.push_back(
|
|
||||||
Sema::OriginalCallArg(OrigParamType, *ArgIdx, ArgType));
|
|
||||||
return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, ParamType,
|
return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, ParamType,
|
||||||
ArgType, Info, Deduced, TDF);
|
ArgType, Info, Deduced, TDF);
|
||||||
}
|
}
|
||||||
|
@ -3388,7 +3443,7 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
|
||||||
// ... with the type of the corresponding argument
|
// ... with the type of the corresponding argument
|
||||||
return DeduceTemplateArgumentsFromCallArgument(
|
return DeduceTemplateArgumentsFromCallArgument(
|
||||||
*this, TemplateParams, ParamType, Args[ArgIdx], Info, Deduced,
|
*this, TemplateParams, ParamType, Args[ArgIdx], Info, Deduced,
|
||||||
OriginalCallArgs, ArgIdx, /*TDF*/ 0);
|
OriginalCallArgs, /*Decomposed*/false, ArgIdx, /*TDF*/ 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Deduce template arguments from the function parameters.
|
// Deduce template arguments from the function parameters.
|
||||||
|
@ -4075,7 +4130,8 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *&Init, QualType &Result,
|
||||||
for (unsigned i = 0, e = InitList->getNumInits(); i < e; ++i) {
|
for (unsigned i = 0, e = InitList->getNumInits(); i < e; ++i) {
|
||||||
if (DeduceTemplateArgumentsFromCallArgument(
|
if (DeduceTemplateArgumentsFromCallArgument(
|
||||||
*this, TemplateParamsSt.get(), TemplArg, InitList->getInit(i),
|
*this, TemplateParamsSt.get(), TemplArg, InitList->getInit(i),
|
||||||
Info, Deduced, OriginalCallArgs, None, /*TDF*/0))
|
Info, Deduced, OriginalCallArgs, /*Decomposed*/ true,
|
||||||
|
/*ArgIdx*/ 0, /*TDF*/ 0))
|
||||||
return DeductionFailed();
|
return DeductionFailed();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -4086,7 +4142,7 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *&Init, QualType &Result,
|
||||||
|
|
||||||
if (DeduceTemplateArgumentsFromCallArgument(
|
if (DeduceTemplateArgumentsFromCallArgument(
|
||||||
*this, TemplateParamsSt.get(), FuncParam, Init, Info, Deduced,
|
*this, TemplateParamsSt.get(), FuncParam, Init, Info, Deduced,
|
||||||
OriginalCallArgs, /*ArgIdx*/0, /*TDF*/0))
|
OriginalCallArgs, /*Decomposed*/ false, /*ArgIdx*/ 0, /*TDF*/ 0))
|
||||||
return DeductionFailed();
|
return DeductionFailed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4108,8 +4164,11 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *&Init, QualType &Result,
|
||||||
|
|
||||||
// Check that the deduced argument type is compatible with the original
|
// Check that the deduced argument type is compatible with the original
|
||||||
// argument type per C++ [temp.deduct.call]p4.
|
// argument type per C++ [temp.deduct.call]p4.
|
||||||
|
QualType DeducedA = InitList ? Deduced[0].getAsType() : Result;
|
||||||
for (const OriginalCallArg &OriginalArg : OriginalCallArgs) {
|
for (const OriginalCallArg &OriginalArg : OriginalCallArgs) {
|
||||||
if (CheckOriginalCallArgDeduction(*this, OriginalArg, Result)) {
|
assert((bool)InitList == OriginalArg.DecomposedParam &&
|
||||||
|
"decomposed non-init-list in auto deduction?");
|
||||||
|
if (CheckOriginalCallArgDeduction(*this, OriginalArg, DeducedA)) {
|
||||||
Result = QualType();
|
Result = QualType();
|
||||||
return DeductionFailed();
|
return DeductionFailed();
|
||||||
}
|
}
|
||||||
|
|
|
@ -105,6 +105,7 @@ T deduce_ref(const std::initializer_list<T>&); // expected-note {{conflicting ty
|
||||||
|
|
||||||
template<typename T, typename U> struct pair { pair(...); };
|
template<typename T, typename U> struct pair { pair(...); };
|
||||||
template<typename T> void deduce_pairs(std::initializer_list<pair<T, typename T::type>>);
|
template<typename T> void deduce_pairs(std::initializer_list<pair<T, typename T::type>>);
|
||||||
|
// expected-note@-1 {{deduced type 'pair<[...], typename WithIntType::type>' of element of 1st parameter does not match adjusted type 'pair<[...], float>' of element of argument [with T = WithIntType]}}
|
||||||
struct WithIntType { typedef int type; };
|
struct WithIntType { typedef int type; };
|
||||||
|
|
||||||
template<typename ...T> void deduce_after_init_list_in_pack(void (*)(T...), T...); // expected-note {{<int, int> vs. <(no value), double>}}
|
template<typename ...T> void deduce_after_init_list_in_pack(void (*)(T...), T...); // expected-note {{<int, int> vs. <(no value), double>}}
|
||||||
|
@ -123,7 +124,7 @@ void argument_deduction() {
|
||||||
pair<WithIntType, int> pi;
|
pair<WithIntType, int> pi;
|
||||||
pair<WithIntType, float> pf;
|
pair<WithIntType, float> pf;
|
||||||
deduce_pairs({pi, pi, pi}); // ok
|
deduce_pairs({pi, pi, pi}); // ok
|
||||||
deduce_pairs({pi, pf, pi}); // FIXME: This should be rejected, as we fail to produce a type that exactly matches the argument type.
|
deduce_pairs({pi, pf, pi}); // expected-error {{no matching function}}
|
||||||
|
|
||||||
deduce_after_init_list_in_pack((void(*)(int,int))0, {}, 0);
|
deduce_after_init_list_in_pack((void(*)(int,int))0, {}, 0);
|
||||||
deduce_after_init_list_in_pack((void(*)(int,int))0, {}, 0.0); // expected-error {{no matching function}}
|
deduce_after_init_list_in_pack((void(*)(int,int))0, {}, 0.0); // expected-error {{no matching function}}
|
||||||
|
@ -298,9 +299,18 @@ namespace TemporaryInitListSourceRange_PR22367 {
|
||||||
|
|
||||||
namespace ParameterPackNestedInitializerLists_PR23904c3 {
|
namespace ParameterPackNestedInitializerLists_PR23904c3 {
|
||||||
template <typename ...T>
|
template <typename ...T>
|
||||||
void f(std::initializer_list<std::initializer_list<T>> ...tt);
|
void f(std::initializer_list<std::initializer_list<T>> ...tt); // expected-note 2{{conflicting}} expected-note {{incomplete pack}}
|
||||||
|
|
||||||
void foo() { f({{0}}, {{'\0'}}); }
|
void foo() {
|
||||||
|
f({{0}}, {{'\0'}}); // ok, T = <int, char>
|
||||||
|
f({{0}, {'\0'}}); // expected-error {{no match}}
|
||||||
|
f({{0, '\0'}}); // expected-error {{no match}}
|
||||||
|
|
||||||
|
f({{0}}, {{{}}}); // expected-error {{no match}}
|
||||||
|
f({{0}}, {{{}, '\0'}}); // ok, T = <int, char>
|
||||||
|
f({{0}, {{}}}); // ok, T = <int>
|
||||||
|
f({{0, {}}}); // ok, T = <int>
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace update_rbrace_loc_crash {
|
namespace update_rbrace_loc_crash {
|
||||||
|
|
Loading…
Reference in New Issue