[clang] 13fd717 - [clang] Changes to produce sugared converted template arguments
Matheus Izvekov via cfe-commits
cfe-commits at lists.llvm.org
Wed Oct 26 20:50:56 PDT 2022
Author: Matheus Izvekov
Date: 2022-10-27T05:50:00+02:00
New Revision: 13fd717b2217b764c228eec572b11483a675279d
URL: https://github.com/llvm/llvm-project/commit/13fd717b2217b764c228eec572b11483a675279d
DIFF: https://github.com/llvm/llvm-project/commit/13fd717b2217b764c228eec572b11483a675279d.diff
LOG: [clang] Changes to produce sugared converted template arguments
Makes CheckTemplateArgumentList and the template deduction functions
produce a sugared converted argument list in addition to the canonical one.
This is mostly NFC except that we hook this up to a few diagnostics in
SemaOverload.
The infrastructure here will be used in subsequent patches
where we perform a finalized sugared substitution for entities
which we do not unique per specializations on canonical arguments,
and later on will be used for template specialization resugaring.
Signed-off-by: Matheus Izvekov <mizvekov at gmail.com>
Differential Revision: https://reviews.llvm.org/D133874
Added:
Modified:
clang/include/clang/Sema/Sema.h
clang/include/clang/Sema/TemplateDeduction.h
clang/lib/Sema/SemaLookup.cpp
clang/lib/Sema/SemaOverload.cpp
clang/lib/Sema/SemaTemplate.cpp
clang/lib/Sema/SemaTemplateDeduction.cpp
clang/lib/Sema/SemaTemplateInstantiate.cpp
clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
clang/test/SemaCXX/ppc-pair-mma-types.cpp
clang/test/SemaTemplate/deduction.cpp
clang/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index e84e6b22f2817..0fdc69ef7e1df 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -8224,14 +8224,13 @@ class Sema final {
CTAK_DeducedFromArrayBound
};
- bool CheckTemplateArgument(NamedDecl *Param,
- TemplateArgumentLoc &Arg,
- NamedDecl *Template,
- SourceLocation TemplateLoc,
- SourceLocation RAngleLoc,
- unsigned ArgumentPackIndex,
- SmallVectorImpl<TemplateArgument> &Converted,
- CheckTemplateArgumentKind CTAK = CTAK_Specified);
+ bool
+ CheckTemplateArgument(NamedDecl *Param, TemplateArgumentLoc &Arg,
+ NamedDecl *Template, SourceLocation TemplateLoc,
+ SourceLocation RAngleLoc, unsigned ArgumentPackIndex,
+ SmallVectorImpl<TemplateArgument> &SugaredConverted,
+ SmallVectorImpl<TemplateArgument> &CanonicalConverted,
+ CheckTemplateArgumentKind CTAK);
/// Check that the given template arguments can be be provided to
/// the given template, converting the arguments along the way.
@@ -8262,23 +8261,25 @@ class Sema final {
/// the template not being satisfied by the template arguments.
///
/// \returns true if an error occurred, false otherwise.
- bool CheckTemplateArgumentList(TemplateDecl *Template,
- SourceLocation TemplateLoc,
- TemplateArgumentListInfo &TemplateArgs,
- bool PartialTemplateArgs,
- SmallVectorImpl<TemplateArgument> &Converted,
- bool UpdateArgsWithConversions = true,
- bool *ConstraintsNotSatisfied = nullptr);
-
- bool CheckTemplateTypeArgument(TemplateTypeParmDecl *Param,
- TemplateArgumentLoc &Arg,
- SmallVectorImpl<TemplateArgument> &Converted);
+ bool CheckTemplateArgumentList(
+ TemplateDecl *Template, SourceLocation TemplateLoc,
+ TemplateArgumentListInfo &TemplateArgs, bool PartialTemplateArgs,
+ SmallVectorImpl<TemplateArgument> &SugaredConverted,
+ SmallVectorImpl<TemplateArgument> &CanonicalConverted,
+ bool UpdateArgsWithConversions = true,
+ bool *ConstraintsNotSatisfied = nullptr);
+
+ bool CheckTemplateTypeArgument(
+ TemplateTypeParmDecl *Param, TemplateArgumentLoc &Arg,
+ SmallVectorImpl<TemplateArgument> &SugaredConverted,
+ SmallVectorImpl<TemplateArgument> &CanonicalConverted);
bool CheckTemplateArgument(TypeSourceInfo *Arg);
ExprResult CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
QualType InstantiatedParamType, Expr *Arg,
- TemplateArgument &Converted,
- CheckTemplateArgumentKind CTAK = CTAK_Specified);
+ TemplateArgument &SugaredConverted,
+ TemplateArgument &CanonicalConverted,
+ CheckTemplateArgumentKind CTAK);
bool CheckTemplateTemplateArgument(TemplateTemplateParmDecl *Param,
TemplateParameterList *Params,
TemplateArgumentLoc &Arg);
diff --git a/clang/include/clang/Sema/TemplateDeduction.h b/clang/include/clang/Sema/TemplateDeduction.h
index c0af9f3260b6d..ba35a5a744959 100644
--- a/clang/include/clang/Sema/TemplateDeduction.h
+++ b/clang/include/clang/Sema/TemplateDeduction.h
@@ -41,7 +41,7 @@ namespace sema {
/// TemplateDeductionResult value.
class TemplateDeductionInfo {
/// The deduced template argument list.
- TemplateArgumentList *Deduced = nullptr;
+ TemplateArgumentList *DeducedSugared = nullptr, *DeducedCanonical = nullptr;
/// The source location at which template argument
/// deduction is occurring.
@@ -71,8 +71,8 @@ class TemplateDeductionInfo {
/// Create temporary template deduction info for speculatively deducing
/// against a base class of an argument's type.
TemplateDeductionInfo(ForBaseTag, const TemplateDeductionInfo &Info)
- : Deduced(Info.Deduced), Loc(Info.Loc), DeducedDepth(Info.DeducedDepth),
- ExplicitArgs(Info.ExplicitArgs) {}
+ : DeducedSugared(Info.DeducedSugared), Loc(Info.Loc),
+ DeducedDepth(Info.DeducedDepth), ExplicitArgs(Info.ExplicitArgs) {}
/// Returns the location at which template argument is
/// occurring.
@@ -91,10 +91,15 @@ class TemplateDeductionInfo {
return ExplicitArgs;
}
- /// Take ownership of the deduced template argument list.
- TemplateArgumentList *take() {
- TemplateArgumentList *Result = Deduced;
- Deduced = nullptr;
+ /// Take ownership of the deduced template argument lists.
+ TemplateArgumentList *takeSugared() {
+ TemplateArgumentList *Result = DeducedSugared;
+ DeducedSugared = nullptr;
+ return Result;
+ }
+ TemplateArgumentList *takeCanonical() {
+ TemplateArgumentList *Result = DeducedCanonical;
+ DeducedCanonical = nullptr;
return Result;
}
@@ -120,15 +125,20 @@ class TemplateDeductionInfo {
/// Provide an initial template argument list that contains the
/// explicitly-specified arguments.
- void setExplicitArgs(TemplateArgumentList *NewDeduced) {
- Deduced = NewDeduced;
- ExplicitArgs = Deduced->size();
+ void setExplicitArgs(TemplateArgumentList *NewDeducedSugared,
+ TemplateArgumentList *NewDeducedCanonical) {
+ assert(NewDeducedSugared->size() == NewDeducedCanonical->size());
+ DeducedSugared = NewDeducedSugared;
+ DeducedCanonical = NewDeducedCanonical;
+ ExplicitArgs = DeducedSugared->size();
}
/// Provide a new template argument list that contains the
/// results of template argument deduction.
- void reset(TemplateArgumentList *NewDeduced) {
- Deduced = NewDeduced;
+ void reset(TemplateArgumentList *NewDeducedSugared,
+ TemplateArgumentList *NewDeducedCanonical) {
+ DeducedSugared = NewDeducedSugared;
+ DeducedCanonical = NewDeducedCanonical;
}
/// Is a SFINAE diagnostic available?
diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index a144cb40b7abc..845fa2f56df2f 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -3694,11 +3694,11 @@ Sema::LookupLiteralOperator(Scope *S, LookupResult &R,
// is a well-formed template argument for the template parameter.
if (StringLit) {
SFINAETrap Trap(*this);
- SmallVector<TemplateArgument, 1> Checked;
+ SmallVector<TemplateArgument, 1> SugaredChecked, CanonicalChecked;
TemplateArgumentLoc Arg(TemplateArgument(StringLit), StringLit);
- if (CheckTemplateArgument(Params->getParam(0), Arg, FD,
- R.getNameLoc(), R.getNameLoc(), 0,
- Checked) ||
+ if (CheckTemplateArgument(
+ Params->getParam(0), Arg, FD, R.getNameLoc(), R.getNameLoc(),
+ 0, SugaredChecked, CanonicalChecked, CTAK_Specified) ||
Trap.hasErrorOccurred())
IsTemplate = false;
}
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index d3f6d1b256c57..4171b97cf7070 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -640,7 +640,7 @@ clang::MakeDeductionFailureInfo(ASTContext &Context,
auto *Saved = new (Context) DFIDeducedMismatchArgs;
Saved->FirstArg = Info.FirstArg;
Saved->SecondArg = Info.SecondArg;
- Saved->TemplateArgs = Info.take();
+ Saved->TemplateArgs = Info.takeSugared();
Saved->CallArgIndex = Info.CallArgIndex;
Result.Data = Saved;
break;
@@ -669,7 +669,7 @@ clang::MakeDeductionFailureInfo(ASTContext &Context,
}
case Sema::TDK_SubstitutionFailure:
- Result.Data = Info.take();
+ Result.Data = Info.takeSugared();
if (Info.hasSFINAEDiagnostic()) {
PartialDiagnosticAt *Diag = new (Result.Diagnostic) PartialDiagnosticAt(
SourceLocation(), PartialDiagnostic::NullDiagnostic());
@@ -680,7 +680,7 @@ clang::MakeDeductionFailureInfo(ASTContext &Context,
case Sema::TDK_ConstraintsNotSatisfied: {
CNSInfo *Saved = new (Context) CNSInfo;
- Saved->TemplateArgs = Info.take();
+ Saved->TemplateArgs = Info.takeSugared();
Saved->Satisfaction = Info.AssociatedConstraintsSatisfaction;
Result.Data = Saved;
break;
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 7a30a736bff9f..86c7ce1b8ee8a 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -1592,9 +1592,10 @@ NamedDecl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
if (DiagnoseUnexpandedParameterPack(Default, UPPC_DefaultArgument))
return Param;
- TemplateArgument Converted;
- ExprResult DefaultRes =
- CheckTemplateArgument(Param, Param->getType(), Default, Converted);
+ TemplateArgument SugaredConverted, CanonicalConverted;
+ ExprResult DefaultRes = CheckTemplateArgument(
+ Param, Param->getType(), Default, SugaredConverted, CanonicalConverted,
+ CTAK_Specified);
if (DefaultRes.isInvalid()) {
Param->setInvalidDecl();
return Param;
@@ -3844,9 +3845,9 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
// Check that the template argument list is well-formed for this
// template.
- SmallVector<TemplateArgument, 4> Converted;
- if (CheckTemplateArgumentList(Template, TemplateLoc, TemplateArgs,
- false, Converted,
+ SmallVector<TemplateArgument, 4> SugaredConverted, CanonicalConverted;
+ if (CheckTemplateArgumentList(Template, TemplateLoc, TemplateArgs, false,
+ SugaredConverted, CanonicalConverted,
/*UpdateArgsWithConversions=*/true))
return QualType();
@@ -3861,7 +3862,7 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
return QualType();
TemplateArgumentList StackTemplateArgs(TemplateArgumentList::OnStack,
- Converted);
+ CanonicalConverted);
// Only substitute for the innermost template argument list.
MultiLevelTemplateArgumentList TemplateArgLists;
@@ -3914,11 +3915,11 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
return QualType();
}
} else if (auto *BTD = dyn_cast<BuiltinTemplateDecl>(Template)) {
- CanonType = checkBuiltinTemplateIdType(*this, BTD, Converted, TemplateLoc,
- TemplateArgs);
+ CanonType = checkBuiltinTemplateIdType(*this, BTD, CanonicalConverted,
+ TemplateLoc, TemplateArgs);
} else if (Name.isDependent() ||
TemplateSpecializationType::anyDependentTemplateArguments(
- TemplateArgs, Converted)) {
+ TemplateArgs, CanonicalConverted)) {
// This class template specialization is a dependent
// type. Therefore, its canonical type is another class template
// specialization type that contains all of the converted
@@ -3926,7 +3927,8 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
// A<T, T> have identical types when A is declared as:
//
// template<typename T, typename U = T> struct A;
- CanonType = Context.getCanonicalTemplateSpecializationType(Name, Converted);
+ CanonType = Context.getCanonicalTemplateSpecializationType(
+ Name, CanonicalConverted);
// This might work out to be a current instantiation, in which
// case the canonical type needs to be the InjectedClassNameType.
@@ -3970,8 +3972,8 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
// Find the class template specialization declaration that
// corresponds to these arguments.
void *InsertPos = nullptr;
- ClassTemplateSpecializationDecl *Decl
- = ClassTemplate->findSpecialization(Converted, InsertPos);
+ ClassTemplateSpecializationDecl *Decl =
+ ClassTemplate->findSpecialization(CanonicalConverted, InsertPos);
if (!Decl) {
// This is the first time we have referenced this class template
// specialization. Create the canonical declaration and add it to
@@ -3980,7 +3982,8 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
Context, ClassTemplate->getTemplatedDecl()->getTagKind(),
ClassTemplate->getDeclContext(),
ClassTemplate->getTemplatedDecl()->getBeginLoc(),
- ClassTemplate->getLocation(), ClassTemplate, Converted, nullptr);
+ ClassTemplate->getLocation(), ClassTemplate, CanonicalConverted,
+ nullptr);
ClassTemplate->AddSpecialization(Decl, InsertPos);
if (ClassTemplate->isOutOfLine())
Decl->setLexicalDeclContext(ClassTemplate->getLexicalDeclContext());
@@ -3991,7 +3994,8 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
InstantiatingTemplate Inst(*this, TemplateLoc, Decl);
if (!Inst.isInvalid()) {
MultiLevelTemplateArgumentList TemplateArgLists;
- TemplateArgLists.addOuterTemplateArguments(Template, Converted);
+ TemplateArgLists.addOuterTemplateArguments(Template,
+ CanonicalConverted);
InstantiateAttrsForDecl(TemplateArgLists,
ClassTemplate->getTemplatedDecl(), Decl);
}
@@ -4499,9 +4503,9 @@ DeclResult Sema::ActOnVarTemplateSpecialization(
// Check that the template argument list is well-formed for this
// template.
- SmallVector<TemplateArgument, 4> Converted;
+ SmallVector<TemplateArgument, 4> SugaredConverted, CanonicalConverted;
if (CheckTemplateArgumentList(VarTemplate, TemplateNameLoc, TemplateArgs,
- false, Converted,
+ false, SugaredConverted, CanonicalConverted,
/*UpdateArgsWithConversions=*/true))
return true;
@@ -4509,21 +4513,22 @@ DeclResult Sema::ActOnVarTemplateSpecialization(
// corresponds to these arguments.
if (IsPartialSpecialization) {
if (CheckTemplatePartialSpecializationArgs(TemplateNameLoc, VarTemplate,
- TemplateArgs.size(), Converted))
+ TemplateArgs.size(),
+ CanonicalConverted))
return true;
// FIXME: Move these checks to CheckTemplatePartialSpecializationArgs so we
// also do them during instantiation.
if (!Name.isDependent() &&
- !TemplateSpecializationType::anyDependentTemplateArguments(TemplateArgs,
- Converted)) {
+ !TemplateSpecializationType::anyDependentTemplateArguments(
+ TemplateArgs, CanonicalConverted)) {
Diag(TemplateNameLoc, diag::err_partial_spec_fully_specialized)
<< VarTemplate->getDeclName();
IsPartialSpecialization = false;
}
if (isSameAsPrimaryTemplate(VarTemplate->getTemplateParameters(),
- Converted) &&
+ CanonicalConverted) &&
(!Context.getLangOpts().CPlusPlus20 ||
!TemplateParams->hasAssociatedConstraints())) {
// C++ [temp.class.spec]p9b3:
@@ -4544,10 +4549,10 @@ DeclResult Sema::ActOnVarTemplateSpecialization(
VarTemplateSpecializationDecl *PrevDecl = nullptr;
if (IsPartialSpecialization)
- PrevDecl = VarTemplate->findPartialSpecialization(Converted, TemplateParams,
- InsertPos);
+ PrevDecl = VarTemplate->findPartialSpecialization(
+ CanonicalConverted, TemplateParams, InsertPos);
else
- PrevDecl = VarTemplate->findSpecialization(Converted, InsertPos);
+ PrevDecl = VarTemplate->findSpecialization(CanonicalConverted, InsertPos);
VarTemplateSpecializationDecl *Specialization = nullptr;
@@ -4574,7 +4579,7 @@ DeclResult Sema::ActOnVarTemplateSpecialization(
VarTemplatePartialSpecializationDecl::Create(
Context, VarTemplate->getDeclContext(), TemplateKWLoc,
TemplateNameLoc, TemplateParams, VarTemplate, DI->getType(), DI, SC,
- Converted, TemplateArgs);
+ CanonicalConverted, TemplateArgs);
if (!PrevPartial)
VarTemplate->AddPartialSpecialization(Partial, InsertPos);
@@ -4591,7 +4596,7 @@ DeclResult Sema::ActOnVarTemplateSpecialization(
// this explicit specialization or friend declaration.
Specialization = VarTemplateSpecializationDecl::Create(
Context, VarTemplate->getDeclContext(), TemplateKWLoc, TemplateNameLoc,
- VarTemplate, DI->getType(), DI, SC, Converted);
+ VarTemplate, DI->getType(), DI, SC, CanonicalConverted);
Specialization->setTemplateArgsInfo(TemplateArgs);
if (!PrevDecl)
@@ -4669,24 +4674,25 @@ Sema::CheckVarTemplateId(VarTemplateDecl *Template, SourceLocation TemplateLoc,
assert(Template && "A variable template id without template?");
// Check that the template argument list is well-formed for this template.
- SmallVector<TemplateArgument, 4> Converted;
+ SmallVector<TemplateArgument, 4> SugaredConverted, CanonicalConverted;
if (CheckTemplateArgumentList(
Template, TemplateNameLoc,
const_cast<TemplateArgumentListInfo &>(TemplateArgs), false,
- Converted, /*UpdateArgsWithConversions=*/true))
+ SugaredConverted, CanonicalConverted,
+ /*UpdateArgsWithConversions=*/true))
return true;
// Produce a placeholder value if the specialization is dependent.
if (Template->getDeclContext()->isDependentContext() ||
- TemplateSpecializationType::anyDependentTemplateArguments(TemplateArgs,
- Converted))
+ TemplateSpecializationType::anyDependentTemplateArguments(
+ TemplateArgs, CanonicalConverted))
return DeclResult();
// Find the variable template specialization declaration that
// corresponds to these arguments.
void *InsertPos = nullptr;
- if (VarTemplateSpecializationDecl *Spec = Template->findSpecialization(
- Converted, InsertPos)) {
+ if (VarTemplateSpecializationDecl *Spec =
+ Template->findSpecialization(CanonicalConverted, InsertPos)) {
checkSpecializationReachability(TemplateNameLoc, Spec);
// If we already have a variable template specialization, return it.
return Spec;
@@ -4698,7 +4704,7 @@ Sema::CheckVarTemplateId(VarTemplateDecl *Template, SourceLocation TemplateLoc,
// that it represents. That is,
VarDecl *InstantiationPattern = Template->getTemplatedDecl();
TemplateArgumentList TemplateArgList(TemplateArgumentList::OnStack,
- Converted);
+ CanonicalConverted);
TemplateArgumentList *InstantiationArgs = &TemplateArgList;
bool AmbiguousPartialSpec = false;
typedef PartialSpecMatchResult MatchResult;
@@ -4730,7 +4736,7 @@ Sema::CheckVarTemplateId(VarTemplateDecl *Template, SourceLocation TemplateLoc,
} else {
Matched.push_back(PartialSpecMatchResult());
Matched.back().Partial = Partial;
- Matched.back().Args = Info.take();
+ Matched.back().Args = Info.takeCanonical();
}
}
@@ -4786,7 +4792,7 @@ Sema::CheckVarTemplateId(VarTemplateDecl *Template, SourceLocation TemplateLoc,
// FIXME: LateAttrs et al.?
VarTemplateSpecializationDecl *Decl = BuildVarTemplateInstantiation(
Template, InstantiationPattern, *InstantiationArgs, TemplateArgs,
- Converted, TemplateNameLoc /*, LateAttrs, StartingScope*/);
+ CanonicalConverted, TemplateNameLoc /*, LateAttrs, StartingScope*/);
if (!Decl)
return true;
@@ -4857,22 +4863,22 @@ Sema::CheckConceptTemplateId(const CXXScopeSpec &SS,
const TemplateArgumentListInfo *TemplateArgs) {
assert(NamedConcept && "A concept template id without a template?");
- llvm::SmallVector<TemplateArgument, 4> Converted;
- if (CheckTemplateArgumentList(NamedConcept, ConceptNameInfo.getLoc(),
- const_cast<TemplateArgumentListInfo&>(*TemplateArgs),
- /*PartialTemplateArgs=*/false, Converted,
- /*UpdateArgsWithConversions=*/false))
+ llvm::SmallVector<TemplateArgument, 4> SugaredConverted, CanonicalConverted;
+ if (CheckTemplateArgumentList(
+ NamedConcept, ConceptNameInfo.getLoc(),
+ const_cast<TemplateArgumentListInfo &>(*TemplateArgs),
+ /*PartialTemplateArgs=*/false, SugaredConverted, CanonicalConverted,
+ /*UpdateArgsWithConversions=*/false))
return ExprError();
auto *CSD = ImplicitConceptSpecializationDecl::Create(
Context, NamedConcept->getDeclContext(), NamedConcept->getLocation(),
- Converted);
+ CanonicalConverted);
ConstraintSatisfaction Satisfaction;
bool AreArgsDependent =
- TemplateSpecializationType::anyDependentTemplateArguments(*TemplateArgs,
- Converted);
- MultiLevelTemplateArgumentList MLTAL;
- MLTAL.addOuterTemplateArguments(NamedConcept, Converted);
+ TemplateSpecializationType::anyDependentTemplateArguments(
+ *TemplateArgs, CanonicalConverted);
+ MultiLevelTemplateArgumentList MLTAL(NamedConcept, CanonicalConverted);
LocalInstantiationScope Scope(*this);
EnterExpressionEvaluationContext EECtx{
@@ -5132,9 +5138,10 @@ TemplateNameKind Sema::ActOnTemplateName(Scope *S,
return TNK_Non_template;
}
-bool Sema::CheckTemplateTypeArgument(TemplateTypeParmDecl *Param,
- TemplateArgumentLoc &AL,
- SmallVectorImpl<TemplateArgument> &Converted) {
+bool Sema::CheckTemplateTypeArgument(
+ TemplateTypeParmDecl *Param, TemplateArgumentLoc &AL,
+ SmallVectorImpl<TemplateArgument> &SugaredConverted,
+ SmallVectorImpl<TemplateArgument> &CanonicalConverted) {
const TemplateArgument &Arg = AL.getArgument();
QualType ArgType;
TypeSourceInfo *TSI = nullptr;
@@ -5227,9 +5234,6 @@ bool Sema::CheckTemplateTypeArgument(TemplateTypeParmDecl *Param,
if (CheckTemplateArgument(TSI))
return true;
- // Add the converted template type argument.
- ArgType = Context.getCanonicalType(ArgType);
-
// Objective-C ARC:
// If an explicitly-specified template argument type is a lifetime type
// with no lifetime qualifier, the __strong lifetime qualifier is inferred.
@@ -5241,7 +5245,9 @@ bool Sema::CheckTemplateTypeArgument(TemplateTypeParmDecl *Param,
ArgType = Context.getQualifiedType(ArgType, Qs);
}
- Converted.push_back(TemplateArgument(ArgType));
+ SugaredConverted.push_back(TemplateArgument(ArgType));
+ CanonicalConverted.push_back(
+ TemplateArgument(Context.getCanonicalType(ArgType)));
return false;
}
@@ -5547,17 +5553,17 @@ convertTypeTemplateArgumentToTemplate(ASTContext &Context, TypeLoc TLoc) {
/// explicitly written, deduced, etc.
///
/// \returns true on error, false otherwise.
-bool Sema::CheckTemplateArgument(NamedDecl *Param,
- TemplateArgumentLoc &Arg,
- NamedDecl *Template,
- SourceLocation TemplateLoc,
- SourceLocation RAngleLoc,
- unsigned ArgumentPackIndex,
- SmallVectorImpl<TemplateArgument> &Converted,
- CheckTemplateArgumentKind CTAK) {
+bool Sema::CheckTemplateArgument(
+ NamedDecl *Param, TemplateArgumentLoc &Arg, NamedDecl *Template,
+ SourceLocation TemplateLoc, SourceLocation RAngleLoc,
+ unsigned ArgumentPackIndex,
+ SmallVectorImpl<TemplateArgument> &SugaredConverted,
+ SmallVectorImpl<TemplateArgument> &CanonicalConverted,
+ CheckTemplateArgumentKind CTAK) {
// Check template type parameters.
if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
- return CheckTemplateTypeArgument(TTP, Arg, Converted);
+ return CheckTemplateTypeArgument(TTP, Arg, SugaredConverted,
+ CanonicalConverted);
// Check non-type template parameters.
if (NonTypeTemplateParmDecl *NTTP =dyn_cast<NonTypeTemplateParmDecl>(Param)) {
@@ -5572,14 +5578,14 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param,
!isa<TemplateTemplateParmDecl>(Template) &&
!Template->getDeclContext()->isDependentContext()) {
// Do substitution on the type of the non-type template parameter.
- InstantiatingTemplate Inst(*this, TemplateLoc, Template,
- NTTP, Converted,
+ InstantiatingTemplate Inst(*this, TemplateLoc, Template, NTTP,
+ CanonicalConverted,
SourceRange(TemplateLoc, RAngleLoc));
if (Inst.isInvalid())
return true;
TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack,
- Converted);
+ CanonicalConverted);
MultiLevelTemplateArgumentList MLTAL(Template, TemplateArgs.asArray());
// If the parameter is a pack expansion, expand this slice of the pack.
@@ -5607,11 +5613,11 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param,
llvm_unreachable("Should never see a NULL template argument here");
case TemplateArgument::Expression: {
- TemplateArgument Result;
+ Expr *E = Arg.getArgument().getAsExpr();
+ TemplateArgument SugaredResult, CanonicalResult;
unsigned CurSFINAEErrors = NumSFINAEErrors;
- ExprResult Res =
- CheckTemplateArgument(NTTP, NTTPType, Arg.getArgument().getAsExpr(),
- Result, CTAK);
+ ExprResult Res = CheckTemplateArgument(NTTP, NTTPType, E, SugaredResult,
+ CanonicalResult, CTAK);
if (Res.isInvalid())
return true;
// If the current template argument causes an error, give up now.
@@ -5620,12 +5626,13 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param,
// If the resulting expression is new, then use it in place of the
// old expression in the template argument.
- if (Res.get() != Arg.getArgument().getAsExpr()) {
+ if (Res.get() != E) {
TemplateArgument TA(Res.get());
Arg = TemplateArgumentLoc(TA, Res.get());
}
- Converted.push_back(Result);
+ SugaredConverted.push_back(SugaredResult);
+ CanonicalConverted.push_back(CanonicalResult);
break;
}
@@ -5634,7 +5641,9 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param,
case TemplateArgument::NullPtr:
// We've already checked this template argument, so just copy
// it to the list of converted arguments.
- Converted.push_back(Arg.getArgument());
+ SugaredConverted.push_back(Arg.getArgument());
+ CanonicalConverted.push_back(
+ Context.getCanonicalTemplateArgument(Arg.getArgument()));
break;
case TemplateArgument::Template:
@@ -5670,12 +5679,14 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param,
return true;
}
- TemplateArgument Result;
- E = CheckTemplateArgument(NTTP, NTTPType, E.get(), Result);
+ TemplateArgument SugaredResult, CanonicalResult;
+ E = CheckTemplateArgument(NTTP, NTTPType, E.get(), SugaredResult,
+ CanonicalResult, CTAK_Specified);
if (E.isInvalid())
return true;
- Converted.push_back(Result);
+ SugaredConverted.push_back(SugaredResult);
+ CanonicalConverted.push_back(CanonicalResult);
break;
}
@@ -5733,14 +5744,14 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param,
// Set up a template instantiation context.
LocalInstantiationScope Scope(*this);
InstantiatingTemplate Inst(*this, TemplateLoc, Template, TempParm,
- Converted, SourceRange(TemplateLoc, RAngleLoc));
+ SugaredConverted,
+ SourceRange(TemplateLoc, RAngleLoc));
if (Inst.isInvalid())
return true;
- TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, Converted);
Params = SubstTemplateParams(
Params, CurContext,
- MultiLevelTemplateArgumentList(Template, TemplateArgs.asArray()));
+ MultiLevelTemplateArgumentList(Template, CanonicalConverted));
if (!Params)
return true;
}
@@ -5765,7 +5776,8 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param,
if (CheckTemplateTemplateArgument(TempParm, Params, Arg))
return true;
- Converted.push_back(
+ SugaredConverted.push_back(Arg.getArgument());
+ CanonicalConverted.push_back(
Context.getCanonicalTemplateArgument(Arg.getArgument()));
break;
@@ -5833,7 +5845,8 @@ static bool diagnoseMissingArgument(Sema &S, SourceLocation Loc,
bool Sema::CheckTemplateArgumentList(
TemplateDecl *Template, SourceLocation TemplateLoc,
TemplateArgumentListInfo &TemplateArgs, bool PartialTemplateArgs,
- SmallVectorImpl<TemplateArgument> &Converted,
+ SmallVectorImpl<TemplateArgument> &SugaredConverted,
+ SmallVectorImpl<TemplateArgument> &CanonicalConverted,
bool UpdateArgsWithConversions, bool *ConstraintsNotSatisfied) {
if (ConstraintsNotSatisfied)
@@ -5859,7 +5872,8 @@ bool Sema::CheckTemplateArgumentList(
// corresponding parameter declared by the template in its
// template-parameter-list.
bool isTemplateTemplateParameter = isa<TemplateTemplateParmDecl>(Template);
- SmallVector<TemplateArgument, 2> ArgumentPack;
+ SmallVector<TemplateArgument, 2> SugaredArgumentPack;
+ SmallVector<TemplateArgument, 2> CanonicalArgumentPack;
unsigned ArgIdx = 0, NumArgs = NewArgs.size();
LocalInstantiationScope InstScope(*this, true);
for (TemplateParameterList::iterator Param = Params->begin(),
@@ -5868,12 +5882,16 @@ bool Sema::CheckTemplateArgumentList(
// If we have an expanded parameter pack, make sure we don't have too
// many arguments.
if (Optional<unsigned> Expansions = getExpandedPackSize(*Param)) {
- if (*Expansions == ArgumentPack.size()) {
+ if (*Expansions == SugaredArgumentPack.size()) {
// We're done with this parameter pack. Pack up its arguments and add
// them to the list.
- Converted.push_back(
- TemplateArgument::CreatePackCopy(Context, ArgumentPack));
- ArgumentPack.clear();
+ SugaredConverted.push_back(
+ TemplateArgument::CreatePackCopy(Context, SugaredArgumentPack));
+ SugaredArgumentPack.clear();
+
+ CanonicalConverted.push_back(
+ TemplateArgument::CreatePackCopy(Context, CanonicalArgumentPack));
+ CanonicalArgumentPack.clear();
// This argument is assigned to the next parameter.
++Param;
@@ -5892,9 +5910,10 @@ bool Sema::CheckTemplateArgumentList(
if (ArgIdx < NumArgs) {
// Check the template argument we were given.
- if (CheckTemplateArgument(*Param, NewArgs[ArgIdx], Template,
- TemplateLoc, RAngleLoc,
- ArgumentPack.size(), Converted))
+ if (CheckTemplateArgument(*Param, NewArgs[ArgIdx], Template, TemplateLoc,
+ RAngleLoc, SugaredArgumentPack.size(),
+ SugaredConverted, CanonicalConverted,
+ CTAK_Specified))
return true;
bool PackExpansionIntoNonPack =
@@ -5923,7 +5942,8 @@ bool Sema::CheckTemplateArgumentList(
// deduced argument and place it on the argument pack. Note that we
// stay on the same template parameter so that we can deduce more
// arguments.
- ArgumentPack.push_back(Converted.pop_back_val());
+ SugaredArgumentPack.push_back(SugaredConverted.pop_back_val());
+ CanonicalArgumentPack.push_back(CanonicalConverted.pop_back_val());
} else {
// Move to the next template parameter.
++Param;
@@ -5933,17 +5953,25 @@ bool Sema::CheckTemplateArgumentList(
// the remaining arguments, because we don't know what parameters they'll
// match up with.
if (PackExpansionIntoNonPack) {
- if (!ArgumentPack.empty()) {
+ if (!SugaredArgumentPack.empty()) {
// If we were part way through filling in an expanded parameter pack,
// fall back to just producing individual arguments.
- for (const TemplateArgument &I : ArgumentPack)
- Converted.push_back(Context.getCanonicalTemplateArgument(I));
- ArgumentPack.clear();
+ SugaredConverted.insert(SugaredConverted.end(),
+ SugaredArgumentPack.begin(),
+ SugaredArgumentPack.end());
+ SugaredArgumentPack.clear();
+
+ CanonicalConverted.insert(CanonicalConverted.end(),
+ CanonicalArgumentPack.begin(),
+ CanonicalArgumentPack.end());
+ CanonicalArgumentPack.clear();
}
while (ArgIdx < NumArgs) {
- Converted.push_back(Context.getCanonicalTemplateArgument(
- NewArgs[ArgIdx].getArgument()));
+ const TemplateArgument &Arg = NewArgs[ArgIdx].getArgument();
+ SugaredConverted.push_back(Arg);
+ CanonicalConverted.push_back(
+ Context.getCanonicalTemplateArgument(Arg));
++ArgIdx;
}
@@ -5955,9 +5983,12 @@ bool Sema::CheckTemplateArgumentList(
// If we're checking a partial template argument list, we're done.
if (PartialTemplateArgs) {
- if ((*Param)->isTemplateParameterPack() && !ArgumentPack.empty())
- Converted.push_back(
- TemplateArgument::CreatePackCopy(Context, ArgumentPack));
+ if ((*Param)->isTemplateParameterPack() && !SugaredArgumentPack.empty()) {
+ SugaredConverted.push_back(
+ TemplateArgument::CreatePackCopy(Context, SugaredArgumentPack));
+ CanonicalConverted.push_back(
+ TemplateArgument::CreatePackCopy(Context, CanonicalArgumentPack));
+ }
return false;
}
@@ -5973,9 +6004,13 @@ bool Sema::CheckTemplateArgumentList(
if (Param + 1 != ParamEnd)
return true;
- Converted.push_back(
- TemplateArgument::CreatePackCopy(Context, ArgumentPack));
- ArgumentPack.clear();
+ SugaredConverted.push_back(
+ TemplateArgument::CreatePackCopy(Context, SugaredArgumentPack));
+ SugaredArgumentPack.clear();
+
+ CanonicalConverted.push_back(
+ TemplateArgument::CreatePackCopy(Context, CanonicalArgumentPack));
+ CanonicalArgumentPack.clear();
++Param;
continue;
@@ -5994,12 +6029,8 @@ bool Sema::CheckTemplateArgumentList(
return diagnoseMissingArgument(*this, TemplateLoc, Template, TTP,
NewArgs);
- TypeSourceInfo *ArgType = SubstDefaultTemplateArgument(*this,
- Template,
- TemplateLoc,
- RAngleLoc,
- TTP,
- Converted);
+ TypeSourceInfo *ArgType = SubstDefaultTemplateArgument(
+ *this, Template, TemplateLoc, RAngleLoc, TTP, CanonicalConverted);
if (!ArgType)
return true;
@@ -6011,11 +6042,8 @@ bool Sema::CheckTemplateArgumentList(
return diagnoseMissingArgument(*this, TemplateLoc, Template, NTTP,
NewArgs);
- ExprResult E = SubstDefaultTemplateArgument(*this, Template,
- TemplateLoc,
- RAngleLoc,
- NTTP,
- Converted);
+ ExprResult E = SubstDefaultTemplateArgument(
+ *this, Template, TemplateLoc, RAngleLoc, NTTP, CanonicalConverted);
if (E.isInvalid())
return true;
@@ -6030,12 +6058,9 @@ bool Sema::CheckTemplateArgumentList(
NewArgs);
NestedNameSpecifierLoc QualifierLoc;
- TemplateName Name = SubstDefaultTemplateArgument(*this, Template,
- TemplateLoc,
- RAngleLoc,
- TempParm,
- Converted,
- QualifierLoc);
+ TemplateName Name = SubstDefaultTemplateArgument(
+ *this, Template, TemplateLoc, RAngleLoc, TempParm, CanonicalConverted,
+ QualifierLoc);
if (Name.isNull())
return true;
@@ -6048,14 +6073,16 @@ bool Sema::CheckTemplateArgumentList(
// the default template argument. We're not actually instantiating a
// template here, we just create this object to put a note into the
// context stack.
- InstantiatingTemplate Inst(*this, RAngleLoc, Template, *Param, Converted,
+ InstantiatingTemplate Inst(*this, RAngleLoc, Template, *Param,
+ CanonicalConverted,
SourceRange(TemplateLoc, RAngleLoc));
if (Inst.isInvalid())
return true;
// Check the default template argument.
- if (CheckTemplateArgument(*Param, Arg, Template, TemplateLoc,
- RAngleLoc, 0, Converted))
+ if (CheckTemplateArgument(*Param, Arg, Template, TemplateLoc, RAngleLoc, 0,
+ SugaredConverted, CanonicalConverted,
+ CTAK_Specified))
return true;
// Core issue 150 (assumed resolution): if this is a template template
@@ -6075,9 +6102,12 @@ bool Sema::CheckTemplateArgumentList(
// still dependent).
if (ArgIdx < NumArgs && CurrentInstantiationScope &&
CurrentInstantiationScope->getPartiallySubstitutedPack()) {
- while (ArgIdx < NumArgs && NewArgs[ArgIdx].getArgument().isPackExpansion())
- Converted.push_back(Context.getCanonicalTemplateArgument(
- NewArgs[ArgIdx++].getArgument()));
+ while (ArgIdx < NumArgs &&
+ NewArgs[ArgIdx].getArgument().isPackExpansion()) {
+ const TemplateArgument &Arg = NewArgs[ArgIdx++].getArgument();
+ SugaredConverted.push_back(Arg);
+ CanonicalConverted.push_back(Context.getCanonicalTemplateArgument(Arg));
+ }
}
// If we have any leftover arguments, then there were too many arguments.
@@ -6100,7 +6130,7 @@ bool Sema::CheckTemplateArgumentList(
if (!PartialTemplateArgs) {
TemplateArgumentList StackTemplateArgs(TemplateArgumentList::OnStack,
- Converted);
+ CanonicalConverted);
// Setup the context/ThisScope for the case where we are needing to
// re-instantiate constraints outside of normal instantiation.
DeclContext *NewContext = Template->getDeclContext();
@@ -6617,12 +6647,9 @@ static bool CheckTemplateArgumentIsCompatibleWithParameter(
/// Checks whether the given template argument is the address
/// of an object or function according to C++ [temp.arg.nontype]p1.
-static bool
-CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S,
- NonTypeTemplateParmDecl *Param,
- QualType ParamType,
- Expr *ArgIn,
- TemplateArgument &Converted) {
+static bool CheckTemplateArgumentAddressOfObjectOrFunction(
+ Sema &S, NonTypeTemplateParmDecl *Param, QualType ParamType, Expr *ArgIn,
+ TemplateArgument &SugaredConverted, TemplateArgument &CanonicalConverted) {
bool Invalid = false;
Expr *Arg = ArgIn;
QualType ArgType = Arg->getType();
@@ -6726,8 +6753,11 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S,
Entity)) {
case NPV_NullPointer:
S.Diag(Arg->getExprLoc(), diag::warn_cxx98_compat_template_arg_null);
- Converted = TemplateArgument(S.Context.getCanonicalType(ParamType),
- /*isNullPtr=*/true);
+ SugaredConverted = TemplateArgument(ParamType,
+ /*isNullPtr=*/true);
+ CanonicalConverted =
+ TemplateArgument(S.Context.getCanonicalType(ParamType),
+ /*isNullPtr=*/true);
return false;
case NPV_Error:
@@ -6741,7 +6771,9 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S,
// Stop checking the precise nature of the argument if it is value dependent,
// it should be checked when instantiated.
if (Arg->isValueDependent()) {
- Converted = TemplateArgument(ArgIn);
+ SugaredConverted = TemplateArgument(ArgIn);
+ CanonicalConverted =
+ S.Context.getCanonicalTemplateArgument(SugaredConverted);
return false;
}
@@ -6871,19 +6903,21 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S,
return true;
// Create the template argument.
- Converted = TemplateArgument(cast<ValueDecl>(Entity->getCanonicalDecl()),
- S.Context.getCanonicalType(ParamType));
+ SugaredConverted = TemplateArgument(Entity, ParamType);
+ CanonicalConverted =
+ TemplateArgument(cast<ValueDecl>(Entity->getCanonicalDecl()),
+ S.Context.getCanonicalType(ParamType));
S.MarkAnyDeclReferenced(Arg->getBeginLoc(), Entity, false);
return false;
}
/// Checks whether the given template argument is a pointer to
/// member constant according to C++ [temp.arg.nontype]p1.
-static bool CheckTemplateArgumentPointerToMember(Sema &S,
- NonTypeTemplateParmDecl *Param,
- QualType ParamType,
- Expr *&ResultArg,
- TemplateArgument &Converted) {
+static bool
+CheckTemplateArgumentPointerToMember(Sema &S, NonTypeTemplateParmDecl *Param,
+ QualType ParamType, Expr *&ResultArg,
+ TemplateArgument &SugaredConverted,
+ TemplateArgument &CanonicalConverted) {
bool Invalid = false;
Expr *Arg = ResultArg;
@@ -6931,10 +6965,14 @@ static bool CheckTemplateArgumentPointerToMember(Sema &S,
if (VD->getType()->isMemberPointerType()) {
if (isa<NonTypeTemplateParmDecl>(VD)) {
if (Arg->isTypeDependent() || Arg->isValueDependent()) {
- Converted = TemplateArgument(Arg);
+ SugaredConverted = TemplateArgument(Arg);
+ CanonicalConverted =
+ S.Context.getCanonicalTemplateArgument(SugaredConverted);
} else {
- VD = cast<ValueDecl>(VD->getCanonicalDecl());
- Converted = TemplateArgument(VD, ParamType);
+ SugaredConverted = TemplateArgument(VD, ParamType);
+ CanonicalConverted =
+ TemplateArgument(cast<ValueDecl>(VD->getCanonicalDecl()),
+ S.Context.getCanonicalType(ParamType));
}
return Invalid;
}
@@ -6952,8 +6990,10 @@ static bool CheckTemplateArgumentPointerToMember(Sema &S,
return true;
case NPV_NullPointer:
S.Diag(ResultArg->getExprLoc(), diag::warn_cxx98_compat_template_arg_null);
- Converted = TemplateArgument(S.Context.getCanonicalType(ParamType),
- /*isNullPtr*/true);
+ SugaredConverted = TemplateArgument(ParamType,
+ /*isNullPtr*/ true);
+ CanonicalConverted = TemplateArgument(S.Context.getCanonicalType(ParamType),
+ /*isNullPtr*/ true);
return false;
case NPV_NotNullPointer:
break;
@@ -6990,10 +7030,15 @@ static bool CheckTemplateArgumentPointerToMember(Sema &S,
// Okay: this is the address of a non-static member, and therefore
// a member pointer constant.
if (Arg->isTypeDependent() || Arg->isValueDependent()) {
- Converted = TemplateArgument(Arg);
+ SugaredConverted = TemplateArgument(Arg);
+ CanonicalConverted =
+ S.Context.getCanonicalTemplateArgument(SugaredConverted);
} else {
- ValueDecl *D = cast<ValueDecl>(DRE->getDecl()->getCanonicalDecl());
- Converted = TemplateArgument(D, S.Context.getCanonicalType(ParamType));
+ ValueDecl *D = DRE->getDecl();
+ SugaredConverted = TemplateArgument(D, ParamType);
+ CanonicalConverted =
+ TemplateArgument(cast<ValueDecl>(D->getCanonicalDecl()),
+ S.Context.getCanonicalType(ParamType));
}
return Invalid;
}
@@ -7014,7 +7059,8 @@ static bool CheckTemplateArgumentPointerToMember(Sema &S,
/// type of the non-type template parameter after it has been instantiated.
ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
QualType ParamType, Expr *Arg,
- TemplateArgument &Converted,
+ TemplateArgument &SugaredConverted,
+ TemplateArgument &CanonicalConverted,
CheckTemplateArgumentKind CTAK) {
SourceLocation StartLoc = Arg->getBeginLoc();
@@ -7029,7 +7075,9 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
if (CTAK == CTAK_Deduced && Arg->isTypeDependent()) {
auto *AT = dyn_cast<AutoType>(DeducedT);
if (AT && AT->isDecltypeAuto()) {
- Converted = TemplateArgument(Arg);
+ SugaredConverted = TemplateArgument(Arg);
+ CanonicalConverted = TemplateArgument(
+ Context.getCanonicalTemplateArgument(SugaredConverted));
return Arg;
}
}
@@ -7107,7 +7155,9 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
// work. Similarly for CTAD, when comparing 'A<x>' against 'A'.
if ((ParamType->isDependentType() || Arg->isTypeDependent()) &&
!Arg->getType()->getContainedDeducedType()) {
- Converted = TemplateArgument(Arg);
+ SugaredConverted = TemplateArgument(Arg);
+ CanonicalConverted = TemplateArgument(
+ Context.getCanonicalTemplateArgument(SugaredConverted));
return Arg;
}
// FIXME: This attempts to implement C++ [temp.deduct.type]p17. Per DR1770,
@@ -7144,7 +7194,9 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
PackExpansionExpr(E.get()->getType(), E.get(), PE->getEllipsisLoc(),
PE->getNumExpansions());
}
- Converted = TemplateArgument(E.get());
+ SugaredConverted = TemplateArgument(E.get());
+ CanonicalConverted = TemplateArgument(
+ Context.getCanonicalTemplateArgument(SugaredConverted));
return E;
}
@@ -7169,11 +7221,16 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
Context.hasSameUnqualifiedType(ParamType, InnerArg->getType())) {
NamedDecl *ND = cast<DeclRefExpr>(InnerArg)->getDecl();
if (auto *TPO = dyn_cast<TemplateParamObjectDecl>(ND)) {
- Converted = TemplateArgument(TPO, CanonParamType);
+
+ SugaredConverted = TemplateArgument(TPO, ParamType);
+ CanonicalConverted =
+ TemplateArgument(TPO->getCanonicalDecl(), CanonParamType);
return Arg;
}
if (isa<NonTypeTemplateParmDecl>(ND)) {
- Converted = TemplateArgument(Arg);
+ SugaredConverted = TemplateArgument(Arg);
+ CanonicalConverted =
+ Context.getCanonicalTemplateArgument(SugaredConverted);
return Arg;
}
}
@@ -7190,7 +7247,9 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
// For a value-dependent argument, CheckConvertedConstantExpression is
// permitted (and expected) to be unable to determine a value.
if (ArgResult.get()->isValueDependent()) {
- Converted = TemplateArgument(ArgResult.get());
+ SugaredConverted = TemplateArgument(ArgResult.get());
+ CanonicalConverted =
+ Context.getCanonicalTemplateArgument(SugaredConverted);
return ArgResult;
}
@@ -7198,14 +7257,17 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
switch (Value.getKind()) {
case APValue::None:
assert(ParamType->isNullPtrType());
- Converted = TemplateArgument(CanonParamType, /*isNullPtr*/true);
+ SugaredConverted = TemplateArgument(ParamType, /*isNullPtr=*/true);
+ CanonicalConverted = TemplateArgument(CanonParamType, /*isNullPtr=*/true);
break;
case APValue::Indeterminate:
llvm_unreachable("result of constant evaluation should be initialized");
break;
case APValue::Int:
assert(ParamType->isIntegralOrEnumerationType());
- Converted = TemplateArgument(Context, Value.getInt(), CanonParamType);
+ SugaredConverted = TemplateArgument(Context, Value.getInt(), ParamType);
+ CanonicalConverted =
+ TemplateArgument(Context, Value.getInt(), CanonParamType);
break;
case APValue::MemberPointer: {
assert(ParamType->isMemberPointerType());
@@ -7220,8 +7282,12 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
}
auto *VD = const_cast<ValueDecl*>(Value.getMemberPointerDecl());
- Converted = VD ? TemplateArgument(VD, CanonParamType)
- : TemplateArgument(CanonParamType, /*isNullPtr*/true);
+ SugaredConverted = VD ? TemplateArgument(VD, ParamType)
+ : TemplateArgument(ParamType, /*isNullPtr=*/true);
+ CanonicalConverted =
+ VD ? TemplateArgument(cast<ValueDecl>(VD->getCanonicalDecl()),
+ CanonParamType)
+ : TemplateArgument(CanonParamType, /*isNullPtr=*/true);
break;
}
case APValue::LValue: {
@@ -7261,17 +7327,25 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
"null reference should not be a constant expression");
assert((!VD || !ParamType->isNullPtrType()) &&
"non-null value of type nullptr_t?");
- Converted = VD ? TemplateArgument(VD, CanonParamType)
- : TemplateArgument(CanonParamType, /*isNullPtr*/true);
+
+ SugaredConverted = VD ? TemplateArgument(VD, ParamType)
+ : TemplateArgument(ParamType, /*isNullPtr=*/true);
+ CanonicalConverted =
+ VD ? TemplateArgument(cast<ValueDecl>(VD->getCanonicalDecl()),
+ CanonParamType)
+ : TemplateArgument(CanonParamType, /*isNullPtr=*/true);
break;
}
case APValue::Struct:
- case APValue::Union:
+ case APValue::Union: {
// Get or create the corresponding template parameter object.
- Converted = TemplateArgument(
- Context.getTemplateParamObjectDecl(CanonParamType, Value),
- CanonParamType);
+ TemplateParamObjectDecl *D =
+ Context.getTemplateParamObjectDecl(ParamType, Value);
+ SugaredConverted = TemplateArgument(D, ParamType);
+ CanonicalConverted =
+ TemplateArgument(D->getCanonicalDecl(), CanonParamType);
break;
+ }
case APValue::AddrLabelDiff:
return Diag(StartLoc, diag::err_non_type_template_arg_addr_label_
diff );
case APValue::FixedPoint:
@@ -7321,7 +7395,9 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
// We can't check arbitrary value-dependent arguments.
if (ArgResult.get()->isValueDependent()) {
- Converted = TemplateArgument(ArgResult.get());
+ SugaredConverted = TemplateArgument(ArgResult.get());
+ CanonicalConverted =
+ Context.getCanonicalTemplateArgument(SugaredConverted);
return ArgResult;
}
@@ -7335,8 +7411,9 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
? Context.getIntWidth(IntegerType)
: Context.getTypeSize(IntegerType));
- Converted = TemplateArgument(Context, Value,
- Context.getCanonicalType(ParamType));
+ SugaredConverted = TemplateArgument(Context, Value, ParamType);
+ CanonicalConverted =
+ TemplateArgument(Context, Value, Context.getCanonicalType(ParamType));
return ArgResult;
}
@@ -7406,13 +7483,16 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
if (Arg->isValueDependent()) {
// The argument is value-dependent. Create a new
// TemplateArgument with the converted expression.
- Converted = TemplateArgument(Arg);
+ SugaredConverted = TemplateArgument(Arg);
+ CanonicalConverted =
+ Context.getCanonicalTemplateArgument(SugaredConverted);
return Arg;
}
- QualType IntegerType = Context.getCanonicalType(ParamType);
- if (const EnumType *Enum = IntegerType->getAs<EnumType>())
- IntegerType = Context.getCanonicalType(Enum->getDecl()->getIntegerType());
+ QualType IntegerType = ParamType;
+ if (const EnumType *Enum = IntegerType->getAs<EnumType>()) {
+ IntegerType = Enum->getDecl()->getIntegerType();
+ }
if (ParamType->isBooleanType()) {
// Value must be zero or one.
@@ -7458,10 +7538,10 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
}
}
- Converted = TemplateArgument(Context, Value,
- ParamType->isEnumeralType()
- ? Context.getCanonicalType(ParamType)
- : IntegerType);
+ QualType T = ParamType->isEnumeralType() ? ParamType : IntegerType;
+ SugaredConverted = TemplateArgument(Context, Value, T);
+ CanonicalConverted =
+ TemplateArgument(Context, Value, Context.getCanonicalType(T));
return Arg;
}
@@ -7506,15 +7586,15 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
}
if (!ParamType->isMemberPointerType()) {
- if (CheckTemplateArgumentAddressOfObjectOrFunction(*this, Param,
- ParamType,
- Arg, Converted))
+ if (CheckTemplateArgumentAddressOfObjectOrFunction(
+ *this, Param, ParamType, Arg, SugaredConverted,
+ CanonicalConverted))
return ExprError();
return Arg;
}
- if (CheckTemplateArgumentPointerToMember(*this, Param, ParamType, Arg,
- Converted))
+ if (CheckTemplateArgumentPointerToMember(
+ *this, Param, ParamType, Arg, SugaredConverted, CanonicalConverted))
return ExprError();
return Arg;
}
@@ -7527,9 +7607,8 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
assert(ParamType->getPointeeType()->isIncompleteOrObjectType() &&
"Only object pointers allowed here");
- if (CheckTemplateArgumentAddressOfObjectOrFunction(*this, Param,
- ParamType,
- Arg, Converted))
+ if (CheckTemplateArgumentAddressOfObjectOrFunction(
+ *this, Param, ParamType, Arg, SugaredConverted, CanonicalConverted))
return ExprError();
return Arg;
}
@@ -7558,9 +7637,8 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
return ExprError();
}
- if (CheckTemplateArgumentAddressOfObjectOrFunction(*this, Param,
- ParamType,
- Arg, Converted))
+ if (CheckTemplateArgumentAddressOfObjectOrFunction(
+ *this, Param, ParamType, Arg, SugaredConverted, CanonicalConverted))
return ExprError();
return Arg;
}
@@ -7568,7 +7646,9 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
// Deal with parameters of type std::nullptr_t.
if (ParamType->isNullPtrType()) {
if (Arg->isTypeDependent() || Arg->isValueDependent()) {
- Converted = TemplateArgument(Arg);
+ SugaredConverted = TemplateArgument(Arg);
+ CanonicalConverted =
+ Context.getCanonicalTemplateArgument(SugaredConverted);
return Arg;
}
@@ -7584,8 +7664,10 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
case NPV_NullPointer:
Diag(Arg->getExprLoc(), diag::warn_cxx98_compat_template_arg_null);
- Converted = TemplateArgument(Context.getCanonicalType(ParamType),
- /*isNullPtr*/true);
+ SugaredConverted = TemplateArgument(ParamType,
+ /*isNullPtr=*/true);
+ CanonicalConverted = TemplateArgument(Context.getCanonicalType(ParamType),
+ /*isNullPtr=*/true);
return Arg;
}
}
@@ -7594,8 +7676,8 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
// member, qualification conversions (4.4) are applied.
assert(ParamType->isMemberPointerType() && "Only pointers to members remain");
- if (CheckTemplateArgumentPointerToMember(*this, Param, ParamType, Arg,
- Converted))
+ if (CheckTemplateArgumentPointerToMember(
+ *this, Param, ParamType, Arg, SugaredConverted, CanonicalConverted))
return ExprError();
return Arg;
}
@@ -8596,9 +8678,9 @@ DeclResult Sema::ActOnClassTemplateSpecialization(
// Check that the template argument list is well-formed for this
// template.
- SmallVector<TemplateArgument, 4> Converted;
- if (CheckTemplateArgumentList(ClassTemplate, TemplateNameLoc,
- TemplateArgs, false, Converted,
+ SmallVector<TemplateArgument, 4> SugaredConverted, CanonicalConverted;
+ if (CheckTemplateArgumentList(ClassTemplate, TemplateNameLoc, TemplateArgs,
+ false, SugaredConverted, CanonicalConverted,
/*UpdateArgsWithConversions=*/true))
return true;
@@ -8606,14 +8688,15 @@ DeclResult Sema::ActOnClassTemplateSpecialization(
// corresponds to these arguments.
if (isPartialSpecialization) {
if (CheckTemplatePartialSpecializationArgs(TemplateNameLoc, ClassTemplate,
- TemplateArgs.size(), Converted))
+ TemplateArgs.size(),
+ CanonicalConverted))
return true;
// FIXME: Move this to CheckTemplatePartialSpecializationArgs so we
// also do it during instantiation.
if (!Name.isDependent() &&
- !TemplateSpecializationType::anyDependentTemplateArguments(TemplateArgs,
- Converted)) {
+ !TemplateSpecializationType::anyDependentTemplateArguments(
+ TemplateArgs, CanonicalConverted)) {
Diag(TemplateNameLoc, diag::err_partial_spec_fully_specialized)
<< ClassTemplate->getDeclName();
isPartialSpecialization = false;
@@ -8624,11 +8707,10 @@ DeclResult Sema::ActOnClassTemplateSpecialization(
ClassTemplateSpecializationDecl *PrevDecl = nullptr;
if (isPartialSpecialization)
- PrevDecl = ClassTemplate->findPartialSpecialization(Converted,
- TemplateParams,
- InsertPos);
+ PrevDecl = ClassTemplate->findPartialSpecialization(
+ CanonicalConverted, TemplateParams, InsertPos);
else
- PrevDecl = ClassTemplate->findSpecialization(Converted, InsertPos);
+ PrevDecl = ClassTemplate->findSpecialization(CanonicalConverted, InsertPos);
ClassTemplateSpecializationDecl *Specialization = nullptr;
@@ -8647,7 +8729,7 @@ DeclResult Sema::ActOnClassTemplateSpecialization(
// arguments of the class template partial specialization.
TemplateName CanonTemplate = Context.getCanonicalTemplateName(Name);
CanonType = Context.getTemplateSpecializationType(CanonTemplate,
- Converted);
+ CanonicalConverted);
if (Context.hasSameType(CanonType,
ClassTemplate->getInjectedClassNameSpecialization()) &&
@@ -8677,16 +8759,11 @@ DeclResult Sema::ActOnClassTemplateSpecialization(
// Create a new class template partial specialization declaration node.
ClassTemplatePartialSpecializationDecl *PrevPartial
= cast_or_null<ClassTemplatePartialSpecializationDecl>(PrevDecl);
- ClassTemplatePartialSpecializationDecl *Partial
- = ClassTemplatePartialSpecializationDecl::Create(Context, Kind,
- ClassTemplate->getDeclContext(),
- KWLoc, TemplateNameLoc,
- TemplateParams,
- ClassTemplate,
- Converted,
- TemplateArgs,
- CanonType,
- PrevPartial);
+ ClassTemplatePartialSpecializationDecl *Partial =
+ ClassTemplatePartialSpecializationDecl::Create(
+ Context, Kind, ClassTemplate->getDeclContext(), KWLoc,
+ TemplateNameLoc, TemplateParams, ClassTemplate, CanonicalConverted,
+ TemplateArgs, CanonType, PrevPartial);
SetNestedNameSpecifier(*this, Partial, SS);
if (TemplateParameterLists.size() > 1 && SS.isSet()) {
Partial->setTemplateParameterListsInfo(
@@ -8706,13 +8783,9 @@ DeclResult Sema::ActOnClassTemplateSpecialization(
} else {
// Create a new class template specialization declaration node for
// this explicit specialization or friend declaration.
- Specialization
- = ClassTemplateSpecializationDecl::Create(Context, Kind,
- ClassTemplate->getDeclContext(),
- KWLoc, TemplateNameLoc,
- ClassTemplate,
- Converted,
- PrevDecl);
+ Specialization = ClassTemplateSpecializationDecl::Create(
+ Context, Kind, ClassTemplate->getDeclContext(), KWLoc, TemplateNameLoc,
+ ClassTemplate, CanonicalConverted, PrevDecl);
SetNestedNameSpecifier(*this, Specialization, SS);
if (TemplateParameterLists.size() > 0) {
Specialization->setTemplateParameterListsInfo(Context,
@@ -8724,8 +8797,8 @@ DeclResult Sema::ActOnClassTemplateSpecialization(
if (CurContext->isDependentContext()) {
TemplateName CanonTemplate = Context.getCanonicalTemplateName(Name);
- CanonType = Context.getTemplateSpecializationType(
- CanonTemplate, Converted);
+ CanonType = Context.getTemplateSpecializationType(CanonTemplate,
+ CanonicalConverted);
} else {
CanonType = Context.getTypeDeclType(Specialization);
}
@@ -9891,17 +9964,17 @@ DeclResult Sema::ActOnExplicitInstantiation(
// Check that the template argument list is well-formed for this
// template.
- SmallVector<TemplateArgument, 4> Converted;
- if (CheckTemplateArgumentList(ClassTemplate, TemplateNameLoc,
- TemplateArgs, false, Converted,
+ SmallVector<TemplateArgument, 4> SugaredConverted, CanonicalConverted;
+ if (CheckTemplateArgumentList(ClassTemplate, TemplateNameLoc, TemplateArgs,
+ false, SugaredConverted, CanonicalConverted,
/*UpdateArgsWithConversions=*/true))
return true;
// Find the class template specialization declaration that
// corresponds to these arguments.
void *InsertPos = nullptr;
- ClassTemplateSpecializationDecl *PrevDecl
- = ClassTemplate->findSpecialization(Converted, InsertPos);
+ ClassTemplateSpecializationDecl *PrevDecl =
+ ClassTemplate->findSpecialization(CanonicalConverted, InsertPos);
TemplateSpecializationKind PrevDecl_TSK
= PrevDecl ? PrevDecl->getTemplateSpecializationKind() : TSK_Undeclared;
@@ -9958,13 +10031,9 @@ DeclResult Sema::ActOnExplicitInstantiation(
if (!Specialization) {
// Create a new class template specialization declaration node for
// this explicit specialization.
- Specialization
- = ClassTemplateSpecializationDecl::Create(Context, Kind,
- ClassTemplate->getDeclContext(),
- KWLoc, TemplateNameLoc,
- ClassTemplate,
- Converted,
- PrevDecl);
+ Specialization = ClassTemplateSpecializationDecl::Create(
+ Context, Kind, ClassTemplate->getDeclContext(), KWLoc, TemplateNameLoc,
+ ClassTemplate, CanonicalConverted, PrevDecl);
SetNestedNameSpecifier(*this, Specialization, SS);
if (!HasNoEffect && !PrevDecl) {
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index 7bc743044b740..24629162ecfce 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -2628,13 +2628,11 @@ Sema::getIdentityTemplateArgumentLoc(NamedDecl *TemplateParm,
/// Convert the given deduced template argument and add it to the set of
/// fully-converted template arguments.
-static bool
-ConvertDeducedTemplateArgument(Sema &S, NamedDecl *Param,
- DeducedTemplateArgument Arg,
- NamedDecl *Template,
- TemplateDeductionInfo &Info,
- bool IsDeduced,
- SmallVectorImpl<TemplateArgument> &Output) {
+static bool ConvertDeducedTemplateArgument(
+ Sema &S, NamedDecl *Param, DeducedTemplateArgument Arg, NamedDecl *Template,
+ TemplateDeductionInfo &Info, bool IsDeduced,
+ SmallVectorImpl<TemplateArgument> &SugaredOutput,
+ SmallVectorImpl<TemplateArgument> &CanonicalOutput) {
auto ConvertArg = [&](DeducedTemplateArgument Arg,
unsigned ArgumentPackIndex) {
// Convert the deduced template argument into a template
@@ -2646,7 +2644,8 @@ ConvertDeducedTemplateArgument(Sema &S, NamedDecl *Param,
// Check the template argument, converting it as necessary.
return S.CheckTemplateArgument(
Param, ArgLoc, Template, Template->getLocation(),
- Template->getSourceRange().getEnd(), ArgumentPackIndex, Output,
+ Template->getSourceRange().getEnd(), ArgumentPackIndex, SugaredOutput,
+ CanonicalOutput,
IsDeduced
? (Arg.wasDeducedFromArrayBound() ? Sema::CTAK_DeducedFromArrayBound
: Sema::CTAK_Deduced)
@@ -2656,7 +2655,8 @@ ConvertDeducedTemplateArgument(Sema &S, NamedDecl *Param,
if (Arg.getKind() == TemplateArgument::Pack) {
// This is a template argument pack, so check each of its arguments against
// the template parameter.
- SmallVector<TemplateArgument, 2> PackedArgsBuilder;
+ SmallVector<TemplateArgument, 2> SugaredPackedArgsBuilder,
+ CanonicalPackedArgsBuilder;
for (const auto &P : Arg.pack_elements()) {
// When converting the deduced template argument, append it to the
// general output list. We need to do this so that the template argument
@@ -2675,23 +2675,25 @@ ConvertDeducedTemplateArgument(Sema &S, NamedDecl *Param,
<< Arg << Param;
return true;
}
- if (ConvertArg(InnerArg, PackedArgsBuilder.size()))
+ if (ConvertArg(InnerArg, SugaredPackedArgsBuilder.size()))
return true;
// Move the converted template argument into our argument pack.
- PackedArgsBuilder.push_back(Output.pop_back_val());
+ SugaredPackedArgsBuilder.push_back(SugaredOutput.pop_back_val());
+ CanonicalPackedArgsBuilder.push_back(CanonicalOutput.pop_back_val());
}
// If the pack is empty, we still need to substitute into the parameter
// itself, in case that substitution fails.
- if (PackedArgsBuilder.empty()) {
+ if (SugaredPackedArgsBuilder.empty()) {
LocalInstantiationScope Scope(S);
- TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, Output);
+ TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack,
+ CanonicalOutput);
MultiLevelTemplateArgumentList Args(Template, TemplateArgs.asArray());
if (auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Param)) {
Sema::InstantiatingTemplate Inst(S, Template->getLocation(), Template,
- NTTP, Output,
+ NTTP, CanonicalOutput,
Template->getSourceRange());
if (Inst.isInvalid() ||
S.SubstType(NTTP->getType(), Args, NTTP->getLocation(),
@@ -2699,7 +2701,7 @@ ConvertDeducedTemplateArgument(Sema &S, NamedDecl *Param,
return true;
} else if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(Param)) {
Sema::InstantiatingTemplate Inst(S, Template->getLocation(), Template,
- TTP, Output,
+ TTP, CanonicalOutput,
Template->getSourceRange());
if (Inst.isInvalid() || !S.SubstDecl(TTP, S.CurContext, Args))
return true;
@@ -2708,8 +2710,10 @@ ConvertDeducedTemplateArgument(Sema &S, NamedDecl *Param,
}
// Create the resulting argument pack.
- Output.push_back(
- TemplateArgument::CreatePackCopy(S.Context, PackedArgsBuilder));
+ SugaredOutput.push_back(
+ TemplateArgument::CreatePackCopy(S.Context, SugaredPackedArgsBuilder));
+ CanonicalOutput.push_back(TemplateArgument::CreatePackCopy(
+ S.Context, CanonicalPackedArgsBuilder));
return false;
}
@@ -2719,11 +2723,13 @@ ConvertDeducedTemplateArgument(Sema &S, NamedDecl *Param,
// FIXME: This should not be a template, but
// ClassTemplatePartialSpecializationDecl sadly does not derive from
// TemplateDecl.
-template<typename TemplateDeclT>
+template <typename TemplateDeclT>
static Sema::TemplateDeductionResult ConvertDeducedTemplateArguments(
Sema &S, TemplateDeclT *Template, bool IsDeduced,
SmallVectorImpl<DeducedTemplateArgument> &Deduced,
- TemplateDeductionInfo &Info, SmallVectorImpl<TemplateArgument> &Builder,
+ TemplateDeductionInfo &Info,
+ SmallVectorImpl<TemplateArgument> &SugaredBuilder,
+ SmallVectorImpl<TemplateArgument> &CanonicalBuilder,
LocalInstantiationScope *CurrentInstantiationScope = nullptr,
unsigned NumAlreadyConverted = 0, bool PartialOverloading = false) {
TemplateParameterList *TemplateParams = Template->getTemplateParameters();
@@ -2757,7 +2763,9 @@ static Sema::TemplateDeductionResult ConvertDeducedTemplateArguments(
// We have already fully type-checked and converted this
// argument, because it was explicitly-specified. Just record the
// presence of this argument.
- Builder.push_back(Deduced[I]);
+ SugaredBuilder.push_back(Deduced[I]);
+ CanonicalBuilder.push_back(
+ S.Context.getCanonicalTemplateArgument(Deduced[I]));
continue;
}
}
@@ -2765,10 +2773,13 @@ static Sema::TemplateDeductionResult ConvertDeducedTemplateArguments(
// We may have deduced this argument, so it still needs to be
// checked and converted.
if (ConvertDeducedTemplateArgument(S, Param, Deduced[I], Template, Info,
- IsDeduced, Builder)) {
+ IsDeduced, SugaredBuilder,
+ CanonicalBuilder)) {
Info.Param = makeTemplateParameter(Param);
// FIXME: These template arguments are temporary. Free them!
- Info.reset(TemplateArgumentList::CreateCopy(S.Context, Builder));
+ Info.reset(
+ TemplateArgumentList::CreateCopy(S.Context, SugaredBuilder),
+ TemplateArgumentList::CreateCopy(S.Context, CanonicalBuilder));
return Sema::TDK_SubstitutionFailure;
}
@@ -2799,15 +2810,16 @@ static Sema::TemplateDeductionResult ConvertDeducedTemplateArguments(
S.getLangOpts().CPlusPlus17);
DefArg = S.SubstDefaultTemplateArgumentIfAvailable(
- TD, TD->getLocation(), TD->getSourceRange().getEnd(), Param, Builder,
- HasDefaultArg);
+ TD, TD->getLocation(), TD->getSourceRange().getEnd(), Param,
+ CanonicalBuilder, HasDefaultArg);
}
// If there was no default argument, deduction is incomplete.
if (DefArg.getArgument().isNull()) {
Info.Param = makeTemplateParameter(
const_cast<NamedDecl *>(TemplateParams->getParam(I)));
- Info.reset(TemplateArgumentList::CreateCopy(S.Context, Builder));
+ Info.reset(TemplateArgumentList::CreateCopy(S.Context, SugaredBuilder),
+ TemplateArgumentList::CreateCopy(S.Context, CanonicalBuilder));
if (PartialOverloading) break;
return HasDefaultArg ? Sema::TDK_SubstitutionFailure
@@ -2815,13 +2827,14 @@ static Sema::TemplateDeductionResult ConvertDeducedTemplateArguments(
}
// Check whether we can actually use the default argument.
- if (S.CheckTemplateArgument(Param, DefArg, TD, TD->getLocation(),
- TD->getSourceRange().getEnd(), 0, Builder,
- Sema::CTAK_Specified)) {
+ if (S.CheckTemplateArgument(
+ Param, DefArg, TD, TD->getLocation(), TD->getSourceRange().getEnd(),
+ 0, SugaredBuilder, CanonicalBuilder, Sema::CTAK_Specified)) {
Info.Param = makeTemplateParameter(
const_cast<NamedDecl *>(TemplateParams->getParam(I)));
// FIXME: These template arguments are temporary. Free them!
- Info.reset(TemplateArgumentList::CreateCopy(S.Context, Builder));
+ Info.reset(TemplateArgumentList::CreateCopy(S.Context, SugaredBuilder),
+ TemplateArgumentList::CreateCopy(S.Context, CanonicalBuilder));
return Sema::TDK_SubstitutionFailure;
}
@@ -2863,16 +2876,18 @@ bool DeducedArgsNeedReplacement<ClassTemplatePartialSpecializationDecl>(
return !Spec->isClassScopeExplicitSpecialization();
}
-template<typename TemplateDeclT>
+template <typename TemplateDeclT>
static Sema::TemplateDeductionResult
-CheckDeducedArgumentConstraints(Sema& S, TemplateDeclT *Template,
- ArrayRef<TemplateArgument> DeducedArgs,
- TemplateDeductionInfo& Info) {
+CheckDeducedArgumentConstraints(Sema &S, TemplateDeclT *Template,
+ ArrayRef<TemplateArgument> SugaredDeducedArgs,
+ ArrayRef<TemplateArgument> CanonicalDeducedArgs,
+ TemplateDeductionInfo &Info) {
llvm::SmallVector<const Expr *, 3> AssociatedConstraints;
Template->getAssociatedConstraints(AssociatedConstraints);
bool NeedsReplacement = DeducedArgsNeedReplacement(Template);
- TemplateArgumentList DeducedTAL{TemplateArgumentList::OnStack, DeducedArgs};
+ TemplateArgumentList DeducedTAL{TemplateArgumentList::OnStack,
+ CanonicalDeducedArgs};
MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs(
Template, /*InnerMost=*/NeedsReplacement ? nullptr : &DeducedTAL,
@@ -2884,13 +2899,15 @@ CheckDeducedArgumentConstraints(Sema& S, TemplateDeclT *Template,
// not class-scope explicit specialization, so replace with Deduced Args
// instead of adding to inner-most.
if (NeedsReplacement)
- MLTAL.replaceInnermostTemplateArguments(DeducedArgs);
+ MLTAL.replaceInnermostTemplateArguments(CanonicalDeducedArgs);
if (S.CheckConstraintSatisfaction(Template, AssociatedConstraints, MLTAL,
Info.getLocation(),
Info.AssociatedConstraintsSatisfaction) ||
!Info.AssociatedConstraintsSatisfaction.IsSatisfied) {
- Info.reset(TemplateArgumentList::CreateCopy(S.Context, DeducedArgs));
+ Info.reset(
+ TemplateArgumentList::CreateCopy(S.Context, SugaredDeducedArgs),
+ TemplateArgumentList::CreateCopy(S.Context, CanonicalDeducedArgs));
return Sema::TDK_ConstraintsNotSatisfied;
}
return Sema::TDK_Success;
@@ -2915,16 +2932,19 @@ FinishTemplateArgumentDeduction(
// C++ [temp.deduct.type]p2:
// [...] or if any template argument remains neither deduced nor
// explicitly specified, template argument deduction fails.
- SmallVector<TemplateArgument, 4> Builder;
+ SmallVector<TemplateArgument, 4> SugaredBuilder, CanonicalBuilder;
if (auto Result = ConvertDeducedTemplateArguments(
- S, Partial, IsPartialOrdering, Deduced, Info, Builder))
+ S, Partial, IsPartialOrdering, Deduced, Info, SugaredBuilder,
+ CanonicalBuilder))
return Result;
// Form the template argument list from the deduced template arguments.
- TemplateArgumentList *DeducedArgumentList
- = TemplateArgumentList::CreateCopy(S.Context, Builder);
+ TemplateArgumentList *SugaredDeducedArgumentList =
+ TemplateArgumentList::CreateCopy(S.Context, SugaredBuilder);
+ TemplateArgumentList *CanonicalDeducedArgumentList =
+ TemplateArgumentList::CreateCopy(S.Context, CanonicalBuilder);
- Info.reset(DeducedArgumentList);
+ Info.reset(SugaredDeducedArgumentList, CanonicalDeducedArgumentList);
// Substitute the deduced template arguments into the template
// arguments of the class template partial specialization, and
@@ -2939,10 +2959,11 @@ FinishTemplateArgumentDeduction(
TemplateArgumentListInfo InstArgs(PartialTemplArgInfo->LAngleLoc,
PartialTemplArgInfo->RAngleLoc);
- if (S.SubstTemplateArguments(PartialTemplArgInfo->arguments(),
- MultiLevelTemplateArgumentList(
- Partial, DeducedArgumentList->asArray()),
- InstArgs)) {
+ if (S.SubstTemplateArguments(
+ PartialTemplArgInfo->arguments(),
+ MultiLevelTemplateArgumentList(
+ Partial, CanonicalDeducedArgumentList->asArray()),
+ InstArgs)) {
unsigned ArgIdx = InstArgs.size(), ParamIdx = ArgIdx;
if (ParamIdx >= Partial->getTemplateParameters()->size())
ParamIdx = Partial->getTemplateParameters()->size() - 1;
@@ -2955,17 +2976,18 @@ FinishTemplateArgumentDeduction(
}
bool ConstraintsNotSatisfied;
- SmallVector<TemplateArgument, 4> ConvertedInstArgs;
- if (S.CheckTemplateArgumentList(Template, Partial->getLocation(), InstArgs,
- false, ConvertedInstArgs,
- /*UpdateArgsWithConversions=*/true,
- &ConstraintsNotSatisfied))
- return ConstraintsNotSatisfied ? Sema::TDK_ConstraintsNotSatisfied :
- Sema::TDK_SubstitutionFailure;
+ SmallVector<TemplateArgument, 4> SugaredConvertedInstArgs,
+ CanonicalConvertedInstArgs;
+ if (S.CheckTemplateArgumentList(
+ Template, Partial->getLocation(), InstArgs, false,
+ SugaredConvertedInstArgs, CanonicalConvertedInstArgs,
+ /*UpdateArgsWithConversions=*/true, &ConstraintsNotSatisfied))
+ return ConstraintsNotSatisfied ? Sema::TDK_ConstraintsNotSatisfied
+ : Sema::TDK_SubstitutionFailure;
TemplateParameterList *TemplateParams = Template->getTemplateParameters();
for (unsigned I = 0, E = TemplateParams->size(); I != E; ++I) {
- TemplateArgument InstArg = ConvertedInstArgs.data()[I];
+ TemplateArgument InstArg = SugaredConvertedInstArgs.data()[I];
if (!isSameTemplateArg(S.Context, TemplateArgs[I], InstArg,
IsPartialOrdering)) {
Info.Param = makeTemplateParameter(TemplateParams->getParam(I));
@@ -2978,7 +3000,8 @@ FinishTemplateArgumentDeduction(
if (Trap.hasErrorOccurred())
return Sema::TDK_SubstitutionFailure;
- if (auto Result = CheckDeducedArgumentConstraints(S, Partial, Builder, Info))
+ if (auto Result = CheckDeducedArgumentConstraints(S, Partial, SugaredBuilder,
+ CanonicalBuilder, Info))
return Result;
return Sema::TDK_Success;
@@ -3002,17 +3025,20 @@ static Sema::TemplateDeductionResult FinishTemplateArgumentDeduction(
// C++ [temp.deduct.type]p2:
// [...] or if any template argument remains neither deduced nor
// explicitly specified, template argument deduction fails.
- SmallVector<TemplateArgument, 4> Builder;
+ SmallVector<TemplateArgument, 4> SugaredBuilder, CanonicalBuilder;
if (auto Result = ConvertDeducedTemplateArguments(
- S, Template, /*IsDeduced*/PartialOrdering, Deduced, Info, Builder))
+ S, Template, /*IsDeduced*/ PartialOrdering, Deduced, Info,
+ SugaredBuilder, CanonicalBuilder,
+ /*CurrentInstantiationScope=*/nullptr,
+ /*NumAlreadyConverted=*/0U, /*PartialOverloading=*/false))
return Result;
// Check that we produced the correct argument list.
TemplateParameterList *TemplateParams = Template->getTemplateParameters();
for (unsigned I = 0, E = TemplateParams->size(); I != E; ++I) {
- TemplateArgument InstArg = Builder[I];
+ TemplateArgument InstArg = CanonicalBuilder[I];
if (!isSameTemplateArg(S.Context, TemplateArgs[I], InstArg, PartialOrdering,
- /*PackExpansionMatchesPack*/ true)) {
+ /*PackExpansionMatchesPack=*/true)) {
Info.Param = makeTemplateParameter(TemplateParams->getParam(I));
Info.FirstArg = TemplateArgs[I];
Info.SecondArg = InstArg;
@@ -3023,8 +3049,8 @@ static Sema::TemplateDeductionResult FinishTemplateArgumentDeduction(
if (Trap.hasErrorOccurred())
return Sema::TDK_SubstitutionFailure;
- if (auto Result = CheckDeducedArgumentConstraints(S, Template, Builder,
- Info))
+ if (auto Result = CheckDeducedArgumentConstraints(S, Template, SugaredBuilder,
+ CanonicalBuilder, Info))
return Result;
return Sema::TDK_Success;
@@ -3176,14 +3202,12 @@ static bool isSimpleTemplateIdType(QualType T) {
///
/// \returns TDK_Success if substitution was successful, or some failure
/// condition.
-Sema::TemplateDeductionResult
-Sema::SubstituteExplicitTemplateArguments(
- FunctionTemplateDecl *FunctionTemplate,
- TemplateArgumentListInfo &ExplicitTemplateArgs,
- SmallVectorImpl<DeducedTemplateArgument> &Deduced,
- SmallVectorImpl<QualType> &ParamTypes,
- QualType *FunctionType,
- TemplateDeductionInfo &Info) {
+Sema::TemplateDeductionResult Sema::SubstituteExplicitTemplateArguments(
+ FunctionTemplateDecl *FunctionTemplate,
+ TemplateArgumentListInfo &ExplicitTemplateArgs,
+ SmallVectorImpl<DeducedTemplateArgument> &Deduced,
+ SmallVectorImpl<QualType> &ParamTypes, QualType *FunctionType,
+ TemplateDeductionInfo &Info) {
FunctionDecl *Function = FunctionTemplate->getTemplatedDecl();
TemplateParameterList *TemplateParams
= FunctionTemplate->getTemplateParameters();
@@ -3209,7 +3233,7 @@ Sema::SubstituteExplicitTemplateArguments(
// declaration order of their corresponding template-parameters. The
// template argument list shall not specify more template-arguments than
// there are corresponding template-parameters.
- SmallVector<TemplateArgument, 4> Builder;
+ SmallVector<TemplateArgument, 4> SugaredBuilder, CanonicalBuilder;
// Enter a new template instantiation context where we check the
// explicitly-specified template arguments against this function template,
@@ -3222,9 +3246,11 @@ Sema::SubstituteExplicitTemplateArguments(
return TDK_InstantiationDepth;
if (CheckTemplateArgumentList(FunctionTemplate, SourceLocation(),
- ExplicitTemplateArgs, true, Builder, false) ||
+ ExplicitTemplateArgs, true, SugaredBuilder,
+ CanonicalBuilder,
+ /*UpdateArgsWithConversions=*/false) ||
Trap.hasErrorOccurred()) {
- unsigned Index = Builder.size();
+ unsigned Index = SugaredBuilder.size();
if (Index >= TemplateParams->size())
return TDK_SubstitutionFailure;
Info.Param = makeTemplateParameter(TemplateParams->getParam(Index));
@@ -3233,9 +3259,12 @@ Sema::SubstituteExplicitTemplateArguments(
// Form the template argument list from the explicitly-specified
// template arguments.
- TemplateArgumentList *ExplicitArgumentList
- = TemplateArgumentList::CreateCopy(Context, Builder);
- Info.setExplicitArgs(ExplicitArgumentList);
+ TemplateArgumentList *SugaredExplicitArgumentList =
+ TemplateArgumentList::CreateCopy(Context, SugaredBuilder);
+ TemplateArgumentList *CanonicalExplicitArgumentList =
+ TemplateArgumentList::CreateCopy(Context, CanonicalBuilder);
+ Info.setExplicitArgs(SugaredExplicitArgumentList,
+ CanonicalExplicitArgumentList);
// Template argument deduction and the final substitution should be
// done in the context of the templated declaration. Explicit
@@ -3248,15 +3277,15 @@ Sema::SubstituteExplicitTemplateArguments(
// the explicit template arguments. They'll be used as part of deduction
// for this template parameter pack.
unsigned PartiallySubstitutedPackIndex = -1u;
- if (!Builder.empty()) {
- const TemplateArgument &Arg = Builder.back();
+ if (!CanonicalBuilder.empty()) {
+ const TemplateArgument &Arg = CanonicalBuilder.back();
if (Arg.getKind() == TemplateArgument::Pack) {
- auto *Param = TemplateParams->getParam(Builder.size() - 1);
+ auto *Param = TemplateParams->getParam(CanonicalBuilder.size() - 1);
// If this is a fully-saturated fixed-size pack, it should be
// fully-substituted, not partially-substituted.
Optional<unsigned> Expansions = getExpandedPackSize(Param);
if (!Expansions || Arg.pack_size() < *Expansions) {
- PartiallySubstitutedPackIndex = Builder.size() - 1;
+ PartiallySubstitutedPackIndex = CanonicalBuilder.size() - 1;
CurrentInstantiationScope->SetPartiallySubstitutedPack(
Param, Arg.pack_begin(), Arg.pack_size());
}
@@ -3277,11 +3306,12 @@ Sema::SubstituteExplicitTemplateArguments(
// return type, substitute it after the arguments to ensure we substitute
// in lexical order.
if (Proto->hasTrailingReturn()) {
- if (SubstParmTypes(Function->getLocation(), Function->parameters(),
- Proto->getExtParameterInfosOrNull(),
- MultiLevelTemplateArgumentList(
- FunctionTemplate, ExplicitArgumentList->asArray()),
- ParamTypes, /*params*/ nullptr, ExtParamInfos))
+ if (SubstParmTypes(
+ Function->getLocation(), Function->parameters(),
+ Proto->getExtParameterInfosOrNull(),
+ MultiLevelTemplateArgumentList(
+ FunctionTemplate, CanonicalExplicitArgumentList->asArray()),
+ ParamTypes, /*params=*/nullptr, ExtParamInfos))
return TDK_SubstitutionFailure;
}
@@ -3304,11 +3334,11 @@ Sema::SubstituteExplicitTemplateArguments(
CXXThisScopeRAII ThisScope(*this, ThisContext, ThisTypeQuals,
getLangOpts().CPlusPlus11);
- ResultType =
- SubstType(Proto->getReturnType(),
- MultiLevelTemplateArgumentList(
- FunctionTemplate, ExplicitArgumentList->asArray()),
- Function->getTypeSpecStartLoc(), Function->getDeclName());
+ ResultType = SubstType(
+ Proto->getReturnType(),
+ MultiLevelTemplateArgumentList(
+ FunctionTemplate, CanonicalExplicitArgumentList->asArray()),
+ Function->getTypeSpecStartLoc(), Function->getDeclName());
if (ResultType.isNull() || Trap.hasErrorOccurred())
return TDK_SubstitutionFailure;
// CUDA: Kernel function must have 'void' return type.
@@ -3323,11 +3353,12 @@ Sema::SubstituteExplicitTemplateArguments(
// Instantiate the types of each of the function parameters given the
// explicitly-specified template arguments if we didn't do so earlier.
if (!Proto->hasTrailingReturn() &&
- SubstParmTypes(Function->getLocation(), Function->parameters(),
- Proto->getExtParameterInfosOrNull(),
- MultiLevelTemplateArgumentList(
- FunctionTemplate, ExplicitArgumentList->asArray()),
- ParamTypes, /*params*/ nullptr, ExtParamInfos))
+ SubstParmTypes(
+ Function->getLocation(), Function->parameters(),
+ Proto->getExtParameterInfosOrNull(),
+ MultiLevelTemplateArgumentList(
+ FunctionTemplate, CanonicalExplicitArgumentList->asArray()),
+ ParamTypes, /*params*/ nullptr, ExtParamInfos))
return TDK_SubstitutionFailure;
if (FunctionType) {
@@ -3341,8 +3372,8 @@ Sema::SubstituteExplicitTemplateArguments(
if (getLangOpts().CPlusPlus17 &&
SubstExceptionSpec(
Function->getLocation(), EPI.ExceptionSpec, ExceptionStorage,
- MultiLevelTemplateArgumentList(FunctionTemplate,
- ExplicitArgumentList->asArray())))
+ MultiLevelTemplateArgumentList(
+ FunctionTemplate, CanonicalExplicitArgumentList->asArray())))
return TDK_SubstitutionFailure;
*FunctionType = BuildFunctionType(ResultType, ParamTypes,
@@ -3364,8 +3395,8 @@ Sema::SubstituteExplicitTemplateArguments(
// parameter pack, however, will be set to NULL since the deduction
// mechanism handles the partially-substituted argument pack directly.
Deduced.reserve(TemplateParams->size());
- for (unsigned I = 0, N = ExplicitArgumentList->size(); I != N; ++I) {
- const TemplateArgument &Arg = ExplicitArgumentList->get(I);
+ for (unsigned I = 0, N = SugaredExplicitArgumentList->size(); I != N; ++I) {
+ const TemplateArgument &Arg = SugaredExplicitArgumentList->get(I);
if (I == PartiallySubstitutedPackIndex)
Deduced.push_back(DeducedTemplateArgument());
else
@@ -3553,11 +3584,11 @@ Sema::TemplateDeductionResult Sema::FinishTemplateArgumentDeduction(
// C++ [temp.deduct.type]p2:
// [...] or if any template argument remains neither deduced nor
// explicitly specified, template argument deduction fails.
- SmallVector<TemplateArgument, 4> Builder;
+ SmallVector<TemplateArgument, 4> SugaredBuilder, CanonicalBuilder;
if (auto Result = ConvertDeducedTemplateArguments(
- *this, FunctionTemplate, /*IsDeduced*/true, Deduced, Info, Builder,
- CurrentInstantiationScope, NumExplicitlySpecified,
- PartialOverloading))
+ *this, FunctionTemplate, /*IsDeduced*/ true, Deduced, Info,
+ SugaredBuilder, CanonicalBuilder, CurrentInstantiationScope,
+ NumExplicitlySpecified, PartialOverloading))
return Result;
// C++ [temp.deduct.call]p10: [DR1391]
@@ -3573,17 +3604,19 @@ Sema::TemplateDeductionResult Sema::FinishTemplateArgumentDeduction(
return TDK_NonDependentConversionFailure;
// Form the template argument list from the deduced template arguments.
- TemplateArgumentList *DeducedArgumentList
- = TemplateArgumentList::CreateCopy(Context, Builder);
- Info.reset(DeducedArgumentList);
+ TemplateArgumentList *SugaredDeducedArgumentList =
+ TemplateArgumentList::CreateCopy(Context, SugaredBuilder);
+ TemplateArgumentList *CanonicalDeducedArgumentList =
+ TemplateArgumentList::CreateCopy(Context, CanonicalBuilder);
+ Info.reset(SugaredDeducedArgumentList, CanonicalDeducedArgumentList);
// Substitute the deduced template arguments into the function template
// declaration to produce the function template specialization.
DeclContext *Owner = FunctionTemplate->getDeclContext();
if (FunctionTemplate->getFriendObjectKind())
Owner = FunctionTemplate->getLexicalDeclContext();
- MultiLevelTemplateArgumentList SubstArgs(FunctionTemplate,
- DeducedArgumentList->asArray());
+ MultiLevelTemplateArgumentList SubstArgs(
+ FunctionTemplate, CanonicalDeducedArgumentList->asArray());
Specialization = cast_or_null<FunctionDecl>(
SubstDecl(FunctionTemplate->getTemplatedDecl(), Owner, SubstArgs));
if (!Specialization || Specialization->isInvalidDecl())
@@ -3594,9 +3627,10 @@ Sema::TemplateDeductionResult Sema::FinishTemplateArgumentDeduction(
// If the template argument list is owned by the function template
// specialization, release it.
- if (Specialization->getTemplateSpecializationArgs() == DeducedArgumentList &&
+ if (Specialization->getTemplateSpecializationArgs() ==
+ CanonicalDeducedArgumentList &&
!Trap.hasErrorOccurred())
- Info.take();
+ Info.takeCanonical();
// There may have been an error that did not prevent us from constructing a
// declaration. Mark the declaration invalid and return with a substitution
@@ -3615,13 +3649,16 @@ Sema::TemplateDeductionResult Sema::FinishTemplateArgumentDeduction(
// ([temp.constr.constr]). If the constraints are not satisfied, type
// deduction fails.
if (!PartialOverloading ||
- (Builder.size() == FunctionTemplate->getTemplateParameters()->size())) {
- if (CheckInstantiatedFunctionTemplateConstraints(Info.getLocation(),
- Specialization, Builder, Info.AssociatedConstraintsSatisfaction))
+ (CanonicalBuilder.size() ==
+ FunctionTemplate->getTemplateParameters()->size())) {
+ if (CheckInstantiatedFunctionTemplateConstraints(
+ Info.getLocation(), Specialization, CanonicalBuilder,
+ Info.AssociatedConstraintsSatisfaction))
return TDK_MiscellaneousDeductionFailure;
if (!Info.AssociatedConstraintsSatisfaction.IsSatisfied) {
- Info.reset(TemplateArgumentList::CreateCopy(Context, Builder));
+ Info.reset(Info.takeSugared(),
+ TemplateArgumentList::CreateCopy(Context, CanonicalBuilder));
return TDK_ConstraintsNotSatisfied;
}
}
@@ -4635,12 +4672,12 @@ static bool CheckDeducedPlaceholderConstraints(Sema &S, const AutoType &Type,
for (unsigned I = 0, C = TypeLoc.getNumArgs(); I != C; ++I)
TemplateArgs.addArgument(TypeLoc.getArgLoc(I));
- llvm::SmallVector<TemplateArgument, 4> Converted;
+ llvm::SmallVector<TemplateArgument, 4> SugaredConverted, CanonicalConverted;
if (S.CheckTemplateArgumentList(Concept, SourceLocation(), TemplateArgs,
- /*PartialTemplateArgs=*/false, Converted))
+ /*PartialTemplateArgs=*/false,
+ SugaredConverted, CanonicalConverted))
return true;
- MultiLevelTemplateArgumentList MLTAL;
- MLTAL.addOuterTemplateArguments(Concept, Converted);
+ MultiLevelTemplateArgumentList MLTAL(Concept, CanonicalConverted);
if (S.CheckConstraintSatisfaction(Concept, {Concept->getConstraintExpr()},
MLTAL, TypeLoc.getLocalSourceRange(),
Satisfaction))
@@ -5773,13 +5810,15 @@ bool Sema::isTemplateTemplateParameterAtLeastAsSpecializedAs(
// C++1z [temp.arg.template]p3:
// If the rewrite produces an invalid type, then P is not at least as
// specialized as A.
- if (CheckTemplateArgumentList(AArg, Loc, PArgList, false, PArgs) ||
+ SmallVector<TemplateArgument, 4> SugaredPArgs;
+ if (CheckTemplateArgumentList(AArg, Loc, PArgList, false, SugaredPArgs,
+ PArgs) ||
Trap.hasErrorOccurred())
return false;
}
- QualType AType = Context.getTemplateSpecializationType(X, AArgs);
- QualType PType = Context.getTemplateSpecializationType(X, PArgs);
+ QualType AType = Context.getCanonicalTemplateSpecializationType(X, AArgs);
+ QualType PType = Context.getCanonicalTemplateSpecializationType(X, PArgs);
// ... the function template corresponding to P is at least as specialized
// as the function template corresponding to A according to the partial
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 7475289745c7d..c19714c7a8b4d 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -1831,14 +1831,16 @@ TemplateInstantiator::TransformSubstNonTypeTemplateParmExpr(
// Type=char)),
// Type=decltype(2)))
// The call to CheckTemplateArgument here produces the ImpCast.
- TemplateArgument Converted;
- if (SemaRef.CheckTemplateArgument(E->getParameter(), SubstType,
- SubstReplacement.get(),
- Converted).isInvalid())
+ TemplateArgument SugaredConverted, CanonicalConverted;
+ if (SemaRef
+ .CheckTemplateArgument(E->getParameter(), SubstType,
+ SubstReplacement.get(), SugaredConverted,
+ CanonicalConverted, Sema::CTAK_Specified)
+ .isInvalid())
return true;
return transformNonTypeTemplateParmRef(E->getAssociatedDecl(),
E->getParameter(), E->getExprLoc(),
- Converted, E->getPackIndex());
+ CanonicalConverted, E->getPackIndex());
}
ExprResult TemplateInstantiator::RebuildVarDeclRefExpr(VarDecl *PD,
@@ -3445,7 +3447,7 @@ getPatternForClassTemplateSpecialization(
} else {
Matched.push_back(PartialSpecMatchResult());
Matched.back().Partial = Partial;
- Matched.back().Args = Info.take();
+ Matched.back().Args = Info.takeCanonical();
}
}
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index dc694b2cb7c97..112137a2dcfb9 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -3752,12 +3752,10 @@ TemplateDeclInstantiator::VisitClassTemplateSpecializationDecl(
// Check that the template argument list is well-formed for this
// class template.
- SmallVector<TemplateArgument, 4> Converted;
- if (SemaRef.CheckTemplateArgumentList(InstClassTemplate,
- D->getLocation(),
- InstTemplateArgs,
- false,
- Converted,
+ SmallVector<TemplateArgument, 4> SugaredConverted, CanonicalConverted;
+ if (SemaRef.CheckTemplateArgumentList(InstClassTemplate, D->getLocation(),
+ InstTemplateArgs, false,
+ SugaredConverted, CanonicalConverted,
/*UpdateArgsWithConversions=*/true))
return nullptr;
@@ -3765,7 +3763,7 @@ TemplateDeclInstantiator::VisitClassTemplateSpecializationDecl(
// in the member template's set of class template explicit specializations.
void *InsertPos = nullptr;
ClassTemplateSpecializationDecl *PrevDecl =
- InstClassTemplate->findSpecialization(Converted, InsertPos);
+ InstClassTemplate->findSpecialization(CanonicalConverted, InsertPos);
// Check whether we've already seen a conflicting instantiation of this
// declaration (for instance, if there was a prior implicit instantiation).
@@ -3803,7 +3801,7 @@ TemplateDeclInstantiator::VisitClassTemplateSpecializationDecl(
ClassTemplateSpecializationDecl *InstD =
ClassTemplateSpecializationDecl::Create(
SemaRef.Context, D->getTagKind(), Owner, D->getBeginLoc(),
- D->getLocation(), InstClassTemplate, Converted, PrevDecl);
+ D->getLocation(), InstClassTemplate, CanonicalConverted, PrevDecl);
// Add this partial specialization to the set of class template partial
// specializations.
@@ -3817,7 +3815,7 @@ TemplateDeclInstantiator::VisitClassTemplateSpecializationDecl(
// Build the canonical type that describes the converted template
// arguments of the class template explicit specialization.
QualType CanonType = SemaRef.Context.getTemplateSpecializationType(
- TemplateName(InstClassTemplate), Converted,
+ TemplateName(InstClassTemplate), CanonicalConverted,
SemaRef.Context.getRecordType(InstD));
// Build the fully-sugared type for this class template
@@ -3879,16 +3877,17 @@ Decl *TemplateDeclInstantiator::VisitVarTemplateSpecializationDecl(
}
// Check that the template argument list is well-formed for this template.
- SmallVector<TemplateArgument, 4> Converted;
+ SmallVector<TemplateArgument, 4> SugaredConverted, CanonicalConverted;
if (SemaRef.CheckTemplateArgumentList(InstVarTemplate, D->getLocation(),
- VarTemplateArgsInfo, false, Converted,
+ VarTemplateArgsInfo, false,
+ SugaredConverted, CanonicalConverted,
/*UpdateArgsWithConversions=*/true))
return nullptr;
// Check whether we've already seen a declaration of this specialization.
void *InsertPos = nullptr;
VarTemplateSpecializationDecl *PrevDecl =
- InstVarTemplate->findSpecialization(Converted, InsertPos);
+ InstVarTemplate->findSpecialization(CanonicalConverted, InsertPos);
// Check whether we've already seen a conflicting instantiation of this
// declaration (for instance, if there was a prior implicit instantiation).
@@ -3900,7 +3899,7 @@ Decl *TemplateDeclInstantiator::VisitVarTemplateSpecializationDecl(
return nullptr;
return VisitVarTemplateSpecializationDecl(
- InstVarTemplate, D, VarTemplateArgsInfo, Converted, PrevDecl);
+ InstVarTemplate, D, VarTemplateArgsInfo, CanonicalConverted, PrevDecl);
}
Decl *TemplateDeclInstantiator::VisitVarTemplateSpecializationDecl(
@@ -4142,32 +4141,29 @@ TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization(
// Check that the template argument list is well-formed for this
// class template.
- SmallVector<TemplateArgument, 4> Converted;
- if (SemaRef.CheckTemplateArgumentList(ClassTemplate,
- PartialSpec->getLocation(),
- InstTemplateArgs,
- false,
- Converted))
+ SmallVector<TemplateArgument, 4> SugaredConverted, CanonicalConverted;
+ if (SemaRef.CheckTemplateArgumentList(
+ ClassTemplate, PartialSpec->getLocation(), InstTemplateArgs,
+ /*PartialTemplateArgs=*/false, SugaredConverted, CanonicalConverted))
return nullptr;
// Check these arguments are valid for a template partial specialization.
if (SemaRef.CheckTemplatePartialSpecializationArgs(
PartialSpec->getLocation(), ClassTemplate, InstTemplateArgs.size(),
- Converted))
+ CanonicalConverted))
return nullptr;
// Figure out where to insert this class template partial specialization
// in the member template's set of class template partial specializations.
void *InsertPos = nullptr;
- ClassTemplateSpecializationDecl *PrevDecl
- = ClassTemplate->findPartialSpecialization(Converted, InstParams,
+ ClassTemplateSpecializationDecl *PrevDecl =
+ ClassTemplate->findPartialSpecialization(CanonicalConverted, InstParams,
InsertPos);
// Build the canonical type that describes the converted template
// arguments of the class template partial specialization.
- QualType CanonType
- = SemaRef.Context.getTemplateSpecializationType(TemplateName(ClassTemplate),
- Converted);
+ QualType CanonType = SemaRef.Context.getTemplateSpecializationType(
+ TemplateName(ClassTemplate), CanonicalConverted);
// Build the fully-sugared type for this class template
// specialization as the user wrote in the specialization
@@ -4212,7 +4208,8 @@ TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization(
ClassTemplatePartialSpecializationDecl::Create(
SemaRef.Context, PartialSpec->getTagKind(), Owner,
PartialSpec->getBeginLoc(), PartialSpec->getLocation(), InstParams,
- ClassTemplate, Converted, InstTemplateArgs, CanonType, nullptr);
+ ClassTemplate, CanonicalConverted, InstTemplateArgs, CanonType,
+ nullptr);
// Substitute the nested name specifier, if any.
if (SubstQualifier(PartialSpec, InstPartialSpec))
return nullptr;
@@ -4269,27 +4266,29 @@ TemplateDeclInstantiator::InstantiateVarTemplatePartialSpecialization(
// Check that the template argument list is well-formed for this
// class template.
- SmallVector<TemplateArgument, 4> Converted;
- if (SemaRef.CheckTemplateArgumentList(VarTemplate, PartialSpec->getLocation(),
- InstTemplateArgs, false, Converted))
+ SmallVector<TemplateArgument, 4> SugaredConverted, CanonicalConverted;
+ if (SemaRef.CheckTemplateArgumentList(
+ VarTemplate, PartialSpec->getLocation(), InstTemplateArgs,
+ /*PartialTemplateArgs=*/false, SugaredConverted, CanonicalConverted))
return nullptr;
// Check these arguments are valid for a template partial specialization.
if (SemaRef.CheckTemplatePartialSpecializationArgs(
PartialSpec->getLocation(), VarTemplate, InstTemplateArgs.size(),
- Converted))
+ CanonicalConverted))
return nullptr;
// Figure out where to insert this variable template partial specialization
// in the member template's set of variable template partial specializations.
void *InsertPos = nullptr;
VarTemplateSpecializationDecl *PrevDecl =
- VarTemplate->findPartialSpecialization(Converted, InstParams, InsertPos);
+ VarTemplate->findPartialSpecialization(CanonicalConverted, InstParams,
+ InsertPos);
// Build the canonical type that describes the converted template
// arguments of the variable template partial specialization.
QualType CanonType = SemaRef.Context.getTemplateSpecializationType(
- TemplateName(VarTemplate), Converted);
+ TemplateName(VarTemplate), CanonicalConverted);
// Build the fully-sugared type for this variable template
// specialization as the user wrote in the specialization
@@ -4345,7 +4344,8 @@ TemplateDeclInstantiator::InstantiateVarTemplatePartialSpecialization(
VarTemplatePartialSpecializationDecl::Create(
SemaRef.Context, Owner, PartialSpec->getInnerLocStart(),
PartialSpec->getLocation(), InstParams, VarTemplate, DI->getType(),
- DI, PartialSpec->getStorageClass(), Converted, InstTemplateArgs);
+ DI, PartialSpec->getStorageClass(), CanonicalConverted,
+ InstTemplateArgs);
// Substitute the nested name specifier, if any.
if (SubstQualifier(PartialSpec, InstPartialSpec))
diff --git a/clang/test/SemaCXX/ppc-pair-mma-types.cpp b/clang/test/SemaCXX/ppc-pair-mma-types.cpp
index 085db9abd1def..933990fa80ba6 100644
--- a/clang/test/SemaCXX/ppc-pair-mma-types.cpp
+++ b/clang/test/SemaCXX/ppc-pair-mma-types.cpp
@@ -85,8 +85,8 @@ class TestClassVQ {
// template argument
template <typename T = __vector_quad>
- void testVQTemplate(T v, T *p) { // expected-note {{candidate template ignored: substitution failure [with T = __vector_quad]: invalid use of PPC MMA type}} \
- expected-note {{candidate template ignored: substitution failure [with T = __vector_quad]: invalid use of PPC MMA type}}
+ void testVQTemplate(T v, T *p) { // expected-note {{candidate template ignored: substitution failure [with T = vq_t]: invalid use of PPC MMA type}} \
+ expected-note {{candidate template ignored: substitution failure [with T = __vector_quad]: invalid use of PPC MMA type}}
*(p + 1) = v;
}
@@ -276,8 +276,8 @@ class TestClassVP {
// template argument
template <typename T = __vector_pair>
- void testVPTemplate(T v, T *p) { // expected-note {{candidate template ignored: substitution failure [with T = __vector_pair]: invalid use of PPC MMA type}} \
- expected-note {{candidate template ignored: substitution failure [with T = __vector_pair]: invalid use of PPC MMA type}}
+ void testVPTemplate(T v, T *p) { // expected-note {{candidate template ignored: substitution failure [with T = vp_t]: invalid use of PPC MMA type}} \
+ expected-note {{candidate template ignored: substitution failure [with T = __vector_pair]: invalid use of PPC MMA type}}
*(p + 1) = v;
}
diff --git a/clang/test/SemaTemplate/deduction.cpp b/clang/test/SemaTemplate/deduction.cpp
index c865c1a2962c3..7a45d1a425728 100644
--- a/clang/test/SemaTemplate/deduction.cpp
+++ b/clang/test/SemaTemplate/deduction.cpp
@@ -1,5 +1,6 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11
// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++1z
+// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++2b
// Template argument deduction with template template parameters.
template<typename T, template<T> class A>
@@ -661,3 +662,25 @@ namespace PR49724 {
template<void (A::*P)()> void f(Y<P>);
void g(Y<nullptr> y) { f(y); }
}
+
+namespace sugared_deduction {
+using Int = int;
+
+template <class T, int C> void f1(T(&)[C], T(&)[C+1]);
+// expected-note at -1 {{candidate template ignored: deduced type 'int[3]' of 2nd parameter does not match adjusted type 'Int[2]' (aka 'int[2]') of argument [with T = Int, C = 2]}}
+
+void t1() {
+ Int a[2], b[2];
+ f1(a, b); // expected-error {{no matching function for call to 'f1'}}
+}
+
+#if defined(__cpp_concepts)
+template <class T> void f2() requires false {}
+// expected-note at -1 {{candidate template ignored: constraints not satisfied [with T = Int]}}
+// expected-note at -2 {{because 'false' evaluated to false}}
+
+void t2() {
+ f2<Int>(); // expected-error {{no matching function for call to 'f2'}}
+}
+#endif
+} // namespace sugared_deduction
diff --git a/clang/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp b/clang/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp
index c872e770fd2ff..6ab9ecbfd573b 100644
--- a/clang/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp
+++ b/clang/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp
@@ -597,4 +597,9 @@ namespace PR47792 {
const I &r3 = m;
static_assert(&a<r1> == &a<r3>, "should have
diff erent types");
static_assert(&a<r2> != &a<r3>, "should have
diff erent types");
+
+ void foo();
+ template <void () = foo> void bar() {}
+ template void bar<>(); // expected-note {{previous explicit instantiation is here}}
+ template void bar<foo>(); // expected-error {{duplicate explicit instantiation of 'bar<&PR47792::foo>'}}
}
More information about the cfe-commits
mailing list