[clang] initial template arg fix push (PR #122754)
Aidan Goldfarb via cfe-commits
cfe-commits at lists.llvm.org
Tue Jan 14 08:41:32 PST 2025
https://github.com/AidanGoldfarb updated https://github.com/llvm/llvm-project/pull/122754
>From b6c576fb90362640b2fd4e41bd7f13dfee95d04d Mon Sep 17 00:00:00 2001
From: Aidan <aidan.goldfarb at mail.mcgill.ca>
Date: Mon, 13 Jan 2025 11:53:39 -0500
Subject: [PATCH 1/2] initial template arg fix push
---
.../clang/Basic/DiagnosticSemaKinds.td | 4 +-
clang/include/clang/Sema/TemplateDeduction.h | 5 ++
clang/lib/Sema/SemaOverload.cpp | 56 +++++++++++++++----
clang/lib/Sema/SemaTemplateDeduction.cpp | 8 +++
4 files changed, 61 insertions(+), 12 deletions(-)
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 8be4f946dce1cc..1456f34538bcc0 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -4871,8 +4871,8 @@ def note_ovl_candidate_inconsistent_deduction_types : Note<
"of conflicting types for parameter %0 (%1 of type $ vs. %3 of type $)|"
"%1 and %3 of conflicting types for parameter %0}2,4">;
def note_ovl_candidate_explicit_arg_mismatch_named : Note<
- "candidate template ignored: invalid explicitly-specified argument "
- "for template parameter %0">;
+ "template argument deduction/substitution failed:"
+ "error: could not convert '%0' from %1 to %2">;
def note_ovl_candidate_unsatisfied_constraints : Note<
"candidate template ignored: constraints not satisfied%0">;
def note_ovl_candidate_explicit_arg_mismatch_unnamed : Note<
diff --git a/clang/include/clang/Sema/TemplateDeduction.h b/clang/include/clang/Sema/TemplateDeduction.h
index 28b014fd84e4b3..9edd3724cf53cd 100644
--- a/clang/include/clang/Sema/TemplateDeduction.h
+++ b/clang/include/clang/Sema/TemplateDeduction.h
@@ -250,6 +250,9 @@ class TemplateDeductionInfo {
/// \brief The constraint satisfaction details resulting from the associated
/// constraints satisfaction tests.
ConstraintSatisfaction AssociatedConstraintsSatisfaction;
+
+ /// \brief Type supplied by user for deduction
+ TemplateArgument SuppliedType;
};
} // namespace sema
@@ -300,6 +303,8 @@ struct DeductionFailureInfo {
TemplateDeductionResult getResult() const {
return static_cast<TemplateDeductionResult>(Result);
}
+
+ const TemplateArgument *getSuppliedType();
};
/// TemplateSpecCandidate - This is a generalization of OverloadCandidate
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 34c287926b1d7d..6c437a52be21db 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -715,12 +715,18 @@ namespace {
struct DFIParamWithArguments : DFIArguments {
TemplateParameter Param;
};
+
// Structure used by DeductionFailureInfo to store template argument
// information and the index of the problematic call argument.
struct DFIDeducedMismatchArgs : DFIArguments {
TemplateArgumentList *TemplateArgs;
unsigned CallArgIndex;
};
+
+ struct DFIParamWithArgumentsAndSuppliedType : DFIArguments {
+ TemplateParameter Param;
+ TemplateArgument SuppliedType;
+ };
// Structure used by DeductionFailureInfo to store information about
// unsatisfied constraints.
struct CNSInfo {
@@ -736,8 +742,10 @@ clang::MakeDeductionFailureInfo(ASTContext &Context,
TemplateDeductionResult TDK,
TemplateDeductionInfo &Info) {
DeductionFailureInfo Result;
+
Result.Result = static_cast<unsigned>(TDK);
Result.HasDiagnostic = false;
+
switch (TDK) {
case TemplateDeductionResult::Invalid:
case TemplateDeductionResult::InstantiationDepth:
@@ -749,10 +757,9 @@ clang::MakeDeductionFailureInfo(ASTContext &Context,
break;
case TemplateDeductionResult::Incomplete:
- case TemplateDeductionResult::InvalidExplicitArguments:
+ // case TemplateDeductionResult::InvalidExplicitArguments:
Result.Data = Info.Param.getOpaqueValue();
break;
-
case TemplateDeductionResult::DeducedMismatch:
case TemplateDeductionResult::DeducedMismatchNested: {
// FIXME: Should allocate from normal heap so that we can free this later.
@@ -777,6 +784,7 @@ clang::MakeDeductionFailureInfo(ASTContext &Context,
case TemplateDeductionResult::IncompletePack:
// FIXME: It's slightly wasteful to allocate two TemplateArguments for this.
case TemplateDeductionResult::Inconsistent:
+
case TemplateDeductionResult::Underqualified: {
// FIXME: Should allocate from normal heap so that we can free this later.
DFIParamWithArguments *Saved = new (Context) DFIParamWithArguments;
@@ -786,6 +794,16 @@ clang::MakeDeductionFailureInfo(ASTContext &Context,
Result.Data = Saved;
break;
}
+ case TemplateDeductionResult::InvalidExplicitArguments: {
+ DFIParamWithArgumentsAndSuppliedType *Saved =
+ new (Context) DFIParamWithArgumentsAndSuppliedType;
+ Saved->Param = Info.Param;
+ Saved->FirstArg = Info.FirstArg;
+ Saved->SecondArg = Info.SecondArg;
+ Saved->SuppliedType = Info.SuppliedType;
+ Result.Data = Saved;
+ break;
+ }
case TemplateDeductionResult::SubstitutionFailure:
Result.Data = Info.takeSugared();
@@ -822,13 +840,14 @@ void DeductionFailureInfo::Destroy() {
case TemplateDeductionResult::Incomplete:
case TemplateDeductionResult::TooManyArguments:
case TemplateDeductionResult::TooFewArguments:
- case TemplateDeductionResult::InvalidExplicitArguments:
+ // case TemplateDeductionResult::InvalidExplicitArguments:
case TemplateDeductionResult::CUDATargetMismatch:
case TemplateDeductionResult::NonDependentConversionFailure:
break;
case TemplateDeductionResult::IncompletePack:
case TemplateDeductionResult::Inconsistent:
+ case TemplateDeductionResult::InvalidExplicitArguments:
case TemplateDeductionResult::Underqualified:
case TemplateDeductionResult::DeducedMismatch:
case TemplateDeductionResult::DeducedMismatchNested:
@@ -885,11 +904,11 @@ TemplateParameter DeductionFailureInfo::getTemplateParameter() {
return TemplateParameter();
case TemplateDeductionResult::Incomplete:
- case TemplateDeductionResult::InvalidExplicitArguments:
return TemplateParameter::getFromOpaqueValue(Data);
case TemplateDeductionResult::IncompletePack:
case TemplateDeductionResult::Inconsistent:
+ case TemplateDeductionResult::InvalidExplicitArguments:
case TemplateDeductionResult::Underqualified:
return static_cast<DFIParamWithArguments*>(Data)->Param;
@@ -938,6 +957,16 @@ TemplateArgumentList *DeductionFailureInfo::getTemplateArgumentList() {
return nullptr;
}
+const TemplateArgument *DeductionFailureInfo::getSuppliedType() {
+ switch (static_cast<TemplateDeductionResult>(Result)) {
+ case TemplateDeductionResult::InvalidExplicitArguments:
+ return &static_cast<DFIParamWithArgumentsAndSuppliedType *>(Data)
+ ->SuppliedType;
+ default:
+ return nullptr;
+ }
+}
+
const TemplateArgument *DeductionFailureInfo::getFirstArg() {
switch (static_cast<TemplateDeductionResult>(Result)) {
case TemplateDeductionResult::Success:
@@ -946,15 +975,17 @@ const TemplateArgument *DeductionFailureInfo::getFirstArg() {
case TemplateDeductionResult::Incomplete:
case TemplateDeductionResult::TooManyArguments:
case TemplateDeductionResult::TooFewArguments:
- case TemplateDeductionResult::InvalidExplicitArguments:
+ // case TemplateDeductionResult::InvalidExplicitArguments:
case TemplateDeductionResult::SubstitutionFailure:
case TemplateDeductionResult::CUDATargetMismatch:
case TemplateDeductionResult::NonDependentConversionFailure:
case TemplateDeductionResult::ConstraintsNotSatisfied:
return nullptr;
-
+ // case TemplateDeductionResult::InvalidExplicitArguments: //move back up
+ // there^^
case TemplateDeductionResult::IncompletePack:
case TemplateDeductionResult::Inconsistent:
+ case TemplateDeductionResult::InvalidExplicitArguments:
case TemplateDeductionResult::Underqualified:
case TemplateDeductionResult::DeducedMismatch:
case TemplateDeductionResult::DeducedMismatchNested:
@@ -979,7 +1010,7 @@ const TemplateArgument *DeductionFailureInfo::getSecondArg() {
case TemplateDeductionResult::IncompletePack:
case TemplateDeductionResult::TooManyArguments:
case TemplateDeductionResult::TooFewArguments:
- case TemplateDeductionResult::InvalidExplicitArguments:
+ // case TemplateDeductionResult::InvalidExplicitArguments:
case TemplateDeductionResult::SubstitutionFailure:
case TemplateDeductionResult::CUDATargetMismatch:
case TemplateDeductionResult::NonDependentConversionFailure:
@@ -987,6 +1018,7 @@ const TemplateArgument *DeductionFailureInfo::getSecondArg() {
return nullptr;
case TemplateDeductionResult::Inconsistent:
+ case TemplateDeductionResult::InvalidExplicitArguments:
case TemplateDeductionResult::Underqualified:
case TemplateDeductionResult::DeducedMismatch:
case TemplateDeductionResult::DeducedMismatchNested:
@@ -11613,6 +11645,7 @@ static void DiagnoseBadDeduction(Sema &S, NamedDecl *Found, Decl *Templated,
(ParamD = Param.dyn_cast<TemplateTypeParmDecl*>()) ||
(ParamD = Param.dyn_cast<NonTypeTemplateParmDecl*>()) ||
(ParamD = Param.dyn_cast<TemplateTemplateParmDecl*>());
+
switch (DeductionFailure.getResult()) {
case TemplateDeductionResult::Success:
llvm_unreachable(
@@ -11716,11 +11749,14 @@ static void DiagnoseBadDeduction(Sema &S, NamedDecl *Found, Decl *Templated,
case TemplateDeductionResult::InvalidExplicitArguments:
assert(ParamD && "no parameter found for invalid explicit arguments");
- if (ParamD->getDeclName())
+ if (ParamD->getDeclName()) {
+ auto FirstArg = *DeductionFailure.getFirstArg();
+ auto SecondArg = *DeductionFailure.getSecondArg();
+ auto SuppliedType = *DeductionFailure.getSuppliedType();
S.Diag(Templated->getLocation(),
diag::note_ovl_candidate_explicit_arg_mismatch_named)
- << ParamD->getDeclName();
- else {
+ << FirstArg << SuppliedType << SecondArg;
+ } else {
int index = 0;
if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(ParamD))
index = TTP->getIndex();
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index 1c1f6e30ab7b83..92415d49ee7a49 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -3575,7 +3575,15 @@ TemplateDeductionResult Sema::SubstituteExplicitTemplateArguments(
unsigned Index = SugaredBuilder.size();
if (Index >= TemplateParams->size())
return TemplateDeductionResult::SubstitutionFailure;
+
Info.Param = makeTemplateParameter(TemplateParams->getParam(Index));
+ Info.FirstArg = ExplicitTemplateArgs[Index].getArgument();
+ Info.SecondArg = TemplateArgument(
+ dyn_cast<NonTypeTemplateParmDecl>(TemplateParams->getParam(Index))
+ ->getType());
+ Info.SuppliedType = TemplateArgument(
+ ExplicitTemplateArgs[Index].getSourceExpression()->getType());
+
return TemplateDeductionResult::InvalidExplicitArguments;
}
>From e3a60c1f0adbf1801d51ab4d7834469349c0382a Mon Sep 17 00:00:00 2001
From: Aidan <aidan.goldfarb at mail.mcgill.ca>
Date: Tue, 14 Jan 2025 11:41:17 -0500
Subject: [PATCH 2/2] Improved safety, added some rt checks
---
clang/lib/Sema/SemaTemplateDeduction.cpp | 24 +++++++++++++++++++-----
1 file changed, 19 insertions(+), 5 deletions(-)
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index 92415d49ee7a49..521e0da3ef2f92 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -766,6 +766,12 @@ static TemplateParameter makeTemplateParameter(Decl *D) {
return TemplateParameter(cast<TemplateTemplateParmDecl>(D));
}
+// Helper function to make template argument
+static TemplateArgument makeTemplateArgument(Decl *D) {
+ if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D))
+ return TemplateArgument(NTTP->getType());
+ return TemplateArgument();
+}
/// A pack that we're currently deducing.
struct clang::DeducedPack {
@@ -3578,11 +3584,19 @@ TemplateDeductionResult Sema::SubstituteExplicitTemplateArguments(
Info.Param = makeTemplateParameter(TemplateParams->getParam(Index));
Info.FirstArg = ExplicitTemplateArgs[Index].getArgument();
- Info.SecondArg = TemplateArgument(
- dyn_cast<NonTypeTemplateParmDecl>(TemplateParams->getParam(Index))
- ->getType());
- Info.SuppliedType = TemplateArgument(
- ExplicitTemplateArgs[Index].getSourceExpression()->getType());
+ Info.SecondArg = makeTemplateArgument(TemplateParams->getParam(Index));
+ // Info.SecondArg = TemplateArgument(
+ // dyn_cast<NonTypeTemplateParmDecl>(TemplateParams->getParam(Index))
+ // ->getType());
+
+ // NonTypeTemplateParmDecl tmp =
+ // makeTemplateArgument(TemplateParams->getParam(Index)); if(!tmp.isNull()){
+ // Info.SecondArg = tmp->getType();
+ // }
+ if (ExplicitTemplateArgs[Index].getArgument().getKind() ==
+ TemplateArgument::Expression)
+ Info.SuppliedType = TemplateArgument(
+ ExplicitTemplateArgs[Index].getSourceExpression()->getType());
return TemplateDeductionResult::InvalidExplicitArguments;
}
More information about the cfe-commits
mailing list