r291190 - Add missing "original call argument has same type as deduced parameter type"
Richard Smith via cfe-commits
cfe-commits at lists.llvm.org
Thu Jan 5 15:02:44 PST 2017
Author: rsmith
Date: Thu Jan 5 17:02:44 2017
New Revision: 291190
URL: http://llvm.org/viewvc/llvm-project?rev=291190&view=rev
Log:
Add missing "original call argument has same type as deduced parameter type"
check for deductions from elements of a braced-init-list.
Modified:
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/include/clang/Sema/Sema.h
cfe/trunk/lib/Sema/SemaOverload.cpp
cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
cfe/trunk/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=291190&r1=291189&r2=291190&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Thu Jan 5 17:02:44 2017
@@ -3377,8 +3377,10 @@ def note_addrof_ovl_candidate_disabled_b
"candidate function made ineligible by enable_if">;
def note_ovl_candidate_deduced_mismatch : Note<
"candidate template ignored: deduced type "
- "%diff{$ of %ordinal0 parameter does not match adjusted type $ of argument"
- "|of %ordinal0 parameter does not match adjusted type of argument}1,2%3">;
+ "%diff{$ of %select{|element of }4%ordinal0 parameter does not match "
+ "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<
"candidate template ignored: could not match %diff{$ against $|types}0,1">;
// This note is needed because the above note would sometimes print two
Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=291190&r1=291189&r2=291190&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Thu Jan 5 17:02:44 2017
@@ -6564,6 +6564,10 @@ public:
/// \brief After substituting deduced template arguments, a dependent
/// parameter type did not match the corresponding argument.
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
/// corresponding component of the argument.
TDK_NonDeducedMismatch,
@@ -6602,13 +6606,14 @@ public:
/// brief A function argument from which we performed template argument
// deduction for a call.
struct OriginalCallArg {
- OriginalCallArg(QualType OriginalParamType,
- unsigned ArgIdx,
- QualType OriginalArgType)
- : OriginalParamType(OriginalParamType), ArgIdx(ArgIdx),
- OriginalArgType(OriginalArgType) { }
+ OriginalCallArg(QualType OriginalParamType, bool DecomposedParam,
+ unsigned ArgIdx, QualType OriginalArgType)
+ : OriginalParamType(OriginalParamType),
+ DecomposedParam(DecomposedParam), ArgIdx(ArgIdx),
+ OriginalArgType(OriginalArgType) {}
QualType OriginalParamType;
+ bool DecomposedParam;
unsigned ArgIdx;
QualType OriginalArgType;
};
Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=291190&r1=291189&r2=291190&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Thu Jan 5 17:02:44 2017
@@ -604,7 +604,8 @@ clang::MakeDeductionFailureInfo(ASTConte
Result.Data = Info.Param.getOpaqueValue();
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.
auto *Saved = new (Context) DFIDeducedMismatchArgs;
Saved->FirstArg = Info.FirstArg;
@@ -664,6 +665,7 @@ void DeductionFailureInfo::Destroy() {
case Sema::TDK_Inconsistent:
case Sema::TDK_Underqualified:
case Sema::TDK_DeducedMismatch:
+ case Sema::TDK_DeducedMismatchNested:
case Sema::TDK_NonDeducedMismatch:
// FIXME: Destroy the data?
Data = nullptr;
@@ -699,6 +701,7 @@ TemplateParameter DeductionFailureInfo::
case Sema::TDK_TooFewArguments:
case Sema::TDK_SubstitutionFailure:
case Sema::TDK_DeducedMismatch:
+ case Sema::TDK_DeducedMismatchNested:
case Sema::TDK_NonDeducedMismatch:
case Sema::TDK_CUDATargetMismatch:
return TemplateParameter();
@@ -735,6 +738,7 @@ TemplateArgumentList *DeductionFailureIn
return nullptr;
case Sema::TDK_DeducedMismatch:
+ case Sema::TDK_DeducedMismatchNested:
return static_cast<DFIDeducedMismatchArgs*>(Data)->TemplateArgs;
case Sema::TDK_SubstitutionFailure:
@@ -764,6 +768,7 @@ const TemplateArgument *DeductionFailure
case Sema::TDK_Inconsistent:
case Sema::TDK_Underqualified:
case Sema::TDK_DeducedMismatch:
+ case Sema::TDK_DeducedMismatchNested:
case Sema::TDK_NonDeducedMismatch:
return &static_cast<DFIArguments*>(Data)->FirstArg;
@@ -791,6 +796,7 @@ const TemplateArgument *DeductionFailure
case Sema::TDK_Inconsistent:
case Sema::TDK_Underqualified:
case Sema::TDK_DeducedMismatch:
+ case Sema::TDK_DeducedMismatchNested:
case Sema::TDK_NonDeducedMismatch:
return &static_cast<DFIArguments*>(Data)->SecondArg;
@@ -803,11 +809,14 @@ const TemplateArgument *DeductionFailure
}
llvm::Optional<unsigned> DeductionFailureInfo::getCallArgIndex() {
- if (static_cast<Sema::TemplateDeductionResult>(Result) ==
- Sema::TDK_DeducedMismatch)
+ switch (static_cast<Sema::TemplateDeductionResult>(Result)) {
+ case Sema::TDK_DeducedMismatch:
+ case Sema::TDK_DeducedMismatchNested:
return static_cast<DFIDeducedMismatchArgs*>(Data)->CallArgIndex;
- return llvm::None;
+ default:
+ return llvm::None;
+ }
}
void OverloadCandidateSet::destroyCandidates() {
@@ -9682,7 +9691,8 @@ static void DiagnoseBadDeduction(Sema &S
return;
}
- case Sema::TDK_DeducedMismatch: {
+ case Sema::TDK_DeducedMismatch:
+ case Sema::TDK_DeducedMismatchNested: {
// Format the template argument list into the argument string.
SmallString<128> TemplateArgString;
if (TemplateArgumentList *Args =
@@ -9695,7 +9705,8 @@ static void DiagnoseBadDeduction(Sema &S
S.Diag(Templated->getLocation(), diag::note_ovl_candidate_deduced_mismatch)
<< (*DeductionFailure.getCallArgIndex() + 1)
<< *DeductionFailure.getFirstArg() << *DeductionFailure.getSecondArg()
- << TemplateArgString;
+ << TemplateArgString
+ << (DeductionFailure.Result == Sema::TDK_DeducedMismatchNested);
break;
}
@@ -10012,6 +10023,7 @@ static unsigned RankDeductionFailure(con
case Sema::TDK_SubstitutionFailure:
case Sema::TDK_DeducedMismatch:
+ case Sema::TDK_DeducedMismatchNested:
case Sema::TDK_NonDeducedMismatch:
case Sema::TDK_MiscellaneousDeductionFailure:
case Sema::TDK_CUDATargetMismatch:
Modified: cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp?rev=291190&r1=291189&r2=291190&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp Thu Jan 5 17:02:44 2017
@@ -19,6 +19,7 @@
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/StmtVisitor.h"
+#include "clang/AST/TypeOrdering.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/Sema.h"
#include "clang/Sema/Template.h"
@@ -2856,6 +2857,36 @@ CheckOriginalCallArgDeduction(Sema &S, S
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,
/// checking the deduced template arguments for completeness and forming
/// the function template specialization.
@@ -2906,9 +2937,9 @@ Sema::FinishTemplateArgumentDeduction(Fu
DeclContext *Owner = FunctionTemplate->getDeclContext();
if (FunctionTemplate->getFriendObjectKind())
Owner = FunctionTemplate->getLexicalDeclContext();
+ MultiLevelTemplateArgumentList SubstArgs(*DeducedArgumentList);
Specialization = cast_or_null<FunctionDecl>(
- SubstDecl(FunctionTemplate->getTemplatedDecl(), Owner,
- MultiLevelTemplateArgumentList(*DeducedArgumentList)));
+ SubstDecl(FunctionTemplate->getTemplatedDecl(), Owner, SubstArgs));
if (!Specialization || Specialization->isInvalidDecl())
return TDK_SubstitutionFailure;
@@ -2934,19 +2965,46 @@ Sema::FinishTemplateArgumentDeduction(Fu
// In general, the deduction process attempts to find template argument
// values that will make the deduced A identical to A (after the type A
// is transformed as described above). [...]
+ llvm::SmallDenseMap<std::pair<unsigned, QualType>, QualType> DeducedATypes;
for (unsigned I = 0, N = OriginalCallArgs->size(); I != N; ++I) {
OriginalCallArg OriginalArg = (*OriginalCallArgs)[I];
- unsigned ParamIdx = OriginalArg.ArgIdx;
+ auto ParamIdx = OriginalArg.ArgIdx;
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;
- 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)) {
Info.FirstArg = TemplateArgument(DeducedA);
Info.SecondArg = TemplateArgument(OriginalArg.OriginalArgType);
Info.CallArgIndex = OriginalArg.ArgIdx;
- return TDK_DeducedMismatch;
+ return OriginalArg.DecomposedParam ? TDK_DeducedMismatchNested
+ : TDK_DeducedMismatch;
}
}
}
@@ -3203,7 +3261,7 @@ static Sema::TemplateDeductionResult Ded
Expr *Arg, TemplateDeductionInfo &Info,
SmallVectorImpl<DeducedTemplateArgument> &Deduced,
SmallVectorImpl<Sema::OriginalCallArg> &OriginalCallArgs,
- Optional<unsigned> ArgIdx, unsigned TDF);
+ bool DecomposedParam, unsigned ArgIdx, unsigned TDF);
/// \brief Attempt template argument deduction from an initializer list
/// deemed to be an argument in a function call.
@@ -3211,7 +3269,8 @@ static Sema::TemplateDeductionResult Ded
Sema &S, TemplateParameterList *TemplateParams, QualType AdjustedParamType,
InitListExpr *ILE, TemplateDeductionInfo &Info,
SmallVectorImpl<DeducedTemplateArgument> &Deduced,
- SmallVectorImpl<Sema::OriginalCallArg> &OriginalCallArgs, unsigned TDF) {
+ SmallVectorImpl<Sema::OriginalCallArg> &OriginalCallArgs, unsigned ArgIdx,
+ unsigned TDF) {
// C++ [temp.deduct.call]p1: (CWG 1591)
// 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
@@ -3237,8 +3296,8 @@ static Sema::TemplateDeductionResult Ded
if (ElTy->isDependentType()) {
for (Expr *E : ILE->inits()) {
if (auto Result = DeduceTemplateArgumentsFromCallArgument(
- S, TemplateParams, ElTy, E, Info, Deduced, OriginalCallArgs, None,
- TDF))
+ S, TemplateParams, ElTy, E, Info, Deduced, OriginalCallArgs, true,
+ ArgIdx, TDF))
return Result;
}
}
@@ -3270,7 +3329,7 @@ static Sema::TemplateDeductionResult Ded
Expr *Arg, TemplateDeductionInfo &Info,
SmallVectorImpl<DeducedTemplateArgument> &Deduced,
SmallVectorImpl<Sema::OriginalCallArg> &OriginalCallArgs,
- Optional<unsigned> ArgIdx, unsigned TDF) {
+ bool DecomposedParam, unsigned ArgIdx, unsigned TDF) {
QualType ArgType = Arg->getType();
QualType OrigParamType = ParamType;
@@ -3283,19 +3342,15 @@ static Sema::TemplateDeductionResult Ded
// If [...] the argument is a non-empty initializer list [...]
if (InitListExpr *ILE = dyn_cast<InitListExpr>(Arg))
return DeduceFromInitializerList(S, TemplateParams, ParamType, ILE, Info,
- Deduced, OriginalCallArgs, TDF);
+ Deduced, OriginalCallArgs, ArgIdx, TDF);
// [...] the deduction process attempts to find template argument values
// that will make the deduced A identical to A
//
// Keep track of the argument type and corresponding parameter index,
// so we can check for compatibility between the deduced A and A.
- //
- // FIXME: We are supposed to perform this check for the P/A pairs we extract
- // from the initializer list case too.
- if (ArgIdx)
- OriginalCallArgs.push_back(
- Sema::OriginalCallArg(OrigParamType, *ArgIdx, ArgType));
+ OriginalCallArgs.push_back(
+ Sema::OriginalCallArg(OrigParamType, DecomposedParam, ArgIdx, ArgType));
return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, ParamType,
ArgType, Info, Deduced, TDF);
}
@@ -3388,7 +3443,7 @@ Sema::TemplateDeductionResult Sema::Dedu
// ... with the type of the corresponding argument
return DeduceTemplateArgumentsFromCallArgument(
*this, TemplateParams, ParamType, Args[ArgIdx], Info, Deduced,
- OriginalCallArgs, ArgIdx, /*TDF*/ 0);
+ OriginalCallArgs, /*Decomposed*/false, ArgIdx, /*TDF*/ 0);
};
// Deduce template arguments from the function parameters.
@@ -4075,7 +4130,8 @@ Sema::DeduceAutoType(TypeLoc Type, Expr
for (unsigned i = 0, e = InitList->getNumInits(); i < e; ++i) {
if (DeduceTemplateArgumentsFromCallArgument(
*this, TemplateParamsSt.get(), TemplArg, InitList->getInit(i),
- Info, Deduced, OriginalCallArgs, None, /*TDF*/0))
+ Info, Deduced, OriginalCallArgs, /*Decomposed*/ true,
+ /*ArgIdx*/ 0, /*TDF*/ 0))
return DeductionFailed();
}
} else {
@@ -4086,7 +4142,7 @@ Sema::DeduceAutoType(TypeLoc Type, Expr
if (DeduceTemplateArgumentsFromCallArgument(
*this, TemplateParamsSt.get(), FuncParam, Init, Info, Deduced,
- OriginalCallArgs, /*ArgIdx*/0, /*TDF*/0))
+ OriginalCallArgs, /*Decomposed*/ false, /*ArgIdx*/ 0, /*TDF*/ 0))
return DeductionFailed();
}
@@ -4108,8 +4164,11 @@ Sema::DeduceAutoType(TypeLoc Type, Expr
// Check that the deduced argument type is compatible with the original
// argument type per C++ [temp.deduct.call]p4.
+ QualType DeducedA = InitList ? Deduced[0].getAsType() : Result;
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();
return DeductionFailed();
}
Modified: cfe/trunk/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp?rev=291190&r1=291189&r2=291190&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp (original)
+++ cfe/trunk/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp Thu Jan 5 17:02:44 2017
@@ -105,6 +105,7 @@ T deduce_ref(const std::initializer_list
template<typename T, typename U> struct pair { pair(...); };
template<typename T> void deduce_pairs(std::initializer_list<pair<T, typename T::type>>);
+// expected-note at -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; };
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, float> pf;
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.0); // expected-error {{no matching function}}
@@ -298,9 +299,18 @@ namespace TemporaryInitListSourceRange_P
namespace ParameterPackNestedInitializerLists_PR23904c3 {
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 {
More information about the cfe-commits
mailing list