summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaTemplateDeduction.cpp
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2017-01-05 23:02:44 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2017-01-05 23:02:44 +0000
commitc92d206ce441934a28e5886b5d635748f865a808 (patch)
treecc70df83508f88b410b563f53fa0f68b90e797ad /clang/lib/Sema/SemaTemplateDeduction.cpp
parent1594e0629d02a4a5c7598da6b5bb2a2bfef4207e (diff)
downloadbcm5719-llvm-c92d206ce441934a28e5886b5d635748f865a808.tar.gz
bcm5719-llvm-c92d206ce441934a28e5886b5d635748f865a808.zip
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
Diffstat (limited to 'clang/lib/Sema/SemaTemplateDeduction.cpp')
-rw-r--r--clang/lib/Sema/SemaTemplateDeduction.cpp101
1 files changed, 80 insertions, 21 deletions
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index 7750b9c0eae..043e5c37160 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -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, Sema::OriginalCallArg OriginalArg,
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(FunctionTemplateDecl *FunctionTemplate,
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(FunctionTemplateDecl *FunctionTemplate,
// 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 DeduceTemplateArgumentsFromCallArgument(
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 DeduceFromInitializerList(
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 DeduceFromInitializerList(
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 DeduceTemplateArgumentsFromCallArgument(
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 DeduceTemplateArgumentsFromCallArgument(
// 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::DeduceTemplateArguments(
// ... 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 *&Init, QualType &Result,
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 *&Init, QualType &Result,
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 *&Init, QualType &Result,
// 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();
}
OpenPOWER on IntegriCloud