[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-03-08 Thread Haojian Wu via cfe-commits

https://github.com/hokein closed https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-03-08 Thread via cfe-commits

cor3ntin wrote:

> BTW, should we close #54051 with this PR? or should we keep it open until the 
> feature is fully implemented? The `is_deducible` part is a major missing 
> piece, I think we can close #54051 and open a separate issue to track the 
> missing piece, WDYT?

Sounds good

https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-03-08 Thread Haojian Wu via cfe-commits

hokein wrote:

> > Thank you for all the reviews, I will wait 1 or 2 days before merging it in 
> > case anyone has more comments.
> 
> Sure! Do you plan to keep working on completing this feature?

Yeah, I plan to complete this feature before the next clang release. If anyone 
is willing to help, that would be even greater.

BTW, should we close https://github.com/llvm/llvm-project/issues/54051 with 
this PR? or should we keep it open until the feature is fully implemented? The 
`is_deducible` part is a major missing piece, I think we can close #54051 and 
open a separate issue to track the missing piece, WDYT?


https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-03-07 Thread via cfe-commits

cor3ntin wrote:

> Thank you for all the reviews, I will wait 1 or 2 days before merging it in 
> case anyone has more comments.

Sure!
Do you plan to keep working on completing this feature?

https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-03-07 Thread Haojian Wu via cfe-commits

hokein wrote:

Thank you for all the reviews, I will wait 1 or 2 days before merging it in 
case anyone has more comments.

https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-03-07 Thread Haojian Wu via cfe-commits


@@ -10598,10 +10598,34 @@ QualType 
Sema::DeduceTemplateSpecializationFromInitializer(
   if (TemplateName.isDependent())
 return SubstAutoTypeDependent(TSInfo->getType());
 
-  // We can only perform deduction for class templates.
+  // We can only perform deduction for class templates or alias templates.
   auto *Template =
   dyn_cast_or_null(TemplateName.getAsTemplateDecl());
+  TemplateDecl* LookupTemplateDecl = Template;
+  if (!Template && getLangOpts().CPlusPlus20) { // type alias template
+if (auto *AliasTemplate = dyn_cast_or_null(
+TemplateName.getAsTemplateDecl());
+AliasTemplate) {
+  LookupTemplateDecl = AliasTemplate;
+  auto UnderlyingType = AliasTemplate->getTemplatedDecl()
+->getUnderlyingType()
+.getDesugaredType(Context);
+  if (const auto *TST =
+  UnderlyingType->getAs()) {
+Template = dyn_cast_or_null(
+TST->getTemplateName().getAsTemplateDecl());
+  } else if (const auto *RT = UnderlyingType->getAs()) {
+// Cases where template arguments in the RHS of the alias are not
+// dependent. e.g.
+//   using AliasFoo = Foo;
+if (const auto *CTSD = llvm::dyn_cast(
+RT->getAsCXXRecordDecl()))
+  Template = CTSD->getSpecializedTemplate();
+  }

hokein wrote:

Yes, exactly. 

https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-03-07 Thread via cfe-commits

https://github.com/cor3ntin approved this pull request.

LGTM
Thanks for working on that!

https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-03-07 Thread via cfe-commits


@@ -10598,10 +10598,34 @@ QualType 
Sema::DeduceTemplateSpecializationFromInitializer(
   if (TemplateName.isDependent())
 return SubstAutoTypeDependent(TSInfo->getType());
 
-  // We can only perform deduction for class templates.
+  // We can only perform deduction for class templates or alias templates.
   auto *Template =
   dyn_cast_or_null(TemplateName.getAsTemplateDecl());
+  TemplateDecl* LookupTemplateDecl = Template;
+  if (!Template && getLangOpts().CPlusPlus20) { // type alias template
+if (auto *AliasTemplate = dyn_cast_or_null(
+TemplateName.getAsTemplateDecl());
+AliasTemplate) {
+  LookupTemplateDecl = AliasTemplate;
+  auto UnderlyingType = AliasTemplate->getTemplatedDecl()
+->getUnderlyingType()
+.getDesugaredType(Context);
+  if (const auto *TST =
+  UnderlyingType->getAs()) {
+Template = dyn_cast_or_null(
+TST->getTemplateName().getAsTemplateDecl());
+  } else if (const auto *RT = UnderlyingType->getAs()) {
+// Cases where template arguments in the RHS of the alias are not
+// dependent. e.g.
+//   using AliasFoo = Foo;
+if (const auto *CTSD = llvm::dyn_cast(
+RT->getAsCXXRecordDecl()))
+  Template = CTSD->getSpecializedTemplate();
+  }

cor3ntin wrote:

The point of the To make sure, in all non-handled case, `Template` would be 
null and we emit a diag?
That works for me

https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-03-07 Thread Vlad Serebrennikov via cfe-commits

https://github.com/Endilll commented:

`Sema.h` changes look good.

https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-03-07 Thread Haojian Wu via cfe-commits


@@ -96,6 +96,10 @@ C++20 Feature Support
   behavior can use the flag '-Xclang -fno-skip-odr-check-in-gmf'.
   (`#79240 `_).
 
+- Initial support for class template argument deduciton (CTAD) for type alias
+  templates (`P1814R0 `_).

hokein wrote:

Done.

https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-03-07 Thread Haojian Wu via cfe-commits

https://github.com/hokein edited https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-03-07 Thread Haojian Wu via cfe-commits


@@ -10598,10 +10598,38 @@ QualType 
Sema::DeduceTemplateSpecializationFromInitializer(
   if (TemplateName.isDependent())
 return SubstAutoTypeDependent(TSInfo->getType());
 
-  // We can only perform deduction for class templates.
+  // We can only perform deduction for class templates or alias templates.
   auto *Template =
   dyn_cast_or_null(TemplateName.getAsTemplateDecl());
+  TemplateDecl* LookupTemplateDecl = Template;
   if (!Template) {
+if (auto *AliasTemplate = dyn_cast_or_null(
+TemplateName.getAsTemplateDecl())) {
+  Diag(Kind.getLocation(),
+   diag::warn_cxx17_compat_ctad_for_alias_templates);
+  LookupTemplateDecl = AliasTemplate;
+  auto UnderlyingType = AliasTemplate->getTemplatedDecl()
+->getUnderlyingType()
+.getCanonicalType();
+  // C++ [over.match.class.deduct#3]: ..., the defining-type-id of A must 
be
+  // of the form
+  //   [typename] [nested-name-specifier] [template] simple-template-id
+  if (const auto *TST =
+  UnderlyingType->getAs()) {
+Template = dyn_cast_or_null(
+TST->getTemplateName().getAsTemplateDecl());
+  } else if (const auto *RT = UnderlyingType->getAs()) {
+// Cases where template arguments in the RHS of the alias are not
+// dependent. e.g.
+//   using AliasFoo = Foo;
+if (const auto *CTSD = llvm::dyn_cast(
+RT->getAsCXXRecordDecl()))
+  Template = CTSD->getSpecializedTemplate();
+  }
+}
+  }
+  if (!Template) {
+// FIXME: update the diagnostic message to include C++20 alias templates

hokein wrote:

Sure, please take a look on the new change. I also rename the diagnostic to 
`err_deduced_non_class_or_alias_template_specialization_type`.

https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-03-07 Thread Haojian Wu via cfe-commits


@@ -96,6 +96,10 @@ C++20 Feature Support
   behavior can use the flag '-Xclang -fno-skip-odr-check-in-gmf'.
   (`#79240 `_).
 
+- Initial support for class template argument deduciton (CTAD) for type alias

hokein wrote:

Done.

https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-03-06 Thread via cfe-commits

https://github.com/h-vetinari edited 
https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-03-06 Thread via cfe-commits


@@ -96,6 +96,10 @@ C++20 Feature Support
   behavior can use the flag '-Xclang -fno-skip-odr-check-in-gmf'.
   (`#79240 `_).
 
+- Initial support for class template argument deduciton (CTAD) for type alias
+  templates (`P1814R0 `_).

h-vetinari wrote:

Probably should update to at least a `Partial` under
https://github.com/llvm/llvm-project/blob/e946b5a87b2db307da076093d0a9a72ecb4ec089/clang/www/cxx_status.html#L843-L847

https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-03-06 Thread via cfe-commits

cor3ntin wrote:

Can you mark the status of the paper in cxx_status.html as partial (with a 
`` tag explaining what is missing)?
Can you update the commit message / changelog to refer to the paper number?

Thanks

https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-03-06 Thread via cfe-commits


@@ -2612,44 +2669,312 @@ struct ConvertConstructorToDeductionGuideTransform {
 SemaRef.CurrentInstantiationScope->InstantiatedLocal(OldParam, NewParam);
 return NewParam;
   }
+};
 
-  FunctionTemplateDecl *buildDeductionGuide(
-  TemplateParameterList *TemplateParams, CXXConstructorDecl *Ctor,
-  ExplicitSpecifier ES, TypeSourceInfo *TInfo, SourceLocation LocStart,
-  SourceLocation Loc, SourceLocation LocEnd,
-  llvm::ArrayRef MaterializedTypedefs = {}) {
-DeclarationNameInfo Name(DeductionGuideName, Loc);
-ArrayRef Params =
-TInfo->getTypeLoc().castAs().getParams();
+// Find all template parameters that appear in the given DeducedArgs.
+// Return the indices of the template parameters in the TemplateParams.
+SmallVector TemplateParamsReferencedInTemplateArgumentList(
+ArrayRef TemplateParams,
+ArrayRef DeducedArgs) {
+  struct FindAppearedTemplateParams
+  : public RecursiveASTVisitor {
+llvm::DenseSet TemplateParams;
+llvm::DenseSet AppearedTemplateParams;
+
+FindAppearedTemplateParams(ArrayRef TemplateParams)
+: TemplateParams(TemplateParams.begin(), TemplateParams.end()) {}
+
+bool VisitTemplateTypeParmType(TemplateTypeParmType *TTP) {
+  TTP->getIndex();
+  MarkAppeared(TTP->getDecl());
+  return true;
+}
+bool VisitDeclRefExpr(DeclRefExpr *DRE) {
+  MarkAppeared(DRE->getFoundDecl());
+  return true;
+}
 
-// Build the implicit deduction guide template.
-auto *Guide =
-CXXDeductionGuideDecl::Create(SemaRef.Context, DC, LocStart, ES, Name,
-  TInfo->getType(), TInfo, LocEnd, Ctor);
-Guide->setImplicit();
-Guide->setParams(Params);
+void MarkAppeared(NamedDecl *ND) {
+  if (TemplateParams.contains(ND))
+AppearedTemplateParams.insert(ND);
+}
+  };
+  FindAppearedTemplateParams MarkAppeared(TemplateParams);
+  MarkAppeared.TraverseTemplateArguments(DeducedArgs);
 
-for (auto *Param : Params)
-  Param->setDeclContext(Guide);
-for (auto *TD : MaterializedTypedefs)
-  TD->setDeclContext(Guide);
+  SmallVector Results;
+  for (unsigned Index = 0; Index < TemplateParams.size(); ++Index) {
+if (MarkAppeared.AppearedTemplateParams.contains(
+TemplateParams[Index]))
+  Results.push_back(Index);
+  }
+  return Results;
+}
+
+bool hasDeclaredDeductionGuides(DeclarationName Name, DeclContext *DC) {
+  // Check whether we've already declared deduction guides for this template.
+  // FIXME: Consider storing a flag on the template to indicate this.
+  assert(Name.getNameKind() ==
+ DeclarationName::NameKind::CXXDeductionGuideName &&
+ "name must be a deduction guide name");
+  auto Existing = DC->lookup(Name);
+  for (auto *D : Existing)
+if (D->isImplicit())
+  return true;
+  return false;
+}
+
+// Build deduction guides for a type alias template.
+void DeclareImplicitDeductionGuidesForTypeAlias(
+Sema , TypeAliasTemplateDecl *AliasTemplate, SourceLocation Loc) {
+  auto  = SemaRef.Context;
+  // FIXME: if there is an explicit deduction guide after the first use of the
+  // type alias usage, we will not cover this explicit deduction guide. fix 
this
+  // case.
+  if (hasDeclaredDeductionGuides(
+  Context.DeclarationNames.getCXXDeductionGuideName(AliasTemplate),
+  AliasTemplate->getDeclContext()))
+return;
+  // Unwrap the sugared ElaboratedType.
+  auto RhsType = AliasTemplate->getTemplatedDecl()
+ ->getUnderlyingType()
+ .getSingleStepDesugaredType(Context);
+  TemplateDecl *Template = nullptr;
+  llvm::ArrayRef AliasRhsTemplateArgs;
+  if (const auto *TST = RhsType->getAs()) {
+// Cases where the RHS of the alias is dependent. e.g.
+//   template
+//   using AliasFoo1 = Foo; // a class/type alias template 
specialization
+Template = TST->getTemplateName().getAsTemplateDecl();
+AliasRhsTemplateArgs = TST->template_arguments();
+  } else if (const auto *RT = RhsType->getAs()) {
+// Cases where template arguments in the RHS of the alias are not
+// dependent. e.g.
+//   using AliasFoo = Foo;
+if (const auto *CTSD = llvm::dyn_cast(
+RT->getAsCXXRecordDecl())) {
+  Template = CTSD->getSpecializedTemplate();
+  AliasRhsTemplateArgs = CTSD->getTemplateArgs().asArray();
+}
+  } else {
+assert(false && "unhandled RHS type of the alias");
+  }
+  if (!Template)
+return;
+  DeclarationNameInfo NameInfo(
+  Context.DeclarationNames.getCXXDeductionGuideName(Template), Loc);
+  LookupResult Guides(SemaRef, NameInfo, clang::Sema::LookupOrdinaryName);
+  SemaRef.LookupQualifiedName(Guides, Template->getDeclContext());
+  Guides.suppressDiagnostics();
+
+  for (auto *G : Guides) {
+FunctionTemplateDecl *F = dyn_cast(G);
+if (!F)
+  continue;
+auto RType = F->getTemplatedDecl()->getReturnType();
+// The 

[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-03-06 Thread via cfe-commits


@@ -10598,10 +10598,38 @@ QualType 
Sema::DeduceTemplateSpecializationFromInitializer(
   if (TemplateName.isDependent())
 return SubstAutoTypeDependent(TSInfo->getType());
 
-  // We can only perform deduction for class templates.
+  // We can only perform deduction for class templates or alias templates.
   auto *Template =
   dyn_cast_or_null(TemplateName.getAsTemplateDecl());
+  TemplateDecl* LookupTemplateDecl = Template;
   if (!Template) {
+if (auto *AliasTemplate = dyn_cast_or_null(
+TemplateName.getAsTemplateDecl())) {
+  Diag(Kind.getLocation(),
+   diag::warn_cxx17_compat_ctad_for_alias_templates);
+  LookupTemplateDecl = AliasTemplate;
+  auto UnderlyingType = AliasTemplate->getTemplatedDecl()
+->getUnderlyingType()
+.getCanonicalType();
+  // C++ [over.match.class.deduct#3]: ..., the defining-type-id of A must 
be
+  // of the form
+  //   [typename] [nested-name-specifier] [template] simple-template-id
+  if (const auto *TST =
+  UnderlyingType->getAs()) {
+Template = dyn_cast_or_null(
+TST->getTemplateName().getAsTemplateDecl());
+  } else if (const auto *RT = UnderlyingType->getAs()) {
+// Cases where template arguments in the RHS of the alias are not
+// dependent. e.g.
+//   using AliasFoo = Foo;
+if (const auto *CTSD = llvm::dyn_cast(
+RT->getAsCXXRecordDecl()))
+  Template = CTSD->getSpecializedTemplate();
+  }
+}
+  }
+  if (!Template) {
+// FIXME: update the diagnostic message to include C++20 alias templates

cor3ntin wrote:

I think we might as well, yes (unless it's more complicated than i think it is)

https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-03-06 Thread Erich Keane via cfe-commits

https://github.com/erichkeane commented:

I'm happy when Corentin is, so he can approve when he's ready.

https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-03-06 Thread Erich Keane via cfe-commits


@@ -96,6 +96,10 @@ C++20 Feature Support
   behavior can use the flag '-Xclang -fno-skip-odr-check-in-gmf'.
   (`#79240 `_).
 
+- Initial support for class template argument deduciton (CTAD) for type alias

erichkeane wrote:

```suggestion
- Initial support for class template argument deduction (CTAD) for type alias
```

https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-03-06 Thread Haojian Wu via cfe-commits


@@ -2612,44 +2669,312 @@ struct ConvertConstructorToDeductionGuideTransform {
 SemaRef.CurrentInstantiationScope->InstantiatedLocal(OldParam, NewParam);
 return NewParam;
   }
+};
 
-  FunctionTemplateDecl *buildDeductionGuide(
-  TemplateParameterList *TemplateParams, CXXConstructorDecl *Ctor,
-  ExplicitSpecifier ES, TypeSourceInfo *TInfo, SourceLocation LocStart,
-  SourceLocation Loc, SourceLocation LocEnd,
-  llvm::ArrayRef MaterializedTypedefs = {}) {
-DeclarationNameInfo Name(DeductionGuideName, Loc);
-ArrayRef Params =
-TInfo->getTypeLoc().castAs().getParams();
+// Find all template parameters that appear in the given DeducedArgs.
+// Return the indices of the template parameters in the TemplateParams.
+SmallVector TemplateParamsReferencedInTemplateArgumentList(
+ArrayRef TemplateParams,
+ArrayRef DeducedArgs) {
+  struct FindAppearedTemplateParams

hokein wrote:

OK, I'm not sure `Type` is the best fit, I'd stay close with template params.  
Renamed it to `TemplateParamsReferencedFinder` (if we want to use a 
less-verbose name, I'm fine with `Finder` since this is a structure defined in 
a function body).

https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-03-06 Thread Erich Keane via cfe-commits


@@ -2612,44 +2669,312 @@ struct ConvertConstructorToDeductionGuideTransform {
 SemaRef.CurrentInstantiationScope->InstantiatedLocal(OldParam, NewParam);
 return NewParam;
   }
+};
 
-  FunctionTemplateDecl *buildDeductionGuide(
-  TemplateParameterList *TemplateParams, CXXConstructorDecl *Ctor,
-  ExplicitSpecifier ES, TypeSourceInfo *TInfo, SourceLocation LocStart,
-  SourceLocation Loc, SourceLocation LocEnd,
-  llvm::ArrayRef MaterializedTypedefs = {}) {
-DeclarationNameInfo Name(DeductionGuideName, Loc);
-ArrayRef Params =
-TInfo->getTypeLoc().castAs().getParams();
+// Find all template parameters that appear in the given DeducedArgs.
+// Return the indices of the template parameters in the TemplateParams.
+SmallVector TemplateParamsReferencedInTemplateArgumentList(
+ArrayRef TemplateParams,
+ArrayRef DeducedArgs) {
+  struct FindAppearedTemplateParams

erichkeane wrote:

> I missed this one when renaming the function. What do you think about the 
> current one `ReferenceFinder`?

ReferenceFinder is a little overloaded of a name :)  Perhaps 
`TypeReferencedFinder`? Note the 'd' which I think prevents it from being 
mistaken with a "finds all things with an L or R value reference".

https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-03-06 Thread Haojian Wu via cfe-commits


@@ -96,6 +96,10 @@ C++20 Feature Support
   behavior can use the flag '-Xclang -fno-skip-odr-check-in-gmf'.
   (`#79240 `_).
 
+- Initial support for class template argument deduciton (CTAD) for type alias
+  templates.
+  (`#54051 https://github.com/llvm/llvm-project/issues/54051`_).

hokein wrote:

I see, I were not aware of it. Switched to the `GH` form.

https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-03-06 Thread via cfe-commits


@@ -96,6 +96,10 @@ C++20 Feature Support
   behavior can use the flag '-Xclang -fno-skip-odr-check-in-gmf'.
   (`#79240 `_).
 
+- Initial support for class template argument deduciton (CTAD) for type alias
+  templates.
+  (`#54051 https://github.com/llvm/llvm-project/issues/54051`_).

cor3ntin wrote:

That changes recently (either way, you were missing <>)

https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-03-06 Thread Haojian Wu via cfe-commits


@@ -2612,44 +2669,312 @@ struct ConvertConstructorToDeductionGuideTransform {
 SemaRef.CurrentInstantiationScope->InstantiatedLocal(OldParam, NewParam);
 return NewParam;
   }
+};
 
-  FunctionTemplateDecl *buildDeductionGuide(
-  TemplateParameterList *TemplateParams, CXXConstructorDecl *Ctor,
-  ExplicitSpecifier ES, TypeSourceInfo *TInfo, SourceLocation LocStart,
-  SourceLocation Loc, SourceLocation LocEnd,
-  llvm::ArrayRef MaterializedTypedefs = {}) {
-DeclarationNameInfo Name(DeductionGuideName, Loc);
-ArrayRef Params =
-TInfo->getTypeLoc().castAs().getParams();
+// Find all template parameters that appear in the given DeducedArgs.
+// Return the indices of the template parameters in the TemplateParams.
+SmallVector TemplateParamsReferencedInTemplateArgumentList(
+ArrayRef TemplateParams,
+ArrayRef DeducedArgs) {
+  struct FindAppearedTemplateParams
+  : public RecursiveASTVisitor {
+llvm::DenseSet TemplateParams;
+llvm::DenseSet AppearedTemplateParams;
+
+FindAppearedTemplateParams(ArrayRef TemplateParams)
+: TemplateParams(TemplateParams.begin(), TemplateParams.end()) {}
+
+bool VisitTemplateTypeParmType(TemplateTypeParmType *TTP) {
+  TTP->getIndex();
+  MarkAppeared(TTP->getDecl());
+  return true;
+}
+bool VisitDeclRefExpr(DeclRefExpr *DRE) {
+  MarkAppeared(DRE->getFoundDecl());
+  return true;
+}
 
-// Build the implicit deduction guide template.
-auto *Guide =
-CXXDeductionGuideDecl::Create(SemaRef.Context, DC, LocStart, ES, Name,
-  TInfo->getType(), TInfo, LocEnd, Ctor);
-Guide->setImplicit();
-Guide->setParams(Params);
+void MarkAppeared(NamedDecl *ND) {
+  if (TemplateParams.contains(ND))
+AppearedTemplateParams.insert(ND);
+}
+  };
+  FindAppearedTemplateParams MarkAppeared(TemplateParams);
+  MarkAppeared.TraverseTemplateArguments(DeducedArgs);
 
-for (auto *Param : Params)
-  Param->setDeclContext(Guide);
-for (auto *TD : MaterializedTypedefs)
-  TD->setDeclContext(Guide);
+  SmallVector Results;
+  for (unsigned Index = 0; Index < TemplateParams.size(); ++Index) {
+if (MarkAppeared.AppearedTemplateParams.contains(
+TemplateParams[Index]))
+  Results.push_back(Index);
+  }
+  return Results;
+}
+
+bool hasDeclaredDeductionGuides(DeclarationName Name, DeclContext *DC) {
+  // Check whether we've already declared deduction guides for this template.
+  // FIXME: Consider storing a flag on the template to indicate this.
+  assert(Name.getNameKind() ==
+ DeclarationName::NameKind::CXXDeductionGuideName &&
+ "name must be a deduction guide name");
+  auto Existing = DC->lookup(Name);
+  for (auto *D : Existing)
+if (D->isImplicit())
+  return true;
+  return false;
+}
+
+// Build deduction guides for a type alias template.
+void DeclareImplicitDeductionGuidesForTypeAlias(
+Sema , TypeAliasTemplateDecl *AliasTemplate, SourceLocation Loc) {
+  auto  = SemaRef.Context;
+  // FIXME: if there is an explicit deduction guide after the first use of the
+  // type alias usage, we will not cover this explicit deduction guide. fix 
this
+  // case.
+  if (hasDeclaredDeductionGuides(
+  Context.DeclarationNames.getCXXDeductionGuideName(AliasTemplate),
+  AliasTemplate->getDeclContext()))
+return;
+  // Unwrap the sugared ElaboratedType.
+  auto RhsType = AliasTemplate->getTemplatedDecl()
+ ->getUnderlyingType()
+ .getSingleStepDesugaredType(Context);
+  TemplateDecl *Template = nullptr;
+  llvm::ArrayRef AliasRhsTemplateArgs;
+  if (const auto *TST = RhsType->getAs()) {
+// Cases where the RHS of the alias is dependent. e.g.
+//   template
+//   using AliasFoo1 = Foo; // a class/type alias template 
specialization
+Template = TST->getTemplateName().getAsTemplateDecl();
+AliasRhsTemplateArgs = TST->template_arguments();
+  } else if (const auto *RT = RhsType->getAs()) {
+// Cases where template arguments in the RHS of the alias are not
+// dependent. e.g.
+//   using AliasFoo = Foo;
+if (const auto *CTSD = llvm::dyn_cast(
+RT->getAsCXXRecordDecl())) {
+  Template = CTSD->getSpecializedTemplate();
+  AliasRhsTemplateArgs = CTSD->getTemplateArgs().asArray();
+}
+  } else {
+assert(false && "unhandled RHS type of the alias");
+  }
+  if (!Template)
+return;
+  DeclarationNameInfo NameInfo(
+  Context.DeclarationNames.getCXXDeductionGuideName(Template), Loc);
+  LookupResult Guides(SemaRef, NameInfo, clang::Sema::LookupOrdinaryName);
+  SemaRef.LookupQualifiedName(Guides, Template->getDeclContext());
+  Guides.suppressDiagnostics();
+
+  for (auto *G : Guides) {
+FunctionTemplateDecl *F = dyn_cast(G);
+if (!F)
+  continue;
+auto RType = F->getTemplatedDecl()->getReturnType();
+// The 

[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-03-06 Thread Haojian Wu via cfe-commits


@@ -2612,44 +2669,312 @@ struct ConvertConstructorToDeductionGuideTransform {
 SemaRef.CurrentInstantiationScope->InstantiatedLocal(OldParam, NewParam);
 return NewParam;
   }
+};
 
-  FunctionTemplateDecl *buildDeductionGuide(
-  TemplateParameterList *TemplateParams, CXXConstructorDecl *Ctor,
-  ExplicitSpecifier ES, TypeSourceInfo *TInfo, SourceLocation LocStart,
-  SourceLocation Loc, SourceLocation LocEnd,
-  llvm::ArrayRef MaterializedTypedefs = {}) {
-DeclarationNameInfo Name(DeductionGuideName, Loc);
-ArrayRef Params =
-TInfo->getTypeLoc().castAs().getParams();
+// Find all template parameters that appear in the given DeducedArgs.
+// Return the indices of the template parameters in the TemplateParams.
+SmallVector TemplateParamsReferencedInTemplateArgumentList(
+ArrayRef TemplateParams,
+ArrayRef DeducedArgs) {
+  struct FindAppearedTemplateParams
+  : public RecursiveASTVisitor {
+llvm::DenseSet TemplateParams;
+llvm::DenseSet AppearedTemplateParams;
+
+FindAppearedTemplateParams(ArrayRef TemplateParams)
+: TemplateParams(TemplateParams.begin(), TemplateParams.end()) {}
+
+bool VisitTemplateTypeParmType(TemplateTypeParmType *TTP) {
+  TTP->getIndex();
+  MarkAppeared(TTP->getDecl());
+  return true;
+}
+bool VisitDeclRefExpr(DeclRefExpr *DRE) {
+  MarkAppeared(DRE->getFoundDecl());
+  return true;
+}
 
-// Build the implicit deduction guide template.
-auto *Guide =
-CXXDeductionGuideDecl::Create(SemaRef.Context, DC, LocStart, ES, Name,
-  TInfo->getType(), TInfo, LocEnd, Ctor);
-Guide->setImplicit();
-Guide->setParams(Params);
+void MarkAppeared(NamedDecl *ND) {
+  if (TemplateParams.contains(ND))
+AppearedTemplateParams.insert(ND);
+}
+  };
+  FindAppearedTemplateParams MarkAppeared(TemplateParams);
+  MarkAppeared.TraverseTemplateArguments(DeducedArgs);
 
-for (auto *Param : Params)
-  Param->setDeclContext(Guide);
-for (auto *TD : MaterializedTypedefs)
-  TD->setDeclContext(Guide);
+  SmallVector Results;
+  for (unsigned Index = 0; Index < TemplateParams.size(); ++Index) {
+if (MarkAppeared.AppearedTemplateParams.contains(
+TemplateParams[Index]))
+  Results.push_back(Index);
+  }
+  return Results;
+}
+
+bool hasDeclaredDeductionGuides(DeclarationName Name, DeclContext *DC) {
+  // Check whether we've already declared deduction guides for this template.
+  // FIXME: Consider storing a flag on the template to indicate this.
+  assert(Name.getNameKind() ==
+ DeclarationName::NameKind::CXXDeductionGuideName &&
+ "name must be a deduction guide name");
+  auto Existing = DC->lookup(Name);
+  for (auto *D : Existing)
+if (D->isImplicit())
+  return true;
+  return false;
+}
+
+// Build deduction guides for a type alias template.
+void DeclareImplicitDeductionGuidesForTypeAlias(
+Sema , TypeAliasTemplateDecl *AliasTemplate, SourceLocation Loc) {
+  auto  = SemaRef.Context;
+  // FIXME: if there is an explicit deduction guide after the first use of the
+  // type alias usage, we will not cover this explicit deduction guide. fix 
this
+  // case.
+  if (hasDeclaredDeductionGuides(
+  Context.DeclarationNames.getCXXDeductionGuideName(AliasTemplate),
+  AliasTemplate->getDeclContext()))
+return;
+  // Unwrap the sugared ElaboratedType.
+  auto RhsType = AliasTemplate->getTemplatedDecl()
+ ->getUnderlyingType()
+ .getSingleStepDesugaredType(Context);
+  TemplateDecl *Template = nullptr;
+  llvm::ArrayRef AliasRhsTemplateArgs;
+  if (const auto *TST = RhsType->getAs()) {
+// Cases where the RHS of the alias is dependent. e.g.
+//   template
+//   using AliasFoo1 = Foo; // a class/type alias template 
specialization
+Template = TST->getTemplateName().getAsTemplateDecl();
+AliasRhsTemplateArgs = TST->template_arguments();
+  } else if (const auto *RT = RhsType->getAs()) {
+// Cases where template arguments in the RHS of the alias are not
+// dependent. e.g.
+//   using AliasFoo = Foo;
+if (const auto *CTSD = llvm::dyn_cast(
+RT->getAsCXXRecordDecl())) {
+  Template = CTSD->getSpecializedTemplate();
+  AliasRhsTemplateArgs = CTSD->getTemplateArgs().asArray();
+}
+  } else {
+assert(false && "unhandled RHS type of the alias");
+  }
+  if (!Template)
+return;
+  DeclarationNameInfo NameInfo(
+  Context.DeclarationNames.getCXXDeductionGuideName(Template), Loc);
+  LookupResult Guides(SemaRef, NameInfo, clang::Sema::LookupOrdinaryName);
+  SemaRef.LookupQualifiedName(Guides, Template->getDeclContext());
+  Guides.suppressDiagnostics();
+
+  for (auto *G : Guides) {
+FunctionTemplateDecl *F = dyn_cast(G);
+if (!F)
+  continue;
+auto RType = F->getTemplatedDecl()->getReturnType();
+// The 

[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-03-06 Thread Haojian Wu via cfe-commits


@@ -2612,44 +2669,312 @@ struct ConvertConstructorToDeductionGuideTransform {
 SemaRef.CurrentInstantiationScope->InstantiatedLocal(OldParam, NewParam);
 return NewParam;
   }
+};
 
-  FunctionTemplateDecl *buildDeductionGuide(
-  TemplateParameterList *TemplateParams, CXXConstructorDecl *Ctor,
-  ExplicitSpecifier ES, TypeSourceInfo *TInfo, SourceLocation LocStart,
-  SourceLocation Loc, SourceLocation LocEnd,
-  llvm::ArrayRef MaterializedTypedefs = {}) {
-DeclarationNameInfo Name(DeductionGuideName, Loc);
-ArrayRef Params =
-TInfo->getTypeLoc().castAs().getParams();
+// Find all template parameters that appear in the given DeducedArgs.
+// Return the indices of the template parameters in the TemplateParams.
+SmallVector TemplateParamsReferencedInTemplateArgumentList(
+ArrayRef TemplateParams,
+ArrayRef DeducedArgs) {
+  struct FindAppearedTemplateParams

hokein wrote:

I missed this one when renaming the function. What do you think about the 
current one `ReferenceFinder`?

https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-03-06 Thread Haojian Wu via cfe-commits


@@ -1446,6 +1447,59 @@ namespace {
   return inherited::TransformFunctionProtoType(TLB, TL);
 }
 
+QualType TransformInjectedClassNameType(TypeLocBuilder ,
+InjectedClassNameTypeLoc TL) {
+  auto Type = inherited::TransformInjectedClassNameType(TLB, TL);
+  // Special case for transforming a deduction guide, we return a
+  // transformed TemplateSpecializationType.
+  if (Type.isNull() &&
+  SemaRef.CodeSynthesisContexts.back().Kind ==
+  Sema::CodeSynthesisContext::BuildingDeductionGuides) {
+// Return a TemplateSpecializationType for transforming a deduction
+// guide.
+if (auto *ICT = TL.getType()->getAs()) {
+  auto Type = 
+  inherited::TransformType(ICT->getInjectedSpecializationType());
+  TLB.pushTrivial(SemaRef.Context, Type, TL.getNameLoc());
+  return Type;
+}
+  }
+  return Type;
+}
+// Override the default version to handle a rewrite-template-arg-pack case
+// for building a deduction guide.
+bool TransformTemplateArgument(const TemplateArgumentLoc ,
+   TemplateArgumentLoc ,
+   bool Uneval = false) {
+  const TemplateArgument  = Input.getArgument();
+  std::vector TArgs;
+  switch (Arg.getKind()) {
+  case TemplateArgument::Pack:
+// Iterially rewrite the template argument pack, instead of unpacking

hokein wrote:

this is a typo here, I mean `literally`.

https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-03-06 Thread Haojian Wu via cfe-commits


@@ -10598,10 +10598,38 @@ QualType 
Sema::DeduceTemplateSpecializationFromInitializer(
   if (TemplateName.isDependent())
 return SubstAutoTypeDependent(TSInfo->getType());
 
-  // We can only perform deduction for class templates.
+  // We can only perform deduction for class templates or alias templates.
   auto *Template =
   dyn_cast_or_null(TemplateName.getAsTemplateDecl());
+  TemplateDecl* LookupTemplateDecl = Template;
   if (!Template) {
+if (auto *AliasTemplate = dyn_cast_or_null(
+TemplateName.getAsTemplateDecl())) {
+  Diag(Kind.getLocation(),
+   diag::warn_cxx17_compat_ctad_for_alias_templates);
+  LookupTemplateDecl = AliasTemplate;
+  auto UnderlyingType = AliasTemplate->getTemplatedDecl()
+->getUnderlyingType()
+.getCanonicalType();
+  // C++ [over.match.class.deduct#3]: ..., the defining-type-id of A must 
be
+  // of the form
+  //   [typename] [nested-name-specifier] [template] simple-template-id
+  if (const auto *TST =
+  UnderlyingType->getAs()) {
+Template = dyn_cast_or_null(
+TST->getTemplateName().getAsTemplateDecl());
+  } else if (const auto *RT = UnderlyingType->getAs()) {
+// Cases where template arguments in the RHS of the alias are not
+// dependent. e.g.
+//   using AliasFoo = Foo;
+if (const auto *CTSD = llvm::dyn_cast(
+RT->getAsCXXRecordDecl()))
+  Template = CTSD->getSpecializedTemplate();
+  }
+}
+  }
+  if (!Template) {
+// FIXME: update the diagnostic message to include C++20 alias templates

hokein wrote:

Are you suggesting to address it now? My original plan is to address it in a 
followup, but it seems small enough to do it in this patch. 

https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-03-06 Thread Haojian Wu via cfe-commits


@@ -96,6 +96,10 @@ C++20 Feature Support
   behavior can use the flag '-Xclang -fno-skip-odr-check-in-gmf'.
   (`#79240 `_).
 
+- Initial support for class template argument deduciton (CTAD) for type alias
+  templates.
+  (`#54051 https://github.com/llvm/llvm-project/issues/54051`_).

hokein wrote:

This doesn't follow the pattern used in this file, we use `# 
https://github.com/llvm/llvm-project/issues/`.

https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-03-06 Thread Haojian Wu via cfe-commits


@@ -96,6 +96,10 @@ C++20 Feature Support
   behavior can use the flag '-Xclang -fno-skip-odr-check-in-gmf'.
   (`#79240 `_).
 
+- Initial support for class template argument deduciton (CTAD) for type alias
+  templates.

hokein wrote:

Done.

https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-03-06 Thread Haojian Wu via cfe-commits


@@ -10598,10 +10598,34 @@ QualType 
Sema::DeduceTemplateSpecializationFromInitializer(
   if (TemplateName.isDependent())
 return SubstAutoTypeDependent(TSInfo->getType());
 
-  // We can only perform deduction for class templates.
+  // We can only perform deduction for class templates or alias templates.
   auto *Template =
   dyn_cast_or_null(TemplateName.getAsTemplateDecl());
+  TemplateDecl* LookupTemplateDecl = Template;
+  if (!Template && getLangOpts().CPlusPlus20) { // type alias template
+if (auto *AliasTemplate = dyn_cast_or_null(
+TemplateName.getAsTemplateDecl());
+AliasTemplate) {
+  LookupTemplateDecl = AliasTemplate;
+  auto UnderlyingType = AliasTemplate->getTemplatedDecl()
+->getUnderlyingType()
+.getDesugaredType(Context);
+  if (const auto *TST =
+  UnderlyingType->getAs()) {
+Template = dyn_cast_or_null(
+TST->getTemplateName().getAsTemplateDecl());
+  } else if (const auto *RT = UnderlyingType->getAs()) {
+// Cases where template arguments in the RHS of the alias are not
+// dependent. e.g.
+//   using AliasFoo = Foo;
+if (const auto *CTSD = llvm::dyn_cast(
+RT->getAsCXXRecordDecl()))
+  Template = CTSD->getSpecializedTemplate();
+  }

hokein wrote:

ah, sorry, I added it and then removed later. There are some other cases which 
are not supported, see the testcase `test17`. 

https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-03-06 Thread via cfe-commits


@@ -2612,44 +2669,312 @@ struct ConvertConstructorToDeductionGuideTransform {
 SemaRef.CurrentInstantiationScope->InstantiatedLocal(OldParam, NewParam);
 return NewParam;
   }
+};
 
-  FunctionTemplateDecl *buildDeductionGuide(
-  TemplateParameterList *TemplateParams, CXXConstructorDecl *Ctor,
-  ExplicitSpecifier ES, TypeSourceInfo *TInfo, SourceLocation LocStart,
-  SourceLocation Loc, SourceLocation LocEnd,
-  llvm::ArrayRef MaterializedTypedefs = {}) {
-DeclarationNameInfo Name(DeductionGuideName, Loc);
-ArrayRef Params =
-TInfo->getTypeLoc().castAs().getParams();
+// Find all template parameters that appear in the given DeducedArgs.
+// Return the indices of the template parameters in the TemplateParams.
+SmallVector TemplateParamsReferencedInTemplateArgumentList(
+ArrayRef TemplateParams,
+ArrayRef DeducedArgs) {
+  struct FindAppearedTemplateParams
+  : public RecursiveASTVisitor {
+llvm::DenseSet TemplateParams;
+llvm::DenseSet AppearedTemplateParams;
+
+FindAppearedTemplateParams(ArrayRef TemplateParams)
+: TemplateParams(TemplateParams.begin(), TemplateParams.end()) {}
+
+bool VisitTemplateTypeParmType(TemplateTypeParmType *TTP) {
+  TTP->getIndex();
+  MarkAppeared(TTP->getDecl());
+  return true;
+}
+bool VisitDeclRefExpr(DeclRefExpr *DRE) {
+  MarkAppeared(DRE->getFoundDecl());
+  return true;
+}
 
-// Build the implicit deduction guide template.
-auto *Guide =
-CXXDeductionGuideDecl::Create(SemaRef.Context, DC, LocStart, ES, Name,
-  TInfo->getType(), TInfo, LocEnd, Ctor);
-Guide->setImplicit();
-Guide->setParams(Params);
+void MarkAppeared(NamedDecl *ND) {
+  if (TemplateParams.contains(ND))
+AppearedTemplateParams.insert(ND);
+}
+  };
+  FindAppearedTemplateParams MarkAppeared(TemplateParams);
+  MarkAppeared.TraverseTemplateArguments(DeducedArgs);
 
-for (auto *Param : Params)
-  Param->setDeclContext(Guide);
-for (auto *TD : MaterializedTypedefs)
-  TD->setDeclContext(Guide);
+  SmallVector Results;
+  for (unsigned Index = 0; Index < TemplateParams.size(); ++Index) {
+if (MarkAppeared.AppearedTemplateParams.contains(
+TemplateParams[Index]))
+  Results.push_back(Index);
+  }
+  return Results;
+}
+
+bool hasDeclaredDeductionGuides(DeclarationName Name, DeclContext *DC) {
+  // Check whether we've already declared deduction guides for this template.
+  // FIXME: Consider storing a flag on the template to indicate this.
+  assert(Name.getNameKind() ==
+ DeclarationName::NameKind::CXXDeductionGuideName &&
+ "name must be a deduction guide name");
+  auto Existing = DC->lookup(Name);
+  for (auto *D : Existing)
+if (D->isImplicit())
+  return true;
+  return false;
+}
+
+// Build deduction guides for a type alias template.
+void DeclareImplicitDeductionGuidesForTypeAlias(
+Sema , TypeAliasTemplateDecl *AliasTemplate, SourceLocation Loc) {
+  auto  = SemaRef.Context;
+  // FIXME: if there is an explicit deduction guide after the first use of the
+  // type alias usage, we will not cover this explicit deduction guide. fix 
this
+  // case.
+  if (hasDeclaredDeductionGuides(
+  Context.DeclarationNames.getCXXDeductionGuideName(AliasTemplate),
+  AliasTemplate->getDeclContext()))
+return;
+  // Unwrap the sugared ElaboratedType.
+  auto RhsType = AliasTemplate->getTemplatedDecl()
+ ->getUnderlyingType()
+ .getSingleStepDesugaredType(Context);
+  TemplateDecl *Template = nullptr;
+  llvm::ArrayRef AliasRhsTemplateArgs;
+  if (const auto *TST = RhsType->getAs()) {
+// Cases where the RHS of the alias is dependent. e.g.
+//   template
+//   using AliasFoo1 = Foo; // a class/type alias template 
specialization
+Template = TST->getTemplateName().getAsTemplateDecl();
+AliasRhsTemplateArgs = TST->template_arguments();
+  } else if (const auto *RT = RhsType->getAs()) {
+// Cases where template arguments in the RHS of the alias are not
+// dependent. e.g.
+//   using AliasFoo = Foo;
+if (const auto *CTSD = llvm::dyn_cast(
+RT->getAsCXXRecordDecl())) {
+  Template = CTSD->getSpecializedTemplate();
+  AliasRhsTemplateArgs = CTSD->getTemplateArgs().asArray();
+}
+  } else {
+assert(false && "unhandled RHS type of the alias");
+  }
+  if (!Template)
+return;
+  DeclarationNameInfo NameInfo(
+  Context.DeclarationNames.getCXXDeductionGuideName(Template), Loc);
+  LookupResult Guides(SemaRef, NameInfo, clang::Sema::LookupOrdinaryName);
+  SemaRef.LookupQualifiedName(Guides, Template->getDeclContext());
+  Guides.suppressDiagnostics();
+
+  for (auto *G : Guides) {
+FunctionTemplateDecl *F = dyn_cast(G);
+if (!F)
+  continue;
+auto RType = F->getTemplatedDecl()->getReturnType();
+// The 

[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-03-06 Thread via cfe-commits


@@ -96,6 +96,10 @@ C++20 Feature Support
   behavior can use the flag '-Xclang -fno-skip-odr-check-in-gmf'.
   (`#79240 `_).
 
+- Initial support for class template argument deduciton (CTAD) for type alias
+  templates.
+  (`#54051 https://github.com/llvm/llvm-project/issues/54051`_).

cor3ntin wrote:

```suggestion
  (#GH54051).
```

https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-03-06 Thread via cfe-commits


@@ -96,6 +96,10 @@ C++20 Feature Support
   behavior can use the flag '-Xclang -fno-skip-odr-check-in-gmf'.
   (`#79240 `_).
 
+- Initial support for class template argument deduciton (CTAD) for type alias
+  templates.

cor3ntin wrote:

```suggestion
  templates (`P1814R0 `_).
```

https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-03-06 Thread via cfe-commits


@@ -2612,44 +2669,312 @@ struct ConvertConstructorToDeductionGuideTransform {
 SemaRef.CurrentInstantiationScope->InstantiatedLocal(OldParam, NewParam);
 return NewParam;
   }
+};
 
-  FunctionTemplateDecl *buildDeductionGuide(
-  TemplateParameterList *TemplateParams, CXXConstructorDecl *Ctor,
-  ExplicitSpecifier ES, TypeSourceInfo *TInfo, SourceLocation LocStart,
-  SourceLocation Loc, SourceLocation LocEnd,
-  llvm::ArrayRef MaterializedTypedefs = {}) {
-DeclarationNameInfo Name(DeductionGuideName, Loc);
-ArrayRef Params =
-TInfo->getTypeLoc().castAs().getParams();
+// Find all template parameters that appear in the given DeducedArgs.
+// Return the indices of the template parameters in the TemplateParams.
+SmallVector TemplateParamsReferencedInTemplateArgumentList(
+ArrayRef TemplateParams,
+ArrayRef DeducedArgs) {
+  struct FindAppearedTemplateParams
+  : public RecursiveASTVisitor {
+llvm::DenseSet TemplateParams;
+llvm::DenseSet AppearedTemplateParams;
+
+FindAppearedTemplateParams(ArrayRef TemplateParams)
+: TemplateParams(TemplateParams.begin(), TemplateParams.end()) {}
+
+bool VisitTemplateTypeParmType(TemplateTypeParmType *TTP) {
+  TTP->getIndex();
+  MarkAppeared(TTP->getDecl());
+  return true;
+}
+bool VisitDeclRefExpr(DeclRefExpr *DRE) {
+  MarkAppeared(DRE->getFoundDecl());
+  return true;
+}
 
-// Build the implicit deduction guide template.
-auto *Guide =
-CXXDeductionGuideDecl::Create(SemaRef.Context, DC, LocStart, ES, Name,
-  TInfo->getType(), TInfo, LocEnd, Ctor);
-Guide->setImplicit();
-Guide->setParams(Params);
+void MarkAppeared(NamedDecl *ND) {
+  if (TemplateParams.contains(ND))
+AppearedTemplateParams.insert(ND);
+}
+  };
+  FindAppearedTemplateParams MarkAppeared(TemplateParams);
+  MarkAppeared.TraverseTemplateArguments(DeducedArgs);
 
-for (auto *Param : Params)
-  Param->setDeclContext(Guide);
-for (auto *TD : MaterializedTypedefs)
-  TD->setDeclContext(Guide);
+  SmallVector Results;
+  for (unsigned Index = 0; Index < TemplateParams.size(); ++Index) {
+if (MarkAppeared.AppearedTemplateParams.contains(
+TemplateParams[Index]))
+  Results.push_back(Index);
+  }
+  return Results;
+}
+
+bool hasDeclaredDeductionGuides(DeclarationName Name, DeclContext *DC) {
+  // Check whether we've already declared deduction guides for this template.
+  // FIXME: Consider storing a flag on the template to indicate this.
+  assert(Name.getNameKind() ==
+ DeclarationName::NameKind::CXXDeductionGuideName &&
+ "name must be a deduction guide name");
+  auto Existing = DC->lookup(Name);
+  for (auto *D : Existing)
+if (D->isImplicit())
+  return true;
+  return false;
+}
+
+// Build deduction guides for a type alias template.
+void DeclareImplicitDeductionGuidesForTypeAlias(
+Sema , TypeAliasTemplateDecl *AliasTemplate, SourceLocation Loc) {
+  auto  = SemaRef.Context;
+  // FIXME: if there is an explicit deduction guide after the first use of the
+  // type alias usage, we will not cover this explicit deduction guide. fix 
this
+  // case.
+  if (hasDeclaredDeductionGuides(
+  Context.DeclarationNames.getCXXDeductionGuideName(AliasTemplate),
+  AliasTemplate->getDeclContext()))
+return;
+  // Unwrap the sugared ElaboratedType.
+  auto RhsType = AliasTemplate->getTemplatedDecl()
+ ->getUnderlyingType()
+ .getSingleStepDesugaredType(Context);
+  TemplateDecl *Template = nullptr;
+  llvm::ArrayRef AliasRhsTemplateArgs;
+  if (const auto *TST = RhsType->getAs()) {
+// Cases where the RHS of the alias is dependent. e.g.
+//   template
+//   using AliasFoo1 = Foo; // a class/type alias template 
specialization
+Template = TST->getTemplateName().getAsTemplateDecl();
+AliasRhsTemplateArgs = TST->template_arguments();
+  } else if (const auto *RT = RhsType->getAs()) {
+// Cases where template arguments in the RHS of the alias are not
+// dependent. e.g.
+//   using AliasFoo = Foo;
+if (const auto *CTSD = llvm::dyn_cast(
+RT->getAsCXXRecordDecl())) {
+  Template = CTSD->getSpecializedTemplate();
+  AliasRhsTemplateArgs = CTSD->getTemplateArgs().asArray();
+}
+  } else {
+assert(false && "unhandled RHS type of the alias");
+  }
+  if (!Template)
+return;
+  DeclarationNameInfo NameInfo(
+  Context.DeclarationNames.getCXXDeductionGuideName(Template), Loc);
+  LookupResult Guides(SemaRef, NameInfo, clang::Sema::LookupOrdinaryName);
+  SemaRef.LookupQualifiedName(Guides, Template->getDeclContext());
+  Guides.suppressDiagnostics();
+
+  for (auto *G : Guides) {
+FunctionTemplateDecl *F = dyn_cast(G);
+if (!F)
+  continue;
+auto RType = F->getTemplatedDecl()->getReturnType();
+// The 

[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-03-06 Thread via cfe-commits


@@ -6286,8 +6284,18 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation 
Loc, NamedDecl *D,
   QualType T = CheckTemplateIdType(TemplateName(TD), Loc, Args);
   if (T.isNull())
 return nullptr;
-  auto *SubstRecord = T->getAsCXXRecordDecl();
-  assert(SubstRecord && "class template id not a class type?");
+  CXXRecordDecl *SubstRecord = T->getAsCXXRecordDecl();
+
+  if (!SubstRecord) {
+// The T can be a dependent TemplateSpecializationType when
+// performing a substitution for building a deduction guide,

cor3ntin wrote:

```suggestion
// T can be a dependent TemplateSpecializationType when
// performing a substitution for building a deduction guide.
```

https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-03-06 Thread via cfe-commits


@@ -10598,10 +10598,34 @@ QualType 
Sema::DeduceTemplateSpecializationFromInitializer(
   if (TemplateName.isDependent())
 return SubstAutoTypeDependent(TSInfo->getType());
 
-  // We can only perform deduction for class templates.
+  // We can only perform deduction for class templates or alias templates.
   auto *Template =
   dyn_cast_or_null(TemplateName.getAsTemplateDecl());
+  TemplateDecl* LookupTemplateDecl = Template;
+  if (!Template && getLangOpts().CPlusPlus20) { // type alias template
+if (auto *AliasTemplate = dyn_cast_or_null(
+TemplateName.getAsTemplateDecl());
+AliasTemplate) {
+  LookupTemplateDecl = AliasTemplate;
+  auto UnderlyingType = AliasTemplate->getTemplatedDecl()
+->getUnderlyingType()
+.getDesugaredType(Context);
+  if (const auto *TST =
+  UnderlyingType->getAs()) {
+Template = dyn_cast_or_null(
+TST->getTemplateName().getAsTemplateDecl());
+  } else if (const auto *RT = UnderlyingType->getAs()) {
+// Cases where template arguments in the RHS of the alias are not
+// dependent. e.g.
+//   using AliasFoo = Foo;
+if (const auto *CTSD = llvm::dyn_cast(
+RT->getAsCXXRecordDecl()))
+  Template = CTSD->getSpecializedTemplate();
+  }

cor3ntin wrote:

I don't see it

https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-03-06 Thread via cfe-commits


@@ -1446,6 +1447,59 @@ namespace {
   return inherited::TransformFunctionProtoType(TLB, TL);
 }
 
+QualType TransformInjectedClassNameType(TypeLocBuilder ,
+InjectedClassNameTypeLoc TL) {
+  auto Type = inherited::TransformInjectedClassNameType(TLB, TL);
+  // Special case for transforming a deduction guide, we return a
+  // transformed TemplateSpecializationType.
+  if (Type.isNull() &&
+  SemaRef.CodeSynthesisContexts.back().Kind ==
+  Sema::CodeSynthesisContext::BuildingDeductionGuides) {
+// Return a TemplateSpecializationType for transforming a deduction
+// guide.
+if (auto *ICT = TL.getType()->getAs()) {
+  auto Type = 
+  inherited::TransformType(ICT->getInjectedSpecializationType());
+  TLB.pushTrivial(SemaRef.Context, Type, TL.getNameLoc());
+  return Type;
+}
+  }
+  return Type;
+}
+// Override the default version to handle a rewrite-template-arg-pack case
+// for building a deduction guide.
+bool TransformTemplateArgument(const TemplateArgumentLoc ,
+   TemplateArgumentLoc ,
+   bool Uneval = false) {
+  const TemplateArgument  = Input.getArgument();
+  std::vector TArgs;
+  switch (Arg.getKind()) {
+  case TemplateArgument::Pack:
+// Iterially rewrite the template argument pack, instead of unpacking

cor3ntin wrote:

Iteratively ?

https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-03-06 Thread via cfe-commits


@@ -10598,10 +10598,38 @@ QualType 
Sema::DeduceTemplateSpecializationFromInitializer(
   if (TemplateName.isDependent())
 return SubstAutoTypeDependent(TSInfo->getType());
 
-  // We can only perform deduction for class templates.
+  // We can only perform deduction for class templates or alias templates.
   auto *Template =
   dyn_cast_or_null(TemplateName.getAsTemplateDecl());
+  TemplateDecl* LookupTemplateDecl = Template;
   if (!Template) {
+if (auto *AliasTemplate = dyn_cast_or_null(
+TemplateName.getAsTemplateDecl())) {
+  Diag(Kind.getLocation(),
+   diag::warn_cxx17_compat_ctad_for_alias_templates);
+  LookupTemplateDecl = AliasTemplate;
+  auto UnderlyingType = AliasTemplate->getTemplatedDecl()
+->getUnderlyingType()
+.getCanonicalType();
+  // C++ [over.match.class.deduct#3]: ..., the defining-type-id of A must 
be
+  // of the form
+  //   [typename] [nested-name-specifier] [template] simple-template-id
+  if (const auto *TST =
+  UnderlyingType->getAs()) {
+Template = dyn_cast_or_null(
+TST->getTemplateName().getAsTemplateDecl());
+  } else if (const auto *RT = UnderlyingType->getAs()) {
+// Cases where template arguments in the RHS of the alias are not
+// dependent. e.g.
+//   using AliasFoo = Foo;
+if (const auto *CTSD = llvm::dyn_cast(
+RT->getAsCXXRecordDecl()))
+  Template = CTSD->getSpecializedTemplate();
+  }
+}
+  }
+  if (!Template) {
+// FIXME: update the diagnostic message to include C++20 alias templates

cor3ntin wrote:

There is a FIXME here

https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-03-06 Thread via cfe-commits


@@ -2612,44 +2669,312 @@ struct ConvertConstructorToDeductionGuideTransform {
 SemaRef.CurrentInstantiationScope->InstantiatedLocal(OldParam, NewParam);
 return NewParam;
   }
+};
 
-  FunctionTemplateDecl *buildDeductionGuide(
-  TemplateParameterList *TemplateParams, CXXConstructorDecl *Ctor,
-  ExplicitSpecifier ES, TypeSourceInfo *TInfo, SourceLocation LocStart,
-  SourceLocation Loc, SourceLocation LocEnd,
-  llvm::ArrayRef MaterializedTypedefs = {}) {
-DeclarationNameInfo Name(DeductionGuideName, Loc);
-ArrayRef Params =
-TInfo->getTypeLoc().castAs().getParams();
+// Find all template parameters that appear in the given DeducedArgs.
+// Return the indices of the template parameters in the TemplateParams.
+SmallVector TemplateParamsReferencedInTemplateArgumentList(
+ArrayRef TemplateParams,
+ArrayRef DeducedArgs) {
+  struct FindAppearedTemplateParams

cor3ntin wrote:

@erichkeane you are find with the name? I'm really not a fan!

https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-03-06 Thread Haojian Wu via cfe-commits

hokein wrote:

> > @cor3ntin, @erichkeane, thanks for all review comments. I'm not sure you 
> > have reviewed the whole patch. My feeling is that the core part 
> > (`DeclareImplicitDeductionGuidesForTypeAlias`) may not have received 
> > sufficient reviews. It would be great if you can take a closer look at this 
> > part.
> 
> I've looked through it a few times(including again now) and didn't see 
> anything that stuck out as wrong to me. I don't believe I can review it any 
> more thoroughly.

Great, thanks. I think I have addressed all comments.

https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-03-06 Thread Haojian Wu via cfe-commits


@@ -2612,44 +2671,309 @@ struct ConvertConstructorToDeductionGuideTransform {
 SemaRef.CurrentInstantiationScope->InstantiatedLocal(OldParam, NewParam);
 return NewParam;
   }
+};
 
-  FunctionTemplateDecl *buildDeductionGuide(
-  TemplateParameterList *TemplateParams, CXXConstructorDecl *Ctor,
-  ExplicitSpecifier ES, TypeSourceInfo *TInfo, SourceLocation LocStart,
-  SourceLocation Loc, SourceLocation LocEnd,
-  llvm::ArrayRef MaterializedTypedefs = {}) {
-DeclarationNameInfo Name(DeductionGuideName, Loc);
-ArrayRef Params =
-TInfo->getTypeLoc().castAs().getParams();
+// Find all template parameters of the AliasTemplate that appear in the
+// given DeducedArgs.
+SmallVector
+FindAppearedTemplateParamsInAlias(ArrayRef DeducedArgs,

hokein wrote:

OK, that makes sense. I made it a generic function.

https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-03-06 Thread Haojian Wu via cfe-commits


@@ -2258,6 +2258,94 @@ class ExtractTypeForDeductionGuide
   }
 };
 
+// Build a deduction guide with the specified parameter types.
+FunctionTemplateDecl *
+buildDeductionGuide(Sema , TemplateDecl *OriginalTemplate,
+TemplateParameterList *TemplateParams,
+CXXConstructorDecl *Ctor, ExplicitSpecifier ES,
+TypeSourceInfo *TInfo, SourceLocation LocStart,
+SourceLocation Loc, SourceLocation LocEnd, bool IsImplicit,
+llvm::ArrayRef MaterializedTypedefs = 
{}) {
+  DeclContext *DC = OriginalTemplate->getDeclContext();
+  auto DeductionGuideName =
+  SemaRef.Context.DeclarationNames.getCXXDeductionGuideName(
+  OriginalTemplate);
+
+  DeclarationNameInfo Name(DeductionGuideName, Loc);
+  ArrayRef Params =
+  TInfo->getTypeLoc().castAs().getParams();
+
+  // Build the implicit deduction guide template.
+  auto *Guide =
+  CXXDeductionGuideDecl::Create(SemaRef.Context, DC, LocStart, ES, Name,
+TInfo->getType(), TInfo, LocEnd, Ctor);
+  Guide->setImplicit(IsImplicit);
+  Guide->setParams(Params);
+
+  for (auto *Param : Params)
+Param->setDeclContext(Guide);
+  for (auto *TD : MaterializedTypedefs)
+TD->setDeclContext(Guide);
+
+  auto *GuideTemplate = FunctionTemplateDecl::Create(
+  SemaRef.Context, DC, Loc, DeductionGuideName, TemplateParams, Guide);
+  GuideTemplate->setImplicit(IsImplicit);
+  Guide->setDescribedFunctionTemplate(GuideTemplate);
+
+  if (isa(DC)) {
+Guide->setAccess(AS_public);
+GuideTemplate->setAccess(AS_public);
+  }
+
+  DC->addDecl(GuideTemplate);
+  return GuideTemplate;
+}
+
+// Transform a given template type parameter `TTP`.
+TemplateTypeParmDecl *
+transformTemplateTypeParam(Sema , DeclContext *DC,
+   TemplateTypeParmDecl *TTP,
+   MultiLevelTemplateArgumentList ,
+   unsigned NewDepth, unsigned NewIndex) {
+  // TemplateTypeParmDecl's index cannot be changed after creation, so
+  // substitute it directly.
+  auto *NewTTP = TemplateTypeParmDecl::Create(
+  SemaRef.Context, DC, TTP->getBeginLoc(), TTP->getLocation(), NewDepth,
+  NewIndex, TTP->getIdentifier(), TTP->wasDeclaredWithTypename(),
+  TTP->isParameterPack(), TTP->hasTypeConstraint(),
+  TTP->isExpandedParameterPack()
+  ? std::optional(TTP->getNumExpansionParameters())
+  : std::nullopt);
+  if (const auto *TC = TTP->getTypeConstraint())
+SemaRef.SubstTypeConstraint(NewTTP, TC, Args,
+/*EvaluateConstraint*/ true);

hokein wrote:

Yeah, we're replacing them 1:1. 

https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-03-05 Thread Erich Keane via cfe-commits

erichkeane wrote:

> @cor3ntin, @erichkeane, thanks for all review comments. I'm not sure you have 
> reviewed the whole patch. My feeling is that the core part 
> (`DeclareImplicitDeductionGuidesForTypeAlias`) may not have received 
> sufficient reviews. It would be great if you can take a closer look at this 
> part.

I've looked through it a few times(including again now) and didn't see anything 
that stuck out as wrong to me.  I don't believe I can review it any more 
thoroughly.

https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-03-05 Thread Erich Keane via cfe-commits


@@ -2612,44 +2671,309 @@ struct ConvertConstructorToDeductionGuideTransform {
 SemaRef.CurrentInstantiationScope->InstantiatedLocal(OldParam, NewParam);
 return NewParam;
   }
+};
 
-  FunctionTemplateDecl *buildDeductionGuide(
-  TemplateParameterList *TemplateParams, CXXConstructorDecl *Ctor,
-  ExplicitSpecifier ES, TypeSourceInfo *TInfo, SourceLocation LocStart,
-  SourceLocation Loc, SourceLocation LocEnd,
-  llvm::ArrayRef MaterializedTypedefs = {}) {
-DeclarationNameInfo Name(DeductionGuideName, Loc);
-ArrayRef Params =
-TInfo->getTypeLoc().castAs().getParams();
+// Find all template parameters of the AliasTemplate that appear in the
+// given DeducedArgs.
+SmallVector
+FindAppearedTemplateParamsInAlias(ArrayRef DeducedArgs,

erichkeane wrote:

The generic suggestion is because it would, I believe, make this a much more 
readable function with very minor changes in the 'use'.  So I think there is 
value there.

I see what you mean about the index, I think it is alright to leave the index 
part.

https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-03-05 Thread Erich Keane via cfe-commits


@@ -2258,6 +2258,94 @@ class ExtractTypeForDeductionGuide
   }
 };
 
+// Build a deduction guide with the specified parameter types.
+FunctionTemplateDecl *
+buildDeductionGuide(Sema , TemplateDecl *OriginalTemplate,
+TemplateParameterList *TemplateParams,
+CXXConstructorDecl *Ctor, ExplicitSpecifier ES,
+TypeSourceInfo *TInfo, SourceLocation LocStart,
+SourceLocation Loc, SourceLocation LocEnd, bool IsImplicit,
+llvm::ArrayRef MaterializedTypedefs = 
{}) {
+  DeclContext *DC = OriginalTemplate->getDeclContext();
+  auto DeductionGuideName =
+  SemaRef.Context.DeclarationNames.getCXXDeductionGuideName(
+  OriginalTemplate);
+
+  DeclarationNameInfo Name(DeductionGuideName, Loc);
+  ArrayRef Params =
+  TInfo->getTypeLoc().castAs().getParams();
+
+  // Build the implicit deduction guide template.
+  auto *Guide =
+  CXXDeductionGuideDecl::Create(SemaRef.Context, DC, LocStart, ES, Name,
+TInfo->getType(), TInfo, LocEnd, Ctor);
+  Guide->setImplicit(IsImplicit);
+  Guide->setParams(Params);
+
+  for (auto *Param : Params)
+Param->setDeclContext(Guide);
+  for (auto *TD : MaterializedTypedefs)
+TD->setDeclContext(Guide);
+
+  auto *GuideTemplate = FunctionTemplateDecl::Create(
+  SemaRef.Context, DC, Loc, DeductionGuideName, TemplateParams, Guide);
+  GuideTemplate->setImplicit(IsImplicit);
+  Guide->setDescribedFunctionTemplate(GuideTemplate);
+
+  if (isa(DC)) {
+Guide->setAccess(AS_public);
+GuideTemplate->setAccess(AS_public);
+  }
+
+  DC->addDecl(GuideTemplate);
+  return GuideTemplate;
+}
+
+// Transform a given template type parameter `TTP`.
+TemplateTypeParmDecl *
+transformTemplateTypeParam(Sema , DeclContext *DC,
+   TemplateTypeParmDecl *TTP,
+   MultiLevelTemplateArgumentList ,
+   unsigned NewDepth, unsigned NewIndex) {
+  // TemplateTypeParmDecl's index cannot be changed after creation, so
+  // substitute it directly.
+  auto *NewTTP = TemplateTypeParmDecl::Create(
+  SemaRef.Context, DC, TTP->getBeginLoc(), TTP->getLocation(), NewDepth,
+  NewIndex, TTP->getIdentifier(), TTP->wasDeclaredWithTypename(),
+  TTP->isParameterPack(), TTP->hasTypeConstraint(),
+  TTP->isExpandedParameterPack()
+  ? std::optional(TTP->getNumExpansionParameters())
+  : std::nullopt);
+  if (const auto *TC = TTP->getTypeConstraint())
+SemaRef.SubstTypeConstraint(NewTTP, TC, Args,
+/*EvaluateConstraint*/ true);

erichkeane wrote:

Hmm... if it is always dependent template args we're putting in that part 
should be fine.  At that point it becomes just a 'replace args' instead of a 
substitution, which should be ok.

However, are we making sure we're replacing them 1:1 (including parent 
templates)?  Else the depth of some of them is going to 'change' and later 
substitution is going to fail.

https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-03-05 Thread Haojian Wu via cfe-commits

hokein wrote:

@cor3ntin, @erichkeane, thanks for all review comments. I'm not sure you have 
reviewed the whole patch. My feeling is that the core part 
(`DeclareImplicitDeductionGuidesForTypeAlias`) may not have received sufficient 
reviews. It would be great if you can take a closer look at this part. 

https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-03-04 Thread Erich Keane via cfe-commits


@@ -2612,44 +2671,309 @@ struct ConvertConstructorToDeductionGuideTransform {
 SemaRef.CurrentInstantiationScope->InstantiatedLocal(OldParam, NewParam);
 return NewParam;
   }
+};
 
-  FunctionTemplateDecl *buildDeductionGuide(
-  TemplateParameterList *TemplateParams, CXXConstructorDecl *Ctor,
-  ExplicitSpecifier ES, TypeSourceInfo *TInfo, SourceLocation LocStart,
-  SourceLocation Loc, SourceLocation LocEnd,
-  llvm::ArrayRef MaterializedTypedefs = {}) {
-DeclarationNameInfo Name(DeductionGuideName, Loc);
-ArrayRef Params =
-TInfo->getTypeLoc().castAs().getParams();
+// Find all template parameters of the AliasTemplate that appear in the
+// given DeducedArgs.
+SmallVector
+FindAppearedTemplateParamsInAlias(ArrayRef DeducedArgs,

erichkeane wrote:

I might suggest we instead genericize this to not be AliasTemplate specific, 
and have it take a list of NamedDecls and template args.  Then call it 
something like, `DeclsReferencedInTemplateArgumentList`.

I also probably wouldn't have this return a list of 'ints', and just return the 
pointers themselves, as this little trade back and forth is a little awkward.

https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-03-04 Thread via cfe-commits


@@ -2258,6 +2260,94 @@ class ExtractTypeForDeductionGuide
   }
 };
 
+// Build a deduction guide with the specified parameter types.
+FunctionTemplateDecl *
+buildDeductionGuide(Sema , TemplateDecl *OriginalTemplate,
+TemplateParameterList *TemplateParams,
+CXXConstructorDecl *Ctor, ExplicitSpecifier ES,
+TypeSourceInfo *TInfo, SourceLocation LocStart,
+SourceLocation Loc, SourceLocation LocEnd, bool IsImplicit,
+llvm::ArrayRef MaterializedTypedefs = 
{}) {

cor3ntin wrote:

I missed that was pre existing, (but they are pretty bad names!)

https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-03-04 Thread via cfe-commits


@@ -2612,44 +2671,309 @@ struct ConvertConstructorToDeductionGuideTransform {
 SemaRef.CurrentInstantiationScope->InstantiatedLocal(OldParam, NewParam);
 return NewParam;
   }
+};
 
-  FunctionTemplateDecl *buildDeductionGuide(
-  TemplateParameterList *TemplateParams, CXXConstructorDecl *Ctor,
-  ExplicitSpecifier ES, TypeSourceInfo *TInfo, SourceLocation LocStart,
-  SourceLocation Loc, SourceLocation LocEnd,
-  llvm::ArrayRef MaterializedTypedefs = {}) {
-DeclarationNameInfo Name(DeductionGuideName, Loc);
-ArrayRef Params =
-TInfo->getTypeLoc().castAs().getParams();
+// Find all template parameters of the AliasTemplate that appear in the
+// given DeducedArgs.
+SmallVector
+FindAppearedTemplateParamsInAlias(ArrayRef DeducedArgs,

cor3ntin wrote:

@erichkeane 

https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-02-28 Thread Erich Keane via cfe-commits


@@ -2258,6 +2258,94 @@ class ExtractTypeForDeductionGuide
   }
 };
 
+// Build a deduction guide with the specified parameter types.
+FunctionTemplateDecl *
+buildDeductionGuide(Sema , TemplateDecl *OriginalTemplate,
+TemplateParameterList *TemplateParams,
+CXXConstructorDecl *Ctor, ExplicitSpecifier ES,
+TypeSourceInfo *TInfo, SourceLocation LocStart,
+SourceLocation Loc, SourceLocation LocEnd, bool IsImplicit,
+llvm::ArrayRef MaterializedTypedefs = 
{}) {
+  DeclContext *DC = OriginalTemplate->getDeclContext();
+  auto DeductionGuideName =
+  SemaRef.Context.DeclarationNames.getCXXDeductionGuideName(
+  OriginalTemplate);
+
+  DeclarationNameInfo Name(DeductionGuideName, Loc);
+  ArrayRef Params =
+  TInfo->getTypeLoc().castAs().getParams();
+
+  // Build the implicit deduction guide template.
+  auto *Guide =
+  CXXDeductionGuideDecl::Create(SemaRef.Context, DC, LocStart, ES, Name,
+TInfo->getType(), TInfo, LocEnd, Ctor);
+  Guide->setImplicit(IsImplicit);
+  Guide->setParams(Params);
+
+  for (auto *Param : Params)
+Param->setDeclContext(Guide);
+  for (auto *TD : MaterializedTypedefs)
+TD->setDeclContext(Guide);
+
+  auto *GuideTemplate = FunctionTemplateDecl::Create(
+  SemaRef.Context, DC, Loc, DeductionGuideName, TemplateParams, Guide);
+  GuideTemplate->setImplicit(IsImplicit);
+  Guide->setDescribedFunctionTemplate(GuideTemplate);
+
+  if (isa(DC)) {
+Guide->setAccess(AS_public);
+GuideTemplate->setAccess(AS_public);
+  }
+
+  DC->addDecl(GuideTemplate);
+  return GuideTemplate;
+}
+
+// Transform a given template type parameter `TTP`.
+TemplateTypeParmDecl *
+transformTemplateTypeParam(Sema , DeclContext *DC,
+   TemplateTypeParmDecl *TTP,
+   MultiLevelTemplateArgumentList ,
+   unsigned NewDepth, unsigned NewIndex) {
+  // TemplateTypeParmDecl's index cannot be changed after creation, so
+  // substitute it directly.
+  auto *NewTTP = TemplateTypeParmDecl::Create(
+  SemaRef.Context, DC, TTP->getBeginLoc(), TTP->getLocation(), NewDepth,
+  NewIndex, TTP->getIdentifier(), TTP->wasDeclaredWithTypename(),
+  TTP->isParameterPack(), TTP->hasTypeConstraint(),
+  TTP->isExpandedParameterPack()
+  ? std::optional(TTP->getNumExpansionParameters())
+  : std::nullopt);
+  if (const auto *TC = TTP->getTypeConstraint())
+SemaRef.SubstTypeConstraint(NewTTP, TC, Args,
+/*EvaluateConstraint*/ true);

erichkeane wrote:

Hmm... but as-written it seems like it would cause problems where the original 
function-template isn't instantiate-able.  It seems to me that instead of 
substituting it, perhaps we should be 'converting' it in some way to update the 
references?  I'll have to think on it, though I'm @zygoloid  can come around 
and answer for us.

https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-02-28 Thread Haojian Wu via cfe-commits


@@ -10598,10 +10598,36 @@ QualType 
Sema::DeduceTemplateSpecializationFromInitializer(
   if (TemplateName.isDependent())
 return SubstAutoTypeDependent(TSInfo->getType());
 
-  // We can only perform deduction for class templates.
+  // We can only perform deduction for class templates or alias templates.
   auto *Template =
   dyn_cast_or_null(TemplateName.getAsTemplateDecl());
+  TemplateDecl* LookupTemplateDecl = Template;
+  if (!Template && getLangOpts().CPlusPlus20) { // type alias template

hokein wrote:

thanks, good to know that. I were not aware of these.

I added one `warn_cxx17_compat_ctad_for_alias_templates` .

https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-02-28 Thread Haojian Wu via cfe-commits


@@ -10598,10 +10598,36 @@ QualType 
Sema::DeduceTemplateSpecializationFromInitializer(
   if (TemplateName.isDependent())
 return SubstAutoTypeDependent(TSInfo->getType());
 
-  // We can only perform deduction for class templates.
+  // We can only perform deduction for class templates or alias templates.
   auto *Template =
   dyn_cast_or_null(TemplateName.getAsTemplateDecl());
+  TemplateDecl* LookupTemplateDecl = Template;
+  if (!Template && getLangOpts().CPlusPlus20) { // type alias template
+if (auto *AliasTemplate = dyn_cast_or_null(
+TemplateName.getAsTemplateDecl());
+AliasTemplate) {
+  LookupTemplateDecl = AliasTemplate;
+  auto UnderlyingType = AliasTemplate->getTemplatedDecl()
+->getUnderlyingType()
+.getDesugaredType(Context);

hokein wrote:

thanks for the clarification. Switched to `Canonical`. Per 
https://eel.is/c++draft/over.match.class.deduct#3, CTAD is only allowed for 
aliases with the form of `[typename] [nested-name-specifier] [template] 
simple-template-id`.  Pointers and references are not accounted.

Added a test case for pointer types.


https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-02-28 Thread Haojian Wu via cfe-commits


@@ -2258,6 +2258,94 @@ class ExtractTypeForDeductionGuide
   }
 };
 
+// Build a deduction guide with the specified parameter types.
+FunctionTemplateDecl *
+buildDeductionGuide(Sema , TemplateDecl *OriginalTemplate,
+TemplateParameterList *TemplateParams,
+CXXConstructorDecl *Ctor, ExplicitSpecifier ES,
+TypeSourceInfo *TInfo, SourceLocation LocStart,
+SourceLocation Loc, SourceLocation LocEnd, bool IsImplicit,
+llvm::ArrayRef MaterializedTypedefs = 
{}) {
+  DeclContext *DC = OriginalTemplate->getDeclContext();
+  auto DeductionGuideName =
+  SemaRef.Context.DeclarationNames.getCXXDeductionGuideName(
+  OriginalTemplate);
+
+  DeclarationNameInfo Name(DeductionGuideName, Loc);
+  ArrayRef Params =
+  TInfo->getTypeLoc().castAs().getParams();
+
+  // Build the implicit deduction guide template.
+  auto *Guide =
+  CXXDeductionGuideDecl::Create(SemaRef.Context, DC, LocStart, ES, Name,
+TInfo->getType(), TInfo, LocEnd, Ctor);
+  Guide->setImplicit(IsImplicit);
+  Guide->setParams(Params);
+
+  for (auto *Param : Params)
+Param->setDeclContext(Guide);
+  for (auto *TD : MaterializedTypedefs)
+TD->setDeclContext(Guide);
+
+  auto *GuideTemplate = FunctionTemplateDecl::Create(
+  SemaRef.Context, DC, Loc, DeductionGuideName, TemplateParams, Guide);
+  GuideTemplate->setImplicit(IsImplicit);
+  Guide->setDescribedFunctionTemplate(GuideTemplate);
+
+  if (isa(DC)) {
+Guide->setAccess(AS_public);
+GuideTemplate->setAccess(AS_public);
+  }
+
+  DC->addDecl(GuideTemplate);
+  return GuideTemplate;
+}
+
+// Transform a given template type parameter `TTP`.
+TemplateTypeParmDecl *
+transformTemplateTypeParam(Sema , DeclContext *DC,
+   TemplateTypeParmDecl *TTP,
+   MultiLevelTemplateArgumentList ,
+   unsigned NewDepth, unsigned NewIndex) {
+  // TemplateTypeParmDecl's index cannot be changed after creation, so
+  // substitute it directly.
+  auto *NewTTP = TemplateTypeParmDecl::Create(
+  SemaRef.Context, DC, TTP->getBeginLoc(), TTP->getLocation(), NewDepth,
+  NewIndex, TTP->getIdentifier(), TTP->wasDeclaredWithTypename(),
+  TTP->isParameterPack(), TTP->hasTypeConstraint(),
+  TTP->isExpandedParameterPack()
+  ? std::optional(TTP->getNumExpansionParameters())
+  : std::nullopt);
+  if (const auto *TC = TTP->getTypeConstraint())
+SemaRef.SubstTypeConstraint(NewTTP, TC, Args,
+/*EvaluateConstraint*/ true);

hokein wrote:

> For the most part, we WANT the 'old' constraint to attach. All the work to 
> instantiate the constraints end up going against the original template.

I think this is not we want for this case, we're in the process of building a 
new `FunctionTemplate` from the original template here, specifically building 
the `TemplateTypeParmDecl` for the new template. Attaching the `old` constraint 
to it is not correct because this will make the instantiation of the new 
template go against the template parameter in original template, and will lead 
to crashes in the normal CTAD cases, e.g. 

```
template 
concept True = true;
struct concepts {
  template 
  struct B {
template  Z> B(Y, Z);
  };
};

concepts::B b(0, 1);
```


https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-02-27 Thread Erich Keane via cfe-commits


@@ -2258,6 +2258,94 @@ class ExtractTypeForDeductionGuide
   }
 };
 
+// Build a deduction guide with the specified parameter types.
+FunctionTemplateDecl *
+buildDeductionGuide(Sema , TemplateDecl *OriginalTemplate,
+TemplateParameterList *TemplateParams,
+CXXConstructorDecl *Ctor, ExplicitSpecifier ES,
+TypeSourceInfo *TInfo, SourceLocation LocStart,
+SourceLocation Loc, SourceLocation LocEnd, bool IsImplicit,
+llvm::ArrayRef MaterializedTypedefs = 
{}) {
+  DeclContext *DC = OriginalTemplate->getDeclContext();
+  auto DeductionGuideName =
+  SemaRef.Context.DeclarationNames.getCXXDeductionGuideName(
+  OriginalTemplate);
+
+  DeclarationNameInfo Name(DeductionGuideName, Loc);
+  ArrayRef Params =
+  TInfo->getTypeLoc().castAs().getParams();
+
+  // Build the implicit deduction guide template.
+  auto *Guide =
+  CXXDeductionGuideDecl::Create(SemaRef.Context, DC, LocStart, ES, Name,
+TInfo->getType(), TInfo, LocEnd, Ctor);
+  Guide->setImplicit(IsImplicit);
+  Guide->setParams(Params);
+
+  for (auto *Param : Params)
+Param->setDeclContext(Guide);
+  for (auto *TD : MaterializedTypedefs)
+TD->setDeclContext(Guide);
+
+  auto *GuideTemplate = FunctionTemplateDecl::Create(
+  SemaRef.Context, DC, Loc, DeductionGuideName, TemplateParams, Guide);
+  GuideTemplate->setImplicit(IsImplicit);
+  Guide->setDescribedFunctionTemplate(GuideTemplate);
+
+  if (isa(DC)) {
+Guide->setAccess(AS_public);
+GuideTemplate->setAccess(AS_public);
+  }
+
+  DC->addDecl(GuideTemplate);
+  return GuideTemplate;
+}
+
+// Transform a given template type parameter `TTP`.
+TemplateTypeParmDecl *
+transformTemplateTypeParam(Sema , DeclContext *DC,
+   TemplateTypeParmDecl *TTP,
+   MultiLevelTemplateArgumentList ,
+   unsigned NewDepth, unsigned NewIndex) {
+  // TemplateTypeParmDecl's index cannot be changed after creation, so
+  // substitute it directly.
+  auto *NewTTP = TemplateTypeParmDecl::Create(
+  SemaRef.Context, DC, TTP->getBeginLoc(), TTP->getLocation(), NewDepth,
+  NewIndex, TTP->getIdentifier(), TTP->wasDeclaredWithTypename(),
+  TTP->isParameterPack(), TTP->hasTypeConstraint(),
+  TTP->isExpandedParameterPack()
+  ? std::optional(TTP->getNumExpansionParameters())
+  : std::nullopt);
+  if (const auto *TC = TTP->getTypeConstraint())
+SemaRef.SubstTypeConstraint(NewTTP, TC, Args,
+/*EvaluateConstraint*/ true);

erichkeane wrote:

For the most part, we WANT the 'old' constraint to attach.  All the work to 
instantiate the constraints end up going against the original template.

By doing this constraint evaluation, you're now making substitution failures 
observable way before they are allowed to be observed from the looks of it.

https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-02-27 Thread Erich Keane via cfe-commits


@@ -10598,10 +10598,36 @@ QualType 
Sema::DeduceTemplateSpecializationFromInitializer(
   if (TemplateName.isDependent())
 return SubstAutoTypeDependent(TSInfo->getType());
 
-  // We can only perform deduction for class templates.
+  // We can only perform deduction for class templates or alias templates.
   auto *Template =
   dyn_cast_or_null(TemplateName.getAsTemplateDecl());
+  TemplateDecl* LookupTemplateDecl = Template;
+  if (!Template && getLangOpts().CPlusPlus20) { // type alias template
+if (auto *AliasTemplate = dyn_cast_or_null(
+TemplateName.getAsTemplateDecl());
+AliasTemplate) {
+  LookupTemplateDecl = AliasTemplate;
+  auto UnderlyingType = AliasTemplate->getTemplatedDecl()
+->getUnderlyingType()
+.getDesugaredType(Context);

erichkeane wrote:

`Desugar` doesn't remove all of the typedefs/etc, and leaves sugar in 
pointees/references.  So this is very likely to end up being an underlying type 
of, for example, `SomeTypedef*`.  Canonical canonicalizes EVERYTHING.

https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-02-27 Thread Erich Keane via cfe-commits


@@ -10598,10 +10598,36 @@ QualType 
Sema::DeduceTemplateSpecializationFromInitializer(
   if (TemplateName.isDependent())
 return SubstAutoTypeDependent(TSInfo->getType());
 
-  // We can only perform deduction for class templates.
+  // We can only perform deduction for class templates or alias templates.
   auto *Template =
   dyn_cast_or_null(TemplateName.getAsTemplateDecl());
+  TemplateDecl* LookupTemplateDecl = Template;
+  if (!Template && getLangOpts().CPlusPlus20) { // type alias template

erichkeane wrote:

We actually have a TON of those sorts of things: See the warning groups named 
like `CXXPre20Compat`.

https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-02-27 Thread Haojian Wu via cfe-commits


@@ -2612,44 +2669,313 @@ struct ConvertConstructorToDeductionGuideTransform {
 SemaRef.CurrentInstantiationScope->InstantiatedLocal(OldParam, NewParam);
 return NewParam;
   }
+};
 
-  FunctionTemplateDecl *buildDeductionGuide(
-  TemplateParameterList *TemplateParams, CXXConstructorDecl *Ctor,
-  ExplicitSpecifier ES, TypeSourceInfo *TInfo, SourceLocation LocStart,
-  SourceLocation Loc, SourceLocation LocEnd,
-  llvm::ArrayRef MaterializedTypedefs = {}) {
-DeclarationNameInfo Name(DeductionGuideName, Loc);
-ArrayRef Params =
-TInfo->getTypeLoc().castAs().getParams();
+// Find all template parameters of the AliasTemplate that appear in the
+// given DeducedArgs.
+SmallVector
+FindAppearedTemplateParamsInAlias(ArrayRef DeducedArgs,
+  TypeAliasTemplateDecl *AliasTemplate) {
+  struct FindAppearedTemplateParams
+  : public RecursiveASTVisitor {
+llvm::DenseSet TemplateParamsInAlias;
+llvm::DenseSet AppearedTemplateParams;
+
+FindAppearedTemplateParams(ArrayRef TemplateParamsInAlias)
+: TemplateParamsInAlias(TemplateParamsInAlias.begin(),
+TemplateParamsInAlias.end()) {}
+
+bool VisitTemplateTypeParmType(TemplateTypeParmType *TTP) {
+  TTP->getIndex();
+  MarkAppeared(TTP->getDecl());
+  return true;
+}
+bool VisitDeclRefExpr(DeclRefExpr *DRE) {
+  MarkAppeared(DRE->getFoundDecl());
+  return true;
+}
 
-// Build the implicit deduction guide template.
-auto *Guide =
-CXXDeductionGuideDecl::Create(SemaRef.Context, DC, LocStart, ES, Name,
-  TInfo->getType(), TInfo, LocEnd, Ctor);
-Guide->setImplicit();
-Guide->setParams(Params);
+void MarkAppeared(NamedDecl *ND) {
+  if (TemplateParamsInAlias.contains(ND))
+AppearedTemplateParams.insert(ND);
+}
+  };
+  ArrayRef TemplateParamsInAlias =
+  AliasTemplate->getTemplateParameters()->asArray();
+  FindAppearedTemplateParams MarkAppeared(TemplateParamsInAlias);
+  MarkAppeared.TraverseTemplateArguments(DeducedArgs);
 
-for (auto *Param : Params)
-  Param->setDeclContext(Guide);
-for (auto *TD : MaterializedTypedefs)
-  TD->setDeclContext(Guide);
+  SmallVector Results;
+  for (unsigned Index = 0; Index < TemplateParamsInAlias.size(); ++Index) {
+if (MarkAppeared.AppearedTemplateParams.contains(
+TemplateParamsInAlias[Index]))
+  Results.push_back(Index);
+  }
+  return Results;
+}
+
+bool hasDeclaredDeductionGuides(DeclarationName Name, DeclContext *DC) {
+  // Check whether we've already declared deduction guides for this template.
+  // FIXME: Consider storing a flag on the template to indicate this.

hokein wrote:

I think the flag change is orthogonal to the current patch, and we already do 
this lookup for non-type-alias CTAD implementation. 

We can address it in a followup.

https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-02-27 Thread Haojian Wu via cfe-commits


@@ -10598,10 +10598,36 @@ QualType 
Sema::DeduceTemplateSpecializationFromInitializer(
   if (TemplateName.isDependent())
 return SubstAutoTypeDependent(TSInfo->getType());
 
-  // We can only perform deduction for class templates.
+  // We can only perform deduction for class templates or alias templates.
   auto *Template =
   dyn_cast_or_null(TemplateName.getAsTemplateDecl());
+  TemplateDecl* LookupTemplateDecl = Template;
+  if (!Template && getLangOpts().CPlusPlus20) { // type alias template
+if (auto *AliasTemplate = dyn_cast_or_null(
+TemplateName.getAsTemplateDecl());
+AliasTemplate) {
+  LookupTemplateDecl = AliasTemplate;
+  auto UnderlyingType = AliasTemplate->getTemplatedDecl()
+->getUnderlyingType()
+.getDesugaredType(Context);

hokein wrote:

Here we'd like to get the underlying type with all alias stripped. I think both 
`Desugar` and `Canonical` can achieve the goal here, but `Desugar` seems more 
explicit.

https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-02-27 Thread Haojian Wu via cfe-commits


@@ -10598,10 +10598,36 @@ QualType 
Sema::DeduceTemplateSpecializationFromInitializer(
   if (TemplateName.isDependent())
 return SubstAutoTypeDependent(TSInfo->getType());
 
-  // We can only perform deduction for class templates.
+  // We can only perform deduction for class templates or alias templates.
   auto *Template =
   dyn_cast_or_null(TemplateName.getAsTemplateDecl());
+  TemplateDecl* LookupTemplateDecl = Template;
+  if (!Template && getLangOpts().CPlusPlus20) { // type alias template
+if (auto *AliasTemplate = dyn_cast_or_null(

hokein wrote:

oh, good catch (this part of code has been moved and rewritten several times, I 
probably missed to cleanup it). Done. 

https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-02-27 Thread Haojian Wu via cfe-commits


@@ -2258,6 +2258,94 @@ class ExtractTypeForDeductionGuide
   }
 };
 
+// Build a deduction guide with the specified parameter types.
+FunctionTemplateDecl *
+buildDeductionGuide(Sema , TemplateDecl *OriginalTemplate,
+TemplateParameterList *TemplateParams,
+CXXConstructorDecl *Ctor, ExplicitSpecifier ES,
+TypeSourceInfo *TInfo, SourceLocation LocStart,
+SourceLocation Loc, SourceLocation LocEnd, bool IsImplicit,
+llvm::ArrayRef MaterializedTypedefs = 
{}) {
+  DeclContext *DC = OriginalTemplate->getDeclContext();
+  auto DeductionGuideName =
+  SemaRef.Context.DeclarationNames.getCXXDeductionGuideName(
+  OriginalTemplate);
+
+  DeclarationNameInfo Name(DeductionGuideName, Loc);
+  ArrayRef Params =
+  TInfo->getTypeLoc().castAs().getParams();
+
+  // Build the implicit deduction guide template.
+  auto *Guide =
+  CXXDeductionGuideDecl::Create(SemaRef.Context, DC, LocStart, ES, Name,
+TInfo->getType(), TInfo, LocEnd, Ctor);
+  Guide->setImplicit(IsImplicit);
+  Guide->setParams(Params);
+
+  for (auto *Param : Params)
+Param->setDeclContext(Guide);
+  for (auto *TD : MaterializedTypedefs)
+TD->setDeclContext(Guide);
+
+  auto *GuideTemplate = FunctionTemplateDecl::Create(
+  SemaRef.Context, DC, Loc, DeductionGuideName, TemplateParams, Guide);
+  GuideTemplate->setImplicit(IsImplicit);
+  Guide->setDescribedFunctionTemplate(GuideTemplate);
+
+  if (isa(DC)) {
+Guide->setAccess(AS_public);
+GuideTemplate->setAccess(AS_public);
+  }
+
+  DC->addDecl(GuideTemplate);
+  return GuideTemplate;
+}
+
+// Transform a given template type parameter `TTP`.
+TemplateTypeParmDecl *
+transformTemplateTypeParam(Sema , DeclContext *DC,
+   TemplateTypeParmDecl *TTP,
+   MultiLevelTemplateArgumentList ,
+   unsigned NewDepth, unsigned NewIndex) {
+  // TemplateTypeParmDecl's index cannot be changed after creation, so
+  // substitute it directly.
+  auto *NewTTP = TemplateTypeParmDecl::Create(
+  SemaRef.Context, DC, TTP->getBeginLoc(), TTP->getLocation(), NewDepth,
+  NewIndex, TTP->getIdentifier(), TTP->wasDeclaredWithTypename(),
+  TTP->isParameterPack(), TTP->hasTypeConstraint(),
+  TTP->isExpandedParameterPack()
+  ? std::optional(TTP->getNumExpansionParameters())
+  : std::nullopt);
+  if (const auto *TC = TTP->getTypeConstraint())
+SemaRef.SubstTypeConstraint(NewTTP, TC, Args,
+/*EvaluateConstraint*/ true);

hokein wrote:

Yes, I think so, though the function parameter name is a bit confusing.

Here, we intend to *rewrite* the `TTP->getTypeConstraint()` (update the old 
template occurrences with the new template parameters). Looking at the 
`SubstTypeConstraint` implementation, if we set it to false, it will 
[attach](https://github.com/llvm/llvm-project/blob/main/clang/lib/Sema/SemaTemplateInstantiate.cpp#L2886-L2890)
 the old constraint to `NewTTP`.

(This is a refactoring change which lifts the existing function from 
`ConvertConstructorToDeductionGuideTransform` for code sharing purpose).  

https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-02-27 Thread Haojian Wu via cfe-commits


@@ -10598,10 +10598,36 @@ QualType 
Sema::DeduceTemplateSpecializationFromInitializer(
   if (TemplateName.isDependent())
 return SubstAutoTypeDependent(TSInfo->getType());
 
-  // We can only perform deduction for class templates.
+  // We can only perform deduction for class templates or alias templates.
   auto *Template =
   dyn_cast_or_null(TemplateName.getAsTemplateDecl());
+  TemplateDecl* LookupTemplateDecl = Template;
+  if (!Template && getLangOpts().CPlusPlus20) { // type alias template

hokein wrote:

We could add one for that, but I'm not sure, it seems that in general clang 
doesn't provide diagnostics for features that aren't available in the current 
`-std=` version (at least I didn't such a diagnostic).

For example, when we use C++ concepts without `-std=c++20`, clang rejects it 
with a diagnostic `unknown type name 'concept'`. gcc have better diagnostics 
(`note: 'concept' only available with '-std=c++20' or '-fconcepts'`).

I have a somewhat-relevant FIXME below, it is about to adjust 
`err_deduced_non_class_template_specialization_type` message to include the 
type-alias templates.

https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-02-26 Thread Erich Keane via cfe-commits


@@ -2612,44 +2669,313 @@ struct ConvertConstructorToDeductionGuideTransform {
 SemaRef.CurrentInstantiationScope->InstantiatedLocal(OldParam, NewParam);
 return NewParam;
   }
+};
 
-  FunctionTemplateDecl *buildDeductionGuide(
-  TemplateParameterList *TemplateParams, CXXConstructorDecl *Ctor,
-  ExplicitSpecifier ES, TypeSourceInfo *TInfo, SourceLocation LocStart,
-  SourceLocation Loc, SourceLocation LocEnd,
-  llvm::ArrayRef MaterializedTypedefs = {}) {
-DeclarationNameInfo Name(DeductionGuideName, Loc);
-ArrayRef Params =
-TInfo->getTypeLoc().castAs().getParams();
+// Find all template parameters of the AliasTemplate that appear in the
+// given DeducedArgs.
+SmallVector
+FindAppearedTemplateParamsInAlias(ArrayRef DeducedArgs,
+  TypeAliasTemplateDecl *AliasTemplate) {
+  struct FindAppearedTemplateParams
+  : public RecursiveASTVisitor {
+llvm::DenseSet TemplateParamsInAlias;
+llvm::DenseSet AppearedTemplateParams;
+
+FindAppearedTemplateParams(ArrayRef TemplateParamsInAlias)
+: TemplateParamsInAlias(TemplateParamsInAlias.begin(),
+TemplateParamsInAlias.end()) {}
+
+bool VisitTemplateTypeParmType(TemplateTypeParmType *TTP) {
+  TTP->getIndex();
+  MarkAppeared(TTP->getDecl());
+  return true;
+}
+bool VisitDeclRefExpr(DeclRefExpr *DRE) {
+  MarkAppeared(DRE->getFoundDecl());
+  return true;
+}
 
-// Build the implicit deduction guide template.
-auto *Guide =
-CXXDeductionGuideDecl::Create(SemaRef.Context, DC, LocStart, ES, Name,
-  TInfo->getType(), TInfo, LocEnd, Ctor);
-Guide->setImplicit();
-Guide->setParams(Params);
+void MarkAppeared(NamedDecl *ND) {
+  if (TemplateParamsInAlias.contains(ND))
+AppearedTemplateParams.insert(ND);
+}
+  };
+  ArrayRef TemplateParamsInAlias =
+  AliasTemplate->getTemplateParameters()->asArray();
+  FindAppearedTemplateParams MarkAppeared(TemplateParamsInAlias);
+  MarkAppeared.TraverseTemplateArguments(DeducedArgs);
 
-for (auto *Param : Params)
-  Param->setDeclContext(Guide);
-for (auto *TD : MaterializedTypedefs)
-  TD->setDeclContext(Guide);
+  SmallVector Results;
+  for (unsigned Index = 0; Index < TemplateParamsInAlias.size(); ++Index) {
+if (MarkAppeared.AppearedTemplateParams.contains(
+TemplateParamsInAlias[Index]))
+  Results.push_back(Index);
+  }
+  return Results;
+}
+
+bool hasDeclaredDeductionGuides(DeclarationName Name, DeclContext *DC) {
+  // Check whether we've already declared deduction guides for this template.
+  // FIXME: Consider storing a flag on the template to indicate this.

erichkeane wrote:

The cost of a lookup can be pretty bad, I think the flag on the template is 
worth doing ASAP.

https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-02-26 Thread Erich Keane via cfe-commits


@@ -10598,10 +10598,36 @@ QualType 
Sema::DeduceTemplateSpecializationFromInitializer(
   if (TemplateName.isDependent())
 return SubstAutoTypeDependent(TSInfo->getType());
 
-  // We can only perform deduction for class templates.
+  // We can only perform deduction for class templates or alias templates.
   auto *Template =
   dyn_cast_or_null(TemplateName.getAsTemplateDecl());
+  TemplateDecl* LookupTemplateDecl = Template;
+  if (!Template && getLangOpts().CPlusPlus20) { // type alias template
+if (auto *AliasTemplate = dyn_cast_or_null(

erichkeane wrote:

Whats the point of using the initializer to just go and test against 
AliasTemplate?  The semi-colon and everything after is not needed, right?

https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-02-26 Thread Erich Keane via cfe-commits


@@ -2258,6 +2258,94 @@ class ExtractTypeForDeductionGuide
   }
 };
 
+// Build a deduction guide with the specified parameter types.
+FunctionTemplateDecl *
+buildDeductionGuide(Sema , TemplateDecl *OriginalTemplate,
+TemplateParameterList *TemplateParams,
+CXXConstructorDecl *Ctor, ExplicitSpecifier ES,
+TypeSourceInfo *TInfo, SourceLocation LocStart,
+SourceLocation Loc, SourceLocation LocEnd, bool IsImplicit,
+llvm::ArrayRef MaterializedTypedefs = 
{}) {
+  DeclContext *DC = OriginalTemplate->getDeclContext();
+  auto DeductionGuideName =
+  SemaRef.Context.DeclarationNames.getCXXDeductionGuideName(
+  OriginalTemplate);
+
+  DeclarationNameInfo Name(DeductionGuideName, Loc);
+  ArrayRef Params =
+  TInfo->getTypeLoc().castAs().getParams();
+
+  // Build the implicit deduction guide template.
+  auto *Guide =
+  CXXDeductionGuideDecl::Create(SemaRef.Context, DC, LocStart, ES, Name,
+TInfo->getType(), TInfo, LocEnd, Ctor);
+  Guide->setImplicit(IsImplicit);
+  Guide->setParams(Params);
+
+  for (auto *Param : Params)
+Param->setDeclContext(Guide);
+  for (auto *TD : MaterializedTypedefs)
+TD->setDeclContext(Guide);
+
+  auto *GuideTemplate = FunctionTemplateDecl::Create(
+  SemaRef.Context, DC, Loc, DeductionGuideName, TemplateParams, Guide);
+  GuideTemplate->setImplicit(IsImplicit);
+  Guide->setDescribedFunctionTemplate(GuideTemplate);
+
+  if (isa(DC)) {
+Guide->setAccess(AS_public);
+GuideTemplate->setAccess(AS_public);
+  }
+
+  DC->addDecl(GuideTemplate);
+  return GuideTemplate;
+}
+
+// Transform a given template type parameter `TTP`.
+TemplateTypeParmDecl *
+transformTemplateTypeParam(Sema , DeclContext *DC,
+   TemplateTypeParmDecl *TTP,
+   MultiLevelTemplateArgumentList ,
+   unsigned NewDepth, unsigned NewIndex) {
+  // TemplateTypeParmDecl's index cannot be changed after creation, so
+  // substitute it directly.
+  auto *NewTTP = TemplateTypeParmDecl::Create(
+  SemaRef.Context, DC, TTP->getBeginLoc(), TTP->getLocation(), NewDepth,
+  NewIndex, TTP->getIdentifier(), TTP->wasDeclaredWithTypename(),
+  TTP->isParameterPack(), TTP->hasTypeConstraint(),
+  TTP->isExpandedParameterPack()
+  ? std::optional(TTP->getNumExpansionParameters())
+  : std::nullopt);
+  if (const auto *TC = TTP->getTypeConstraint())
+SemaRef.SubstTypeConstraint(NewTTP, TC, Args,
+/*EvaluateConstraint*/ true);

erichkeane wrote:

```suggestion
/*EvaluateConstraint=*/ true);
```
Do we mean to evaluate the constraint?  Typically we don't want to evaluate the 
constraint unless we are checking the decl for a call, or for constraint 
comparisons.  So we really don't ever substitute these ever (and the 
substituted versions don't really end up in the AST).

https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-02-26 Thread Erich Keane via cfe-commits


@@ -10598,10 +10598,36 @@ QualType 
Sema::DeduceTemplateSpecializationFromInitializer(
   if (TemplateName.isDependent())
 return SubstAutoTypeDependent(TSInfo->getType());
 
-  // We can only perform deduction for class templates.
+  // We can only perform deduction for class templates or alias templates.
   auto *Template =
   dyn_cast_or_null(TemplateName.getAsTemplateDecl());
+  TemplateDecl* LookupTemplateDecl = Template;
+  if (!Template && getLangOpts().CPlusPlus20) { // type alias template
+if (auto *AliasTemplate = dyn_cast_or_null(
+TemplateName.getAsTemplateDecl());
+AliasTemplate) {
+  LookupTemplateDecl = AliasTemplate;
+  auto UnderlyingType = AliasTemplate->getTemplatedDecl()
+->getUnderlyingType()
+.getDesugaredType(Context);

erichkeane wrote:

Do we mean Desugar here, or Canonical?

https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-02-26 Thread Erich Keane via cfe-commits

https://github.com/erichkeane commented:

We probably need an entry in ReleaseNotes.rst here as well.  

https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-02-26 Thread Erich Keane via cfe-commits


@@ -10598,10 +10598,36 @@ QualType 
Sema::DeduceTemplateSpecializationFromInitializer(
   if (TemplateName.isDependent())
 return SubstAutoTypeDependent(TSInfo->getType());
 
-  // We can only perform deduction for class templates.
+  // We can only perform deduction for class templates or alias templates.
   auto *Template =
   dyn_cast_or_null(TemplateName.getAsTemplateDecl());
+  TemplateDecl* LookupTemplateDecl = Template;
+  if (!Template && getLangOpts().CPlusPlus20) { // type alias template

erichkeane wrote:

I think we need a diagnostic here for the 'is a C++20 feature', right?

https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-02-26 Thread Erich Keane via cfe-commits

https://github.com/erichkeane edited 
https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-02-26 Thread Haojian Wu via cfe-commits


@@ -2612,44 +2671,309 @@ struct ConvertConstructorToDeductionGuideTransform {
 SemaRef.CurrentInstantiationScope->InstantiatedLocal(OldParam, NewParam);
 return NewParam;
   }
+};
 
-  FunctionTemplateDecl *buildDeductionGuide(
-  TemplateParameterList *TemplateParams, CXXConstructorDecl *Ctor,
-  ExplicitSpecifier ES, TypeSourceInfo *TInfo, SourceLocation LocStart,
-  SourceLocation Loc, SourceLocation LocEnd,
-  llvm::ArrayRef MaterializedTypedefs = {}) {
-DeclarationNameInfo Name(DeductionGuideName, Loc);
-ArrayRef Params =
-TInfo->getTypeLoc().castAs().getParams();
+// Find all template parameters of the AliasTemplate that appear in the
+// given DeducedArgs.
+SmallVector
+FindAppearedTemplateParamsInAlias(ArrayRef DeducedArgs,
+  TypeAliasTemplateDecl *AliasTemplate) {
+  struct FindAppearedTemplateParams
+  : public RecursiveASTVisitor {
+llvm::DenseSet TemplateParamsInAlias;
+llvm::DenseSet AppearedTemplateParams;
+
+FindAppearedTemplateParams(ArrayRef TemplateParamsInAlias)
+: TemplateParamsInAlias(TemplateParamsInAlias.begin(),
+TemplateParamsInAlias.end()) {}
+
+bool VisitTemplateTypeParmType(TemplateTypeParmType *TTP) {
+  TTP->getIndex();
+  MarkAppeared(TTP->getDecl());
+  return true;
+}
+bool VisitDeclRefExpr(DeclRefExpr *DRE) {
+  MarkAppeared(DRE->getFoundDecl());
+  return true;
+}
 
-// Build the implicit deduction guide template.
-auto *Guide =
-CXXDeductionGuideDecl::Create(SemaRef.Context, DC, LocStart, ES, Name,
-  TInfo->getType(), TInfo, LocEnd, Ctor);
-Guide->setImplicit();
-Guide->setParams(Params);
+void MarkAppeared(NamedDecl *ND) {
+  if (TemplateParamsInAlias.contains(ND))
+AppearedTemplateParams.insert(ND);
+}
+  };
+  ArrayRef TemplateParamsInAlias =
+  AliasTemplate->getTemplateParameters()->asArray();
+  FindAppearedTemplateParams MarkAppeared(TemplateParamsInAlias);
+  MarkAppeared.TraverseTemplateArguments(DeducedArgs);
 
-for (auto *Param : Params)
-  Param->setDeclContext(Guide);
-for (auto *TD : MaterializedTypedefs)
-  TD->setDeclContext(Guide);
+  SmallVector Results;
+  for (unsigned Index = 0; Index < TemplateParamsInAlias.size(); ++Index) {
+if (MarkAppeared.AppearedTemplateParams.contains(
+TemplateParamsInAlias[Index]))
+  Results.push_back(Index);
+  }
+  return Results;
+}
 
-auto *GuideTemplate = FunctionTemplateDecl::Create(
-SemaRef.Context, DC, Loc, DeductionGuideName, TemplateParams, Guide);
-GuideTemplate->setImplicit();
-Guide->setDescribedFunctionTemplate(GuideTemplate);
+bool hasDeclaredDeductionGuides(DeclarationName Name, DeclContext* DC) {
+  // Check whether we've already declared deduction guides for this template.
+  // FIXME: Consider storing a flag on the template to indicate this.
+  auto Existing = DC->lookup(Name);
+  for (auto *D : Existing)
+if (D->isImplicit())
+  return true;
+  return false;
+}
 
-if (isa(DC)) {
-  Guide->setAccess(AS_public);
-  GuideTemplate->setAccess(AS_public);
+// Build deduction guides for a type alias template.
+void DeclareImplicitDeductionGuidesForTypeAlias(
+Sema , TypeAliasTemplateDecl *AliasTemplate, SourceLocation Loc) {
+  auto  = SemaRef.Context;
+  // FIXME: if there is an explicit deduction guide after the first use of the
+  // type alias usage, we will not cover this explicit deduction guide. fix 
this
+  // case.
+  if (hasDeclaredDeductionGuides(
+  Context.DeclarationNames.getCXXDeductionGuideName(AliasTemplate),
+  AliasTemplate->getDeclContext()))
+return;
+  // Unrap the sugar ElaboratedType.
+  auto RhsType = AliasTemplate->getTemplatedDecl()
+ ->getUnderlyingType()
+ .getSingleStepDesugaredType(Context);
+  TemplateDecl *Template = nullptr;
+  llvm::ArrayRef AliasRhsTemplateArgs;
+  if (const auto *TST = RhsType->getAs()) {
+// TemplateName in TEST can be a TypeAliasTemplateDecl if
+// the right hand side of the alias is also a type alias, e.g.
+//
+// template
+// using AliasFoo1 = Foo;  // Foo is a class template
+// specialization
+//
+// template
+// using AliasFoo2 = AliasFoo1; // AliasFoo1 is a type alias
+Template = TST->getTemplateName().getAsTemplateDecl();
+AliasRhsTemplateArgs = TST->template_arguments();
+  } else if (const auto *RT = RhsType->getAs()) {
+// Cases where template arguments in the RHS of the alias are not
+// dependent. e.g.
+//   using AliasFoo = Foo;
+if (const auto *CTSD = llvm::dyn_cast(
+RT->getAsCXXRecordDecl())) {
+  Template = CTSD->getSpecializedTemplate();
+  AliasRhsTemplateArgs = CTSD->getTemplateArgs().asArray();
+}

hokein wrote:

Done.


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-02-23 Thread via cfe-commits


@@ -2612,44 +2671,309 @@ struct ConvertConstructorToDeductionGuideTransform {
 SemaRef.CurrentInstantiationScope->InstantiatedLocal(OldParam, NewParam);
 return NewParam;
   }
+};
 
-  FunctionTemplateDecl *buildDeductionGuide(
-  TemplateParameterList *TemplateParams, CXXConstructorDecl *Ctor,
-  ExplicitSpecifier ES, TypeSourceInfo *TInfo, SourceLocation LocStart,
-  SourceLocation Loc, SourceLocation LocEnd,
-  llvm::ArrayRef MaterializedTypedefs = {}) {
-DeclarationNameInfo Name(DeductionGuideName, Loc);
-ArrayRef Params =
-TInfo->getTypeLoc().castAs().getParams();
+// Find all template parameters of the AliasTemplate that appear in the
+// given DeducedArgs.
+SmallVector
+FindAppearedTemplateParamsInAlias(ArrayRef DeducedArgs,
+  TypeAliasTemplateDecl *AliasTemplate) {
+  struct FindAppearedTemplateParams
+  : public RecursiveASTVisitor {
+llvm::DenseSet TemplateParamsInAlias;
+llvm::DenseSet AppearedTemplateParams;
+
+FindAppearedTemplateParams(ArrayRef TemplateParamsInAlias)
+: TemplateParamsInAlias(TemplateParamsInAlias.begin(),
+TemplateParamsInAlias.end()) {}
+
+bool VisitTemplateTypeParmType(TemplateTypeParmType *TTP) {
+  TTP->getIndex();
+  MarkAppeared(TTP->getDecl());
+  return true;
+}
+bool VisitDeclRefExpr(DeclRefExpr *DRE) {
+  MarkAppeared(DRE->getFoundDecl());
+  return true;
+}
 
-// Build the implicit deduction guide template.
-auto *Guide =
-CXXDeductionGuideDecl::Create(SemaRef.Context, DC, LocStart, ES, Name,
-  TInfo->getType(), TInfo, LocEnd, Ctor);
-Guide->setImplicit();
-Guide->setParams(Params);
+void MarkAppeared(NamedDecl *ND) {
+  if (TemplateParamsInAlias.contains(ND))
+AppearedTemplateParams.insert(ND);
+}
+  };
+  ArrayRef TemplateParamsInAlias =
+  AliasTemplate->getTemplateParameters()->asArray();
+  FindAppearedTemplateParams MarkAppeared(TemplateParamsInAlias);
+  MarkAppeared.TraverseTemplateArguments(DeducedArgs);
 
-for (auto *Param : Params)
-  Param->setDeclContext(Guide);
-for (auto *TD : MaterializedTypedefs)
-  TD->setDeclContext(Guide);
+  SmallVector Results;
+  for (unsigned Index = 0; Index < TemplateParamsInAlias.size(); ++Index) {
+if (MarkAppeared.AppearedTemplateParams.contains(
+TemplateParamsInAlias[Index]))
+  Results.push_back(Index);
+  }
+  return Results;
+}
 
-auto *GuideTemplate = FunctionTemplateDecl::Create(
-SemaRef.Context, DC, Loc, DeductionGuideName, TemplateParams, Guide);
-GuideTemplate->setImplicit();
-Guide->setDescribedFunctionTemplate(GuideTemplate);
+bool hasDeclaredDeductionGuides(DeclarationName Name, DeclContext* DC) {
+  // Check whether we've already declared deduction guides for this template.
+  // FIXME: Consider storing a flag on the template to indicate this.
+  auto Existing = DC->lookup(Name);
+  for (auto *D : Existing)
+if (D->isImplicit())
+  return true;
+  return false;
+}
 
-if (isa(DC)) {
-  Guide->setAccess(AS_public);
-  GuideTemplate->setAccess(AS_public);
+// Build deduction guides for a type alias template.
+void DeclareImplicitDeductionGuidesForTypeAlias(
+Sema , TypeAliasTemplateDecl *AliasTemplate, SourceLocation Loc) {
+  auto  = SemaRef.Context;
+  // FIXME: if there is an explicit deduction guide after the first use of the
+  // type alias usage, we will not cover this explicit deduction guide. fix 
this
+  // case.
+  if (hasDeclaredDeductionGuides(
+  Context.DeclarationNames.getCXXDeductionGuideName(AliasTemplate),
+  AliasTemplate->getDeclContext()))
+return;
+  // Unrap the sugar ElaboratedType.
+  auto RhsType = AliasTemplate->getTemplatedDecl()
+ ->getUnderlyingType()
+ .getSingleStepDesugaredType(Context);
+  TemplateDecl *Template = nullptr;
+  llvm::ArrayRef AliasRhsTemplateArgs;
+  if (const auto *TST = RhsType->getAs()) {
+// TemplateName in TEST can be a TypeAliasTemplateDecl if
+// the right hand side of the alias is also a type alias, e.g.
+//
+// template
+// using AliasFoo1 = Foo;  // Foo is a class template
+// specialization
+//
+// template
+// using AliasFoo2 = AliasFoo1; // AliasFoo1 is a type alias
+Template = TST->getTemplateName().getAsTemplateDecl();
+AliasRhsTemplateArgs = TST->template_arguments();
+  } else if (const auto *RT = RhsType->getAs()) {
+// Cases where template arguments in the RHS of the alias are not
+// dependent. e.g.
+//   using AliasFoo = Foo;
+if (const auto *CTSD = llvm::dyn_cast(
+RT->getAsCXXRecordDecl())) {
+  Template = CTSD->getSpecializedTemplate();
+  AliasRhsTemplateArgs = CTSD->getTemplateArgs().asArray();
+}

cor3ntin wrote:

An `assert(false)` 

[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-02-23 Thread Haojian Wu via cfe-commits

https://github.com/hokein edited https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-02-23 Thread Haojian Wu via cfe-commits


@@ -2612,44 +2671,309 @@ struct ConvertConstructorToDeductionGuideTransform {
 SemaRef.CurrentInstantiationScope->InstantiatedLocal(OldParam, NewParam);
 return NewParam;
   }
+};
 
-  FunctionTemplateDecl *buildDeductionGuide(
-  TemplateParameterList *TemplateParams, CXXConstructorDecl *Ctor,
-  ExplicitSpecifier ES, TypeSourceInfo *TInfo, SourceLocation LocStart,
-  SourceLocation Loc, SourceLocation LocEnd,
-  llvm::ArrayRef MaterializedTypedefs = {}) {
-DeclarationNameInfo Name(DeductionGuideName, Loc);
-ArrayRef Params =
-TInfo->getTypeLoc().castAs().getParams();
+// Find all template parameters of the AliasTemplate that appear in the
+// given DeducedArgs.
+SmallVector
+FindAppearedTemplateParamsInAlias(ArrayRef DeducedArgs,
+  TypeAliasTemplateDecl *AliasTemplate) {
+  struct FindAppearedTemplateParams
+  : public RecursiveASTVisitor {
+llvm::DenseSet TemplateParamsInAlias;
+llvm::DenseSet AppearedTemplateParams;
+
+FindAppearedTemplateParams(ArrayRef TemplateParamsInAlias)
+: TemplateParamsInAlias(TemplateParamsInAlias.begin(),
+TemplateParamsInAlias.end()) {}
+
+bool VisitTemplateTypeParmType(TemplateTypeParmType *TTP) {
+  TTP->getIndex();
+  MarkAppeared(TTP->getDecl());
+  return true;
+}
+bool VisitDeclRefExpr(DeclRefExpr *DRE) {
+  MarkAppeared(DRE->getFoundDecl());
+  return true;
+}
 
-// Build the implicit deduction guide template.
-auto *Guide =
-CXXDeductionGuideDecl::Create(SemaRef.Context, DC, LocStart, ES, Name,
-  TInfo->getType(), TInfo, LocEnd, Ctor);
-Guide->setImplicit();
-Guide->setParams(Params);
+void MarkAppeared(NamedDecl *ND) {
+  if (TemplateParamsInAlias.contains(ND))
+AppearedTemplateParams.insert(ND);
+}
+  };
+  ArrayRef TemplateParamsInAlias =
+  AliasTemplate->getTemplateParameters()->asArray();
+  FindAppearedTemplateParams MarkAppeared(TemplateParamsInAlias);
+  MarkAppeared.TraverseTemplateArguments(DeducedArgs);
 
-for (auto *Param : Params)
-  Param->setDeclContext(Guide);
-for (auto *TD : MaterializedTypedefs)
-  TD->setDeclContext(Guide);
+  SmallVector Results;
+  for (unsigned Index = 0; Index < TemplateParamsInAlias.size(); ++Index) {
+if (MarkAppeared.AppearedTemplateParams.contains(
+TemplateParamsInAlias[Index]))
+  Results.push_back(Index);
+  }
+  return Results;
+}
 
-auto *GuideTemplate = FunctionTemplateDecl::Create(
-SemaRef.Context, DC, Loc, DeductionGuideName, TemplateParams, Guide);
-GuideTemplate->setImplicit();
-Guide->setDescribedFunctionTemplate(GuideTemplate);
+bool hasDeclaredDeductionGuides(DeclarationName Name, DeclContext* DC) {
+  // Check whether we've already declared deduction guides for this template.
+  // FIXME: Consider storing a flag on the template to indicate this.
+  auto Existing = DC->lookup(Name);
+  for (auto *D : Existing)
+if (D->isImplicit())
+  return true;
+  return false;
+}
 
-if (isa(DC)) {
-  Guide->setAccess(AS_public);
-  GuideTemplate->setAccess(AS_public);
+// Build deduction guides for a type alias template.
+void DeclareImplicitDeductionGuidesForTypeAlias(
+Sema , TypeAliasTemplateDecl *AliasTemplate, SourceLocation Loc) {
+  auto  = SemaRef.Context;
+  // FIXME: if there is an explicit deduction guide after the first use of the
+  // type alias usage, we will not cover this explicit deduction guide. fix 
this
+  // case.
+  if (hasDeclaredDeductionGuides(
+  Context.DeclarationNames.getCXXDeductionGuideName(AliasTemplate),
+  AliasTemplate->getDeclContext()))
+return;
+  // Unrap the sugar ElaboratedType.
+  auto RhsType = AliasTemplate->getTemplatedDecl()
+ ->getUnderlyingType()
+ .getSingleStepDesugaredType(Context);
+  TemplateDecl *Template = nullptr;
+  llvm::ArrayRef AliasRhsTemplateArgs;
+  if (const auto *TST = RhsType->getAs()) {
+// TemplateName in TEST can be a TypeAliasTemplateDecl if
+// the right hand side of the alias is also a type alias, e.g.
+//
+// template
+// using AliasFoo1 = Foo;  // Foo is a class template
+// specialization
+//
+// template
+// using AliasFoo2 = AliasFoo1; // AliasFoo1 is a type alias
+Template = TST->getTemplateName().getAsTemplateDecl();
+AliasRhsTemplateArgs = TST->template_arguments();
+  } else if (const auto *RT = RhsType->getAs()) {
+// Cases where template arguments in the RHS of the alias are not
+// dependent. e.g.
+//   using AliasFoo = Foo;
+if (const auto *CTSD = llvm::dyn_cast(
+RT->getAsCXXRecordDecl())) {
+  Template = CTSD->getSpecializedTemplate();
+  AliasRhsTemplateArgs = CTSD->getTemplateArgs().asArray();
+}
+  }
+  if (!Template)
+return;
+  

[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-02-23 Thread Haojian Wu via cfe-commits


@@ -2612,44 +2671,309 @@ struct ConvertConstructorToDeductionGuideTransform {
 SemaRef.CurrentInstantiationScope->InstantiatedLocal(OldParam, NewParam);
 return NewParam;
   }
+};
 
-  FunctionTemplateDecl *buildDeductionGuide(
-  TemplateParameterList *TemplateParams, CXXConstructorDecl *Ctor,
-  ExplicitSpecifier ES, TypeSourceInfo *TInfo, SourceLocation LocStart,
-  SourceLocation Loc, SourceLocation LocEnd,
-  llvm::ArrayRef MaterializedTypedefs = {}) {
-DeclarationNameInfo Name(DeductionGuideName, Loc);
-ArrayRef Params =
-TInfo->getTypeLoc().castAs().getParams();
+// Find all template parameters of the AliasTemplate that appear in the
+// given DeducedArgs.
+SmallVector
+FindAppearedTemplateParamsInAlias(ArrayRef DeducedArgs,
+  TypeAliasTemplateDecl *AliasTemplate) {
+  struct FindAppearedTemplateParams
+  : public RecursiveASTVisitor {
+llvm::DenseSet TemplateParamsInAlias;
+llvm::DenseSet AppearedTemplateParams;
+
+FindAppearedTemplateParams(ArrayRef TemplateParamsInAlias)
+: TemplateParamsInAlias(TemplateParamsInAlias.begin(),
+TemplateParamsInAlias.end()) {}
+
+bool VisitTemplateTypeParmType(TemplateTypeParmType *TTP) {
+  TTP->getIndex();
+  MarkAppeared(TTP->getDecl());
+  return true;
+}
+bool VisitDeclRefExpr(DeclRefExpr *DRE) {
+  MarkAppeared(DRE->getFoundDecl());
+  return true;
+}
 
-// Build the implicit deduction guide template.
-auto *Guide =
-CXXDeductionGuideDecl::Create(SemaRef.Context, DC, LocStart, ES, Name,
-  TInfo->getType(), TInfo, LocEnd, Ctor);
-Guide->setImplicit();
-Guide->setParams(Params);
+void MarkAppeared(NamedDecl *ND) {
+  if (TemplateParamsInAlias.contains(ND))
+AppearedTemplateParams.insert(ND);
+}
+  };
+  ArrayRef TemplateParamsInAlias =
+  AliasTemplate->getTemplateParameters()->asArray();
+  FindAppearedTemplateParams MarkAppeared(TemplateParamsInAlias);
+  MarkAppeared.TraverseTemplateArguments(DeducedArgs);
 
-for (auto *Param : Params)
-  Param->setDeclContext(Guide);
-for (auto *TD : MaterializedTypedefs)
-  TD->setDeclContext(Guide);
+  SmallVector Results;
+  for (unsigned Index = 0; Index < TemplateParamsInAlias.size(); ++Index) {
+if (MarkAppeared.AppearedTemplateParams.contains(
+TemplateParamsInAlias[Index]))
+  Results.push_back(Index);
+  }
+  return Results;
+}
 
-auto *GuideTemplate = FunctionTemplateDecl::Create(
-SemaRef.Context, DC, Loc, DeductionGuideName, TemplateParams, Guide);
-GuideTemplate->setImplicit();
-Guide->setDescribedFunctionTemplate(GuideTemplate);
+bool hasDeclaredDeductionGuides(DeclarationName Name, DeclContext* DC) {
+  // Check whether we've already declared deduction guides for this template.
+  // FIXME: Consider storing a flag on the template to indicate this.
+  auto Existing = DC->lookup(Name);
+  for (auto *D : Existing)
+if (D->isImplicit())
+  return true;
+  return false;
+}
 
-if (isa(DC)) {
-  Guide->setAccess(AS_public);
-  GuideTemplate->setAccess(AS_public);
+// Build deduction guides for a type alias template.
+void DeclareImplicitDeductionGuidesForTypeAlias(
+Sema , TypeAliasTemplateDecl *AliasTemplate, SourceLocation Loc) {
+  auto  = SemaRef.Context;
+  // FIXME: if there is an explicit deduction guide after the first use of the
+  // type alias usage, we will not cover this explicit deduction guide. fix 
this
+  // case.
+  if (hasDeclaredDeductionGuides(
+  Context.DeclarationNames.getCXXDeductionGuideName(AliasTemplate),
+  AliasTemplate->getDeclContext()))
+return;
+  // Unrap the sugar ElaboratedType.
+  auto RhsType = AliasTemplate->getTemplatedDecl()
+ ->getUnderlyingType()
+ .getSingleStepDesugaredType(Context);
+  TemplateDecl *Template = nullptr;
+  llvm::ArrayRef AliasRhsTemplateArgs;
+  if (const auto *TST = RhsType->getAs()) {
+// TemplateName in TEST can be a TypeAliasTemplateDecl if
+// the right hand side of the alias is also a type alias, e.g.
+//
+// template
+// using AliasFoo1 = Foo;  // Foo is a class template
+// specialization
+//
+// template
+// using AliasFoo2 = AliasFoo1; // AliasFoo1 is a type alias
+Template = TST->getTemplateName().getAsTemplateDecl();
+AliasRhsTemplateArgs = TST->template_arguments();
+  } else if (const auto *RT = RhsType->getAs()) {
+// Cases where template arguments in the RHS of the alias are not
+// dependent. e.g.
+//   using AliasFoo = Foo;
+if (const auto *CTSD = llvm::dyn_cast(
+RT->getAsCXXRecordDecl())) {
+  Template = CTSD->getSpecializedTemplate();
+  AliasRhsTemplateArgs = CTSD->getTemplateArgs().asArray();
+}
+  }
+  if (!Template)
+return;
+  

[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-02-23 Thread Haojian Wu via cfe-commits

https://github.com/hokein commented:

Thanks for the initial review.

https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-02-23 Thread Haojian Wu via cfe-commits


@@ -39,6 +40,7 @@
 #include "llvm/ADT/SmallBitVector.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/Casting.h"

hokein wrote:

Done. 

https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-02-23 Thread Haojian Wu via cfe-commits


@@ -10525,9 +10534,11 @@ class Sema final {
   SourceLocation PointOfInstantiation, FunctionDecl *Decl,
   ArrayRef TemplateArgs,
   ConstraintSatisfaction );
-  FunctionDecl *InstantiateFunctionDeclaration(FunctionTemplateDecl *FTD,
-   const TemplateArgumentList 
*Args,
-   SourceLocation Loc);
+  FunctionDecl *InstantiateFunctionDeclaration(
+  FunctionTemplateDecl *FTD, const TemplateArgumentList *Args,
+  SourceLocation Loc,
+  CodeSynthesisContext::SynthesisKind CSC =
+  CodeSynthesisContext::ExplicitTemplateArgumentSubstitution);

hokein wrote:

This is a refactoring and non-functional change, before this patch, we always 
use the `CodeSynthesisContext::ExplicitTemplateArgumentSubstitution` in this 
API 
[implementation](https://github.com/llvm/llvm-project/blob/main/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp#L4865),
 the change here is to promote it to a function parameter (making a default 
value so that we don't need to change all existing callsites)

https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-02-23 Thread Haojian Wu via cfe-commits


@@ -2612,44 +2671,309 @@ struct ConvertConstructorToDeductionGuideTransform {
 SemaRef.CurrentInstantiationScope->InstantiatedLocal(OldParam, NewParam);
 return NewParam;
   }
+};
 
-  FunctionTemplateDecl *buildDeductionGuide(
-  TemplateParameterList *TemplateParams, CXXConstructorDecl *Ctor,
-  ExplicitSpecifier ES, TypeSourceInfo *TInfo, SourceLocation LocStart,
-  SourceLocation Loc, SourceLocation LocEnd,
-  llvm::ArrayRef MaterializedTypedefs = {}) {
-DeclarationNameInfo Name(DeductionGuideName, Loc);
-ArrayRef Params =
-TInfo->getTypeLoc().castAs().getParams();
+// Find all template parameters of the AliasTemplate that appear in the
+// given DeducedArgs.
+SmallVector
+FindAppearedTemplateParamsInAlias(ArrayRef DeducedArgs,

hokein wrote:

I'm leaning towards `Appeared` to align with the C++ standard. It basically 
does "_whose template parameter list consists of all the template parameters of 
A (including their default template arguments) that appear in the above 
deductions_"

https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-02-23 Thread Haojian Wu via cfe-commits


@@ -2612,44 +2671,309 @@ struct ConvertConstructorToDeductionGuideTransform {
 SemaRef.CurrentInstantiationScope->InstantiatedLocal(OldParam, NewParam);
 return NewParam;
   }
+};
 
-  FunctionTemplateDecl *buildDeductionGuide(
-  TemplateParameterList *TemplateParams, CXXConstructorDecl *Ctor,
-  ExplicitSpecifier ES, TypeSourceInfo *TInfo, SourceLocation LocStart,
-  SourceLocation Loc, SourceLocation LocEnd,
-  llvm::ArrayRef MaterializedTypedefs = {}) {
-DeclarationNameInfo Name(DeductionGuideName, Loc);
-ArrayRef Params =
-TInfo->getTypeLoc().castAs().getParams();
+// Find all template parameters of the AliasTemplate that appear in the
+// given DeducedArgs.
+SmallVector
+FindAppearedTemplateParamsInAlias(ArrayRef DeducedArgs,
+  TypeAliasTemplateDecl *AliasTemplate) {
+  struct FindAppearedTemplateParams
+  : public RecursiveASTVisitor {
+llvm::DenseSet TemplateParamsInAlias;
+llvm::DenseSet AppearedTemplateParams;
+
+FindAppearedTemplateParams(ArrayRef TemplateParamsInAlias)
+: TemplateParamsInAlias(TemplateParamsInAlias.begin(),
+TemplateParamsInAlias.end()) {}
+
+bool VisitTemplateTypeParmType(TemplateTypeParmType *TTP) {
+  TTP->getIndex();
+  MarkAppeared(TTP->getDecl());
+  return true;
+}
+bool VisitDeclRefExpr(DeclRefExpr *DRE) {
+  MarkAppeared(DRE->getFoundDecl());
+  return true;
+}
 
-// Build the implicit deduction guide template.
-auto *Guide =
-CXXDeductionGuideDecl::Create(SemaRef.Context, DC, LocStart, ES, Name,
-  TInfo->getType(), TInfo, LocEnd, Ctor);
-Guide->setImplicit();
-Guide->setParams(Params);
+void MarkAppeared(NamedDecl *ND) {
+  if (TemplateParamsInAlias.contains(ND))
+AppearedTemplateParams.insert(ND);
+}
+  };
+  ArrayRef TemplateParamsInAlias =
+  AliasTemplate->getTemplateParameters()->asArray();
+  FindAppearedTemplateParams MarkAppeared(TemplateParamsInAlias);
+  MarkAppeared.TraverseTemplateArguments(DeducedArgs);
 
-for (auto *Param : Params)
-  Param->setDeclContext(Guide);
-for (auto *TD : MaterializedTypedefs)
-  TD->setDeclContext(Guide);
+  SmallVector Results;
+  for (unsigned Index = 0; Index < TemplateParamsInAlias.size(); ++Index) {
+if (MarkAppeared.AppearedTemplateParams.contains(
+TemplateParamsInAlias[Index]))
+  Results.push_back(Index);
+  }
+  return Results;
+}
 
-auto *GuideTemplate = FunctionTemplateDecl::Create(
-SemaRef.Context, DC, Loc, DeductionGuideName, TemplateParams, Guide);
-GuideTemplate->setImplicit();
-Guide->setDescribedFunctionTemplate(GuideTemplate);
+bool hasDeclaredDeductionGuides(DeclarationName Name, DeclContext* DC) {
+  // Check whether we've already declared deduction guides for this template.
+  // FIXME: Consider storing a flag on the template to indicate this.
+  auto Existing = DC->lookup(Name);
+  for (auto *D : Existing)
+if (D->isImplicit())
+  return true;
+  return false;
+}
 
-if (isa(DC)) {
-  Guide->setAccess(AS_public);
-  GuideTemplate->setAccess(AS_public);
+// Build deduction guides for a type alias template.
+void DeclareImplicitDeductionGuidesForTypeAlias(
+Sema , TypeAliasTemplateDecl *AliasTemplate, SourceLocation Loc) {
+  auto  = SemaRef.Context;
+  // FIXME: if there is an explicit deduction guide after the first use of the
+  // type alias usage, we will not cover this explicit deduction guide. fix 
this
+  // case.
+  if (hasDeclaredDeductionGuides(
+  Context.DeclarationNames.getCXXDeductionGuideName(AliasTemplate),
+  AliasTemplate->getDeclContext()))
+return;
+  // Unrap the sugar ElaboratedType.
+  auto RhsType = AliasTemplate->getTemplatedDecl()
+ ->getUnderlyingType()
+ .getSingleStepDesugaredType(Context);
+  TemplateDecl *Template = nullptr;
+  llvm::ArrayRef AliasRhsTemplateArgs;
+  if (const auto *TST = RhsType->getAs()) {
+// TemplateName in TEST can be a TypeAliasTemplateDecl if
+// the right hand side of the alias is also a type alias, e.g.
+//
+// template
+// using AliasFoo1 = Foo;  // Foo is a class template
+// specialization
+//
+// template
+// using AliasFoo2 = AliasFoo1; // AliasFoo1 is a type alias
+Template = TST->getTemplateName().getAsTemplateDecl();
+AliasRhsTemplateArgs = TST->template_arguments();
+  } else if (const auto *RT = RhsType->getAs()) {
+// Cases where template arguments in the RHS of the alias are not
+// dependent. e.g.
+//   using AliasFoo = Foo;
+if (const auto *CTSD = llvm::dyn_cast(
+RT->getAsCXXRecordDecl())) {
+  Template = CTSD->getSpecializedTemplate();
+  AliasRhsTemplateArgs = CTSD->getTemplateArgs().asArray();
+}
+  }
+  if (!Template)
+return;
+  

[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-02-23 Thread Haojian Wu via cfe-commits


@@ -2612,44 +2671,309 @@ struct ConvertConstructorToDeductionGuideTransform {
 SemaRef.CurrentInstantiationScope->InstantiatedLocal(OldParam, NewParam);
 return NewParam;
   }
+};
 
-  FunctionTemplateDecl *buildDeductionGuide(
-  TemplateParameterList *TemplateParams, CXXConstructorDecl *Ctor,
-  ExplicitSpecifier ES, TypeSourceInfo *TInfo, SourceLocation LocStart,
-  SourceLocation Loc, SourceLocation LocEnd,
-  llvm::ArrayRef MaterializedTypedefs = {}) {
-DeclarationNameInfo Name(DeductionGuideName, Loc);
-ArrayRef Params =
-TInfo->getTypeLoc().castAs().getParams();
+// Find all template parameters of the AliasTemplate that appear in the
+// given DeducedArgs.
+SmallVector
+FindAppearedTemplateParamsInAlias(ArrayRef DeducedArgs,
+  TypeAliasTemplateDecl *AliasTemplate) {
+  struct FindAppearedTemplateParams
+  : public RecursiveASTVisitor {
+llvm::DenseSet TemplateParamsInAlias;
+llvm::DenseSet AppearedTemplateParams;
+
+FindAppearedTemplateParams(ArrayRef TemplateParamsInAlias)
+: TemplateParamsInAlias(TemplateParamsInAlias.begin(),
+TemplateParamsInAlias.end()) {}
+
+bool VisitTemplateTypeParmType(TemplateTypeParmType *TTP) {
+  TTP->getIndex();
+  MarkAppeared(TTP->getDecl());
+  return true;
+}
+bool VisitDeclRefExpr(DeclRefExpr *DRE) {
+  MarkAppeared(DRE->getFoundDecl());
+  return true;
+}
 
-// Build the implicit deduction guide template.
-auto *Guide =
-CXXDeductionGuideDecl::Create(SemaRef.Context, DC, LocStart, ES, Name,
-  TInfo->getType(), TInfo, LocEnd, Ctor);
-Guide->setImplicit();
-Guide->setParams(Params);
+void MarkAppeared(NamedDecl *ND) {
+  if (TemplateParamsInAlias.contains(ND))
+AppearedTemplateParams.insert(ND);
+}
+  };
+  ArrayRef TemplateParamsInAlias =
+  AliasTemplate->getTemplateParameters()->asArray();
+  FindAppearedTemplateParams MarkAppeared(TemplateParamsInAlias);
+  MarkAppeared.TraverseTemplateArguments(DeducedArgs);
 
-for (auto *Param : Params)
-  Param->setDeclContext(Guide);
-for (auto *TD : MaterializedTypedefs)
-  TD->setDeclContext(Guide);
+  SmallVector Results;
+  for (unsigned Index = 0; Index < TemplateParamsInAlias.size(); ++Index) {
+if (MarkAppeared.AppearedTemplateParams.contains(
+TemplateParamsInAlias[Index]))
+  Results.push_back(Index);
+  }
+  return Results;
+}
 
-auto *GuideTemplate = FunctionTemplateDecl::Create(
-SemaRef.Context, DC, Loc, DeductionGuideName, TemplateParams, Guide);
-GuideTemplate->setImplicit();
-Guide->setDescribedFunctionTemplate(GuideTemplate);
+bool hasDeclaredDeductionGuides(DeclarationName Name, DeclContext* DC) {
+  // Check whether we've already declared deduction guides for this template.
+  // FIXME: Consider storing a flag on the template to indicate this.
+  auto Existing = DC->lookup(Name);
+  for (auto *D : Existing)
+if (D->isImplicit())
+  return true;

hokein wrote:

Done.

https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-02-23 Thread Haojian Wu via cfe-commits


@@ -2612,44 +2671,309 @@ struct ConvertConstructorToDeductionGuideTransform {
 SemaRef.CurrentInstantiationScope->InstantiatedLocal(OldParam, NewParam);
 return NewParam;
   }
+};
 
-  FunctionTemplateDecl *buildDeductionGuide(
-  TemplateParameterList *TemplateParams, CXXConstructorDecl *Ctor,
-  ExplicitSpecifier ES, TypeSourceInfo *TInfo, SourceLocation LocStart,
-  SourceLocation Loc, SourceLocation LocEnd,
-  llvm::ArrayRef MaterializedTypedefs = {}) {
-DeclarationNameInfo Name(DeductionGuideName, Loc);
-ArrayRef Params =
-TInfo->getTypeLoc().castAs().getParams();
+// Find all template parameters of the AliasTemplate that appear in the
+// given DeducedArgs.
+SmallVector
+FindAppearedTemplateParamsInAlias(ArrayRef DeducedArgs,
+  TypeAliasTemplateDecl *AliasTemplate) {
+  struct FindAppearedTemplateParams
+  : public RecursiveASTVisitor {
+llvm::DenseSet TemplateParamsInAlias;
+llvm::DenseSet AppearedTemplateParams;
+
+FindAppearedTemplateParams(ArrayRef TemplateParamsInAlias)
+: TemplateParamsInAlias(TemplateParamsInAlias.begin(),
+TemplateParamsInAlias.end()) {}
+
+bool VisitTemplateTypeParmType(TemplateTypeParmType *TTP) {
+  TTP->getIndex();
+  MarkAppeared(TTP->getDecl());
+  return true;
+}
+bool VisitDeclRefExpr(DeclRefExpr *DRE) {
+  MarkAppeared(DRE->getFoundDecl());
+  return true;
+}
 
-// Build the implicit deduction guide template.
-auto *Guide =
-CXXDeductionGuideDecl::Create(SemaRef.Context, DC, LocStart, ES, Name,
-  TInfo->getType(), TInfo, LocEnd, Ctor);
-Guide->setImplicit();
-Guide->setParams(Params);
+void MarkAppeared(NamedDecl *ND) {
+  if (TemplateParamsInAlias.contains(ND))
+AppearedTemplateParams.insert(ND);
+}
+  };
+  ArrayRef TemplateParamsInAlias =
+  AliasTemplate->getTemplateParameters()->asArray();
+  FindAppearedTemplateParams MarkAppeared(TemplateParamsInAlias);
+  MarkAppeared.TraverseTemplateArguments(DeducedArgs);
 
-for (auto *Param : Params)
-  Param->setDeclContext(Guide);
-for (auto *TD : MaterializedTypedefs)
-  TD->setDeclContext(Guide);
+  SmallVector Results;
+  for (unsigned Index = 0; Index < TemplateParamsInAlias.size(); ++Index) {
+if (MarkAppeared.AppearedTemplateParams.contains(
+TemplateParamsInAlias[Index]))
+  Results.push_back(Index);
+  }
+  return Results;
+}
 
-auto *GuideTemplate = FunctionTemplateDecl::Create(
-SemaRef.Context, DC, Loc, DeductionGuideName, TemplateParams, Guide);
-GuideTemplate->setImplicit();
-Guide->setDescribedFunctionTemplate(GuideTemplate);
+bool hasDeclaredDeductionGuides(DeclarationName Name, DeclContext* DC) {
+  // Check whether we've already declared deduction guides for this template.
+  // FIXME: Consider storing a flag on the template to indicate this.
+  auto Existing = DC->lookup(Name);
+  for (auto *D : Existing)
+if (D->isImplicit())
+  return true;
+  return false;
+}
 
-if (isa(DC)) {
-  Guide->setAccess(AS_public);
-  GuideTemplate->setAccess(AS_public);
+// Build deduction guides for a type alias template.
+void DeclareImplicitDeductionGuidesForTypeAlias(
+Sema , TypeAliasTemplateDecl *AliasTemplate, SourceLocation Loc) {
+  auto  = SemaRef.Context;
+  // FIXME: if there is an explicit deduction guide after the first use of the
+  // type alias usage, we will not cover this explicit deduction guide. fix 
this
+  // case.
+  if (hasDeclaredDeductionGuides(
+  Context.DeclarationNames.getCXXDeductionGuideName(AliasTemplate),
+  AliasTemplate->getDeclContext()))
+return;
+  // Unrap the sugar ElaboratedType.
+  auto RhsType = AliasTemplate->getTemplatedDecl()
+ ->getUnderlyingType()
+ .getSingleStepDesugaredType(Context);
+  TemplateDecl *Template = nullptr;
+  llvm::ArrayRef AliasRhsTemplateArgs;
+  if (const auto *TST = RhsType->getAs()) {
+// TemplateName in TEST can be a TypeAliasTemplateDecl if

hokein wrote:

Done.

https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-02-23 Thread Haojian Wu via cfe-commits


@@ -2612,44 +2671,309 @@ struct ConvertConstructorToDeductionGuideTransform {
 SemaRef.CurrentInstantiationScope->InstantiatedLocal(OldParam, NewParam);
 return NewParam;
   }
+};
 
-  FunctionTemplateDecl *buildDeductionGuide(
-  TemplateParameterList *TemplateParams, CXXConstructorDecl *Ctor,
-  ExplicitSpecifier ES, TypeSourceInfo *TInfo, SourceLocation LocStart,
-  SourceLocation Loc, SourceLocation LocEnd,
-  llvm::ArrayRef MaterializedTypedefs = {}) {
-DeclarationNameInfo Name(DeductionGuideName, Loc);
-ArrayRef Params =
-TInfo->getTypeLoc().castAs().getParams();
+// Find all template parameters of the AliasTemplate that appear in the
+// given DeducedArgs.
+SmallVector
+FindAppearedTemplateParamsInAlias(ArrayRef DeducedArgs,
+  TypeAliasTemplateDecl *AliasTemplate) {
+  struct FindAppearedTemplateParams
+  : public RecursiveASTVisitor {
+llvm::DenseSet TemplateParamsInAlias;
+llvm::DenseSet AppearedTemplateParams;
+
+FindAppearedTemplateParams(ArrayRef TemplateParamsInAlias)
+: TemplateParamsInAlias(TemplateParamsInAlias.begin(),
+TemplateParamsInAlias.end()) {}
+
+bool VisitTemplateTypeParmType(TemplateTypeParmType *TTP) {
+  TTP->getIndex();
+  MarkAppeared(TTP->getDecl());
+  return true;
+}
+bool VisitDeclRefExpr(DeclRefExpr *DRE) {
+  MarkAppeared(DRE->getFoundDecl());
+  return true;
+}
 
-// Build the implicit deduction guide template.
-auto *Guide =
-CXXDeductionGuideDecl::Create(SemaRef.Context, DC, LocStart, ES, Name,
-  TInfo->getType(), TInfo, LocEnd, Ctor);
-Guide->setImplicit();
-Guide->setParams(Params);
+void MarkAppeared(NamedDecl *ND) {
+  if (TemplateParamsInAlias.contains(ND))
+AppearedTemplateParams.insert(ND);
+}
+  };
+  ArrayRef TemplateParamsInAlias =
+  AliasTemplate->getTemplateParameters()->asArray();
+  FindAppearedTemplateParams MarkAppeared(TemplateParamsInAlias);
+  MarkAppeared.TraverseTemplateArguments(DeducedArgs);
 
-for (auto *Param : Params)
-  Param->setDeclContext(Guide);
-for (auto *TD : MaterializedTypedefs)
-  TD->setDeclContext(Guide);
+  SmallVector Results;
+  for (unsigned Index = 0; Index < TemplateParamsInAlias.size(); ++Index) {
+if (MarkAppeared.AppearedTemplateParams.contains(
+TemplateParamsInAlias[Index]))
+  Results.push_back(Index);
+  }
+  return Results;
+}
 
-auto *GuideTemplate = FunctionTemplateDecl::Create(
-SemaRef.Context, DC, Loc, DeductionGuideName, TemplateParams, Guide);
-GuideTemplate->setImplicit();
-Guide->setDescribedFunctionTemplate(GuideTemplate);
+bool hasDeclaredDeductionGuides(DeclarationName Name, DeclContext* DC) {
+  // Check whether we've already declared deduction guides for this template.
+  // FIXME: Consider storing a flag on the template to indicate this.
+  auto Existing = DC->lookup(Name);
+  for (auto *D : Existing)
+if (D->isImplicit())
+  return true;
+  return false;
+}
 
-if (isa(DC)) {
-  Guide->setAccess(AS_public);
-  GuideTemplate->setAccess(AS_public);
+// Build deduction guides for a type alias template.
+void DeclareImplicitDeductionGuidesForTypeAlias(
+Sema , TypeAliasTemplateDecl *AliasTemplate, SourceLocation Loc) {
+  auto  = SemaRef.Context;
+  // FIXME: if there is an explicit deduction guide after the first use of the
+  // type alias usage, we will not cover this explicit deduction guide. fix 
this
+  // case.
+  if (hasDeclaredDeductionGuides(
+  Context.DeclarationNames.getCXXDeductionGuideName(AliasTemplate),
+  AliasTemplate->getDeclContext()))
+return;
+  // Unrap the sugar ElaboratedType.

hokein wrote:

Done.

https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-02-23 Thread Haojian Wu via cfe-commits


@@ -10598,10 +10598,34 @@ QualType 
Sema::DeduceTemplateSpecializationFromInitializer(
   if (TemplateName.isDependent())
 return SubstAutoTypeDependent(TSInfo->getType());
 
-  // We can only perform deduction for class templates.
+  // We can only perform deduction for class templates or alias templates.
   auto *Template =
   dyn_cast_or_null(TemplateName.getAsTemplateDecl());
+  TemplateDecl* LookupTemplateDecl = Template;
+  if (!Template && getLangOpts().CPlusPlus20) { // type alias template
+if (auto *AliasTemplate = dyn_cast_or_null(
+TemplateName.getAsTemplateDecl());
+AliasTemplate) {
+  LookupTemplateDecl = AliasTemplate;
+  auto UnderlyingType = AliasTemplate->getTemplatedDecl()
+->getUnderlyingType()
+.getDesugaredType(Context);
+  if (const auto *TST =
+  UnderlyingType->getAs()) {
+Template = dyn_cast_or_null(
+TST->getTemplateName().getAsTemplateDecl());
+  } else if (const auto *RT = UnderlyingType->getAs()) {
+// Cases where template arguments in the RHS of the alias are not
+// dependent. e.g.
+//   using AliasFoo = Foo;
+if (const auto *CTSD = llvm::dyn_cast(
+RT->getAsCXXRecordDecl()))
+  Template = CTSD->getSpecializedTemplate();
+  }

hokein wrote:

added one.

https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-02-23 Thread Haojian Wu via cfe-commits


@@ -2258,6 +2260,94 @@ class ExtractTypeForDeductionGuide
   }
 };
 
+// Build a deduction guide with the specified parameter types.
+FunctionTemplateDecl *
+buildDeductionGuide(Sema , TemplateDecl *OriginalTemplate,
+TemplateParameterList *TemplateParams,
+CXXConstructorDecl *Ctor, ExplicitSpecifier ES,
+TypeSourceInfo *TInfo, SourceLocation LocStart,
+SourceLocation Loc, SourceLocation LocEnd, bool IsImplicit,
+llvm::ArrayRef MaterializedTypedefs = 
{}) {

hokein wrote:

For a function declaration, e.g. `void func();`, `Loc` points to the `func` 
token, `LocStart ` points to the `void` token, `LocEnd` points to `)`.

https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-02-23 Thread Haojian Wu via cfe-commits


@@ -2612,44 +2671,309 @@ struct ConvertConstructorToDeductionGuideTransform {
 SemaRef.CurrentInstantiationScope->InstantiatedLocal(OldParam, NewParam);
 return NewParam;
   }
+};
 
-  FunctionTemplateDecl *buildDeductionGuide(
-  TemplateParameterList *TemplateParams, CXXConstructorDecl *Ctor,
-  ExplicitSpecifier ES, TypeSourceInfo *TInfo, SourceLocation LocStart,
-  SourceLocation Loc, SourceLocation LocEnd,
-  llvm::ArrayRef MaterializedTypedefs = {}) {
-DeclarationNameInfo Name(DeductionGuideName, Loc);
-ArrayRef Params =
-TInfo->getTypeLoc().castAs().getParams();
+// Find all template parameters of the AliasTemplate that appear in the
+// given DeducedArgs.
+SmallVector
+FindAppearedTemplateParamsInAlias(ArrayRef DeducedArgs,
+  TypeAliasTemplateDecl *AliasTemplate) {
+  struct FindAppearedTemplateParams
+  : public RecursiveASTVisitor {
+llvm::DenseSet TemplateParamsInAlias;
+llvm::DenseSet AppearedTemplateParams;
+
+FindAppearedTemplateParams(ArrayRef TemplateParamsInAlias)
+: TemplateParamsInAlias(TemplateParamsInAlias.begin(),
+TemplateParamsInAlias.end()) {}
+
+bool VisitTemplateTypeParmType(TemplateTypeParmType *TTP) {
+  TTP->getIndex();
+  MarkAppeared(TTP->getDecl());
+  return true;
+}
+bool VisitDeclRefExpr(DeclRefExpr *DRE) {
+  MarkAppeared(DRE->getFoundDecl());
+  return true;
+}
 
-// Build the implicit deduction guide template.
-auto *Guide =
-CXXDeductionGuideDecl::Create(SemaRef.Context, DC, LocStart, ES, Name,
-  TInfo->getType(), TInfo, LocEnd, Ctor);
-Guide->setImplicit();
-Guide->setParams(Params);
+void MarkAppeared(NamedDecl *ND) {
+  if (TemplateParamsInAlias.contains(ND))
+AppearedTemplateParams.insert(ND);
+}
+  };
+  ArrayRef TemplateParamsInAlias =
+  AliasTemplate->getTemplateParameters()->asArray();
+  FindAppearedTemplateParams MarkAppeared(TemplateParamsInAlias);
+  MarkAppeared.TraverseTemplateArguments(DeducedArgs);
 
-for (auto *Param : Params)
-  Param->setDeclContext(Guide);
-for (auto *TD : MaterializedTypedefs)
-  TD->setDeclContext(Guide);
+  SmallVector Results;
+  for (unsigned Index = 0; Index < TemplateParamsInAlias.size(); ++Index) {
+if (MarkAppeared.AppearedTemplateParams.contains(
+TemplateParamsInAlias[Index]))
+  Results.push_back(Index);
+  }
+  return Results;
+}
 
-auto *GuideTemplate = FunctionTemplateDecl::Create(
-SemaRef.Context, DC, Loc, DeductionGuideName, TemplateParams, Guide);
-GuideTemplate->setImplicit();
-Guide->setDescribedFunctionTemplate(GuideTemplate);
+bool hasDeclaredDeductionGuides(DeclarationName Name, DeclContext* DC) {
+  // Check whether we've already declared deduction guides for this template.
+  // FIXME: Consider storing a flag on the template to indicate this.
+  auto Existing = DC->lookup(Name);
+  for (auto *D : Existing)
+if (D->isImplicit())
+  return true;
+  return false;
+}
 
-if (isa(DC)) {
-  Guide->setAccess(AS_public);
-  GuideTemplate->setAccess(AS_public);
+// Build deduction guides for a type alias template.
+void DeclareImplicitDeductionGuidesForTypeAlias(
+Sema , TypeAliasTemplateDecl *AliasTemplate, SourceLocation Loc) {
+  auto  = SemaRef.Context;
+  // FIXME: if there is an explicit deduction guide after the first use of the
+  // type alias usage, we will not cover this explicit deduction guide. fix 
this
+  // case.
+  if (hasDeclaredDeductionGuides(
+  Context.DeclarationNames.getCXXDeductionGuideName(AliasTemplate),
+  AliasTemplate->getDeclContext()))
+return;
+  // Unrap the sugar ElaboratedType.
+  auto RhsType = AliasTemplate->getTemplatedDecl()
+ ->getUnderlyingType()
+ .getSingleStepDesugaredType(Context);
+  TemplateDecl *Template = nullptr;
+  llvm::ArrayRef AliasRhsTemplateArgs;
+  if (const auto *TST = RhsType->getAs()) {
+// TemplateName in TEST can be a TypeAliasTemplateDecl if
+// the right hand side of the alias is also a type alias, e.g.
+//
+// template
+// using AliasFoo1 = Foo;  // Foo is a class template
+// specialization
+//
+// template
+// using AliasFoo2 = AliasFoo1; // AliasFoo1 is a type alias
+Template = TST->getTemplateName().getAsTemplateDecl();
+AliasRhsTemplateArgs = TST->template_arguments();
+  } else if (const auto *RT = RhsType->getAs()) {
+// Cases where template arguments in the RHS of the alias are not
+// dependent. e.g.
+//   using AliasFoo = Foo;
+if (const auto *CTSD = llvm::dyn_cast(
+RT->getAsCXXRecordDecl())) {
+  Template = CTSD->getSpecializedTemplate();
+  AliasRhsTemplateArgs = CTSD->getTemplateArgs().asArray();
+}

hokein wrote:

It covers all cases I 

[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-02-23 Thread Haojian Wu via cfe-commits


@@ -1446,6 +1447,58 @@ namespace {
   return inherited::TransformFunctionProtoType(TLB, TL);
 }
 
+QualType TransformInjectedClassNameType(TypeLocBuilder ,
+InjectedClassNameTypeLoc TL) {
+  auto Type = inherited::TransformInjectedClassNameType(TLB, TL);
+  // Special case for transforming a deduction guide, we return a
+  // transformed TemplateSpecializationType.
+  if (Type.isNull() &&
+  SemaRef.CodeSynthesisContexts.back().Kind ==
+  Sema::CodeSynthesisContext::BuildingDeductionGuides) {
+// Return a TemplateSpecializationType for transforming a deduction
+// guide.
+if (auto *ICT = TL.getType()->getAs()) {
+  auto Type = 
+  inherited::TransformType(ICT->getInjectedSpecializationType());
+  TLB.pushTrivial(SemaRef.Context, Type, TL.getNameLoc());
+  return Type;
+}
+  }
+  return Type;
+}
+// Override the default version to handle a rewrite-template-arg-pack case
+// for building a deduction guide.
+bool TransformTemplateArgument(const TemplateArgumentLoc ,
+   TemplateArgumentLoc ,
+   bool Uneval = false) {
+  const TemplateArgument  = Input.getArgument();
+  std::vector TArgs;
+  switch (Arg.getKind()) {
+  case TemplateArgument::Pack:
+// Iterially rewrite the template argument pack, instead of unpacking
+// it.
+assert(
+SemaRef.CodeSynthesisContexts.back().Kind ==
+Sema::CodeSynthesisContext::BuildingDeductionGuides &&
+"Transforming a template argument pack is only allowed in building 
"
+"deduction guide");
+for (auto  : Arg.getPackAsArray()) {
+  TemplateArgumentLoc Input = SemaRef.getTrivialTemplateArgumentLoc(
+  pack, QualType(), SourceLocation{});
+  TemplateArgumentLoc Output;
+  if (!SemaRef.SubstTemplateArgument(Input, TemplateArgs, Output))
+TArgs.push_back(Output.getArgument());

hokein wrote:

Good catch. Added the bailout.

https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-02-23 Thread Haojian Wu via cfe-commits

https://github.com/hokein edited https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-02-20 Thread via cfe-commits


@@ -2612,44 +2671,309 @@ struct ConvertConstructorToDeductionGuideTransform {
 SemaRef.CurrentInstantiationScope->InstantiatedLocal(OldParam, NewParam);
 return NewParam;
   }
+};
 
-  FunctionTemplateDecl *buildDeductionGuide(
-  TemplateParameterList *TemplateParams, CXXConstructorDecl *Ctor,
-  ExplicitSpecifier ES, TypeSourceInfo *TInfo, SourceLocation LocStart,
-  SourceLocation Loc, SourceLocation LocEnd,
-  llvm::ArrayRef MaterializedTypedefs = {}) {
-DeclarationNameInfo Name(DeductionGuideName, Loc);
-ArrayRef Params =
-TInfo->getTypeLoc().castAs().getParams();
+// Find all template parameters of the AliasTemplate that appear in the
+// given DeducedArgs.
+SmallVector
+FindAppearedTemplateParamsInAlias(ArrayRef DeducedArgs,
+  TypeAliasTemplateDecl *AliasTemplate) {
+  struct FindAppearedTemplateParams
+  : public RecursiveASTVisitor {
+llvm::DenseSet TemplateParamsInAlias;
+llvm::DenseSet AppearedTemplateParams;
+
+FindAppearedTemplateParams(ArrayRef TemplateParamsInAlias)
+: TemplateParamsInAlias(TemplateParamsInAlias.begin(),
+TemplateParamsInAlias.end()) {}
+
+bool VisitTemplateTypeParmType(TemplateTypeParmType *TTP) {
+  TTP->getIndex();
+  MarkAppeared(TTP->getDecl());
+  return true;
+}
+bool VisitDeclRefExpr(DeclRefExpr *DRE) {
+  MarkAppeared(DRE->getFoundDecl());
+  return true;
+}
 
-// Build the implicit deduction guide template.
-auto *Guide =
-CXXDeductionGuideDecl::Create(SemaRef.Context, DC, LocStart, ES, Name,
-  TInfo->getType(), TInfo, LocEnd, Ctor);
-Guide->setImplicit();
-Guide->setParams(Params);
+void MarkAppeared(NamedDecl *ND) {
+  if (TemplateParamsInAlias.contains(ND))
+AppearedTemplateParams.insert(ND);
+}
+  };
+  ArrayRef TemplateParamsInAlias =
+  AliasTemplate->getTemplateParameters()->asArray();
+  FindAppearedTemplateParams MarkAppeared(TemplateParamsInAlias);
+  MarkAppeared.TraverseTemplateArguments(DeducedArgs);
 
-for (auto *Param : Params)
-  Param->setDeclContext(Guide);
-for (auto *TD : MaterializedTypedefs)
-  TD->setDeclContext(Guide);
+  SmallVector Results;
+  for (unsigned Index = 0; Index < TemplateParamsInAlias.size(); ++Index) {
+if (MarkAppeared.AppearedTemplateParams.contains(
+TemplateParamsInAlias[Index]))
+  Results.push_back(Index);
+  }
+  return Results;
+}
 
-auto *GuideTemplate = FunctionTemplateDecl::Create(
-SemaRef.Context, DC, Loc, DeductionGuideName, TemplateParams, Guide);
-GuideTemplate->setImplicit();
-Guide->setDescribedFunctionTemplate(GuideTemplate);
+bool hasDeclaredDeductionGuides(DeclarationName Name, DeclContext* DC) {
+  // Check whether we've already declared deduction guides for this template.
+  // FIXME: Consider storing a flag on the template to indicate this.
+  auto Existing = DC->lookup(Name);
+  for (auto *D : Existing)
+if (D->isImplicit())
+  return true;
+  return false;
+}
 
-if (isa(DC)) {
-  Guide->setAccess(AS_public);
-  GuideTemplate->setAccess(AS_public);
+// Build deduction guides for a type alias template.
+void DeclareImplicitDeductionGuidesForTypeAlias(
+Sema , TypeAliasTemplateDecl *AliasTemplate, SourceLocation Loc) {
+  auto  = SemaRef.Context;
+  // FIXME: if there is an explicit deduction guide after the first use of the
+  // type alias usage, we will not cover this explicit deduction guide. fix 
this
+  // case.
+  if (hasDeclaredDeductionGuides(
+  Context.DeclarationNames.getCXXDeductionGuideName(AliasTemplate),
+  AliasTemplate->getDeclContext()))
+return;
+  // Unrap the sugar ElaboratedType.
+  auto RhsType = AliasTemplate->getTemplatedDecl()
+ ->getUnderlyingType()
+ .getSingleStepDesugaredType(Context);
+  TemplateDecl *Template = nullptr;
+  llvm::ArrayRef AliasRhsTemplateArgs;
+  if (const auto *TST = RhsType->getAs()) {
+// TemplateName in TEST can be a TypeAliasTemplateDecl if

cor3ntin wrote:

```suggestion
// TemplateName in TST can be a TypeAliasTemplateDecl if
```

https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-02-20 Thread via cfe-commits

https://github.com/cor3ntin edited 
https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-02-20 Thread via cfe-commits


@@ -2612,44 +2671,309 @@ struct ConvertConstructorToDeductionGuideTransform {
 SemaRef.CurrentInstantiationScope->InstantiatedLocal(OldParam, NewParam);
 return NewParam;
   }
+};
 
-  FunctionTemplateDecl *buildDeductionGuide(
-  TemplateParameterList *TemplateParams, CXXConstructorDecl *Ctor,
-  ExplicitSpecifier ES, TypeSourceInfo *TInfo, SourceLocation LocStart,
-  SourceLocation Loc, SourceLocation LocEnd,
-  llvm::ArrayRef MaterializedTypedefs = {}) {
-DeclarationNameInfo Name(DeductionGuideName, Loc);
-ArrayRef Params =
-TInfo->getTypeLoc().castAs().getParams();
+// Find all template parameters of the AliasTemplate that appear in the
+// given DeducedArgs.
+SmallVector
+FindAppearedTemplateParamsInAlias(ArrayRef DeducedArgs,
+  TypeAliasTemplateDecl *AliasTemplate) {
+  struct FindAppearedTemplateParams
+  : public RecursiveASTVisitor {
+llvm::DenseSet TemplateParamsInAlias;
+llvm::DenseSet AppearedTemplateParams;
+
+FindAppearedTemplateParams(ArrayRef TemplateParamsInAlias)
+: TemplateParamsInAlias(TemplateParamsInAlias.begin(),
+TemplateParamsInAlias.end()) {}
+
+bool VisitTemplateTypeParmType(TemplateTypeParmType *TTP) {
+  TTP->getIndex();
+  MarkAppeared(TTP->getDecl());
+  return true;
+}
+bool VisitDeclRefExpr(DeclRefExpr *DRE) {
+  MarkAppeared(DRE->getFoundDecl());
+  return true;
+}
 
-// Build the implicit deduction guide template.
-auto *Guide =
-CXXDeductionGuideDecl::Create(SemaRef.Context, DC, LocStart, ES, Name,
-  TInfo->getType(), TInfo, LocEnd, Ctor);
-Guide->setImplicit();
-Guide->setParams(Params);
+void MarkAppeared(NamedDecl *ND) {
+  if (TemplateParamsInAlias.contains(ND))
+AppearedTemplateParams.insert(ND);
+}
+  };
+  ArrayRef TemplateParamsInAlias =
+  AliasTemplate->getTemplateParameters()->asArray();
+  FindAppearedTemplateParams MarkAppeared(TemplateParamsInAlias);
+  MarkAppeared.TraverseTemplateArguments(DeducedArgs);
 
-for (auto *Param : Params)
-  Param->setDeclContext(Guide);
-for (auto *TD : MaterializedTypedefs)
-  TD->setDeclContext(Guide);
+  SmallVector Results;
+  for (unsigned Index = 0; Index < TemplateParamsInAlias.size(); ++Index) {
+if (MarkAppeared.AppearedTemplateParams.contains(
+TemplateParamsInAlias[Index]))
+  Results.push_back(Index);
+  }
+  return Results;
+}
 
-auto *GuideTemplate = FunctionTemplateDecl::Create(
-SemaRef.Context, DC, Loc, DeductionGuideName, TemplateParams, Guide);
-GuideTemplate->setImplicit();
-Guide->setDescribedFunctionTemplate(GuideTemplate);
+bool hasDeclaredDeductionGuides(DeclarationName Name, DeclContext* DC) {
+  // Check whether we've already declared deduction guides for this template.
+  // FIXME: Consider storing a flag on the template to indicate this.
+  auto Existing = DC->lookup(Name);
+  for (auto *D : Existing)
+if (D->isImplicit())
+  return true;
+  return false;
+}
 
-if (isa(DC)) {
-  Guide->setAccess(AS_public);
-  GuideTemplate->setAccess(AS_public);
+// Build deduction guides for a type alias template.
+void DeclareImplicitDeductionGuidesForTypeAlias(
+Sema , TypeAliasTemplateDecl *AliasTemplate, SourceLocation Loc) {
+  auto  = SemaRef.Context;
+  // FIXME: if there is an explicit deduction guide after the first use of the
+  // type alias usage, we will not cover this explicit deduction guide. fix 
this
+  // case.
+  if (hasDeclaredDeductionGuides(
+  Context.DeclarationNames.getCXXDeductionGuideName(AliasTemplate),
+  AliasTemplate->getDeclContext()))
+return;
+  // Unrap the sugar ElaboratedType.
+  auto RhsType = AliasTemplate->getTemplatedDecl()
+ ->getUnderlyingType()
+ .getSingleStepDesugaredType(Context);
+  TemplateDecl *Template = nullptr;
+  llvm::ArrayRef AliasRhsTemplateArgs;
+  if (const auto *TST = RhsType->getAs()) {
+// TemplateName in TEST can be a TypeAliasTemplateDecl if
+// the right hand side of the alias is also a type alias, e.g.
+//
+// template
+// using AliasFoo1 = Foo;  // Foo is a class template
+// specialization
+//
+// template
+// using AliasFoo2 = AliasFoo1; // AliasFoo1 is a type alias
+Template = TST->getTemplateName().getAsTemplateDecl();
+AliasRhsTemplateArgs = TST->template_arguments();
+  } else if (const auto *RT = RhsType->getAs()) {
+// Cases where template arguments in the RHS of the alias are not
+// dependent. e.g.
+//   using AliasFoo = Foo;
+if (const auto *CTSD = llvm::dyn_cast(
+RT->getAsCXXRecordDecl())) {
+  Template = CTSD->getSpecializedTemplate();
+  AliasRhsTemplateArgs = CTSD->getTemplateArgs().asArray();
+}
+  }
+  if (!Template)
+return;
+  

[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-02-20 Thread via cfe-commits


@@ -2612,44 +2671,309 @@ struct ConvertConstructorToDeductionGuideTransform {
 SemaRef.CurrentInstantiationScope->InstantiatedLocal(OldParam, NewParam);
 return NewParam;
   }
+};
 
-  FunctionTemplateDecl *buildDeductionGuide(
-  TemplateParameterList *TemplateParams, CXXConstructorDecl *Ctor,
-  ExplicitSpecifier ES, TypeSourceInfo *TInfo, SourceLocation LocStart,
-  SourceLocation Loc, SourceLocation LocEnd,
-  llvm::ArrayRef MaterializedTypedefs = {}) {
-DeclarationNameInfo Name(DeductionGuideName, Loc);
-ArrayRef Params =
-TInfo->getTypeLoc().castAs().getParams();
+// Find all template parameters of the AliasTemplate that appear in the
+// given DeducedArgs.
+SmallVector
+FindAppearedTemplateParamsInAlias(ArrayRef DeducedArgs,
+  TypeAliasTemplateDecl *AliasTemplate) {
+  struct FindAppearedTemplateParams
+  : public RecursiveASTVisitor {
+llvm::DenseSet TemplateParamsInAlias;
+llvm::DenseSet AppearedTemplateParams;
+
+FindAppearedTemplateParams(ArrayRef TemplateParamsInAlias)
+: TemplateParamsInAlias(TemplateParamsInAlias.begin(),
+TemplateParamsInAlias.end()) {}
+
+bool VisitTemplateTypeParmType(TemplateTypeParmType *TTP) {
+  TTP->getIndex();
+  MarkAppeared(TTP->getDecl());
+  return true;
+}
+bool VisitDeclRefExpr(DeclRefExpr *DRE) {
+  MarkAppeared(DRE->getFoundDecl());
+  return true;
+}
 
-// Build the implicit deduction guide template.
-auto *Guide =
-CXXDeductionGuideDecl::Create(SemaRef.Context, DC, LocStart, ES, Name,
-  TInfo->getType(), TInfo, LocEnd, Ctor);
-Guide->setImplicit();
-Guide->setParams(Params);
+void MarkAppeared(NamedDecl *ND) {
+  if (TemplateParamsInAlias.contains(ND))
+AppearedTemplateParams.insert(ND);
+}
+  };
+  ArrayRef TemplateParamsInAlias =
+  AliasTemplate->getTemplateParameters()->asArray();
+  FindAppearedTemplateParams MarkAppeared(TemplateParamsInAlias);
+  MarkAppeared.TraverseTemplateArguments(DeducedArgs);
 
-for (auto *Param : Params)
-  Param->setDeclContext(Guide);
-for (auto *TD : MaterializedTypedefs)
-  TD->setDeclContext(Guide);
+  SmallVector Results;
+  for (unsigned Index = 0; Index < TemplateParamsInAlias.size(); ++Index) {
+if (MarkAppeared.AppearedTemplateParams.contains(
+TemplateParamsInAlias[Index]))
+  Results.push_back(Index);
+  }
+  return Results;
+}
 
-auto *GuideTemplate = FunctionTemplateDecl::Create(
-SemaRef.Context, DC, Loc, DeductionGuideName, TemplateParams, Guide);
-GuideTemplate->setImplicit();
-Guide->setDescribedFunctionTemplate(GuideTemplate);
+bool hasDeclaredDeductionGuides(DeclarationName Name, DeclContext* DC) {

cor3ntin wrote:

```suggestion
static bool hasDeclaredDeductionGuides(DeclarationName Name, DeclContext* DC) {
```

https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-02-20 Thread via cfe-commits


@@ -2612,44 +2671,309 @@ struct ConvertConstructorToDeductionGuideTransform {
 SemaRef.CurrentInstantiationScope->InstantiatedLocal(OldParam, NewParam);
 return NewParam;
   }
+};
 
-  FunctionTemplateDecl *buildDeductionGuide(
-  TemplateParameterList *TemplateParams, CXXConstructorDecl *Ctor,
-  ExplicitSpecifier ES, TypeSourceInfo *TInfo, SourceLocation LocStart,
-  SourceLocation Loc, SourceLocation LocEnd,
-  llvm::ArrayRef MaterializedTypedefs = {}) {
-DeclarationNameInfo Name(DeductionGuideName, Loc);
-ArrayRef Params =
-TInfo->getTypeLoc().castAs().getParams();
+// Find all template parameters of the AliasTemplate that appear in the
+// given DeducedArgs.
+SmallVector
+FindAppearedTemplateParamsInAlias(ArrayRef DeducedArgs,
+  TypeAliasTemplateDecl *AliasTemplate) {
+  struct FindAppearedTemplateParams
+  : public RecursiveASTVisitor {
+llvm::DenseSet TemplateParamsInAlias;
+llvm::DenseSet AppearedTemplateParams;
+
+FindAppearedTemplateParams(ArrayRef TemplateParamsInAlias)
+: TemplateParamsInAlias(TemplateParamsInAlias.begin(),
+TemplateParamsInAlias.end()) {}
+
+bool VisitTemplateTypeParmType(TemplateTypeParmType *TTP) {
+  TTP->getIndex();
+  MarkAppeared(TTP->getDecl());
+  return true;
+}
+bool VisitDeclRefExpr(DeclRefExpr *DRE) {
+  MarkAppeared(DRE->getFoundDecl());
+  return true;
+}
 
-// Build the implicit deduction guide template.
-auto *Guide =
-CXXDeductionGuideDecl::Create(SemaRef.Context, DC, LocStart, ES, Name,
-  TInfo->getType(), TInfo, LocEnd, Ctor);
-Guide->setImplicit();
-Guide->setParams(Params);
+void MarkAppeared(NamedDecl *ND) {
+  if (TemplateParamsInAlias.contains(ND))
+AppearedTemplateParams.insert(ND);
+}
+  };
+  ArrayRef TemplateParamsInAlias =
+  AliasTemplate->getTemplateParameters()->asArray();
+  FindAppearedTemplateParams MarkAppeared(TemplateParamsInAlias);
+  MarkAppeared.TraverseTemplateArguments(DeducedArgs);
 
-for (auto *Param : Params)
-  Param->setDeclContext(Guide);
-for (auto *TD : MaterializedTypedefs)
-  TD->setDeclContext(Guide);
+  SmallVector Results;
+  for (unsigned Index = 0; Index < TemplateParamsInAlias.size(); ++Index) {
+if (MarkAppeared.AppearedTemplateParams.contains(
+TemplateParamsInAlias[Index]))
+  Results.push_back(Index);
+  }
+  return Results;
+}
 
-auto *GuideTemplate = FunctionTemplateDecl::Create(
-SemaRef.Context, DC, Loc, DeductionGuideName, TemplateParams, Guide);
-GuideTemplate->setImplicit();
-Guide->setDescribedFunctionTemplate(GuideTemplate);
+bool hasDeclaredDeductionGuides(DeclarationName Name, DeclContext* DC) {
+  // Check whether we've already declared deduction guides for this template.
+  // FIXME: Consider storing a flag on the template to indicate this.
+  auto Existing = DC->lookup(Name);
+  for (auto *D : Existing)
+if (D->isImplicit())
+  return true;
+  return false;
+}
 
-if (isa(DC)) {
-  Guide->setAccess(AS_public);
-  GuideTemplate->setAccess(AS_public);
+// Build deduction guides for a type alias template.
+void DeclareImplicitDeductionGuidesForTypeAlias(
+Sema , TypeAliasTemplateDecl *AliasTemplate, SourceLocation Loc) {
+  auto  = SemaRef.Context;
+  // FIXME: if there is an explicit deduction guide after the first use of the
+  // type alias usage, we will not cover this explicit deduction guide. fix 
this
+  // case.
+  if (hasDeclaredDeductionGuides(
+  Context.DeclarationNames.getCXXDeductionGuideName(AliasTemplate),
+  AliasTemplate->getDeclContext()))
+return;
+  // Unrap the sugar ElaboratedType.
+  auto RhsType = AliasTemplate->getTemplatedDecl()
+ ->getUnderlyingType()
+ .getSingleStepDesugaredType(Context);
+  TemplateDecl *Template = nullptr;
+  llvm::ArrayRef AliasRhsTemplateArgs;
+  if (const auto *TST = RhsType->getAs()) {
+// TemplateName in TEST can be a TypeAliasTemplateDecl if
+// the right hand side of the alias is also a type alias, e.g.
+//
+// template
+// using AliasFoo1 = Foo;  // Foo is a class template
+// specialization
+//
+// template
+// using AliasFoo2 = AliasFoo1; // AliasFoo1 is a type alias
+Template = TST->getTemplateName().getAsTemplateDecl();
+AliasRhsTemplateArgs = TST->template_arguments();
+  } else if (const auto *RT = RhsType->getAs()) {
+// Cases where template arguments in the RHS of the alias are not
+// dependent. e.g.
+//   using AliasFoo = Foo;
+if (const auto *CTSD = llvm::dyn_cast(
+RT->getAsCXXRecordDecl())) {
+  Template = CTSD->getSpecializedTemplate();
+  AliasRhsTemplateArgs = CTSD->getTemplateArgs().asArray();
+}
+  }
+  if (!Template)
+return;
+  

[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-02-20 Thread via cfe-commits


@@ -2612,44 +2671,309 @@ struct ConvertConstructorToDeductionGuideTransform {
 SemaRef.CurrentInstantiationScope->InstantiatedLocal(OldParam, NewParam);
 return NewParam;
   }
+};
 
-  FunctionTemplateDecl *buildDeductionGuide(
-  TemplateParameterList *TemplateParams, CXXConstructorDecl *Ctor,
-  ExplicitSpecifier ES, TypeSourceInfo *TInfo, SourceLocation LocStart,
-  SourceLocation Loc, SourceLocation LocEnd,
-  llvm::ArrayRef MaterializedTypedefs = {}) {
-DeclarationNameInfo Name(DeductionGuideName, Loc);
-ArrayRef Params =
-TInfo->getTypeLoc().castAs().getParams();
+// Find all template parameters of the AliasTemplate that appear in the
+// given DeducedArgs.
+SmallVector
+FindAppearedTemplateParamsInAlias(ArrayRef DeducedArgs,

cor3ntin wrote:

Referenced? Used? Named?

https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-02-20 Thread via cfe-commits


@@ -2612,44 +2671,309 @@ struct ConvertConstructorToDeductionGuideTransform {
 SemaRef.CurrentInstantiationScope->InstantiatedLocal(OldParam, NewParam);
 return NewParam;
   }
+};
 
-  FunctionTemplateDecl *buildDeductionGuide(
-  TemplateParameterList *TemplateParams, CXXConstructorDecl *Ctor,
-  ExplicitSpecifier ES, TypeSourceInfo *TInfo, SourceLocation LocStart,
-  SourceLocation Loc, SourceLocation LocEnd,
-  llvm::ArrayRef MaterializedTypedefs = {}) {
-DeclarationNameInfo Name(DeductionGuideName, Loc);
-ArrayRef Params =
-TInfo->getTypeLoc().castAs().getParams();
+// Find all template parameters of the AliasTemplate that appear in the
+// given DeducedArgs.
+SmallVector
+FindAppearedTemplateParamsInAlias(ArrayRef DeducedArgs,
+  TypeAliasTemplateDecl *AliasTemplate) {
+  struct FindAppearedTemplateParams
+  : public RecursiveASTVisitor {
+llvm::DenseSet TemplateParamsInAlias;
+llvm::DenseSet AppearedTemplateParams;
+
+FindAppearedTemplateParams(ArrayRef TemplateParamsInAlias)
+: TemplateParamsInAlias(TemplateParamsInAlias.begin(),
+TemplateParamsInAlias.end()) {}
+
+bool VisitTemplateTypeParmType(TemplateTypeParmType *TTP) {
+  TTP->getIndex();
+  MarkAppeared(TTP->getDecl());
+  return true;
+}
+bool VisitDeclRefExpr(DeclRefExpr *DRE) {
+  MarkAppeared(DRE->getFoundDecl());
+  return true;
+}
 
-// Build the implicit deduction guide template.
-auto *Guide =
-CXXDeductionGuideDecl::Create(SemaRef.Context, DC, LocStart, ES, Name,
-  TInfo->getType(), TInfo, LocEnd, Ctor);
-Guide->setImplicit();
-Guide->setParams(Params);
+void MarkAppeared(NamedDecl *ND) {
+  if (TemplateParamsInAlias.contains(ND))
+AppearedTemplateParams.insert(ND);
+}
+  };
+  ArrayRef TemplateParamsInAlias =
+  AliasTemplate->getTemplateParameters()->asArray();
+  FindAppearedTemplateParams MarkAppeared(TemplateParamsInAlias);
+  MarkAppeared.TraverseTemplateArguments(DeducedArgs);
 
-for (auto *Param : Params)
-  Param->setDeclContext(Guide);
-for (auto *TD : MaterializedTypedefs)
-  TD->setDeclContext(Guide);
+  SmallVector Results;
+  for (unsigned Index = 0; Index < TemplateParamsInAlias.size(); ++Index) {
+if (MarkAppeared.AppearedTemplateParams.contains(
+TemplateParamsInAlias[Index]))
+  Results.push_back(Index);
+  }
+  return Results;
+}
 
-auto *GuideTemplate = FunctionTemplateDecl::Create(
-SemaRef.Context, DC, Loc, DeductionGuideName, TemplateParams, Guide);
-GuideTemplate->setImplicit();
-Guide->setDescribedFunctionTemplate(GuideTemplate);
+bool hasDeclaredDeductionGuides(DeclarationName Name, DeclContext* DC) {
+  // Check whether we've already declared deduction guides for this template.
+  // FIXME: Consider storing a flag on the template to indicate this.
+  auto Existing = DC->lookup(Name);
+  for (auto *D : Existing)
+if (D->isImplicit())
+  return true;
+  return false;
+}
 
-if (isa(DC)) {
-  Guide->setAccess(AS_public);
-  GuideTemplate->setAccess(AS_public);
+// Build deduction guides for a type alias template.
+void DeclareImplicitDeductionGuidesForTypeAlias(
+Sema , TypeAliasTemplateDecl *AliasTemplate, SourceLocation Loc) {
+  auto  = SemaRef.Context;
+  // FIXME: if there is an explicit deduction guide after the first use of the
+  // type alias usage, we will not cover this explicit deduction guide. fix 
this
+  // case.

cor3ntin wrote:

You have a test case for that?

https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-02-20 Thread via cfe-commits

https://github.com/cor3ntin edited 
https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-02-20 Thread via cfe-commits


@@ -2612,44 +2671,309 @@ struct ConvertConstructorToDeductionGuideTransform {
 SemaRef.CurrentInstantiationScope->InstantiatedLocal(OldParam, NewParam);
 return NewParam;
   }
+};
 
-  FunctionTemplateDecl *buildDeductionGuide(
-  TemplateParameterList *TemplateParams, CXXConstructorDecl *Ctor,
-  ExplicitSpecifier ES, TypeSourceInfo *TInfo, SourceLocation LocStart,
-  SourceLocation Loc, SourceLocation LocEnd,
-  llvm::ArrayRef MaterializedTypedefs = {}) {
-DeclarationNameInfo Name(DeductionGuideName, Loc);
-ArrayRef Params =
-TInfo->getTypeLoc().castAs().getParams();
+// Find all template parameters of the AliasTemplate that appear in the
+// given DeducedArgs.
+SmallVector
+FindAppearedTemplateParamsInAlias(ArrayRef DeducedArgs,

cor3ntin wrote:

Can we find a better name for that?

https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-02-20 Thread via cfe-commits


@@ -2612,44 +2671,309 @@ struct ConvertConstructorToDeductionGuideTransform {
 SemaRef.CurrentInstantiationScope->InstantiatedLocal(OldParam, NewParam);
 return NewParam;
   }
+};
 
-  FunctionTemplateDecl *buildDeductionGuide(
-  TemplateParameterList *TemplateParams, CXXConstructorDecl *Ctor,
-  ExplicitSpecifier ES, TypeSourceInfo *TInfo, SourceLocation LocStart,
-  SourceLocation Loc, SourceLocation LocEnd,
-  llvm::ArrayRef MaterializedTypedefs = {}) {
-DeclarationNameInfo Name(DeductionGuideName, Loc);
-ArrayRef Params =
-TInfo->getTypeLoc().castAs().getParams();
+// Find all template parameters of the AliasTemplate that appear in the
+// given DeducedArgs.
+SmallVector
+FindAppearedTemplateParamsInAlias(ArrayRef DeducedArgs,
+  TypeAliasTemplateDecl *AliasTemplate) {
+  struct FindAppearedTemplateParams
+  : public RecursiveASTVisitor {
+llvm::DenseSet TemplateParamsInAlias;
+llvm::DenseSet AppearedTemplateParams;
+
+FindAppearedTemplateParams(ArrayRef TemplateParamsInAlias)
+: TemplateParamsInAlias(TemplateParamsInAlias.begin(),
+TemplateParamsInAlias.end()) {}
+
+bool VisitTemplateTypeParmType(TemplateTypeParmType *TTP) {
+  TTP->getIndex();
+  MarkAppeared(TTP->getDecl());
+  return true;
+}
+bool VisitDeclRefExpr(DeclRefExpr *DRE) {
+  MarkAppeared(DRE->getFoundDecl());
+  return true;
+}
 
-// Build the implicit deduction guide template.
-auto *Guide =
-CXXDeductionGuideDecl::Create(SemaRef.Context, DC, LocStart, ES, Name,
-  TInfo->getType(), TInfo, LocEnd, Ctor);
-Guide->setImplicit();
-Guide->setParams(Params);
+void MarkAppeared(NamedDecl *ND) {
+  if (TemplateParamsInAlias.contains(ND))
+AppearedTemplateParams.insert(ND);
+}
+  };
+  ArrayRef TemplateParamsInAlias =
+  AliasTemplate->getTemplateParameters()->asArray();
+  FindAppearedTemplateParams MarkAppeared(TemplateParamsInAlias);
+  MarkAppeared.TraverseTemplateArguments(DeducedArgs);
 
-for (auto *Param : Params)
-  Param->setDeclContext(Guide);
-for (auto *TD : MaterializedTypedefs)
-  TD->setDeclContext(Guide);
+  SmallVector Results;
+  for (unsigned Index = 0; Index < TemplateParamsInAlias.size(); ++Index) {
+if (MarkAppeared.AppearedTemplateParams.contains(
+TemplateParamsInAlias[Index]))
+  Results.push_back(Index);
+  }
+  return Results;
+}
 
-auto *GuideTemplate = FunctionTemplateDecl::Create(
-SemaRef.Context, DC, Loc, DeductionGuideName, TemplateParams, Guide);
-GuideTemplate->setImplicit();
-Guide->setDescribedFunctionTemplate(GuideTemplate);
+bool hasDeclaredDeductionGuides(DeclarationName Name, DeclContext* DC) {
+  // Check whether we've already declared deduction guides for this template.
+  // FIXME: Consider storing a flag on the template to indicate this.
+  auto Existing = DC->lookup(Name);
+  for (auto *D : Existing)
+if (D->isImplicit())
+  return true;
+  return false;
+}
 
-if (isa(DC)) {
-  Guide->setAccess(AS_public);
-  GuideTemplate->setAccess(AS_public);
+// Build deduction guides for a type alias template.
+void DeclareImplicitDeductionGuidesForTypeAlias(
+Sema , TypeAliasTemplateDecl *AliasTemplate, SourceLocation Loc) {
+  auto  = SemaRef.Context;
+  // FIXME: if there is an explicit deduction guide after the first use of the
+  // type alias usage, we will not cover this explicit deduction guide. fix 
this
+  // case.
+  if (hasDeclaredDeductionGuides(
+  Context.DeclarationNames.getCXXDeductionGuideName(AliasTemplate),
+  AliasTemplate->getDeclContext()))
+return;
+  // Unrap the sugar ElaboratedType.

cor3ntin wrote:

```suggestion
  // Unwrap the sugared ElaboratedType.
```

https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-02-20 Thread via cfe-commits


@@ -10525,9 +10534,11 @@ class Sema final {
   SourceLocation PointOfInstantiation, FunctionDecl *Decl,
   ArrayRef TemplateArgs,
   ConstraintSatisfaction );
-  FunctionDecl *InstantiateFunctionDeclaration(FunctionTemplateDecl *FTD,
-   const TemplateArgumentList 
*Args,
-   SourceLocation Loc);
+  FunctionDecl *InstantiateFunctionDeclaration(
+  FunctionTemplateDecl *FTD, const TemplateArgumentList *Args,
+  SourceLocation Loc,
+  CodeSynthesisContext::SynthesisKind CSC =
+  CodeSynthesisContext::ExplicitTemplateArgumentSubstitution);

cor3ntin wrote:

Can you explain the default value here?  If there was a default at all, one 
would think it would be TemplateInstantiation

https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement CTAD for type alias template. (PR #77890)

2024-02-20 Thread via cfe-commits


@@ -1446,6 +1447,58 @@ namespace {
   return inherited::TransformFunctionProtoType(TLB, TL);
 }
 
+QualType TransformInjectedClassNameType(TypeLocBuilder ,
+InjectedClassNameTypeLoc TL) {
+  auto Type = inherited::TransformInjectedClassNameType(TLB, TL);
+  // Special case for transforming a deduction guide, we return a
+  // transformed TemplateSpecializationType.
+  if (Type.isNull() &&
+  SemaRef.CodeSynthesisContexts.back().Kind ==
+  Sema::CodeSynthesisContext::BuildingDeductionGuides) {
+// Return a TemplateSpecializationType for transforming a deduction
+// guide.
+if (auto *ICT = TL.getType()->getAs()) {
+  auto Type = 
+  inherited::TransformType(ICT->getInjectedSpecializationType());
+  TLB.pushTrivial(SemaRef.Context, Type, TL.getNameLoc());
+  return Type;
+}
+  }
+  return Type;
+}
+// Override the default version to handle a rewrite-template-arg-pack case
+// for building a deduction guide.
+bool TransformTemplateArgument(const TemplateArgumentLoc ,
+   TemplateArgumentLoc ,
+   bool Uneval = false) {
+  const TemplateArgument  = Input.getArgument();
+  std::vector TArgs;
+  switch (Arg.getKind()) {
+  case TemplateArgument::Pack:
+// Iterially rewrite the template argument pack, instead of unpacking
+// it.
+assert(
+SemaRef.CodeSynthesisContexts.back().Kind ==
+Sema::CodeSynthesisContext::BuildingDeductionGuides &&
+"Transforming a template argument pack is only allowed in building 
"
+"deduction guide");
+for (auto  : Arg.getPackAsArray()) {
+  TemplateArgumentLoc Input = SemaRef.getTrivialTemplateArgumentLoc(
+  pack, QualType(), SourceLocation{});
+  TemplateArgumentLoc Output;
+  if (!SemaRef.SubstTemplateArgument(Input, TemplateArgs, Output))
+TArgs.push_back(Output.getArgument());

cor3ntin wrote:

Shouldn't we fail if SubstTemplateArgument fails?

https://github.com/llvm/llvm-project/pull/77890
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


  1   2   >