aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Sema/SemaTemplateDeduction.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Sema/SemaTemplateDeduction.cpp')
-rw-r--r--clang/lib/Sema/SemaTemplateDeduction.cpp210
1 files changed, 155 insertions, 55 deletions
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index 9e56e697..0d70321 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -37,6 +37,7 @@
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/Specifiers.h"
+#include "clang/Basic/TemplateKinds.h"
#include "clang/Sema/EnterExpressionEvaluationContext.h"
#include "clang/Sema/Ownership.h"
#include "clang/Sema/Sema.h"
@@ -146,11 +147,7 @@ static void MarkUsedTemplateParameters(ASTContext &Ctx, QualType T,
bool OnlyDeduced, unsigned Level,
llvm::SmallBitVector &Deduced);
-/// If the given expression is of a form that permits the deduction
-/// of a non-type template parameter, return the declaration of that
-/// non-type template parameter.
-static const NonTypeTemplateParmDecl *
-getDeducedParameterFromExpr(const Expr *E, unsigned Depth) {
+static const Expr *unwrapExpressionForDeduction(const Expr *E) {
// If we are within an alias template, the expression may have undergone
// any number of parameter substitutions already.
while (true) {
@@ -170,18 +167,100 @@ getDeducedParameterFromExpr(const Expr *E, unsigned Depth) {
} else
break;
}
+ return E;
+}
+
+class NonTypeOrVarTemplateParmDecl {
+public:
+ NonTypeOrVarTemplateParmDecl(const NamedDecl *Template) : Template(Template) {
+ assert(
+ !Template || isa<NonTypeTemplateParmDecl>(Template) ||
+ (isa<TemplateTemplateParmDecl>(Template) &&
+ (cast<TemplateTemplateParmDecl>(Template)->templateParameterKind() ==
+ TNK_Var_template ||
+ cast<TemplateTemplateParmDecl>(Template)->templateParameterKind() ==
+ TNK_Concept_template)));
+ }
+
+ QualType getType() const {
+ if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Template))
+ return NTTP->getType();
+ return getTemplate()->templateParameterKind() == TNK_Concept_template
+ ? getTemplate()->getASTContext().BoolTy
+ : getTemplate()->getASTContext().DependentTy;
+ }
+
+ unsigned getDepth() const {
+ if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Template))
+ return NTTP->getDepth();
+ return getTemplate()->getDepth();
+ }
+
+ unsigned getIndex() const {
+ if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Template))
+ return NTTP->getIndex();
+ return getTemplate()->getIndex();
+ }
+
+ const TemplateTemplateParmDecl *getTemplate() const {
+ return cast<TemplateTemplateParmDecl>(Template);
+ }
+
+ const NonTypeTemplateParmDecl *getNTTP() const {
+ return cast<NonTypeTemplateParmDecl>(Template);
+ }
+
+ TemplateParameter asTemplateParam() const {
+ if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Template))
+ return const_cast<NonTypeTemplateParmDecl *>(NTTP);
+ return const_cast<TemplateTemplateParmDecl *>(getTemplate());
+ }
+
+ bool isExpandedParameterPack() const {
+ if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Template))
+ return NTTP->isExpandedParameterPack();
+ return getTemplate()->isExpandedParameterPack();
+ }
+
+ SourceLocation getLocation() const {
+ if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Template))
+ return NTTP->getLocation();
+ return getTemplate()->getLocation();
+ }
+
+ operator bool() const { return Template; }
+private:
+ const NamedDecl *Template;
+};
+
+/// If the given expression is of a form that permits the deduction
+/// of a non-type template parameter, return the declaration of that
+/// non-type template parameter.
+static NonTypeOrVarTemplateParmDecl
+getDeducedNTTParameterFromExpr(const Expr *E, unsigned Depth) {
+ // If we are within an alias template, the expression may have undergone
+ // any number of parameter substitutions already.
+ E = unwrapExpressionForDeduction(E);
if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(DRE->getDecl()))
if (NTTP->getDepth() == Depth)
return NTTP;
+ if (const auto *ULE = dyn_cast<UnresolvedLookupExpr>(E);
+ ULE && (ULE->isConceptReference() || ULE->isVarDeclReference())) {
+ if (auto *TTP = ULE->getTemplateTemplateDecl()) {
+
+ if (TTP->getDepth() == Depth)
+ return TTP;
+ }
+ }
return nullptr;
}
-static const NonTypeTemplateParmDecl *
-getDeducedParameterFromExpr(TemplateDeductionInfo &Info, Expr *E) {
- return getDeducedParameterFromExpr(E, Info.getDeducedDepth());
+static const NonTypeOrVarTemplateParmDecl
+getDeducedNTTParameterFromExpr(TemplateDeductionInfo &Info, Expr *E) {
+ return getDeducedNTTParameterFromExpr(E, Info.getDeducedDepth());
}
/// Determine whether two declaration pointers refer to the same
@@ -386,29 +465,28 @@ checkDeducedTemplateArguments(ASTContext &Context,
/// deduction is funneled through here.
static TemplateDeductionResult
DeduceNonTypeTemplateArgument(Sema &S, TemplateParameterList *TemplateParams,
- const NonTypeTemplateParmDecl *NTTP,
+ const NonTypeOrVarTemplateParmDecl NTTP,
const DeducedTemplateArgument &NewDeduced,
QualType ValueType, TemplateDeductionInfo &Info,
bool PartialOrdering,
SmallVectorImpl<DeducedTemplateArgument> &Deduced,
bool *HasDeducedAnyParam) {
- assert(NTTP->getDepth() == Info.getDeducedDepth() &&
+ assert(NTTP.getDepth() == Info.getDeducedDepth() &&
"deducing non-type template argument with wrong depth");
DeducedTemplateArgument Result = checkDeducedTemplateArguments(
- S.Context, Deduced[NTTP->getIndex()], NewDeduced);
+ S.Context, Deduced[NTTP.getIndex()], NewDeduced);
if (Result.isNull()) {
- Info.Param = const_cast<NonTypeTemplateParmDecl*>(NTTP);
- Info.FirstArg = Deduced[NTTP->getIndex()];
+ Info.Param = NTTP.asTemplateParam();
+ Info.FirstArg = Deduced[NTTP.getIndex()];
Info.SecondArg = NewDeduced;
return TemplateDeductionResult::Inconsistent;
}
-
- Deduced[NTTP->getIndex()] = Result;
+ Deduced[NTTP.getIndex()] = Result;
if (!S.getLangOpts().CPlusPlus17)
return TemplateDeductionResult::Success;
- if (NTTP->isExpandedParameterPack())
+ if (NTTP.isExpandedParameterPack())
// FIXME: We may still need to deduce parts of the type here! But we
// don't have any way to find which slice of the type to use, and the
// type stored on the NTTP itself is nonsense. Perhaps the type of an
@@ -417,7 +495,7 @@ DeduceNonTypeTemplateArgument(Sema &S, TemplateParameterList *TemplateParams,
// Get the type of the parameter for deduction. If it's a (dependent) array
// or function type, we will not have decayed it yet, so do that now.
- QualType ParamType = S.Context.getAdjustedParameterType(NTTP->getType());
+ QualType ParamType = S.Context.getAdjustedParameterType(NTTP.getType());
if (auto *Expansion = dyn_cast<PackExpansionType>(ParamType))
ParamType = Expansion->getPattern();
@@ -444,7 +522,7 @@ DeduceNonTypeTemplateArgument(Sema &S, TemplateParameterList *TemplateParams,
/// from the given integral constant.
static TemplateDeductionResult DeduceNonTypeTemplateArgument(
Sema &S, TemplateParameterList *TemplateParams,
- const NonTypeTemplateParmDecl *NTTP, const llvm::APSInt &Value,
+ NonTypeOrVarTemplateParmDecl NTTP, const llvm::APSInt &Value,
QualType ValueType, bool DeducedFromArrayBound, TemplateDeductionInfo &Info,
bool PartialOrdering, SmallVectorImpl<DeducedTemplateArgument> &Deduced,
bool *HasDeducedAnyParam) {
@@ -459,14 +537,14 @@ static TemplateDeductionResult DeduceNonTypeTemplateArgument(
/// from the given null pointer template argument type.
static TemplateDeductionResult
DeduceNullPtrTemplateArgument(Sema &S, TemplateParameterList *TemplateParams,
- const NonTypeTemplateParmDecl *NTTP,
+ NonTypeOrVarTemplateParmDecl NTTP,
QualType NullPtrType, TemplateDeductionInfo &Info,
bool PartialOrdering,
SmallVectorImpl<DeducedTemplateArgument> &Deduced,
bool *HasDeducedAnyParam) {
Expr *Value = S.ImpCastExprToType(
new (S.Context) CXXNullPtrLiteralExpr(S.Context.NullPtrTy,
- NTTP->getLocation()),
+ NTTP.getLocation()),
NullPtrType,
NullPtrType->isMemberPointerType() ? CK_NullToMemberPointer
: CK_NullToPointer)
@@ -482,7 +560,7 @@ DeduceNullPtrTemplateArgument(Sema &S, TemplateParameterList *TemplateParams,
/// \returns true if deduction succeeded, false otherwise.
static TemplateDeductionResult
DeduceNonTypeTemplateArgument(Sema &S, TemplateParameterList *TemplateParams,
- const NonTypeTemplateParmDecl *NTTP, Expr *Value,
+ NonTypeOrVarTemplateParmDecl NTTP, Expr *Value,
TemplateDeductionInfo &Info, bool PartialOrdering,
SmallVectorImpl<DeducedTemplateArgument> &Deduced,
bool *HasDeducedAnyParam) {
@@ -497,7 +575,7 @@ DeduceNonTypeTemplateArgument(Sema &S, TemplateParameterList *TemplateParams,
/// \returns true if deduction succeeded, false otherwise.
static TemplateDeductionResult
DeduceNonTypeTemplateArgument(Sema &S, TemplateParameterList *TemplateParams,
- const NonTypeTemplateParmDecl *NTTP, ValueDecl *D,
+ NonTypeOrVarTemplateParmDecl NTTP, ValueDecl *D,
QualType T, TemplateDeductionInfo &Info,
bool PartialOrdering,
SmallVectorImpl<DeducedTemplateArgument> &Deduced,
@@ -1930,14 +2008,14 @@ static TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch(
return Result;
// Determine the array bound is something we can deduce.
- const NonTypeTemplateParmDecl *NTTP =
- getDeducedParameterFromExpr(Info, DAP->getSizeExpr());
+ NonTypeOrVarTemplateParmDecl NTTP =
+ getDeducedNTTParameterFromExpr(Info, DAP->getSizeExpr());
if (!NTTP)
return TemplateDeductionResult::Success;
// We can perform template argument deduction for the given non-type
// template parameter.
- assert(NTTP->getDepth() == Info.getDeducedDepth() &&
+ assert(NTTP.getDepth() == Info.getDeducedDepth() &&
"saw non-type template parameter with wrong depth");
if (const auto *CAA = dyn_cast<ConstantArrayType>(AA)) {
llvm::APSInt Size(CAA->getSize());
@@ -1994,10 +2072,10 @@ static TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch(
// deducing through the noexcept-specifier if it's part of the canonical
// type. libstdc++ relies on this.
Expr *NoexceptExpr = FPP->getNoexceptExpr();
- if (const NonTypeTemplateParmDecl *NTTP =
- NoexceptExpr ? getDeducedParameterFromExpr(Info, NoexceptExpr)
+ if (NonTypeOrVarTemplateParmDecl NTTP =
+ NoexceptExpr ? getDeducedNTTParameterFromExpr(Info, NoexceptExpr)
: nullptr) {
- assert(NTTP->getDepth() == Info.getDeducedDepth() &&
+ assert(NTTP.getDepth() == Info.getDeducedDepth() &&
"saw non-type template parameter with wrong depth");
llvm::APSInt Noexcept(1);
@@ -2191,8 +2269,8 @@ static TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch(
return Result;
// Perform deduction on the vector size, if we can.
- const NonTypeTemplateParmDecl *NTTP =
- getDeducedParameterFromExpr(Info, VP->getSizeExpr());
+ NonTypeOrVarTemplateParmDecl NTTP =
+ getDeducedNTTParameterFromExpr(Info, VP->getSizeExpr());
if (!NTTP)
return TemplateDeductionResult::Success;
@@ -2217,8 +2295,8 @@ static TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch(
return Result;
// Perform deduction on the vector size, if we can.
- const NonTypeTemplateParmDecl *NTTP =
- getDeducedParameterFromExpr(Info, VP->getSizeExpr());
+ NonTypeOrVarTemplateParmDecl NTTP =
+ getDeducedNTTParameterFromExpr(Info, VP->getSizeExpr());
if (!NTTP)
return TemplateDeductionResult::Success;
@@ -2246,8 +2324,8 @@ static TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch(
return Result;
// Perform deduction on the vector size, if we can.
- const NonTypeTemplateParmDecl *NTTP =
- getDeducedParameterFromExpr(Info, VP->getSizeExpr());
+ NonTypeOrVarTemplateParmDecl NTTP =
+ getDeducedNTTParameterFromExpr(Info, VP->getSizeExpr());
if (!NTTP)
return TemplateDeductionResult::Success;
@@ -2271,8 +2349,8 @@ static TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch(
return Result;
// Perform deduction on the vector size, if we can.
- const NonTypeTemplateParmDecl *NTTP =
- getDeducedParameterFromExpr(Info, VP->getSizeExpr());
+ NonTypeOrVarTemplateParmDecl NTTP =
+ getDeducedNTTParameterFromExpr(Info, VP->getSizeExpr());
if (!NTTP)
return TemplateDeductionResult::Success;
@@ -2348,8 +2426,8 @@ static TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch(
return TemplateDeductionResult::NonDeducedMismatch;
}
- const NonTypeTemplateParmDecl *NTTP =
- getDeducedParameterFromExpr(Info, ParamExpr);
+ NonTypeOrVarTemplateParmDecl NTTP =
+ getDeducedNTTParameterFromExpr(Info, ParamExpr);
if (!NTTP)
return TemplateDeductionResult::Success;
@@ -2395,8 +2473,8 @@ static TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch(
return Result;
// Perform deduction on the address space, if we can.
- const NonTypeTemplateParmDecl *NTTP =
- getDeducedParameterFromExpr(Info, ASP->getAddrSpaceExpr());
+ NonTypeOrVarTemplateParmDecl NTTP =
+ getDeducedNTTParameterFromExpr(Info, ASP->getAddrSpaceExpr());
if (!NTTP)
return TemplateDeductionResult::Success;
@@ -2420,8 +2498,8 @@ static TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch(
return Result;
// Perform deduction on the address space, if we can.
- const NonTypeTemplateParmDecl *NTTP =
- getDeducedParameterFromExpr(Info, ASP->getAddrSpaceExpr());
+ NonTypeOrVarTemplateParmDecl NTTP =
+ getDeducedNTTParameterFromExpr(Info, ASP->getAddrSpaceExpr());
if (!NTTP)
return TemplateDeductionResult::Success;
@@ -2440,8 +2518,8 @@ static TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch(
if (IP->isUnsigned() != IA->isUnsigned())
return TemplateDeductionResult::NonDeducedMismatch;
- const NonTypeTemplateParmDecl *NTTP =
- getDeducedParameterFromExpr(Info, IP->getNumBitsExpr());
+ NonTypeOrVarTemplateParmDecl NTTP =
+ getDeducedNTTParameterFromExpr(Info, IP->getNumBitsExpr());
if (!NTTP)
return TemplateDeductionResult::Success;
@@ -2573,8 +2651,8 @@ DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams,
return TemplateDeductionResult::NonDeducedMismatch;
case TemplateArgument::Expression:
- if (const NonTypeTemplateParmDecl *NTTP =
- getDeducedParameterFromExpr(Info, P.getAsExpr())) {
+ if (NonTypeOrVarTemplateParmDecl NTTP =
+ getDeducedNTTParameterFromExpr(Info, P.getAsExpr())) {
switch (A.getKind()) {
case TemplateArgument::Expression: {
const Expr *E = A.getAsExpr();
@@ -2628,7 +2706,6 @@ DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams,
}
llvm_unreachable("Unknown template argument kind");
}
-
// Can't deduce anything, but that's okay.
return TemplateDeductionResult::Success;
case TemplateArgument::Pack:
@@ -4392,8 +4469,8 @@ static TemplateDeductionResult DeduceFromInitializerList(
// from the length of the initializer list.
if (auto *DependentArrTy = dyn_cast_or_null<DependentSizedArrayType>(ArrTy)) {
// Determine the array bound is something we can deduce.
- if (const NonTypeTemplateParmDecl *NTTP =
- getDeducedParameterFromExpr(Info, DependentArrTy->getSizeExpr())) {
+ if (NonTypeOrVarTemplateParmDecl NTTP = getDeducedNTTParameterFromExpr(
+ Info, DependentArrTy->getSizeExpr())) {
// We can perform template argument deduction for the given non-type
// template parameter.
// C++ [temp.deduct.type]p13:
@@ -5098,7 +5175,7 @@ static bool CheckDeducedPlaceholderConstraints(Sema &S, const AutoType &Type,
AutoTypeLoc TypeLoc,
QualType Deduced) {
ConstraintSatisfaction Satisfaction;
- ConceptDecl *Concept = Type.getTypeConstraintConcept();
+ ConceptDecl *Concept = cast<ConceptDecl>(Type.getTypeConstraintConcept());
TemplateArgumentListInfo TemplateArgs(TypeLoc.getLAngleLoc(),
TypeLoc.getRAngleLoc());
TemplateArgs.addArgument(
@@ -6654,6 +6731,18 @@ struct MarkUsedTemplateParameterVisitor : DynamicRecursiveASTVisitor {
Used[NTTP->getIndex()] = true;
return true;
}
+
+ bool VisitUnresolvedLookupExpr(UnresolvedLookupExpr *ULE) override {
+ if (ULE->isConceptReference() || ULE->isVarDeclReference()) {
+ if (auto *TTP = ULE->getTemplateTemplateDecl()) {
+ if (TTP->getDepth() == Depth)
+ Used[TTP->getIndex()] = true;
+ }
+ for (auto &TLoc : ULE->template_arguments())
+ DynamicRecursiveASTVisitor::TraverseTemplateArgumentLoc(TLoc);
+ }
+ return true;
+ }
};
}
@@ -6675,17 +6764,28 @@ MarkUsedTemplateParameters(ASTContext &Ctx,
if (const PackExpansionExpr *Expansion = dyn_cast<PackExpansionExpr>(E))
E = Expansion->getPattern();
- const NonTypeTemplateParmDecl *NTTP = getDeducedParameterFromExpr(E, Depth);
- if (!NTTP)
+ E = unwrapExpressionForDeduction(E);
+ if (const auto *ULE = dyn_cast<UnresolvedLookupExpr>(E);
+ ULE && (ULE->isConceptReference() || ULE->isVarDeclReference())) {
+ if (const auto *TTP = ULE->getTemplateTemplateDecl())
+ Used[TTP->getIndex()] = true;
+ for (auto &TLoc : ULE->template_arguments())
+ MarkUsedTemplateParameters(Ctx, TLoc.getArgument(), OnlyDeduced, Depth,
+ Used);
return;
+ }
- if (NTTP->getDepth() == Depth)
- Used[NTTP->getIndex()] = true;
+ const NonTypeOrVarTemplateParmDecl NTTP =
+ getDeducedNTTParameterFromExpr(E, Depth);
+ if (!NTTP)
+ return;
+ if (NTTP.getDepth() == Depth)
+ Used[NTTP.getIndex()] = true;
// In C++17 mode, additional arguments may be deduced from the type of a
// non-type argument.
if (Ctx.getLangOpts().CPlusPlus17)
- MarkUsedTemplateParameters(Ctx, NTTP->getType(), OnlyDeduced, Depth, Used);
+ MarkUsedTemplateParameters(Ctx, NTTP.getType(), OnlyDeduced, Depth, Used);
}
/// Mark the template parameters that are used by the given