[clang] [Clang] Substitute for the type aliases inside of a CTAD guide (PR #94740)
Haojian Wu via cfe-commits
cfe-commits at lists.llvm.org
Tue Jun 11 04:08:04 PDT 2024
================
@@ -2220,23 +2220,103 @@ namespace {
class ExtractTypeForDeductionGuide
: public TreeTransform<ExtractTypeForDeductionGuide> {
llvm::SmallVectorImpl<TypedefNameDecl *> &MaterializedTypedefs;
+ ClassTemplateDecl *NestedPattern;
+ const MultiLevelTemplateArgumentList *OuterInstantiationArgs;
public:
typedef TreeTransform<ExtractTypeForDeductionGuide> Base;
ExtractTypeForDeductionGuide(
Sema &SemaRef,
- llvm::SmallVectorImpl<TypedefNameDecl *> &MaterializedTypedefs)
- : Base(SemaRef), MaterializedTypedefs(MaterializedTypedefs) {}
+ llvm::SmallVectorImpl<TypedefNameDecl *> &MaterializedTypedefs,
+ ClassTemplateDecl *NestedPattern,
+ const MultiLevelTemplateArgumentList *OuterInstantiationArgs)
+ : Base(SemaRef), MaterializedTypedefs(MaterializedTypedefs),
+ NestedPattern(NestedPattern),
+ OuterInstantiationArgs(OuterInstantiationArgs) {}
TypeSourceInfo *transform(TypeSourceInfo *TSI) { return TransformType(TSI); }
+ /// Returns true if it's safe to substitute \p Typedef with
+ /// \p OuterInstantiationArgs.
+ bool mightReferToOuterTemplateParameters(TypedefNameDecl *Typedef) {
+ if (!NestedPattern)
+ return false;
+
+ static auto WalkUp = [](DeclContext *DC, DeclContext *TargetDC) {
+ if (DC->Equals(TargetDC))
+ return true;
+ while (DC->isRecord()) {
+ if (DC->Equals(TargetDC))
+ return true;
+ DC = DC->getParent();
+ }
+ return false;
+ };
+
+ if (WalkUp(Typedef->getDeclContext(), NestedPattern->getTemplatedDecl()))
+ return true;
+ if (WalkUp(NestedPattern->getTemplatedDecl(), Typedef->getDeclContext()))
+ return true;
+ return false;
+ }
+
+ QualType
+ RebuildTemplateSpecializationType(TemplateName Template,
+ SourceLocation TemplateNameLoc,
+ TemplateArgumentListInfo &TemplateArgs) {
+ if (!OuterInstantiationArgs ||
+ !isa_and_present<TypeAliasTemplateDecl>(Template.getAsTemplateDecl()))
+ return Base::RebuildTemplateSpecializationType(Template, TemplateNameLoc,
+ TemplateArgs);
+
+ auto *TATD = cast<TypeAliasTemplateDecl>(Template.getAsTemplateDecl());
+ auto *Pattern = TATD;
+ while (Pattern->getInstantiatedFromMemberTemplate())
+ Pattern = Pattern->getInstantiatedFromMemberTemplate();
+ if (!mightReferToOuterTemplateParameters(Pattern->getTemplatedDecl()))
+ return Base::RebuildTemplateSpecializationType(Template, TemplateNameLoc,
+ TemplateArgs);
+
+ Decl *NewD = SemaRef.SubstDecl(
+ TATD, SemaRef.getASTContext().getTranslationUnitDecl(),
+ *OuterInstantiationArgs);
+ if (!NewD)
+ return QualType();
+
+ auto *NewTATD = cast<TypeAliasTemplateDecl>(NewD);
+ MaterializedTypedefs.push_back(NewTATD->getTemplatedDecl());
+
+ return Base::RebuildTemplateSpecializationType(
+ TemplateName(NewTATD), TemplateNameLoc, TemplateArgs);
+ }
+
QualType TransformTypedefType(TypeLocBuilder &TLB, TypedefTypeLoc TL) {
ASTContext &Context = SemaRef.getASTContext();
TypedefNameDecl *OrigDecl = TL.getTypedefNameDecl();
TypedefNameDecl *Decl = OrigDecl;
// Transform the underlying type of the typedef and clone the Decl only if
// the typedef has a dependent context.
- if (OrigDecl->getDeclContext()->isDependentContext()) {
+ bool InDependentContext = OrigDecl->getDeclContext()->isDependentContext();
+
+ // A typedef/alias Decl within the NestedPattern may reference the outer
+ // template parameters. They're substituted with corresponding instantiation
+ // arguments here and in RebuildTemplateSpecializationType() above.
+ // Otherwise, we would have a CTAD guide with "dangling" template
+ // parameters.
+ // For example,
+ // template <class T> struct Outer {
+ // using Alias = S<T>;
+ // template <class U> struct Inner {
+ // Inner(Alias);
+ // };
+ // };
+ if (OuterInstantiationArgs && InDependentContext) {
+ Decl = cast_if_present<TypedefNameDecl>(SemaRef.SubstDecl(
+ OrigDecl, Context.getTranslationUnitDecl(), *OuterInstantiationArgs));
----------------
hokein wrote:
and here as well.
https://github.com/llvm/llvm-project/pull/94740
More information about the cfe-commits
mailing list