[llvm-branch-commits] [clang] [clang] fix template argument conversion (PR #124386)
Matheus Izvekov via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Mon Jan 27 11:47:12 PST 2025
================
@@ -5252,63 +5253,73 @@ bool Sema::CheckTemplateArgument(
return true;
}
- switch (Arg.getArgument().getKind()) {
- case TemplateArgument::Null:
- llvm_unreachable("Should never see a NULL template argument here");
-
- case TemplateArgument::Expression: {
- Expr *E = Arg.getArgument().getAsExpr();
+ auto checkExpr = [&](Expr *E) -> Expr * {
TemplateArgument SugaredResult, CanonicalResult;
unsigned CurSFINAEErrors = NumSFINAEErrors;
ExprResult Res =
CheckTemplateArgument(NTTP, NTTPType, E, SugaredResult,
CanonicalResult, PartialOrderingTTP, CTAK);
- if (Res.isInvalid())
- return true;
// If the current template argument causes an error, give up now.
- if (CurSFINAEErrors < NumSFINAEErrors)
- return true;
+ if (Res.isInvalid() || CurSFINAEErrors < NumSFINAEErrors)
+ return nullptr;
+ SugaredConverted.push_back(SugaredResult);
+ CanonicalConverted.push_back(CanonicalResult);
+ return Res.get();
+ };
+
+ switch (Arg.getKind()) {
+ case TemplateArgument::Null:
+ llvm_unreachable("Should never see a NULL template argument here");
+ case TemplateArgument::Expression: {
+ Expr *E = Arg.getAsExpr();
+ Expr *R = checkExpr(E);
+ if (!R)
+ return true;
// If the resulting expression is new, then use it in place of the
// old expression in the template argument.
- if (Res.get() != E) {
- TemplateArgument TA(Res.get());
- Arg = TemplateArgumentLoc(TA, Res.get());
+ if (R != E) {
+ TemplateArgument TA(R);
+ ArgLoc = TemplateArgumentLoc(TA, R);
}
-
- SugaredConverted.push_back(SugaredResult);
- CanonicalConverted.push_back(CanonicalResult);
break;
}
- case TemplateArgument::Declaration:
+ // As for the converted NTTP kinds, they still might need another
+ // conversion, as the new corresponding parameter might be different.
+ // Ideally, we would always perform substitution starting with sugared types
+ // and never need these, as we would still have expressions. Since these are
+ // needed so rarely, it's probably a better tradeoff to just convert them
+ // back to expressions.
case TemplateArgument::Integral:
- case TemplateArgument::StructuralValue:
+ case TemplateArgument::Declaration:
case TemplateArgument::NullPtr:
- // We've already checked this template argument, so just copy
- // it to the list of converted arguments.
- SugaredConverted.push_back(Arg.getArgument());
- CanonicalConverted.push_back(
- Context.getCanonicalTemplateArgument(Arg.getArgument()));
+ case TemplateArgument::StructuralValue: {
+ // FIXME: StructuralValue is untested here.
+ ExprResult R =
+ BuildExpressionFromNonTypeTemplateArgument(Arg, SourceLocation());
----------------
mizvekov wrote:
This is used elsewhere to similar effect, and yes it may produce ASTContext nodes which are unreachable, which is something we are in general not very good at avoiding.
We may rework that function in the future so it can produce a temporary expression. The previous solution in the patch was better in that effect, but would end up duplicating `BuildExpressionFromNonTypeTemplateArgument` in part.
https://github.com/llvm/llvm-project/pull/124386
More information about the llvm-branch-commits
mailing list