1//===- SemaTemplateDeductionGude.cpp - Template Argument Deduction---------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements deduction guides for C++ class template argument
10// deduction.
11//
12//===----------------------------------------------------------------------===//
13
14#include "TreeTransform.h"
15#include "TypeLocBuilder.h"
16#include "clang/AST/ASTConsumer.h"
17#include "clang/AST/ASTContext.h"
18#include "clang/AST/Decl.h"
19#include "clang/AST/DeclBase.h"
20#include "clang/AST/DeclCXX.h"
21#include "clang/AST/DeclFriend.h"
22#include "clang/AST/DeclTemplate.h"
23#include "clang/AST/DeclarationName.h"
24#include "clang/AST/Expr.h"
25#include "clang/AST/ExprCXX.h"
26#include "clang/AST/OperationKinds.h"
27#include "clang/AST/TemplateBase.h"
28#include "clang/AST/TemplateName.h"
29#include "clang/AST/Type.h"
30#include "clang/AST/TypeLoc.h"
31#include "clang/Basic/LLVM.h"
32#include "clang/Basic/SourceLocation.h"
33#include "clang/Basic/Specifiers.h"
34#include "clang/Basic/TypeTraits.h"
35#include "clang/Sema/DeclSpec.h"
36#include "clang/Sema/Initialization.h"
37#include "clang/Sema/Lookup.h"
38#include "clang/Sema/Overload.h"
39#include "clang/Sema/Ownership.h"
40#include "clang/Sema/Scope.h"
41#include "clang/Sema/SemaInternal.h"
42#include "clang/Sema/Template.h"
43#include "clang/Sema/TemplateDeduction.h"
44#include "llvm/ADT/ArrayRef.h"
45#include "llvm/ADT/STLExtras.h"
46#include "llvm/ADT/SmallVector.h"
47#include "llvm/Support/Casting.h"
48#include "llvm/Support/ErrorHandling.h"
49#include <cassert>
50#include <optional>
51#include <utility>
52
53using namespace clang;
54using namespace sema;
55
56namespace {
57
58/// Return true if two associated-constraint sets are semantically equal.
59static bool HaveSameAssociatedConstraints(
60 Sema &SemaRef, const NamedDecl *Old, ArrayRef<AssociatedConstraint> OldACs,
61 const NamedDecl *New, ArrayRef<AssociatedConstraint> NewACs) {
62 if (OldACs.size() != NewACs.size())
63 return false;
64 if (OldACs.empty())
65 return true;
66
67 // General case: pairwise compare each associated constraint expression.
68 Sema::TemplateCompareNewDeclInfo NewInfo(New);
69 for (size_t I = 0, E = OldACs.size(); I != E; ++I)
70 if (!SemaRef.AreConstraintExpressionsEqual(
71 Old, OldConstr: OldACs[I].ConstraintExpr, New: NewInfo, NewConstr: NewACs[I].ConstraintExpr))
72 return false;
73
74 return true;
75}
76
77/// Tree transform to "extract" a transformed type from a class template's
78/// constructor to a deduction guide.
79class ExtractTypeForDeductionGuide
80 : public TreeTransform<ExtractTypeForDeductionGuide> {
81 llvm::SmallVectorImpl<TypedefNameDecl *> &MaterializedTypedefs;
82 ClassTemplateDecl *NestedPattern;
83 const MultiLevelTemplateArgumentList *OuterInstantiationArgs;
84 std::optional<TemplateDeclInstantiator> TypedefNameInstantiator;
85
86public:
87 typedef TreeTransform<ExtractTypeForDeductionGuide> Base;
88 ExtractTypeForDeductionGuide(
89 Sema &SemaRef,
90 llvm::SmallVectorImpl<TypedefNameDecl *> &MaterializedTypedefs,
91 ClassTemplateDecl *NestedPattern = nullptr,
92 const MultiLevelTemplateArgumentList *OuterInstantiationArgs = nullptr)
93 : Base(SemaRef), MaterializedTypedefs(MaterializedTypedefs),
94 NestedPattern(NestedPattern),
95 OuterInstantiationArgs(OuterInstantiationArgs) {
96 if (OuterInstantiationArgs)
97 TypedefNameInstantiator.emplace(
98 args&: SemaRef, args: SemaRef.getASTContext().getTranslationUnitDecl(),
99 args: *OuterInstantiationArgs);
100 }
101
102 TypeSourceInfo *transform(TypeSourceInfo *TSI) { return TransformType(TSI); }
103
104 /// Returns true if it's safe to substitute \p Typedef with
105 /// \p OuterInstantiationArgs.
106 bool mightReferToOuterTemplateParameters(TypedefNameDecl *Typedef) {
107 if (!NestedPattern)
108 return false;
109
110 static auto WalkUp = [](DeclContext *DC, DeclContext *TargetDC) {
111 if (DC->Equals(DC: TargetDC))
112 return true;
113 while (DC->isRecord()) {
114 if (DC->Equals(DC: TargetDC))
115 return true;
116 DC = DC->getParent();
117 }
118 return false;
119 };
120
121 if (WalkUp(Typedef->getDeclContext(), NestedPattern->getTemplatedDecl()))
122 return true;
123 if (WalkUp(NestedPattern->getTemplatedDecl(), Typedef->getDeclContext()))
124 return true;
125 return false;
126 }
127
128 QualType RebuildTemplateSpecializationType(
129 ElaboratedTypeKeyword Keyword, TemplateName Template,
130 SourceLocation TemplateNameLoc, TemplateArgumentListInfo &TemplateArgs) {
131 if (!OuterInstantiationArgs ||
132 !isa_and_present<TypeAliasTemplateDecl>(Val: Template.getAsTemplateDecl()))
133 return Base::RebuildTemplateSpecializationType(
134 Keyword, Template, TemplateNameLoc, TemplateArgs);
135
136 auto *TATD = cast<TypeAliasTemplateDecl>(Val: Template.getAsTemplateDecl());
137 auto *Pattern = TATD;
138 while (Pattern->getInstantiatedFromMemberTemplate())
139 Pattern = Pattern->getInstantiatedFromMemberTemplate();
140 if (!mightReferToOuterTemplateParameters(Typedef: Pattern->getTemplatedDecl()))
141 return Base::RebuildTemplateSpecializationType(
142 Keyword, Template, TemplateNameLoc, TemplateArgs);
143
144 Decl *NewD =
145 TypedefNameInstantiator->InstantiateTypeAliasTemplateDecl(D: TATD);
146 if (!NewD)
147 return QualType();
148
149 auto *NewTATD = cast<TypeAliasTemplateDecl>(Val: NewD);
150 MaterializedTypedefs.push_back(Elt: NewTATD->getTemplatedDecl());
151
152 return Base::RebuildTemplateSpecializationType(
153 Keyword, Template: TemplateName(NewTATD), TemplateNameLoc, TemplateArgs);
154 }
155
156 QualType TransformTypedefType(TypeLocBuilder &TLB, TypedefTypeLoc TL) {
157 ASTContext &Context = SemaRef.getASTContext();
158 TypedefNameDecl *OrigDecl = TL.getDecl();
159 TypedefNameDecl *Decl = OrigDecl;
160 const TypedefType *T = TL.getTypePtr();
161 // Transform the underlying type of the typedef and clone the Decl only if
162 // the typedef has a dependent context.
163 bool InDependentContext = OrigDecl->getDeclContext()->isDependentContext();
164
165 // A typedef/alias Decl within the NestedPattern may reference the outer
166 // template parameters. They're substituted with corresponding instantiation
167 // arguments here and in RebuildTemplateSpecializationType() above.
168 // Otherwise, we would have a CTAD guide with "dangling" template
169 // parameters.
170 // For example,
171 // template <class T> struct Outer {
172 // using Alias = S<T>;
173 // template <class U> struct Inner {
174 // Inner(Alias);
175 // };
176 // };
177 if (OuterInstantiationArgs && InDependentContext &&
178 T->isInstantiationDependentType()) {
179 Decl = cast_if_present<TypedefNameDecl>(
180 Val: TypedefNameInstantiator->InstantiateTypedefNameDecl(
181 D: OrigDecl, /*IsTypeAlias=*/isa<TypeAliasDecl>(Val: OrigDecl)));
182 if (!Decl)
183 return QualType();
184 MaterializedTypedefs.push_back(Elt: Decl);
185 } else if (InDependentContext) {
186 TypeLocBuilder InnerTLB;
187 QualType Transformed =
188 TransformType(TLB&: InnerTLB, T: OrigDecl->getTypeSourceInfo()->getTypeLoc());
189 TypeSourceInfo *TSI = InnerTLB.getTypeSourceInfo(Context, T: Transformed);
190 if (isa<TypeAliasDecl>(Val: OrigDecl))
191 Decl = TypeAliasDecl::Create(
192 C&: Context, DC: Context.getTranslationUnitDecl(), StartLoc: OrigDecl->getBeginLoc(),
193 IdLoc: OrigDecl->getLocation(), Id: OrigDecl->getIdentifier(), TInfo: TSI);
194 else {
195 assert(isa<TypedefDecl>(OrigDecl) && "Not a Type alias or typedef");
196 Decl = TypedefDecl::Create(
197 C&: Context, DC: Context.getTranslationUnitDecl(), StartLoc: OrigDecl->getBeginLoc(),
198 IdLoc: OrigDecl->getLocation(), Id: OrigDecl->getIdentifier(), TInfo: TSI);
199 }
200 MaterializedTypedefs.push_back(Elt: Decl);
201 }
202
203 NestedNameSpecifierLoc QualifierLoc = TL.getQualifierLoc();
204 if (QualifierLoc) {
205 QualifierLoc = getDerived().TransformNestedNameSpecifierLoc(NNS: QualifierLoc);
206 if (!QualifierLoc)
207 return QualType();
208 }
209
210 QualType TDTy = Context.getTypedefType(
211 Keyword: T->getKeyword(), Qualifier: QualifierLoc.getNestedNameSpecifier(), Decl);
212 TLB.push<TypedefTypeLoc>(T: TDTy).set(ElaboratedKeywordLoc: TL.getElaboratedKeywordLoc(),
213 QualifierLoc, NameLoc: TL.getNameLoc());
214 return TDTy;
215 }
216};
217
218// Build a deduction guide using the provided information.
219//
220// A deduction guide can be either a template or a non-template function
221// declaration. If \p TemplateParams is null, a non-template function
222// declaration will be created.
223NamedDecl *
224buildDeductionGuide(Sema &SemaRef, TemplateDecl *OriginalTemplate,
225 TemplateParameterList *TemplateParams,
226 CXXConstructorDecl *Ctor, ExplicitSpecifier ES,
227 TypeSourceInfo *TInfo, SourceLocation LocStart,
228 SourceLocation Loc, SourceLocation LocEnd, bool IsImplicit,
229 llvm::ArrayRef<TypedefNameDecl *> MaterializedTypedefs = {},
230 const AssociatedConstraint &FunctionTrailingRC = {}) {
231 DeclContext *DC = OriginalTemplate->getDeclContext();
232 auto DeductionGuideName =
233 SemaRef.Context.DeclarationNames.getCXXDeductionGuideName(
234 TD: OriginalTemplate);
235
236 DeclarationNameInfo Name(DeductionGuideName, Loc);
237 ArrayRef<ParmVarDecl *> Params =
238 TInfo->getTypeLoc().castAs<FunctionProtoTypeLoc>().getParams();
239
240 // Build the implicit deduction guide template.
241 QualType GuideType = TInfo->getType();
242
243 // In CUDA/HIP mode, avoid duplicate implicit guides that differ only in CUDA
244 // target attributes (same constructor signature and constraints).
245 if (IsImplicit && Ctor && SemaRef.getLangOpts().CUDA) {
246 SmallVector<AssociatedConstraint, 4> NewACs;
247 Ctor->getAssociatedConstraints(ACs&: NewACs);
248
249 for (NamedDecl *Existing : DC->lookup(Name: DeductionGuideName)) {
250 auto *ExistingFT = dyn_cast<FunctionTemplateDecl>(Val: Existing);
251 auto *ExistingGuide =
252 ExistingFT
253 ? dyn_cast<CXXDeductionGuideDecl>(Val: ExistingFT->getTemplatedDecl())
254 : dyn_cast<CXXDeductionGuideDecl>(Val: Existing);
255 if (!ExistingGuide)
256 continue;
257
258 // Only consider guides that were also synthesized from a constructor.
259 auto *ExistingCtor = ExistingGuide->getCorrespondingConstructor();
260 if (!ExistingCtor)
261 continue;
262
263 // If the underlying constructors are overloads (different signatures once
264 // CUDA attributes are ignored), they should each get their own guides.
265 if (SemaRef.IsOverload(New: Ctor, Old: ExistingCtor,
266 /*UseMemberUsingDeclRules=*/false,
267 /*ConsiderCudaAttrs=*/false))
268 continue;
269
270 // At this point, the constructors have the same signature ignoring CUDA
271 // attributes. Decide whether their associated constraints are also the
272 // same; only in that case do we treat one guide as a duplicate of the
273 // other.
274 SmallVector<AssociatedConstraint, 4> ExistingACs;
275 ExistingCtor->getAssociatedConstraints(ACs&: ExistingACs);
276
277 if (HaveSameAssociatedConstraints(SemaRef, Old: ExistingCtor, OldACs: ExistingACs,
278 New: Ctor, NewACs))
279 return Existing;
280 }
281 }
282
283 auto *Guide = CXXDeductionGuideDecl::Create(
284 C&: SemaRef.Context, DC, StartLoc: LocStart, ES, NameInfo: Name, T: GuideType, TInfo, EndLocation: LocEnd, Ctor,
285 Kind: DeductionCandidate::Normal, TrailingRequiresClause: FunctionTrailingRC);
286 Guide->setImplicit(IsImplicit);
287 Guide->setParams(Params);
288
289 for (auto *Param : Params)
290 Param->setDeclContext(Guide);
291 for (auto *TD : MaterializedTypedefs)
292 TD->setDeclContext(Guide);
293 if (isa<CXXRecordDecl>(Val: DC))
294 Guide->setAccess(AS_public);
295
296 if (!TemplateParams) {
297 DC->addDecl(D: Guide);
298 return Guide;
299 }
300
301 auto *GuideTemplate = FunctionTemplateDecl::Create(
302 C&: SemaRef.Context, DC, L: Loc, Name: DeductionGuideName, Params: TemplateParams, Decl: Guide);
303 GuideTemplate->setImplicit(IsImplicit);
304 Guide->setDescribedFunctionTemplate(GuideTemplate);
305
306 if (isa<CXXRecordDecl>(Val: DC))
307 GuideTemplate->setAccess(AS_public);
308
309 DC->addDecl(D: GuideTemplate);
310 return GuideTemplate;
311}
312
313// Transform a given template type parameter `TTP`.
314TemplateTypeParmDecl *transformTemplateTypeParam(
315 Sema &SemaRef, DeclContext *DC, TemplateTypeParmDecl *TTP,
316 MultiLevelTemplateArgumentList &Args, unsigned NewDepth, unsigned NewIndex,
317 bool EvaluateConstraint) {
318 // TemplateTypeParmDecl's index cannot be changed after creation, so
319 // substitute it directly.
320 auto *NewTTP = TemplateTypeParmDecl::Create(
321 C: SemaRef.Context, DC, KeyLoc: TTP->getBeginLoc(), NameLoc: TTP->getLocation(), D: NewDepth,
322 P: NewIndex, Id: TTP->getIdentifier(), Typename: TTP->wasDeclaredWithTypename(),
323 ParameterPack: TTP->isParameterPack(), HasTypeConstraint: TTP->hasTypeConstraint(),
324 NumExpanded: TTP->getNumExpansionParameters());
325 if (const auto *TC = TTP->getTypeConstraint())
326 SemaRef.SubstTypeConstraint(Inst: NewTTP, TC, TemplateArgs: Args,
327 /*EvaluateConstraint=*/EvaluateConstraint);
328 if (TTP->hasDefaultArgument()) {
329 TemplateArgumentLoc InstantiatedDefaultArg;
330 if (!SemaRef.SubstTemplateArgument(
331 Input: TTP->getDefaultArgument(), TemplateArgs: Args, Output&: InstantiatedDefaultArg,
332 Loc: TTP->getDefaultArgumentLoc(), Entity: TTP->getDeclName()))
333 NewTTP->setDefaultArgument(C: SemaRef.Context, DefArg: InstantiatedDefaultArg);
334 }
335 SemaRef.CurrentInstantiationScope->InstantiatedLocal(D: TTP, Inst: NewTTP);
336 return NewTTP;
337}
338// Similar to above, but for non-type template or template template parameters.
339template <typename NonTypeTemplateOrTemplateTemplateParmDecl>
340NonTypeTemplateOrTemplateTemplateParmDecl *
341transformTemplateParam(Sema &SemaRef, DeclContext *DC,
342 NonTypeTemplateOrTemplateTemplateParmDecl *OldParam,
343 MultiLevelTemplateArgumentList &Args, unsigned NewIndex,
344 unsigned NewDepth) {
345 // Ask the template instantiator to do the heavy lifting for us, then adjust
346 // the index of the parameter once it's done.
347 auto *NewParam = cast<NonTypeTemplateOrTemplateTemplateParmDecl>(
348 SemaRef.SubstDecl(D: OldParam, Owner: DC, TemplateArgs: Args));
349 NewParam->setPosition(NewIndex);
350 NewParam->setDepth(NewDepth);
351 return NewParam;
352}
353
354NamedDecl *transformTemplateParameter(Sema &SemaRef, DeclContext *DC,
355 NamedDecl *TemplateParam,
356 MultiLevelTemplateArgumentList &Args,
357 unsigned NewIndex, unsigned NewDepth,
358 bool EvaluateConstraint = true) {
359 if (auto *TTP = dyn_cast<TemplateTypeParmDecl>(Val: TemplateParam))
360 return transformTemplateTypeParam(
361 SemaRef, DC, TTP, Args, NewDepth, NewIndex,
362 /*EvaluateConstraint=*/EvaluateConstraint);
363 if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(Val: TemplateParam))
364 return transformTemplateParam(SemaRef, DC, OldParam: TTP, Args, NewIndex, NewDepth);
365 if (auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Val: TemplateParam))
366 return transformTemplateParam(SemaRef, DC, OldParam: NTTP, Args, NewIndex, NewDepth);
367 llvm_unreachable("Unhandled template parameter types");
368}
369
370/// Transform to convert portions of a constructor declaration into the
371/// corresponding deduction guide, per C++1z [over.match.class.deduct]p1.
372struct ConvertConstructorToDeductionGuideTransform {
373 ConvertConstructorToDeductionGuideTransform(Sema &S,
374 ClassTemplateDecl *Template)
375 : SemaRef(S), Template(Template) {
376 // If the template is nested, then we need to use the original
377 // pattern to iterate over the constructors.
378 ClassTemplateDecl *Pattern = Template;
379 while (Pattern->getInstantiatedFromMemberTemplate()) {
380 if (Pattern->isMemberSpecialization())
381 break;
382 Pattern = Pattern->getInstantiatedFromMemberTemplate();
383 NestedPattern = Pattern;
384 }
385
386 if (NestedPattern)
387 OuterInstantiationArgs = SemaRef.getTemplateInstantiationArgs(D: Template);
388 }
389
390 Sema &SemaRef;
391 ClassTemplateDecl *Template;
392 ClassTemplateDecl *NestedPattern = nullptr;
393
394 DeclContext *DC = Template->getDeclContext();
395 CXXRecordDecl *Primary = Template->getTemplatedDecl();
396 DeclarationName DeductionGuideName =
397 SemaRef.Context.DeclarationNames.getCXXDeductionGuideName(TD: Template);
398
399 QualType DeducedType = SemaRef.Context.getCanonicalTagType(TD: Primary);
400
401 // Index adjustment to apply to convert depth-1 template parameters into
402 // depth-0 template parameters.
403 unsigned Depth1IndexAdjustment = Template->getTemplateParameters()->size();
404
405 // Instantiation arguments for the outermost depth-1 templates
406 // when the template is nested
407 MultiLevelTemplateArgumentList OuterInstantiationArgs;
408
409 /// Transform a constructor declaration into a deduction guide.
410 NamedDecl *transformConstructor(FunctionTemplateDecl *FTD,
411 CXXConstructorDecl *CD) {
412 SmallVector<TemplateArgument, 16> SubstArgs;
413
414 LocalInstantiationScope Scope(SemaRef);
415
416 // C++ [over.match.class.deduct]p1:
417 // -- For each constructor of the class template designated by the
418 // template-name, a function template with the following properties:
419
420 // -- The template parameters are the template parameters of the class
421 // template followed by the template parameters (including default
422 // template arguments) of the constructor, if any.
423 TemplateParameterList *TemplateParams =
424 SemaRef.GetTemplateParameterList(TD: Template);
425 SmallVector<TemplateArgument, 16> Depth1Args;
426 AssociatedConstraint OuterRC(TemplateParams->getRequiresClause());
427 if (FTD) {
428 TemplateParameterList *InnerParams = FTD->getTemplateParameters();
429 SmallVector<NamedDecl *, 16> AllParams;
430 AllParams.reserve(N: TemplateParams->size() + InnerParams->size());
431 AllParams.insert(I: AllParams.begin(), From: TemplateParams->begin(),
432 To: TemplateParams->end());
433 SubstArgs.reserve(N: InnerParams->size());
434 Depth1Args.reserve(N: InnerParams->size());
435
436 // Later template parameters could refer to earlier ones, so build up
437 // a list of substituted template arguments as we go.
438 for (NamedDecl *Param : *InnerParams) {
439 MultiLevelTemplateArgumentList Args;
440 Args.setKind(TemplateSubstitutionKind::Rewrite);
441 Args.addOuterTemplateArguments(Args: Depth1Args);
442 Args.addOuterRetainedLevel();
443 if (NestedPattern)
444 Args.addOuterRetainedLevels(Num: NestedPattern->getTemplateDepth());
445 auto [Depth, Index] = getDepthAndIndex(ND: Param);
446 // Depth can be 0 if FTD belongs to a non-template class/a class
447 // template specialization with an empty template parameter list. In
448 // that case, we don't want the NewDepth to overflow, and it should
449 // remain 0.
450 NamedDecl *NewParam = transformTemplateParameter(
451 SemaRef, DC, TemplateParam: Param, Args, NewIndex: Index + Depth1IndexAdjustment,
452 NewDepth: Depth ? Depth - 1 : 0);
453 if (!NewParam)
454 return nullptr;
455 // Constraints require that we substitute depth-1 arguments
456 // to match depths when substituted for evaluation later
457 Depth1Args.push_back(Elt: SemaRef.Context.getInjectedTemplateArg(ParamDecl: NewParam));
458
459 if (NestedPattern) {
460 auto [Depth, Index] = getDepthAndIndex(ND: NewParam);
461 NewParam = transformTemplateParameter(
462 SemaRef, DC, TemplateParam: NewParam, Args&: OuterInstantiationArgs, NewIndex: Index,
463 NewDepth: Depth - OuterInstantiationArgs.getNumSubstitutedLevels(),
464 /*EvaluateConstraint=*/false);
465 }
466
467 assert(getDepthAndIndex(NewParam).first == 0 &&
468 "Unexpected template parameter depth");
469
470 AllParams.push_back(Elt: NewParam);
471 SubstArgs.push_back(Elt: SemaRef.Context.getInjectedTemplateArg(ParamDecl: NewParam));
472 }
473
474 // Substitute new template parameters into requires-clause if present.
475 Expr *RequiresClause = nullptr;
476 if (Expr *InnerRC = InnerParams->getRequiresClause()) {
477 MultiLevelTemplateArgumentList Args;
478 Args.setKind(TemplateSubstitutionKind::Rewrite);
479 Args.addOuterTemplateArguments(Args: Depth1Args);
480 Args.addOuterRetainedLevel();
481 if (NestedPattern)
482 Args.addOuterRetainedLevels(Num: NestedPattern->getTemplateDepth());
483 ExprResult E =
484 SemaRef.SubstConstraintExprWithoutSatisfaction(E: InnerRC, TemplateArgs: Args);
485 if (!E.isUsable())
486 return nullptr;
487 RequiresClause = E.get();
488 }
489
490 TemplateParams = TemplateParameterList::Create(
491 C: SemaRef.Context, TemplateLoc: InnerParams->getTemplateLoc(),
492 LAngleLoc: InnerParams->getLAngleLoc(), Params: AllParams, RAngleLoc: InnerParams->getRAngleLoc(),
493 RequiresClause);
494 }
495
496 // If we built a new template-parameter-list, track that we need to
497 // substitute references to the old parameters into references to the
498 // new ones.
499 MultiLevelTemplateArgumentList Args;
500 Args.setKind(TemplateSubstitutionKind::Rewrite);
501 if (FTD) {
502 Args.addOuterTemplateArguments(Args: SubstArgs);
503 Args.addOuterRetainedLevel();
504 }
505
506 FunctionProtoTypeLoc FPTL = CD->getTypeSourceInfo()
507 ->getTypeLoc()
508 .getAsAdjusted<FunctionProtoTypeLoc>();
509 assert(FPTL && "no prototype for constructor declaration");
510
511 // Transform the type of the function, adjusting the return type and
512 // replacing references to the old parameters with references to the
513 // new ones.
514 TypeLocBuilder TLB;
515 SmallVector<ParmVarDecl *, 8> Params;
516 SmallVector<TypedefNameDecl *, 4> MaterializedTypedefs;
517 QualType NewType = transformFunctionProtoType(TLB, TL: FPTL, Params, Args,
518 MaterializedTypedefs);
519 if (NewType.isNull())
520 return nullptr;
521 TypeSourceInfo *NewTInfo = TLB.getTypeSourceInfo(Context&: SemaRef.Context, T: NewType);
522
523 // At this point, the function parameters are already 'instantiated' in the
524 // current scope. Substitute into the constructor's trailing
525 // requires-clause, if any.
526 AssociatedConstraint FunctionTrailingRC;
527 if (const AssociatedConstraint &RC = CD->getTrailingRequiresClause()) {
528 MultiLevelTemplateArgumentList Args;
529 Args.setKind(TemplateSubstitutionKind::Rewrite);
530 Args.addOuterTemplateArguments(Args: Depth1Args);
531 Args.addOuterRetainedLevel();
532 if (NestedPattern)
533 Args.addOuterRetainedLevels(Num: NestedPattern->getTemplateDepth());
534 ExprResult E = SemaRef.SubstConstraintExprWithoutSatisfaction(
535 E: const_cast<Expr *>(RC.ConstraintExpr), TemplateArgs: Args);
536 if (!E.isUsable())
537 return nullptr;
538 FunctionTrailingRC = AssociatedConstraint(E.get(), RC.ArgPackSubstIndex);
539 }
540
541 // C++ [over.match.class.deduct]p1:
542 // If C is defined, for each constructor of C, a function template with
543 // the following properties:
544 // [...]
545 // - The associated constraints are the conjunction of the associated
546 // constraints of C and the associated constraints of the constructor, if
547 // any.
548 if (OuterRC) {
549 // The outer template parameters are not transformed, so their
550 // associated constraints don't need substitution.
551 // FIXME: Should simply add another field for the OuterRC, instead of
552 // combining them like this.
553 if (!FunctionTrailingRC)
554 FunctionTrailingRC = OuterRC;
555 else
556 FunctionTrailingRC = AssociatedConstraint(
557 BinaryOperator::Create(
558 C: SemaRef.Context,
559 /*lhs=*/const_cast<Expr *>(OuterRC.ConstraintExpr),
560 /*rhs=*/const_cast<Expr *>(FunctionTrailingRC.ConstraintExpr),
561 opc: BO_LAnd, ResTy: SemaRef.Context.BoolTy, VK: VK_PRValue, OK: OK_Ordinary,
562 opLoc: TemplateParams->getTemplateLoc(), FPFeatures: FPOptionsOverride()),
563 FunctionTrailingRC.ArgPackSubstIndex);
564 }
565
566 return buildDeductionGuide(
567 SemaRef, OriginalTemplate: Template, TemplateParams, Ctor: CD, ES: CD->getExplicitSpecifier(),
568 TInfo: NewTInfo, LocStart: CD->getBeginLoc(), Loc: CD->getLocation(), LocEnd: CD->getEndLoc(),
569 /*IsImplicit=*/true, MaterializedTypedefs, FunctionTrailingRC);
570 }
571
572 /// Build a deduction guide with the specified parameter types.
573 NamedDecl *buildSimpleDeductionGuide(MutableArrayRef<QualType> ParamTypes) {
574 SourceLocation Loc = Template->getLocation();
575
576 // Build the requested type.
577 FunctionProtoType::ExtProtoInfo EPI;
578 EPI.HasTrailingReturn = true;
579 QualType Result = SemaRef.BuildFunctionType(T: DeducedType, ParamTypes, Loc,
580 Entity: DeductionGuideName, EPI);
581 TypeSourceInfo *TSI = SemaRef.Context.getTrivialTypeSourceInfo(T: Result, Loc);
582 if (NestedPattern)
583 TSI = SemaRef.SubstType(T: TSI, TemplateArgs: OuterInstantiationArgs, Loc,
584 Entity: DeductionGuideName);
585
586 if (!TSI)
587 return nullptr;
588
589 FunctionProtoTypeLoc FPTL =
590 TSI->getTypeLoc().castAs<FunctionProtoTypeLoc>();
591
592 // Build the parameters, needed during deduction / substitution.
593 SmallVector<ParmVarDecl *, 4> Params;
594 for (auto T : ParamTypes) {
595 auto *TSI = SemaRef.Context.getTrivialTypeSourceInfo(T, Loc);
596 if (NestedPattern)
597 TSI = SemaRef.SubstType(T: TSI, TemplateArgs: OuterInstantiationArgs, Loc,
598 Entity: DeclarationName());
599 if (!TSI)
600 return nullptr;
601
602 ParmVarDecl *NewParam =
603 ParmVarDecl::Create(C&: SemaRef.Context, DC, StartLoc: Loc, IdLoc: Loc, Id: nullptr,
604 T: TSI->getType(), TInfo: TSI, S: SC_None, DefArg: nullptr);
605 NewParam->setScopeInfo(scopeDepth: 0, parameterIndex: Params.size());
606 FPTL.setParam(i: Params.size(), VD: NewParam);
607 Params.push_back(Elt: NewParam);
608 }
609
610 return buildDeductionGuide(
611 SemaRef, OriginalTemplate: Template, TemplateParams: SemaRef.GetTemplateParameterList(TD: Template), Ctor: nullptr,
612 ES: ExplicitSpecifier(), TInfo: TSI, LocStart: Loc, Loc, LocEnd: Loc, /*IsImplicit=*/true);
613 }
614
615private:
616 QualType transformFunctionProtoType(
617 TypeLocBuilder &TLB, FunctionProtoTypeLoc TL,
618 SmallVectorImpl<ParmVarDecl *> &Params,
619 MultiLevelTemplateArgumentList &Args,
620 SmallVectorImpl<TypedefNameDecl *> &MaterializedTypedefs) {
621 SmallVector<QualType, 4> ParamTypes;
622 const FunctionProtoType *T = TL.getTypePtr();
623
624 // -- The types of the function parameters are those of the constructor.
625 for (auto *OldParam : TL.getParams()) {
626 ParmVarDecl *NewParam = OldParam;
627 // Given
628 // template <class T> struct C {
629 // template <class U> struct D {
630 // template <class V> D(U, V);
631 // };
632 // };
633 // First, transform all the references to template parameters that are
634 // defined outside of the surrounding class template. That is T in the
635 // above example.
636 if (NestedPattern) {
637 NewParam = transformFunctionTypeParam(
638 OldParam: NewParam, Args&: OuterInstantiationArgs, MaterializedTypedefs,
639 /*TransformingOuterPatterns=*/true);
640 if (!NewParam)
641 return QualType();
642 }
643 // Then, transform all the references to template parameters that are
644 // defined at the class template and the constructor. In this example,
645 // they're U and V, respectively.
646 NewParam =
647 transformFunctionTypeParam(OldParam: NewParam, Args, MaterializedTypedefs,
648 /*TransformingOuterPatterns=*/false);
649 if (!NewParam)
650 return QualType();
651 ParamTypes.push_back(Elt: NewParam->getType());
652 Params.push_back(Elt: NewParam);
653 }
654
655 // -- The return type is the class template specialization designated by
656 // the template-name and template arguments corresponding to the
657 // template parameters obtained from the class template.
658 //
659 // We use the injected-class-name type of the primary template instead.
660 // This has the convenient property that it is different from any type that
661 // the user can write in a deduction-guide (because they cannot enter the
662 // context of the template), so implicit deduction guides can never collide
663 // with explicit ones.
664 QualType ReturnType = DeducedType;
665 auto TTL = TLB.push<TagTypeLoc>(T: ReturnType);
666 TTL.setElaboratedKeywordLoc(SourceLocation());
667 TTL.setQualifierLoc(NestedNameSpecifierLoc());
668 TTL.setNameLoc(Primary->getLocation());
669
670 // Resolving a wording defect, we also inherit the variadicness of the
671 // constructor.
672 FunctionProtoType::ExtProtoInfo EPI;
673 EPI.Variadic = T->isVariadic();
674 EPI.HasTrailingReturn = true;
675
676 QualType Result = SemaRef.BuildFunctionType(
677 T: ReturnType, ParamTypes, Loc: TL.getBeginLoc(), Entity: DeductionGuideName, EPI);
678 if (Result.isNull())
679 return QualType();
680
681 FunctionProtoTypeLoc NewTL = TLB.push<FunctionProtoTypeLoc>(T: Result);
682 NewTL.setLocalRangeBegin(TL.getLocalRangeBegin());
683 NewTL.setLParenLoc(TL.getLParenLoc());
684 NewTL.setRParenLoc(TL.getRParenLoc());
685 NewTL.setExceptionSpecRange(SourceRange());
686 NewTL.setLocalRangeEnd(TL.getLocalRangeEnd());
687 for (unsigned I = 0, E = NewTL.getNumParams(); I != E; ++I)
688 NewTL.setParam(i: I, VD: Params[I]);
689
690 return Result;
691 }
692
693 ParmVarDecl *transformFunctionTypeParam(
694 ParmVarDecl *OldParam, MultiLevelTemplateArgumentList &Args,
695 llvm::SmallVectorImpl<TypedefNameDecl *> &MaterializedTypedefs,
696 bool TransformingOuterPatterns) {
697 TypeSourceInfo *OldTSI = OldParam->getTypeSourceInfo();
698 TypeSourceInfo *NewTSI;
699 if (auto PackTL = OldTSI->getTypeLoc().getAs<PackExpansionTypeLoc>()) {
700 // Expand out the one and only element in each inner pack.
701 Sema::ArgPackSubstIndexRAII SubstIndex(SemaRef, 0u);
702 NewTSI =
703 SemaRef.SubstType(TL: PackTL.getPatternLoc(), TemplateArgs: Args,
704 Loc: OldParam->getLocation(), Entity: OldParam->getDeclName());
705 if (!NewTSI)
706 return nullptr;
707 NewTSI =
708 SemaRef.CheckPackExpansion(Pattern: NewTSI, EllipsisLoc: PackTL.getEllipsisLoc(),
709 NumExpansions: PackTL.getTypePtr()->getNumExpansions());
710 } else
711 NewTSI = SemaRef.SubstType(T: OldTSI, TemplateArgs: Args, Loc: OldParam->getLocation(),
712 Entity: OldParam->getDeclName());
713 if (!NewTSI)
714 return nullptr;
715
716 // Extract the type. This (for instance) replaces references to typedef
717 // members of the current instantiations with the definitions of those
718 // typedefs, avoiding triggering instantiation of the deduced type during
719 // deduction.
720 NewTSI = ExtractTypeForDeductionGuide(
721 SemaRef, MaterializedTypedefs, NestedPattern,
722 TransformingOuterPatterns ? &Args : nullptr)
723 .transform(TSI: NewTSI);
724 if (!NewTSI)
725 return nullptr;
726 // Resolving a wording defect, we also inherit default arguments from the
727 // constructor.
728 ExprResult NewDefArg;
729 if (OldParam->hasDefaultArg()) {
730 // We don't care what the value is (we won't use it); just create a
731 // placeholder to indicate there is a default argument.
732 QualType ParamTy = NewTSI->getType();
733 NewDefArg = new (SemaRef.Context)
734 OpaqueValueExpr(OldParam->getDefaultArgRange().getBegin(),
735 ParamTy.getNonLValueExprType(Context: SemaRef.Context),
736 ParamTy->isLValueReferenceType() ? VK_LValue
737 : ParamTy->isRValueReferenceType() ? VK_XValue
738 : VK_PRValue);
739 }
740 // Handle arrays and functions decay.
741 auto NewType = NewTSI->getType();
742 if (NewType->isArrayType() || NewType->isFunctionType())
743 NewType = SemaRef.Context.getDecayedType(T: NewType);
744
745 ParmVarDecl *NewParam = ParmVarDecl::Create(
746 C&: SemaRef.Context, DC, StartLoc: OldParam->getInnerLocStart(),
747 IdLoc: OldParam->getLocation(), Id: OldParam->getIdentifier(), T: NewType, TInfo: NewTSI,
748 S: OldParam->getStorageClass(), DefArg: NewDefArg.get());
749 NewParam->setScopeInfo(scopeDepth: OldParam->getFunctionScopeDepth(),
750 parameterIndex: OldParam->getFunctionScopeIndex());
751 SemaRef.CurrentInstantiationScope->InstantiatedLocal(D: OldParam, Inst: NewParam);
752 return NewParam;
753 }
754};
755
756// Find all template parameters that appear in the given DeducedArgs.
757// Return the indices of the template parameters in the TemplateParams.
758SmallVector<unsigned> TemplateParamsReferencedInTemplateArgumentList(
759 Sema &SemaRef, const TemplateParameterList *TemplateParamsList,
760 ArrayRef<TemplateArgument> DeducedArgs) {
761
762 llvm::SmallBitVector ReferencedTemplateParams(TemplateParamsList->size());
763 SemaRef.MarkUsedTemplateParameters(
764 TemplateArgs: DeducedArgs, Depth: TemplateParamsList->getDepth(), Used&: ReferencedTemplateParams);
765
766 auto MarkDefaultArgs = [&](auto *Param) {
767 if (!Param->hasDefaultArgument())
768 return;
769 SemaRef.MarkUsedTemplateParameters(
770 Param->getDefaultArgument().getArgument(),
771 TemplateParamsList->getDepth(), ReferencedTemplateParams);
772 };
773
774 for (unsigned Index = 0; Index < TemplateParamsList->size(); ++Index) {
775 if (!ReferencedTemplateParams[Index])
776 continue;
777 auto *Param = TemplateParamsList->getParam(Idx: Index);
778 if (auto *TTPD = dyn_cast<TemplateTypeParmDecl>(Val: Param))
779 MarkDefaultArgs(TTPD);
780 else if (auto *NTTPD = dyn_cast<NonTypeTemplateParmDecl>(Val: Param))
781 MarkDefaultArgs(NTTPD);
782 else
783 MarkDefaultArgs(cast<TemplateTemplateParmDecl>(Val: Param));
784 }
785
786 SmallVector<unsigned> Results;
787 for (unsigned Index = 0; Index < TemplateParamsList->size(); ++Index) {
788 if (ReferencedTemplateParams[Index])
789 Results.push_back(Elt: Index);
790 }
791 return Results;
792}
793
794bool hasDeclaredDeductionGuides(DeclarationName Name, DeclContext *DC) {
795 // Check whether we've already declared deduction guides for this template.
796 // FIXME: Consider storing a flag on the template to indicate this.
797 assert(Name.getNameKind() ==
798 DeclarationName::NameKind::CXXDeductionGuideName &&
799 "name must be a deduction guide name");
800 auto Existing = DC->lookup(Name);
801 for (auto *D : Existing)
802 if (D->isImplicit())
803 return true;
804 return false;
805}
806
807// Returns all source deduction guides associated with the declared
808// deduction guides that have the specified deduction guide name.
809llvm::DenseSet<const NamedDecl *> getSourceDeductionGuides(DeclarationName Name,
810 DeclContext *DC) {
811 assert(Name.getNameKind() ==
812 DeclarationName::NameKind::CXXDeductionGuideName &&
813 "name must be a deduction guide name");
814 llvm::DenseSet<const NamedDecl *> Result;
815 for (auto *D : DC->lookup(Name)) {
816 if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(Val: D))
817 D = FTD->getTemplatedDecl();
818
819 if (const auto *GD = dyn_cast<CXXDeductionGuideDecl>(Val: D)) {
820 assert(GD->getSourceDeductionGuide() &&
821 "deduction guide for alias template must have a source deduction "
822 "guide");
823 Result.insert(V: GD->getSourceDeductionGuide());
824 }
825 }
826 return Result;
827}
828
829// Build the associated constraints for the alias deduction guides.
830// C++ [over.match.class.deduct]p3.3:
831// The associated constraints ([temp.constr.decl]) are the conjunction of the
832// associated constraints of g and a constraint that is satisfied if and only
833// if the arguments of A are deducible (see below) from the return type.
834//
835// The return result is expected to be the require-clause for the synthesized
836// alias deduction guide.
837Expr *
838buildAssociatedConstraints(Sema &SemaRef, FunctionTemplateDecl *F,
839 TypeAliasTemplateDecl *AliasTemplate,
840 ArrayRef<DeducedTemplateArgument> DeduceResults,
841 unsigned FirstUndeducedParamIdx, Expr *IsDeducible) {
842 Expr *RC = F->getTemplateParameters()->getRequiresClause();
843 if (!RC)
844 return IsDeducible;
845
846 ASTContext &Context = SemaRef.Context;
847 LocalInstantiationScope Scope(SemaRef);
848
849 // In the clang AST, constraint nodes are deliberately not instantiated unless
850 // they are actively being evaluated. Consequently, occurrences of template
851 // parameters in the require-clause expression have a subtle "depth"
852 // difference compared to normal occurrences in places, such as function
853 // parameters. When transforming the require-clause, we must take this
854 // distinction into account:
855 //
856 // 1) In the transformed require-clause, occurrences of template parameters
857 // must use the "uninstantiated" depth;
858 // 2) When substituting on the require-clause expr of the underlying
859 // deduction guide, we must use the entire set of template argument lists;
860 //
861 // It's important to note that we're performing this transformation on an
862 // *instantiated* AliasTemplate.
863
864 // For 1), if the alias template is nested within a class template, we
865 // calcualte the 'uninstantiated' depth by adding the substitution level back.
866 unsigned AdjustDepth = 0;
867 if (auto *PrimaryTemplate =
868 AliasTemplate->getInstantiatedFromMemberTemplate())
869 AdjustDepth = PrimaryTemplate->getTemplateDepth();
870
871 // We rebuild all template parameters with the uninstantiated depth, and
872 // build template arguments refer to them.
873 SmallVector<TemplateArgument> AdjustedAliasTemplateArgs;
874
875 for (auto *TP : *AliasTemplate->getTemplateParameters()) {
876 // Rebuild any internal references to earlier parameters and reindex
877 // as we go.
878 MultiLevelTemplateArgumentList Args;
879 Args.setKind(TemplateSubstitutionKind::Rewrite);
880 Args.addOuterTemplateArguments(Args: AdjustedAliasTemplateArgs);
881 NamedDecl *NewParam = transformTemplateParameter(
882 SemaRef, DC: AliasTemplate->getDeclContext(), TemplateParam: TP, Args,
883 /*NewIndex=*/AdjustedAliasTemplateArgs.size(),
884 NewDepth: getDepthAndIndex(ND: TP).first + AdjustDepth);
885
886 TemplateArgument NewTemplateArgument =
887 Context.getInjectedTemplateArg(ParamDecl: NewParam);
888 AdjustedAliasTemplateArgs.push_back(Elt: NewTemplateArgument);
889 }
890 // Template arguments used to transform the template arguments in
891 // DeducedResults.
892 SmallVector<TemplateArgument> TemplateArgsForBuildingRC(
893 F->getTemplateParameters()->size());
894 // Transform the transformed template args
895 MultiLevelTemplateArgumentList Args;
896 Args.setKind(TemplateSubstitutionKind::Rewrite);
897 Args.addOuterTemplateArguments(Args: AdjustedAliasTemplateArgs);
898
899 for (unsigned Index = 0; Index < DeduceResults.size(); ++Index) {
900 const auto &D = DeduceResults[Index];
901 if (D.isNull()) { // non-deduced template parameters of f
902 NamedDecl *TP = F->getTemplateParameters()->getParam(Idx: Index);
903 MultiLevelTemplateArgumentList Args;
904 Args.setKind(TemplateSubstitutionKind::Rewrite);
905 Args.addOuterTemplateArguments(Args: TemplateArgsForBuildingRC);
906 // Rebuild the template parameter with updated depth and index.
907 NamedDecl *NewParam =
908 transformTemplateParameter(SemaRef, DC: F->getDeclContext(), TemplateParam: TP, Args,
909 /*NewIndex=*/FirstUndeducedParamIdx,
910 NewDepth: getDepthAndIndex(ND: TP).first + AdjustDepth);
911 FirstUndeducedParamIdx += 1;
912 assert(TemplateArgsForBuildingRC[Index].isNull());
913 TemplateArgsForBuildingRC[Index] =
914 Context.getInjectedTemplateArg(ParamDecl: NewParam);
915 continue;
916 }
917 TemplateArgumentLoc Input =
918 SemaRef.getTrivialTemplateArgumentLoc(Arg: D, NTTPType: QualType(), Loc: SourceLocation{});
919 TemplateArgumentLoc Output;
920 if (!SemaRef.SubstTemplateArgument(Input, TemplateArgs: Args, Output)) {
921 assert(TemplateArgsForBuildingRC[Index].isNull() &&
922 "InstantiatedArgs must be null before setting");
923 TemplateArgsForBuildingRC[Index] = Output.getArgument();
924 }
925 }
926
927 // A list of template arguments for transforming the require-clause of F.
928 // It must contain the entire set of template argument lists.
929 MultiLevelTemplateArgumentList ArgsForBuildingRC;
930 ArgsForBuildingRC.setKind(clang::TemplateSubstitutionKind::Rewrite);
931 ArgsForBuildingRC.addOuterTemplateArguments(Args: TemplateArgsForBuildingRC);
932 // For 2), if the underlying deduction guide F is nested in a class template,
933 // we need the entire template argument list, as the constraint AST in the
934 // require-clause of F remains completely uninstantiated.
935 //
936 // For example:
937 // template <typename T> // depth 0
938 // struct Outer {
939 // template <typename U>
940 // struct Foo { Foo(U); };
941 //
942 // template <typename U> // depth 1
943 // requires C<U>
944 // Foo(U) -> Foo<int>;
945 // };
946 // template <typename U>
947 // using AFoo = Outer<int>::Foo<U>;
948 //
949 // In this scenario, the deduction guide for `Foo` inside `Outer<int>`:
950 // - The occurrence of U in the require-expression is [depth:1, index:0]
951 // - The occurrence of U in the function parameter is [depth:0, index:0]
952 // - The template parameter of U is [depth:0, index:0]
953 //
954 // We add the outer template arguments which is [int] to the multi-level arg
955 // list to ensure that the occurrence U in `C<U>` will be replaced with int
956 // during the substitution.
957 //
958 // NOTE: The underlying deduction guide F is instantiated -- either from an
959 // explicitly-written deduction guide member, or from a constructor.
960 // getInstantiatedFromMemberTemplate() can only handle the former case, so we
961 // check the DeclContext kind.
962 if (F->getLexicalDeclContext()->getDeclKind() ==
963 clang::Decl::ClassTemplateSpecialization) {
964 auto OuterLevelArgs = SemaRef.getTemplateInstantiationArgs(
965 D: F, DC: F->getLexicalDeclContext(),
966 /*Final=*/false, /*Innermost=*/std::nullopt,
967 /*RelativeToPrimary=*/true,
968 /*Pattern=*/nullptr,
969 /*ForConstraintInstantiation=*/true);
970 for (auto It : OuterLevelArgs)
971 ArgsForBuildingRC.addOuterTemplateArguments(Args: It.Args);
972 }
973
974 ExprResult E = SemaRef.SubstExpr(E: RC, TemplateArgs: ArgsForBuildingRC);
975 if (E.isInvalid())
976 return nullptr;
977
978 auto Conjunction =
979 SemaRef.BuildBinOp(S: SemaRef.getCurScope(), OpLoc: SourceLocation{},
980 Opc: BinaryOperatorKind::BO_LAnd, LHSExpr: E.get(), RHSExpr: IsDeducible);
981 if (Conjunction.isInvalid())
982 return nullptr;
983 return Conjunction.getAs<Expr>();
984}
985// Build the is_deducible constraint for the alias deduction guides.
986// [over.match.class.deduct]p3.3:
987// ... and a constraint that is satisfied if and only if the arguments
988// of A are deducible (see below) from the return type.
989Expr *buildIsDeducibleConstraint(Sema &SemaRef,
990 TypeAliasTemplateDecl *AliasTemplate,
991 QualType ReturnType,
992 SmallVector<NamedDecl *> TemplateParams) {
993 ASTContext &Context = SemaRef.Context;
994 // Constraint AST nodes must use uninstantiated depth.
995 if (auto *PrimaryTemplate =
996 AliasTemplate->getInstantiatedFromMemberTemplate();
997 PrimaryTemplate && TemplateParams.size() > 0) {
998 LocalInstantiationScope Scope(SemaRef);
999
1000 // Adjust the depth for TemplateParams.
1001 unsigned AdjustDepth = PrimaryTemplate->getTemplateDepth();
1002 SmallVector<TemplateArgument> TransformedTemplateArgs;
1003 for (auto *TP : TemplateParams) {
1004 // Rebuild any internal references to earlier parameters and reindex
1005 // as we go.
1006 MultiLevelTemplateArgumentList Args;
1007 Args.setKind(TemplateSubstitutionKind::Rewrite);
1008 Args.addOuterTemplateArguments(Args: TransformedTemplateArgs);
1009 NamedDecl *NewParam = transformTemplateParameter(
1010 SemaRef, DC: AliasTemplate->getDeclContext(), TemplateParam: TP, Args,
1011 /*NewIndex=*/TransformedTemplateArgs.size(),
1012 NewDepth: getDepthAndIndex(ND: TP).first + AdjustDepth);
1013
1014 TemplateArgument NewTemplateArgument =
1015 Context.getInjectedTemplateArg(ParamDecl: NewParam);
1016 TransformedTemplateArgs.push_back(Elt: NewTemplateArgument);
1017 }
1018 // Transformed the ReturnType to restore the uninstantiated depth.
1019 MultiLevelTemplateArgumentList Args;
1020 Args.setKind(TemplateSubstitutionKind::Rewrite);
1021 Args.addOuterTemplateArguments(Args: TransformedTemplateArgs);
1022 ReturnType = SemaRef.SubstType(
1023 T: ReturnType, TemplateArgs: Args, Loc: AliasTemplate->getLocation(),
1024 Entity: Context.DeclarationNames.getCXXDeductionGuideName(TD: AliasTemplate));
1025 }
1026
1027 SmallVector<TypeSourceInfo *> IsDeducibleTypeTraitArgs = {
1028 Context.getTrivialTypeSourceInfo(
1029 T: Context.getDeducedTemplateSpecializationType(
1030 Keyword: ElaboratedTypeKeyword::None, Template: TemplateName(AliasTemplate),
1031 /*DeducedType=*/QualType(),
1032 /*IsDependent=*/true),
1033 Loc: AliasTemplate->getLocation()), // template specialization type whose
1034 // arguments will be deduced.
1035 Context.getTrivialTypeSourceInfo(
1036 T: ReturnType, Loc: AliasTemplate->getLocation()), // type from which template
1037 // arguments are deduced.
1038 };
1039 return TypeTraitExpr::Create(
1040 C: Context, T: Context.getLogicalOperationType(), Loc: AliasTemplate->getLocation(),
1041 Kind: TypeTrait::BTT_IsDeducible, Args: IsDeducibleTypeTraitArgs,
1042 RParenLoc: AliasTemplate->getLocation(), /*Value*/ false);
1043}
1044
1045std::pair<TemplateDecl *, llvm::ArrayRef<TemplateArgument>>
1046getRHSTemplateDeclAndArgs(Sema &SemaRef, TypeAliasTemplateDecl *AliasTemplate) {
1047 auto RhsType = AliasTemplate->getTemplatedDecl()->getUnderlyingType();
1048 TemplateDecl *Template = nullptr;
1049 llvm::ArrayRef<TemplateArgument> AliasRhsTemplateArgs;
1050 if (const auto *TST = RhsType->getAs<TemplateSpecializationType>()) {
1051 // Cases where the RHS of the alias is dependent. e.g.
1052 // template<typename T>
1053 // using AliasFoo1 = Foo<T>; // a class/type alias template specialization
1054 Template = TST->getTemplateName().getAsTemplateDecl();
1055 AliasRhsTemplateArgs =
1056 TST->getAsNonAliasTemplateSpecializationType()->template_arguments();
1057 } else if (const auto *RT = RhsType->getAs<RecordType>()) {
1058 // Cases where template arguments in the RHS of the alias are not
1059 // dependent. e.g.
1060 // using AliasFoo = Foo<bool>;
1061 if (const auto *CTSD =
1062 dyn_cast<ClassTemplateSpecializationDecl>(Val: RT->getDecl())) {
1063 Template = CTSD->getSpecializedTemplate();
1064 AliasRhsTemplateArgs = CTSD->getTemplateArgs().asArray();
1065 }
1066 }
1067 return {Template, AliasRhsTemplateArgs};
1068}
1069
1070bool IsNonDeducedArgument(const TemplateArgument &TA) {
1071 // The following cases indicate the template argument is non-deducible:
1072 // 1. The result is null. E.g. When it comes from a default template
1073 // argument that doesn't appear in the alias declaration.
1074 // 2. The template parameter is a pack and that cannot be deduced from
1075 // the arguments within the alias declaration.
1076 // Non-deducible template parameters will persist in the transformed
1077 // deduction guide.
1078 return TA.isNull() ||
1079 (TA.getKind() == TemplateArgument::Pack &&
1080 llvm::any_of(Range: TA.pack_elements(), P: IsNonDeducedArgument));
1081}
1082
1083// Build deduction guides for a type alias template from the given underlying
1084// deduction guide F.
1085FunctionTemplateDecl *
1086BuildDeductionGuideForTypeAlias(Sema &SemaRef,
1087 TypeAliasTemplateDecl *AliasTemplate,
1088 FunctionTemplateDecl *F, SourceLocation Loc) {
1089 LocalInstantiationScope Scope(SemaRef);
1090 Sema::NonSFINAEContext _1(SemaRef);
1091 Sema::InstantiatingTemplate BuildingDeductionGuides(
1092 SemaRef, AliasTemplate->getLocation(), F,
1093 Sema::InstantiatingTemplate::BuildingDeductionGuidesTag{});
1094 if (BuildingDeductionGuides.isInvalid())
1095 return nullptr;
1096
1097 auto &Context = SemaRef.Context;
1098 auto [Template, AliasRhsTemplateArgs] =
1099 getRHSTemplateDeclAndArgs(SemaRef, AliasTemplate);
1100
1101 // We need both types desugared, before we continue to perform type deduction.
1102 // The intent is to get the template argument list 'matched', e.g. in the
1103 // following case:
1104 //
1105 //
1106 // template <class T>
1107 // struct A {};
1108 // template <class T>
1109 // using Foo = A<A<T>>;
1110 // template <class U = int>
1111 // using Bar = Foo<U>;
1112 //
1113 // In terms of Bar, we want U (which has the default argument) to appear in
1114 // the synthesized deduction guide, but U would remain undeduced if we deduced
1115 // A<A<T>> using Foo<U> directly.
1116 //
1117 // Instead, we need to canonicalize both against A, i.e. A<A<T>> and A<A<U>>,
1118 // such that T can be deduced as U.
1119 auto RType = F->getTemplatedDecl()->getReturnType();
1120 // The (trailing) return type of the deduction guide.
1121 const auto *FReturnType = RType->getAs<TemplateSpecializationType>();
1122 if (const auto *ICNT = RType->getAsCanonical<InjectedClassNameType>())
1123 // implicitly-generated deduction guide.
1124 FReturnType = cast<TemplateSpecializationType>(
1125 Val: ICNT->getDecl()->getCanonicalTemplateSpecializationType(
1126 Ctx: SemaRef.Context));
1127 assert(FReturnType && "expected to see a return type");
1128 // Deduce template arguments of the deduction guide f from the RHS of
1129 // the alias.
1130 //
1131 // C++ [over.match.class.deduct]p3: ...For each function or function
1132 // template f in the guides of the template named by the
1133 // simple-template-id of the defining-type-id, the template arguments
1134 // of the return type of f are deduced from the defining-type-id of A
1135 // according to the process in [temp.deduct.type] with the exception
1136 // that deduction does not fail if not all template arguments are
1137 // deduced.
1138 //
1139 //
1140 // template<typename X, typename Y>
1141 // f(X, Y) -> f<Y, X>;
1142 //
1143 // template<typename U>
1144 // using alias = f<int, U>;
1145 //
1146 // The RHS of alias is f<int, U>, we deduced the template arguments of
1147 // the return type of the deduction guide from it: Y->int, X->U
1148 sema::TemplateDeductionInfo TDeduceInfo(Loc);
1149 // Must initialize n elements, this is required by DeduceTemplateArguments.
1150 SmallVector<DeducedTemplateArgument> DeduceResults(
1151 F->getTemplateParameters()->size());
1152
1153 // FIXME: DeduceTemplateArguments stops immediately at the first
1154 // non-deducible template argument. However, this doesn't seem to cause
1155 // issues for practice cases, we probably need to extend it to continue
1156 // performing deduction for rest of arguments to align with the C++
1157 // standard.
1158 SemaRef.DeduceTemplateArguments(
1159 TemplateParams: F->getTemplateParameters(), Ps: FReturnType->template_arguments(),
1160 As: AliasRhsTemplateArgs, Info&: TDeduceInfo, Deduced&: DeduceResults,
1161 /*NumberOfArgumentsMustMatch=*/false);
1162
1163 SmallVector<TemplateArgument> DeducedArgs;
1164 SmallVector<unsigned> NonDeducedTemplateParamsInFIndex;
1165 // !!NOTE: DeduceResults respects the sequence of template parameters of
1166 // the deduction guide f.
1167 for (unsigned Index = 0; Index < DeduceResults.size(); ++Index) {
1168 const auto &D = DeduceResults[Index];
1169 if (!IsNonDeducedArgument(TA: D))
1170 DeducedArgs.push_back(Elt: D);
1171 else
1172 NonDeducedTemplateParamsInFIndex.push_back(Elt: Index);
1173 }
1174 auto DeducedAliasTemplateParams =
1175 TemplateParamsReferencedInTemplateArgumentList(
1176 SemaRef, TemplateParamsList: AliasTemplate->getTemplateParameters(), DeducedArgs);
1177 // All template arguments null by default.
1178 SmallVector<TemplateArgument> TemplateArgsForBuildingFPrime(
1179 F->getTemplateParameters()->size());
1180
1181 // Create a template parameter list for the synthesized deduction guide f'.
1182 //
1183 // C++ [over.match.class.deduct]p3.2:
1184 // If f is a function template, f' is a function template whose template
1185 // parameter list consists of all the template parameters of A
1186 // (including their default template arguments) that appear in the above
1187 // deductions or (recursively) in their default template arguments
1188 SmallVector<NamedDecl *> FPrimeTemplateParams;
1189 // Store template arguments that refer to the newly-created template
1190 // parameters, used for building `TemplateArgsForBuildingFPrime`.
1191 SmallVector<TemplateArgument, 16> TransformedDeducedAliasArgs(
1192 AliasTemplate->getTemplateParameters()->size());
1193 // We might be already within a pack expansion, but rewriting template
1194 // parameters is independent of that. (We may or may not expand new packs
1195 // when rewriting. So clear the state)
1196 Sema::ArgPackSubstIndexRAII PackSubstReset(SemaRef, std::nullopt);
1197
1198 for (unsigned AliasTemplateParamIdx : DeducedAliasTemplateParams) {
1199 auto *TP =
1200 AliasTemplate->getTemplateParameters()->getParam(Idx: AliasTemplateParamIdx);
1201 // Rebuild any internal references to earlier parameters and reindex as
1202 // we go.
1203 MultiLevelTemplateArgumentList Args;
1204 Args.setKind(TemplateSubstitutionKind::Rewrite);
1205 Args.addOuterTemplateArguments(Args: TransformedDeducedAliasArgs);
1206 NamedDecl *NewParam = transformTemplateParameter(
1207 SemaRef, DC: AliasTemplate->getDeclContext(), TemplateParam: TP, Args,
1208 /*NewIndex=*/FPrimeTemplateParams.size(), NewDepth: getDepthAndIndex(ND: TP).first);
1209 FPrimeTemplateParams.push_back(Elt: NewParam);
1210
1211 TemplateArgument NewTemplateArgument =
1212 Context.getInjectedTemplateArg(ParamDecl: NewParam);
1213 TransformedDeducedAliasArgs[AliasTemplateParamIdx] = NewTemplateArgument;
1214 }
1215 unsigned FirstUndeducedParamIdx = FPrimeTemplateParams.size();
1216
1217 // To form a deduction guide f' from f, we leverage clang's instantiation
1218 // mechanism, we construct a template argument list where the template
1219 // arguments refer to the newly-created template parameters of f', and
1220 // then apply instantiation on this template argument list to instantiate
1221 // f, this ensures all template parameter occurrences are updated
1222 // correctly.
1223 //
1224 // The template argument list is formed, in order, from
1225 // 1) For the template parameters of the alias, the corresponding deduced
1226 // template arguments
1227 // 2) For the non-deduced template parameters of f. the
1228 // (rebuilt) template arguments corresponding.
1229 //
1230 // Note: the non-deduced template arguments of `f` might refer to arguments
1231 // deduced in 1), as in a type constraint.
1232 MultiLevelTemplateArgumentList Args;
1233 Args.setKind(TemplateSubstitutionKind::Rewrite);
1234 Args.addOuterTemplateArguments(Args: TransformedDeducedAliasArgs);
1235 for (unsigned Index = 0; Index < DeduceResults.size(); ++Index) {
1236 const auto &D = DeduceResults[Index];
1237 auto *TP = F->getTemplateParameters()->getParam(Idx: Index);
1238 if (IsNonDeducedArgument(TA: D)) {
1239 // 2): Non-deduced template parameters would be substituted later.
1240 continue;
1241 }
1242 TemplateArgumentLoc Input =
1243 SemaRef.getTrivialTemplateArgumentLoc(Arg: D, NTTPType: QualType(), Loc: SourceLocation{});
1244 TemplateArgumentListInfo Output;
1245 if (SemaRef.SubstTemplateArguments(Args: Input, TemplateArgs: Args, Outputs&: Output))
1246 return nullptr;
1247 assert(TemplateArgsForBuildingFPrime[Index].isNull() &&
1248 "InstantiatedArgs must be null before setting");
1249 // CheckTemplateArgument is necessary for NTTP initializations.
1250 // FIXME: We may want to call CheckTemplateArguments instead, but we cannot
1251 // match packs as usual, since packs can appear in the middle of the
1252 // parameter list of a synthesized CTAD guide. See also the FIXME in
1253 // test/SemaCXX/cxx20-ctad-type-alias.cpp:test25.
1254 Sema::CheckTemplateArgumentInfo CTAI;
1255 for (auto TA : Output.arguments())
1256 if (SemaRef.CheckTemplateArgument(
1257 Param: TP, Arg&: TA, Template: F, TemplateLoc: F->getLocation(), RAngleLoc: F->getLocation(),
1258 /*ArgumentPackIndex=*/-1, CTAI,
1259 CTAK: Sema::CheckTemplateArgumentKind::CTAK_Specified))
1260 return nullptr;
1261 if (Input.getArgument().getKind() == TemplateArgument::Pack) {
1262 // We will substitute the non-deduced template arguments with these
1263 // transformed (unpacked at this point) arguments, where that substitution
1264 // requires a pack for the corresponding parameter packs.
1265 TemplateArgsForBuildingFPrime[Index] =
1266 TemplateArgument::CreatePackCopy(Context, Args: CTAI.SugaredConverted);
1267 } else {
1268 assert(Output.arguments().size() == 1);
1269 TemplateArgsForBuildingFPrime[Index] = CTAI.SugaredConverted[0];
1270 }
1271 }
1272
1273 // Case 2)
1274 // ...followed by the template parameters of f that were not deduced
1275 // (including their default template arguments)
1276 for (unsigned FTemplateParamIdx : NonDeducedTemplateParamsInFIndex) {
1277 auto *TP = F->getTemplateParameters()->getParam(Idx: FTemplateParamIdx);
1278 MultiLevelTemplateArgumentList Args;
1279 Args.setKind(TemplateSubstitutionKind::Rewrite);
1280 // We take a shortcut here, it is ok to reuse the
1281 // TemplateArgsForBuildingFPrime.
1282 Args.addOuterTemplateArguments(Args: TemplateArgsForBuildingFPrime);
1283 NamedDecl *NewParam = transformTemplateParameter(
1284 SemaRef, DC: F->getDeclContext(), TemplateParam: TP, Args, NewIndex: FPrimeTemplateParams.size(),
1285 NewDepth: getDepthAndIndex(ND: TP).first);
1286 FPrimeTemplateParams.push_back(Elt: NewParam);
1287
1288 assert(TemplateArgsForBuildingFPrime[FTemplateParamIdx].isNull() &&
1289 "The argument must be null before setting");
1290 TemplateArgsForBuildingFPrime[FTemplateParamIdx] =
1291 Context.getInjectedTemplateArg(ParamDecl: NewParam);
1292 }
1293
1294 auto *TemplateArgListForBuildingFPrime =
1295 TemplateArgumentList::CreateCopy(Context, Args: TemplateArgsForBuildingFPrime);
1296 // Form the f' by substituting the template arguments into f.
1297 if (auto *FPrime = SemaRef.InstantiateFunctionDeclaration(
1298 FTD: F, Args: TemplateArgListForBuildingFPrime, Loc: AliasTemplate->getLocation(),
1299 CSC: Sema::CodeSynthesisContext::BuildingDeductionGuides)) {
1300 auto *GG = cast<CXXDeductionGuideDecl>(Val: FPrime);
1301
1302 Expr *IsDeducible = buildIsDeducibleConstraint(
1303 SemaRef, AliasTemplate, ReturnType: FPrime->getReturnType(), TemplateParams: FPrimeTemplateParams);
1304 Expr *RequiresClause =
1305 buildAssociatedConstraints(SemaRef, F, AliasTemplate, DeduceResults,
1306 FirstUndeducedParamIdx, IsDeducible);
1307
1308 auto *FPrimeTemplateParamList = TemplateParameterList::Create(
1309 C: Context, TemplateLoc: AliasTemplate->getTemplateParameters()->getTemplateLoc(),
1310 LAngleLoc: AliasTemplate->getTemplateParameters()->getLAngleLoc(),
1311 Params: FPrimeTemplateParams,
1312 RAngleLoc: AliasTemplate->getTemplateParameters()->getRAngleLoc(),
1313 /*RequiresClause=*/RequiresClause);
1314 auto *Result = cast<FunctionTemplateDecl>(Val: buildDeductionGuide(
1315 SemaRef, OriginalTemplate: AliasTemplate, TemplateParams: FPrimeTemplateParamList,
1316 Ctor: GG->getCorrespondingConstructor(), ES: GG->getExplicitSpecifier(),
1317 TInfo: GG->getTypeSourceInfo(), LocStart: AliasTemplate->getBeginLoc(),
1318 Loc: AliasTemplate->getLocation(), LocEnd: AliasTemplate->getEndLoc(),
1319 IsImplicit: F->isImplicit()));
1320 auto *DGuide = cast<CXXDeductionGuideDecl>(Val: Result->getTemplatedDecl());
1321 DGuide->setDeductionCandidateKind(GG->getDeductionCandidateKind());
1322 DGuide->setSourceDeductionGuide(
1323 cast<CXXDeductionGuideDecl>(Val: F->getTemplatedDecl()));
1324 DGuide->setSourceDeductionGuideKind(
1325 CXXDeductionGuideDecl::SourceDeductionGuideKind::Alias);
1326 return Result;
1327 }
1328 return nullptr;
1329}
1330
1331void DeclareImplicitDeductionGuidesForTypeAlias(
1332 Sema &SemaRef, TypeAliasTemplateDecl *AliasTemplate, SourceLocation Loc) {
1333 if (AliasTemplate->isInvalidDecl())
1334 return;
1335 auto &Context = SemaRef.Context;
1336 auto [Template, AliasRhsTemplateArgs] =
1337 getRHSTemplateDeclAndArgs(SemaRef, AliasTemplate);
1338 if (!Template)
1339 return;
1340 auto SourceDeductionGuides = getSourceDeductionGuides(
1341 Name: Context.DeclarationNames.getCXXDeductionGuideName(TD: AliasTemplate),
1342 DC: AliasTemplate->getDeclContext());
1343
1344 DeclarationNameInfo NameInfo(
1345 Context.DeclarationNames.getCXXDeductionGuideName(TD: Template), Loc);
1346 LookupResult Guides(SemaRef, NameInfo, clang::Sema::LookupOrdinaryName);
1347 SemaRef.LookupQualifiedName(R&: Guides, LookupCtx: Template->getDeclContext());
1348 Guides.suppressDiagnostics();
1349
1350 for (auto *G : Guides) {
1351 if (auto *DG = dyn_cast<CXXDeductionGuideDecl>(Val: G)) {
1352 if (SourceDeductionGuides.contains(V: DG))
1353 continue;
1354 // The deduction guide is a non-template function decl, we just clone it.
1355 auto *FunctionType =
1356 SemaRef.Context.getTrivialTypeSourceInfo(T: DG->getType());
1357 FunctionProtoTypeLoc FPTL =
1358 FunctionType->getTypeLoc().castAs<FunctionProtoTypeLoc>();
1359
1360 // Clone the parameters.
1361 for (unsigned I = 0, N = DG->getNumParams(); I != N; ++I) {
1362 const auto *P = DG->getParamDecl(i: I);
1363 auto *TSI = SemaRef.Context.getTrivialTypeSourceInfo(T: P->getType());
1364 ParmVarDecl *NewParam = ParmVarDecl::Create(
1365 C&: SemaRef.Context, DC: G->getDeclContext(),
1366 StartLoc: DG->getParamDecl(i: I)->getBeginLoc(), IdLoc: P->getLocation(), Id: nullptr,
1367 T: TSI->getType(), TInfo: TSI, S: SC_None, DefArg: nullptr);
1368 NewParam->setScopeInfo(scopeDepth: 0, parameterIndex: I);
1369 FPTL.setParam(i: I, VD: NewParam);
1370 }
1371 auto *Transformed = cast<CXXDeductionGuideDecl>(Val: buildDeductionGuide(
1372 SemaRef, OriginalTemplate: AliasTemplate, /*TemplateParams=*/nullptr,
1373 /*Constructor=*/Ctor: nullptr, ES: DG->getExplicitSpecifier(), TInfo: FunctionType,
1374 LocStart: AliasTemplate->getBeginLoc(), Loc: AliasTemplate->getLocation(),
1375 LocEnd: AliasTemplate->getEndLoc(), IsImplicit: DG->isImplicit()));
1376 Transformed->setSourceDeductionGuide(DG);
1377 Transformed->setSourceDeductionGuideKind(
1378 CXXDeductionGuideDecl::SourceDeductionGuideKind::Alias);
1379
1380 // FIXME: Here the synthesized deduction guide is not a templated
1381 // function. Per [dcl.decl]p4, the requires-clause shall be present only
1382 // if the declarator declares a templated function, a bug in standard?
1383 AssociatedConstraint Constraint(buildIsDeducibleConstraint(
1384 SemaRef, AliasTemplate, ReturnType: Transformed->getReturnType(), TemplateParams: {}));
1385 if (const AssociatedConstraint &RC = DG->getTrailingRequiresClause()) {
1386 auto Conjunction = SemaRef.BuildBinOp(
1387 S: SemaRef.getCurScope(), OpLoc: SourceLocation{},
1388 Opc: BinaryOperatorKind::BO_LAnd, LHSExpr: const_cast<Expr *>(RC.ConstraintExpr),
1389 RHSExpr: const_cast<Expr *>(Constraint.ConstraintExpr));
1390 if (!Conjunction.isInvalid()) {
1391 Constraint.ConstraintExpr = Conjunction.getAs<Expr>();
1392 Constraint.ArgPackSubstIndex = RC.ArgPackSubstIndex;
1393 }
1394 }
1395 Transformed->setTrailingRequiresClause(Constraint);
1396 continue;
1397 }
1398 FunctionTemplateDecl *F = dyn_cast<FunctionTemplateDecl>(Val: G);
1399 if (!F || SourceDeductionGuides.contains(V: F->getTemplatedDecl()))
1400 continue;
1401 // The **aggregate** deduction guides are handled in a different code path
1402 // (DeclareAggregateDeductionGuideFromInitList), which involves the tricky
1403 // cache.
1404 if (cast<CXXDeductionGuideDecl>(Val: F->getTemplatedDecl())
1405 ->getDeductionCandidateKind() == DeductionCandidate::Aggregate)
1406 continue;
1407
1408 BuildDeductionGuideForTypeAlias(SemaRef, AliasTemplate, F, Loc);
1409 }
1410}
1411
1412// Build an aggregate deduction guide for a type alias template.
1413FunctionTemplateDecl *DeclareAggregateDeductionGuideForTypeAlias(
1414 Sema &SemaRef, TypeAliasTemplateDecl *AliasTemplate,
1415 MutableArrayRef<QualType> ParamTypes, SourceLocation Loc) {
1416 TemplateDecl *RHSTemplate =
1417 getRHSTemplateDeclAndArgs(SemaRef, AliasTemplate).first;
1418 if (!RHSTemplate)
1419 return nullptr;
1420
1421 llvm::SmallVector<TypedefNameDecl *> TypedefDecls;
1422 llvm::SmallVector<QualType> NewParamTypes;
1423 ExtractTypeForDeductionGuide TypeAliasTransformer(SemaRef, TypedefDecls);
1424 for (QualType P : ParamTypes) {
1425 QualType Type = TypeAliasTransformer.TransformType(T: P);
1426 if (Type.isNull())
1427 return nullptr;
1428 NewParamTypes.push_back(Elt: Type);
1429 }
1430
1431 auto *RHSDeductionGuide = SemaRef.DeclareAggregateDeductionGuideFromInitList(
1432 Template: RHSTemplate, ParamTypes: NewParamTypes, Loc);
1433 if (!RHSDeductionGuide)
1434 return nullptr;
1435
1436 for (TypedefNameDecl *TD : TypedefDecls)
1437 TD->setDeclContext(RHSDeductionGuide->getTemplatedDecl());
1438
1439 return BuildDeductionGuideForTypeAlias(SemaRef, AliasTemplate,
1440 F: RHSDeductionGuide, Loc);
1441}
1442
1443} // namespace
1444
1445FunctionTemplateDecl *Sema::DeclareAggregateDeductionGuideFromInitList(
1446 TemplateDecl *Template, MutableArrayRef<QualType> ParamTypes,
1447 SourceLocation Loc) {
1448 llvm::FoldingSetNodeID ID;
1449 ID.AddPointer(Ptr: Template);
1450 for (auto &T : ParamTypes)
1451 T.getCanonicalType().Profile(ID);
1452 unsigned Hash = ID.ComputeHash();
1453
1454 auto Found = AggregateDeductionCandidates.find(Val: Hash);
1455 if (Found != AggregateDeductionCandidates.end()) {
1456 CXXDeductionGuideDecl *GD = Found->getSecond();
1457 return GD->getDescribedFunctionTemplate();
1458 }
1459
1460 if (auto *AliasTemplate = llvm::dyn_cast<TypeAliasTemplateDecl>(Val: Template)) {
1461 if (auto *FTD = DeclareAggregateDeductionGuideForTypeAlias(
1462 SemaRef&: *this, AliasTemplate, ParamTypes, Loc)) {
1463 auto *GD = cast<CXXDeductionGuideDecl>(Val: FTD->getTemplatedDecl());
1464 GD->setDeductionCandidateKind(DeductionCandidate::Aggregate);
1465 AggregateDeductionCandidates[Hash] = GD;
1466 return FTD;
1467 }
1468 }
1469
1470 if (CXXRecordDecl *DefRecord =
1471 cast<CXXRecordDecl>(Val: Template->getTemplatedDecl())->getDefinition()) {
1472 if (TemplateDecl *DescribedTemplate =
1473 DefRecord->getDescribedClassTemplate())
1474 Template = DescribedTemplate;
1475 }
1476
1477 DeclContext *DC = Template->getDeclContext();
1478 if (DC->isDependentContext())
1479 return nullptr;
1480
1481 ConvertConstructorToDeductionGuideTransform Transform(
1482 *this, cast<ClassTemplateDecl>(Val: Template));
1483 if (!isCompleteType(Loc, T: Transform.DeducedType))
1484 return nullptr;
1485
1486 // In case we were expanding a pack when we attempted to declare deduction
1487 // guides, turn off pack expansion for everything we're about to do.
1488 ArgPackSubstIndexRAII SubstIndex(*this, std::nullopt);
1489 // Create a template instantiation record to track the "instantiation" of
1490 // constructors into deduction guides.
1491 InstantiatingTemplate BuildingDeductionGuides(
1492 *this, Loc, Template,
1493 Sema::InstantiatingTemplate::BuildingDeductionGuidesTag{});
1494 if (BuildingDeductionGuides.isInvalid())
1495 return nullptr;
1496
1497 ClassTemplateDecl *Pattern =
1498 Transform.NestedPattern ? Transform.NestedPattern : Transform.Template;
1499 ContextRAII SavedContext(*this, Pattern->getTemplatedDecl());
1500
1501 auto *FTD = cast<FunctionTemplateDecl>(
1502 Val: Transform.buildSimpleDeductionGuide(ParamTypes));
1503 SavedContext.pop();
1504 auto *GD = cast<CXXDeductionGuideDecl>(Val: FTD->getTemplatedDecl());
1505 GD->setDeductionCandidateKind(DeductionCandidate::Aggregate);
1506 AggregateDeductionCandidates[Hash] = GD;
1507 return FTD;
1508}
1509
1510void Sema::DeclareImplicitDeductionGuides(TemplateDecl *Template,
1511 SourceLocation Loc) {
1512 if (auto *AliasTemplate = llvm::dyn_cast<TypeAliasTemplateDecl>(Val: Template)) {
1513 DeclareImplicitDeductionGuidesForTypeAlias(SemaRef&: *this, AliasTemplate, Loc);
1514 return;
1515 }
1516 CXXRecordDecl *DefRecord =
1517 dyn_cast_or_null<CXXRecordDecl>(Val: Template->getTemplatedDecl());
1518 if (!DefRecord)
1519 return;
1520 if (const CXXRecordDecl *Definition = DefRecord->getDefinition()) {
1521 if (TemplateDecl *DescribedTemplate =
1522 Definition->getDescribedClassTemplate())
1523 Template = DescribedTemplate;
1524 }
1525
1526 DeclContext *DC = Template->getDeclContext();
1527 if (DC->isDependentContext())
1528 return;
1529
1530 ConvertConstructorToDeductionGuideTransform Transform(
1531 *this, cast<ClassTemplateDecl>(Val: Template));
1532 if (!isCompleteType(Loc, T: Transform.DeducedType))
1533 return;
1534
1535 if (hasDeclaredDeductionGuides(Name: Transform.DeductionGuideName, DC))
1536 return;
1537
1538 // In case we were expanding a pack when we attempted to declare deduction
1539 // guides, turn off pack expansion for everything we're about to do.
1540 ArgPackSubstIndexRAII SubstIndex(*this, std::nullopt);
1541 // Create a template instantiation record to track the "instantiation" of
1542 // constructors into deduction guides.
1543 InstantiatingTemplate BuildingDeductionGuides(
1544 *this, Loc, Template,
1545 Sema::InstantiatingTemplate::BuildingDeductionGuidesTag{});
1546 if (BuildingDeductionGuides.isInvalid())
1547 return;
1548
1549 // Convert declared constructors into deduction guide templates.
1550 // FIXME: Skip constructors for which deduction must necessarily fail (those
1551 // for which some class template parameter without a default argument never
1552 // appears in a deduced context).
1553 ClassTemplateDecl *Pattern =
1554 Transform.NestedPattern ? Transform.NestedPattern : Transform.Template;
1555 ContextRAII SavedContext(*this, Pattern->getTemplatedDecl());
1556 llvm::SmallPtrSet<NamedDecl *, 8> ProcessedCtors;
1557 bool AddedAny = false;
1558 for (NamedDecl *D : LookupConstructors(Class: Pattern->getTemplatedDecl())) {
1559 D = D->getUnderlyingDecl();
1560 if (D->isInvalidDecl() || D->isImplicit())
1561 continue;
1562
1563 D = cast<NamedDecl>(Val: D->getCanonicalDecl());
1564
1565 // Within C++20 modules, we may have multiple same constructors in
1566 // multiple same RecordDecls. And it doesn't make sense to create
1567 // duplicated deduction guides for the duplicated constructors.
1568 if (ProcessedCtors.count(Ptr: D))
1569 continue;
1570
1571 auto *FTD = dyn_cast<FunctionTemplateDecl>(Val: D);
1572 auto *CD =
1573 dyn_cast_or_null<CXXConstructorDecl>(Val: FTD ? FTD->getTemplatedDecl() : D);
1574 // Class-scope explicit specializations (MS extension) do not result in
1575 // deduction guides.
1576 if (!CD || (!FTD && CD->isFunctionTemplateSpecialization()))
1577 continue;
1578
1579 // Cannot make a deduction guide when unparsed arguments are present.
1580 if (llvm::any_of(Range: CD->parameters(), P: [](ParmVarDecl *P) {
1581 return !P || P->hasUnparsedDefaultArg();
1582 }))
1583 continue;
1584
1585 ProcessedCtors.insert(Ptr: D);
1586 Transform.transformConstructor(FTD, CD);
1587 AddedAny = true;
1588 }
1589
1590 // C++17 [over.match.class.deduct]
1591 // -- If C is not defined or does not declare any constructors, an
1592 // additional function template derived as above from a hypothetical
1593 // constructor C().
1594 if (!AddedAny)
1595 Transform.buildSimpleDeductionGuide(ParamTypes: {});
1596
1597 // -- An additional function template derived as above from a hypothetical
1598 // constructor C(C), called the copy deduction candidate.
1599 cast<CXXDeductionGuideDecl>(
1600 Val: cast<FunctionTemplateDecl>(
1601 Val: Transform.buildSimpleDeductionGuide(ParamTypes: Transform.DeducedType))
1602 ->getTemplatedDecl())
1603 ->setDeductionCandidateKind(DeductionCandidate::Copy);
1604
1605 SavedContext.pop();
1606}
1607