diff options
author | Younan Zhang <zyn7109@gmail.com> | 2025-03-22 22:55:58 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-03-22 22:55:58 +0800 |
commit | 032ad590d6bac76965fac17b9f2ce41e076a5a0a (patch) | |
tree | cbd5a7ee80724e8a583b376f7a201409958c0150 /clang/lib/Sema/SemaTemplateInstantiate.cpp | |
parent | 2186199d085b80fe5d254148c0e1f99412da9026 (diff) | |
download | llvm-032ad590d6bac76965fac17b9f2ce41e076a5a0a.zip llvm-032ad590d6bac76965fac17b9f2ce41e076a5a0a.tar.gz llvm-032ad590d6bac76965fac17b9f2ce41e076a5a0a.tar.bz2 |
[Clang] Fix various bugs in alias CTAD transform (#132061)
Diffstat (limited to 'clang/lib/Sema/SemaTemplateInstantiate.cpp')
-rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiate.cpp | 46 |
1 files changed, 34 insertions, 12 deletions
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index ad49d6f..00dcadb 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -1348,6 +1348,16 @@ std::optional<TemplateDeductionInfo *> Sema::isSFINAEContext() const { return std::nullopt; } +static TemplateArgument +getPackSubstitutedTemplateArgument(Sema &S, TemplateArgument Arg) { + assert(S.ArgumentPackSubstitutionIndex >= 0); + assert(S.ArgumentPackSubstitutionIndex < (int)Arg.pack_size()); + Arg = Arg.pack_begin()[S.ArgumentPackSubstitutionIndex]; + if (Arg.isPackExpansion()) + Arg = Arg.getPackExpansionPattern(); + return Arg; +} + //===----------------------------------------------------------------------===/ // Template Instantiation for Types //===----------------------------------------------------------------------===/ @@ -1467,11 +1477,13 @@ namespace { } } - static TemplateArgument + TemplateArgument getTemplateArgumentPackPatternForRewrite(const TemplateArgument &TA) { if (TA.getKind() != TemplateArgument::Pack) return TA; - assert(TA.pack_size() == 1 && + if (SemaRef.ArgumentPackSubstitutionIndex != -1) + return getPackSubstitutedTemplateArgument(SemaRef, TA); + assert(TA.pack_size() == 1 && TA.pack_begin()->isPackExpansion() && "unexpected pack arguments in template rewrite"); TemplateArgument Arg = *TA.pack_begin(); if (Arg.isPackExpansion()) @@ -1632,6 +1644,9 @@ namespace { std::vector<TemplateArgument> TArgs; switch (Arg.getKind()) { case TemplateArgument::Pack: + assert(SemaRef.CodeSynthesisContexts.empty() || + SemaRef.CodeSynthesisContexts.back().Kind == + Sema::CodeSynthesisContext::BuildingDeductionGuides); // Literally rewrite the template argument pack, instead of unpacking // it. for (auto &pack : Arg.getPackAsArray()) { @@ -1652,6 +1667,23 @@ namespace { return inherited::TransformTemplateArgument(Input, Output, Uneval); } + std::optional<unsigned> ComputeSizeOfPackExprWithoutSubstitution( + ArrayRef<TemplateArgument> PackArgs) { + // Don't do this when rewriting template parameters for CTAD: + // 1) The heuristic needs the unpacked Subst* nodes to figure out the + // expanded size, but this never applies since Subst* nodes are not + // created in rewrite scenarios. + // + // 2) The heuristic substitutes into the pattern with pack expansion + // suppressed, which does not meet the requirements for argument + // rewriting when template arguments include a non-pack matching against + // a pack, particularly when rewriting an alias CTAD. + if (TemplateArgs.isRewrite()) + return std::nullopt; + + return inherited::ComputeSizeOfPackExprWithoutSubstitution(PackArgs); + } + template<typename Fn> QualType TransformFunctionProtoType(TypeLocBuilder &TLB, FunctionProtoTypeLoc TL, @@ -1871,16 +1903,6 @@ bool TemplateInstantiator::AlreadyTransformed(QualType T) { return true; } -static TemplateArgument -getPackSubstitutedTemplateArgument(Sema &S, TemplateArgument Arg) { - assert(S.ArgumentPackSubstitutionIndex >= 0); - assert(S.ArgumentPackSubstitutionIndex < (int)Arg.pack_size()); - Arg = Arg.pack_begin()[S.ArgumentPackSubstitutionIndex]; - if (Arg.isPackExpansion()) - Arg = Arg.getPackExpansionPattern(); - return Arg; -} - Decl *TemplateInstantiator::TransformDecl(SourceLocation Loc, Decl *D) { if (!D) return nullptr; |