aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Sema/SemaTemplateInstantiate.cpp
diff options
context:
space:
mode:
authorMatheus Izvekov <mizvekov@gmail.com>2025-09-24 17:18:41 -0300
committerMatheus Izvekov <mizvekov@gmail.com>2025-09-26 16:18:42 -0300
commit1160542a693e22cc81c719e371d1b6282ecc3800 (patch)
tree1c23ff6c8b9bc54926911560b84450d937e51047 /clang/lib/Sema/SemaTemplateInstantiate.cpp
parent21fe7eea5c0f7dbfe8b08251a594c23ea2e8980d (diff)
downloadllvm-users/mizvekov/fix-substnttp-transform.zip
llvm-users/mizvekov/fix-substnttp-transform.tar.gz
llvm-users/mizvekov/fix-substnttp-transform.tar.bz2
[clang] fix transformation of subst constant template parameter nodesusers/mizvekov/fix-substnttp-transform
This simplifies those transforms a lot, removing a bunch of workarounds which were introducing problems. The transforms become independent of the template instantiator, so they are moved to TreeTransform instead. Fixes #131342
Diffstat (limited to 'clang/lib/Sema/SemaTemplateInstantiate.cpp')
-rw-r--r--clang/lib/Sema/SemaTemplateInstantiate.cpp203
1 files changed, 19 insertions, 184 deletions
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index a72c95d..1ff94d7 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -1373,16 +1373,6 @@ std::optional<TemplateDeductionInfo *> Sema::isSFINAEContext() const {
return std::nullopt;
}
-static TemplateArgument
-getPackSubstitutedTemplateArgument(Sema &S, TemplateArgument Arg) {
- assert(S.ArgPackSubstIndex);
- assert(*S.ArgPackSubstIndex < Arg.pack_size());
- Arg = Arg.pack_begin()[*S.ArgPackSubstIndex];
- if (Arg.isPackExpansion())
- Arg = Arg.getPackExpansionPattern();
- return Arg;
-}
-
//===----------------------------------------------------------------------===/
// Template Instantiation for Types
//===----------------------------------------------------------------------===/
@@ -1449,13 +1439,6 @@ namespace {
return TemplateArgs.getNewDepth(Depth);
}
- UnsignedOrNone getPackIndex(TemplateArgument Pack) {
- UnsignedOrNone Index = getSema().ArgPackSubstIndex;
- if (!Index)
- return std::nullopt;
- return Pack.pack_size() - 1 - *Index;
- }
-
bool TryExpandParameterPacks(SourceLocation EllipsisLoc,
SourceRange PatternRange,
ArrayRef<UnexpandedParameterPack> Unexpanded,
@@ -1537,7 +1520,7 @@ namespace {
if (TA.getKind() != TemplateArgument::Pack)
return TA;
if (SemaRef.ArgPackSubstIndex)
- return getPackSubstitutedTemplateArgument(SemaRef, TA);
+ return SemaRef.getPackSubstitutedTemplateArgument(TA);
assert(TA.pack_size() == 1 && TA.pack_begin()->isPackExpansion() &&
"unexpected pack arguments in template rewrite");
TemplateArgument Arg = *TA.pack_begin();
@@ -1643,10 +1626,6 @@ namespace {
ExprResult TransformTemplateParmRefExpr(DeclRefExpr *E,
NonTypeTemplateParmDecl *D);
- ExprResult TransformSubstNonTypeTemplateParmPackExpr(
- SubstNonTypeTemplateParmPackExpr *E);
- ExprResult TransformSubstNonTypeTemplateParmExpr(
- SubstNonTypeTemplateParmExpr *E);
/// Rebuild a DeclRefExpr for a VarDecl reference.
ExprResult RebuildVarDeclRefExpr(ValueDecl *PD, SourceLocation Loc);
@@ -1933,12 +1912,6 @@ namespace {
SmallVectorImpl<QualType> &PTypes,
SmallVectorImpl<ParmVarDecl *> &TransParams,
Sema::ExtParameterInfoBuilder &PInfos);
-
- private:
- ExprResult
- transformNonTypeTemplateParmRef(Decl *AssociatedDecl, const NamedDecl *parm,
- SourceLocation loc, TemplateArgument arg,
- UnsignedOrNone PackIndex, bool Final);
};
}
@@ -1975,7 +1948,7 @@ Decl *TemplateInstantiator::TransformDecl(SourceLocation Loc, Decl *D) {
if (TTP->isParameterPack()) {
assert(Arg.getKind() == TemplateArgument::Pack &&
"Missing argument pack");
- Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
+ Arg = SemaRef.getPackSubstitutedTemplateArgument(Arg);
}
TemplateName Template = Arg.getAsTemplate();
@@ -2079,7 +2052,7 @@ TemplateInstantiator::TransformFirstQualifierInScope(NamedDecl *D,
if (!getSema().ArgPackSubstIndex)
return nullptr;
- Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
+ Arg = SemaRef.getPackSubstitutedTemplateArgument(Arg);
}
QualType T = Arg.getAsType();
@@ -2165,8 +2138,8 @@ TemplateName TemplateInstantiator::TransformTemplateName(
Arg, AssociatedDecl, TTP->getIndex(), Final);
}
- PackIndex = getPackIndex(Arg);
- Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
+ PackIndex = SemaRef.getPackIndex(Arg);
+ Arg = SemaRef.getPackSubstitutedTemplateArgument(Arg);
}
TemplateName Template = Arg.getAsTemplate();
@@ -2183,10 +2156,10 @@ TemplateName TemplateInstantiator::TransformTemplateName(
TemplateArgument Pack = SubstPack->getArgumentPack();
TemplateName Template =
- getPackSubstitutedTemplateArgument(getSema(), Pack).getAsTemplate();
+ SemaRef.getPackSubstitutedTemplateArgument(Pack).getAsTemplate();
return getSema().Context.getSubstTemplateTemplateParm(
Template, SubstPack->getAssociatedDecl(), SubstPack->getIndex(),
- getPackIndex(Pack), SubstPack->getFinal());
+ SemaRef.getPackIndex(Pack), SubstPack->getFinal());
}
return inherited::TransformTemplateName(
@@ -2252,11 +2225,11 @@ TemplateInstantiator::TransformTemplateParmRefExpr(DeclRefExpr *E,
ExprType, TargetType->isReferenceType() ? VK_LValue : VK_PRValue,
E->getLocation(), Arg, AssociatedDecl, NTTP->getPosition(), Final);
}
- PackIndex = getPackIndex(Arg);
- Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
+ PackIndex = SemaRef.getPackIndex(Arg);
+ Arg = SemaRef.getPackSubstitutedTemplateArgument(Arg);
}
- return transformNonTypeTemplateParmRef(AssociatedDecl, NTTP, E->getLocation(),
- Arg, PackIndex, Final);
+ return SemaRef.BuildSubstNonTypeTemplateParmExpr(
+ AssociatedDecl, NTTP, E->getLocation(), Arg, PackIndex, Final);
}
const AnnotateAttr *
@@ -2344,144 +2317,6 @@ TemplateInstantiator::TransformOpenACCRoutineDeclAttr(
"applies to a Function Decl (and a few places for VarDecl)");
}
-ExprResult TemplateInstantiator::transformNonTypeTemplateParmRef(
- Decl *AssociatedDecl, const NamedDecl *parm, SourceLocation loc,
- TemplateArgument arg, UnsignedOrNone PackIndex, bool Final) {
- ExprResult result;
-
- // Determine the substituted parameter type. We can usually infer this from
- // the template argument, but not always.
- auto SubstParamType = [&] {
- if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(parm)) {
- QualType T;
- if (NTTP->isExpandedParameterPack())
- T = NTTP->getExpansionType(*SemaRef.ArgPackSubstIndex);
- else
- T = NTTP->getType();
- if (parm->isParameterPack() && isa<PackExpansionType>(T))
- T = cast<PackExpansionType>(T)->getPattern();
- return SemaRef.SubstType(T, TemplateArgs, loc, parm->getDeclName());
- }
- return SemaRef.SubstType(arg.getAsExpr()->getType(), TemplateArgs, loc,
- parm->getDeclName());
- };
-
- bool refParam = false;
-
- // The template argument itself might be an expression, in which case we just
- // return that expression. This happens when substituting into an alias
- // template.
- if (arg.getKind() == TemplateArgument::Expression) {
- Expr *argExpr = arg.getAsExpr();
- result = argExpr;
- if (argExpr->isLValue()) {
- if (argExpr->getType()->isRecordType()) {
- // Check whether the parameter was actually a reference.
- QualType paramType = SubstParamType();
- if (paramType.isNull())
- return ExprError();
- refParam = paramType->isReferenceType();
- } else {
- refParam = true;
- }
- }
- } else if (arg.getKind() == TemplateArgument::Declaration ||
- arg.getKind() == TemplateArgument::NullPtr) {
- if (arg.getKind() == TemplateArgument::Declaration) {
- ValueDecl *VD = arg.getAsDecl();
-
- // Find the instantiation of the template argument. This is
- // required for nested templates.
- VD = cast_or_null<ValueDecl>(
- getSema().FindInstantiatedDecl(loc, VD, TemplateArgs));
- if (!VD)
- return ExprError();
- }
-
- QualType paramType = arg.getNonTypeTemplateArgumentType();
- assert(!paramType.isNull() && "type substitution failed for param type");
- assert(!paramType->isDependentType() && "param type still dependent");
- result = SemaRef.BuildExpressionFromDeclTemplateArgument(arg, paramType, loc);
- refParam = paramType->isReferenceType();
- } else {
- QualType paramType = arg.getNonTypeTemplateArgumentType();
- result = SemaRef.BuildExpressionFromNonTypeTemplateArgument(arg, loc);
- refParam = paramType->isReferenceType();
- assert(result.isInvalid() ||
- SemaRef.Context.hasSameType(result.get()->getType(),
- paramType.getNonReferenceType()));
- }
-
- if (result.isInvalid())
- return ExprError();
-
- Expr *resultExpr = result.get();
- return new (SemaRef.Context) SubstNonTypeTemplateParmExpr(
- resultExpr->getType(), resultExpr->getValueKind(), loc, resultExpr,
- AssociatedDecl,
- clang::getDepthAndIndex(const_cast<NamedDecl *>(parm)).second, PackIndex,
- refParam, Final);
-}
-
-ExprResult
-TemplateInstantiator::TransformSubstNonTypeTemplateParmPackExpr(
- SubstNonTypeTemplateParmPackExpr *E) {
- if (!getSema().ArgPackSubstIndex) {
- // We aren't expanding the parameter pack, so just return ourselves.
- return E;
- }
-
- TemplateArgument Pack = E->getArgumentPack();
- TemplateArgument Arg = getPackSubstitutedTemplateArgument(getSema(), Pack);
- return transformNonTypeTemplateParmRef(
- E->getAssociatedDecl(), E->getParameterPack(),
- E->getParameterPackLocation(), Arg, getPackIndex(Pack), E->getFinal());
-}
-
-ExprResult
-TemplateInstantiator::TransformSubstNonTypeTemplateParmExpr(
- SubstNonTypeTemplateParmExpr *E) {
- ExprResult SubstReplacement = E->getReplacement();
- if (!isa<ConstantExpr>(SubstReplacement.get()))
- SubstReplacement = TransformExpr(E->getReplacement());
- if (SubstReplacement.isInvalid())
- return true;
- QualType SubstType = TransformType(E->getParameterType(getSema().Context));
- if (SubstType.isNull())
- return true;
- // The type may have been previously dependent and not now, which means we
- // might have to implicit cast the argument to the new type, for example:
- // template<auto T, decltype(T) U>
- // concept C = sizeof(U) == 4;
- // void foo() requires C<2, 'a'> { }
- // When normalizing foo(), we first form the normalized constraints of C:
- // AtomicExpr(sizeof(U) == 4,
- // U=SubstNonTypeTemplateParmExpr(Param=U,
- // Expr=DeclRef(U),
- // Type=decltype(T)))
- // Then we substitute T = 2, U = 'a' into the parameter mapping, and need to
- // produce:
- // AtomicExpr(sizeof(U) == 4,
- // U=SubstNonTypeTemplateParmExpr(Param=U,
- // Expr=ImpCast(
- // decltype(2),
- // SubstNTTPE(Param=U, Expr='a',
- // Type=char)),
- // Type=decltype(2)))
- // The call to CheckTemplateArgument here produces the ImpCast.
- TemplateArgument SugaredConverted, CanonicalConverted;
- if (SemaRef
- .CheckTemplateArgument(E->getParameter(), SubstType,
- SubstReplacement.get(), SugaredConverted,
- CanonicalConverted,
- /*StrictCheck=*/false, Sema::CTAK_Specified)
- .isInvalid())
- return true;
- return transformNonTypeTemplateParmRef(
- E->getAssociatedDecl(), E->getParameter(), E->getExprLoc(),
- SugaredConverted, E->getPackIndex(), E->getFinal());
-}
-
ExprResult TemplateInstantiator::RebuildVarDeclRefExpr(ValueDecl *PD,
SourceLocation Loc) {
DeclarationNameInfo NameInfo(PD->getDeclName(), Loc);
@@ -2701,8 +2536,8 @@ TemplateInstantiator::TransformTemplateTypeParmType(TypeLocBuilder &TLB,
}
// PackIndex starts from last element.
- PackIndex = getPackIndex(Arg);
- Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
+ PackIndex = SemaRef.getPackIndex(Arg);
+ Arg = SemaRef.getPackSubstitutedTemplateArgument(Arg);
}
assert(Arg.getKind() == TemplateArgument::Type &&
@@ -2749,20 +2584,20 @@ QualType TemplateInstantiator::TransformSubstTemplateTypeParmPackType(
}
TemplateArgument Pack = T->getArgumentPack();
- TemplateArgument Arg = getPackSubstitutedTemplateArgument(getSema(), Pack);
+ TemplateArgument Arg = SemaRef.getPackSubstitutedTemplateArgument(Pack);
return BuildSubstTemplateTypeParmType(
TLB, SuppressObjCLifetime, T->getFinal(), NewReplaced, T->getIndex(),
- getPackIndex(Pack), Arg, TL.getNameLoc());
+ SemaRef.getPackIndex(Pack), Arg, TL.getNameLoc());
}
QualType TemplateInstantiator::TransformSubstBuiltinTemplatePackType(
TypeLocBuilder &TLB, SubstBuiltinTemplatePackTypeLoc TL) {
if (!getSema().ArgPackSubstIndex)
return TreeTransform::TransformSubstBuiltinTemplatePackType(TLB, TL);
- auto &Sema = getSema();
- TemplateArgument Result = getPackSubstitutedTemplateArgument(
- Sema, TL.getTypePtr()->getArgumentPack());
- TLB.pushTrivial(Sema.getASTContext(), Result.getAsType(), TL.getBeginLoc());
+ TemplateArgument Result = SemaRef.getPackSubstitutedTemplateArgument(
+ TL.getTypePtr()->getArgumentPack());
+ TLB.pushTrivial(SemaRef.getASTContext(), Result.getAsType(),
+ TL.getBeginLoc());
return Result.getAsType();
}