clang: lib/Sema/SemaTemplateDeductionGuide.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
45#include "llvm/ADT/ArrayRef.h"
46#include "llvm/ADT/STLExtras.h"
47#include "llvm/ADT/SmallVector.h"
48#include "llvm/Support/Casting.h"
49#include "llvm/Support/ErrorHandling.h"
50#include
51#include
52#include
53
54using namespace clang;
55using namespace sema;
56
57namespace {
58
59
60class ExtractTypeForDeductionGuide
61 : public TreeTransform {
65 std::optional TypedefNameInstantiator;
66
67public:
69 ExtractTypeForDeductionGuide(
70 Sema &SemaRef,
74 : Base(SemaRef), MaterializedTypedefs(MaterializedTypedefs),
75 NestedPattern(NestedPattern),
76 OuterInstantiationArgs(OuterInstantiationArgs) {
77 if (OuterInstantiationArgs)
78 TypedefNameInstantiator.emplace(
80 *OuterInstantiationArgs);
81 }
82
84
85
86
87 bool mightReferToOuterTemplateParameters(TypedefNameDecl *Typedef) {
88 if (!NestedPattern)
89 return false;
90
92 if (DC->Equals(TargetDC))
93 return true;
95 if (DC->Equals(TargetDC))
96 return true;
98 }
99 return false;
100 };
101
103 return true;
105 return true;
106 return false;
107 }
108
113 if (!OuterInstantiationArgs ||
114 !isa_and_present(Template.getAsTemplateDecl()))
116 TemplateArgs);
117
118 auto *TATD = cast(Template.getAsTemplateDecl());
119 auto *Pattern = TATD;
120 while (Pattern->getInstantiatedFromMemberTemplate())
121 Pattern = Pattern->getInstantiatedFromMemberTemplate();
122 if (!mightReferToOuterTemplateParameters(Pattern->getTemplatedDecl()))
124 TemplateArgs);
125
127 TypedefNameInstantiator->InstantiateTypeAliasTemplateDecl(TATD);
128 if (!NewD)
130
131 auto *NewTATD = cast(NewD);
132 MaterializedTypedefs.push_back(NewTATD->getTemplatedDecl());
133
135 TemplateName(NewTATD), TemplateNameLoc, TemplateArgs);
136 }
137
142
143
145
146
147
148
149
150
151
152
153
154
155
156
157
158 if (OuterInstantiationArgs && InDependentContext &&
160 Decl = cast_if_present(
161 TypedefNameInstantiator->InstantiateTypedefNameDecl(
162 OrigDecl, isa(OrigDecl)));
165 MaterializedTypedefs.push_back(Decl);
166 } else if (InDependentContext) {
171 if (isa(OrigDecl))
175 else {
176 assert(isa(OrigDecl) && "Not a Type alias or typedef");
180 }
181 MaterializedTypedefs.push_back(Decl);
182 }
183
187
188 return TDTy;
189 }
190};
191
192
193
194
195
196
198buildDeductionGuide(Sema &SemaRef, TemplateDecl *OriginalTemplate,
204 Expr *FunctionTrailingRC = nullptr) {
206 auto DeductionGuideName =
208 OriginalTemplate);
209
213
214
216 SemaRef.Context, DC, LocStart, ES, Name, TInfo->getType(), TInfo, LocEnd,
217 Ctor, DeductionCandidate::Normal, FunctionTrailingRC);
218 Guide->setImplicit(IsImplicit);
219 Guide->setParams(Params);
220
221 for (auto *Param : Params)
222 Param->setDeclContext(Guide);
223 for (auto *TD : MaterializedTypedefs)
224 TD->setDeclContext(Guide);
225 if (isa(DC))
227
228 if (!TemplateParams) {
230 return Guide;
231 }
232
234 SemaRef.Context, DC, Loc, DeductionGuideName, TemplateParams, Guide);
235 GuideTemplate->setImplicit(IsImplicit);
236 Guide->setDescribedFunctionTemplate(GuideTemplate);
237
238 if (isa(DC))
239 GuideTemplate->setAccess(AS_public);
240
241 DC->addDecl(GuideTemplate);
242 return GuideTemplate;
243}
244
245
249 bool EvaluateConstraint) {
250
251
258 : std::nullopt);
261 EvaluateConstraint);
267 NewTTP->setDefaultArgument(SemaRef.Context, InstantiatedDefaultArg);
268 }
270 return NewTTP;
271}
272
273template
274NonTypeTemplateOrTemplateTemplateParmDecl *
276 NonTypeTemplateOrTemplateTemplateParmDecl *OldParam,
278 unsigned NewDepth) {
279
280
281 auto *NewParam = cast(
282 SemaRef.SubstDecl(OldParam, DC, Args));
283 NewParam->setPosition(NewIndex);
284 NewParam->setDepth(NewDepth);
285 return NewParam;
286}
287
291 unsigned NewIndex, unsigned NewDepth,
292 bool EvaluateConstraint = true) {
293 if (auto *TTP = dyn_cast(TemplateParam))
294 return transformTemplateTypeParam(
295 SemaRef, DC, TTP, Args, NewDepth, NewIndex,
296 EvaluateConstraint);
297 if (auto *TTP = dyn_cast(TemplateParam))
298 return transformTemplateParam(SemaRef, DC, TTP, Args, NewIndex, NewDepth);
299 if (auto *NTTP = dyn_cast(TemplateParam))
300 return transformTemplateParam(SemaRef, DC, NTTP, Args, NewIndex, NewDepth);
301 llvm_unreachable("Unhandled template parameter types");
302}
303
304
305
306struct ConvertConstructorToDeductionGuideTransform {
307 ConvertConstructorToDeductionGuideTransform(Sema &S,
309 : SemaRef(S), Template(Template) {
310
311
315 break;
317 NestedPattern = Pattern;
318 }
319
320 if (NestedPattern)
322 }
323
324 Sema &SemaRef;
327
332
334
335
336
338
339
340
342
343
347
349
350
351
352
353
354
355
356
361 if (FTD) {
364 AllParams.reserve(TemplateParams->size() + InnerParams->size());
365 AllParams.insert(AllParams.begin(), TemplateParams->begin(),
366 TemplateParams->end());
367 SubstArgs.reserve(InnerParams->size());
368 Depth1Args.reserve(InnerParams->size());
369
370
371
372 for (NamedDecl *Param : *InnerParams) {
374 Args.setKind(TemplateSubstitutionKind::Rewrite);
377 if (NestedPattern)
380 NamedDecl *NewParam = transformTemplateParameter(
381 SemaRef, DC, Param, Args, Index + Depth1IndexAdjustment, Depth - 1);
382 if (!NewParam)
383 return nullptr;
384
385
387
388 if (NestedPattern) {
390 NewParam = transformTemplateParameter(
391 SemaRef, DC, NewParam, OuterInstantiationArgs, Index,
393 false);
394 }
395
397 "Unexpected template parameter depth");
398
399 AllParams.push_back(NewParam);
401 }
402
403
404 Expr *RequiresClause = nullptr;
405 if (Expr *InnerRC = InnerParams->getRequiresClause()) {
407 Args.setKind(TemplateSubstitutionKind::Rewrite);
410 if (NestedPattern)
414 if (.isUsable())
415 return nullptr;
416 RequiresClause = E.get();
417 }
418
419 TemplateParams = TemplateParameterList::Create(
420 SemaRef.Context, InnerParams->getTemplateLoc(),
421 InnerParams->getLAngleLoc(), AllParams, InnerParams->getRAngleLoc(),
422 RequiresClause);
423 }
424
425
426
427
429 Args.setKind(TemplateSubstitutionKind::Rewrite);
430 if (FTD) {
433 }
434
438 assert(FPTL && "no prototype for constructor declaration");
439
440
441
442
446 QualType NewType = transformFunctionProtoType(TLB, FPTL, Params, Args,
447 MaterializedTypedefs);
448 if (NewType.isNull())
449 return nullptr;
451
452
453
454
455 Expr *FunctionTrailingRC = nullptr;
458 Args.setKind(TemplateSubstitutionKind::Rewrite);
461 if (NestedPattern)
464 if (.isUsable())
465 return nullptr;
466 FunctionTrailingRC = E.get();
467 }
468
469
470
471
472
473
474
475
476 if (OuterRC) {
477
478
479 if (!FunctionTrailingRC)
480 FunctionTrailingRC = OuterRC;
481 else
483 SemaRef.Context, OuterRC, FunctionTrailingRC,
486 }
487
488 return buildDeductionGuide(
491 true, MaterializedTypedefs, FunctionTrailingRC);
492 }
493
494
497
498
502 DeductionGuideName, EPI);
504 if (NestedPattern)
505 TSI = SemaRef.SubstType(TSI, OuterInstantiationArgs, Loc,
506 DeductionGuideName);
507
508 if (!TSI)
509 return nullptr;
510
513
514
516 for (auto T : ParamTypes) {
518 if (NestedPattern)
519 TSI = SemaRef.SubstType(TSI, OuterInstantiationArgs, Loc,
521 if (!TSI)
522 return nullptr;
523
528 FPTL.setParam(Params.size(), NewParam);
529 Params.push_back(NewParam);
530 }
531
532 return buildDeductionGuide(
535 }
536
537private:
538 QualType transformFunctionProtoType(
545
546
547 for (auto *OldParam : TL.getParams()) {
549
550
551
552
553
554
555
556
557
558 if (NestedPattern) {
559 NewParam = transformFunctionTypeParam(
560 NewParam, OuterInstantiationArgs, MaterializedTypedefs,
561 true);
562 if (!NewParam)
564 }
565
566
567
568 NewParam =
569 transformFunctionTypeParam(NewParam, Args, MaterializedTypedefs,
570 false);
571 if (!NewParam)
573 ParamTypes.push_back(NewParam->getType());
574 Params.push_back(NewParam);
575 }
576
577
578
579
580
581
582
583
584
585
588
589
590
594
596 ReturnType, ParamTypes, TL.getBeginLoc(), DeductionGuideName, EPI);
597 if (Result.isNull())
599
606 for (unsigned I = 0, E = NewTL.getNumParams(); I != E; ++I)
607 NewTL.setParam(I, Params[I]);
608
609 return Result;
610 }
611
615 bool TransformingOuterPatterns) {
619
621 NewDI =
622 SemaRef.SubstType(PackTL.getPatternLoc(), Args,
624 if (!NewDI)
625 return nullptr;
626 NewDI =
628 PackTL.getTypePtr()->getNumExpansions());
629 } else
632 if (!NewDI)
633 return nullptr;
634
635
636
637
638
639 NewDI = ExtractTypeForDeductionGuide(
640 SemaRef, MaterializedTypedefs, NestedPattern,
641 TransformingOuterPatterns ? &Args : nullptr)
642 .transform(NewDI);
643
644
645
648
649
651 NewDefArg = new (SemaRef.Context)
657 }
658
659 auto NewType = NewDI->getType();
662
670 return NewParam;
671 }
672};
673
674
675
681 llvm::BitVector ReferencedTemplateParams;
682
683 TemplateParamsReferencedFinder(
685 : TemplateParamList(TemplateParamList),
686 ReferencedTemplateParams(TemplateParamList->size()) {}
687
689
690
692 return true;
693 }
694
695 bool VisitDeclRefExpr(DeclRefExpr *DRE) override {
697 return true;
698 }
699
702 MarkAppeared(TD);
704 }
705
706 void MarkAppeared(NamedDecl *ND) {
710 Mark(Depth, Index);
711 }
712 }
713 void Mark(unsigned Depth, unsigned Index) {
714 if (Index < TemplateParamList->size() &&
716 ReferencedTemplateParams.set(Index);
717 }
718 };
719 TemplateParamsReferencedFinder Finder(TemplateParamsList);
720 Finder.TraverseTemplateArguments(DeducedArgs);
721
723 for (unsigned Index = 0; Index < TemplateParamsList->size(); ++Index) {
724 if (Finder.ReferencedTemplateParams[Index])
725 Results.push_back(Index);
726 }
727 return Results;
728}
729
731
732
733 assert(Name.getNameKind() ==
734 DeclarationName::NameKind::CXXDeductionGuideName &&
735 "name must be a deduction guide name");
736 auto Existing = DC->lookup(Name);
737 for (auto *D : Existing)
739 return true;
740 return false;
741}
742
743
744
745
746
747
748
749
750
755 unsigned FirstUndeducedParamIdx, Expr *IsDeducible) {
757 if (!RC)
758 return IsDeducible;
759
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780 unsigned AdjustDepth = 0;
781 if (auto *PrimaryTemplate =
782 AliasTemplate->getInstantiatedFromMemberTemplate())
783 AdjustDepth = PrimaryTemplate->getTemplateDepth();
784
785
786
788
789 for (auto *TP : *AliasTemplate->getTemplateParameters()) {
790
791
793 Args.setKind(TemplateSubstitutionKind::Rewrite);
795 NamedDecl *NewParam = transformTemplateParameter(
796 SemaRef, AliasTemplate->getDeclContext(), TP, Args,
797 AdjustedAliasTemplateArgs.size(),
799
802 AdjustedAliasTemplateArgs.push_back(NewTemplateArgument);
803 }
804
805
808
810 Args.setKind(TemplateSubstitutionKind::Rewrite);
812
813 for (unsigned Index = 0; Index < DeduceResults.size(); ++Index) {
814 const auto &D = DeduceResults[Index];
815 if (D.isNull()) {
818 Args.setKind(TemplateSubstitutionKind::Rewrite);
820
822 transformTemplateParameter(SemaRef, F->getDeclContext(), TP, Args,
823 FirstUndeducedParamIdx,
825 FirstUndeducedParamIdx += 1;
826 assert(TemplateArgsForBuildingRC[Index].isNull());
827 TemplateArgsForBuildingRC[Index] =
829 continue;
830 }
835 assert(TemplateArgsForBuildingRC[Index].isNull() &&
836 "InstantiatedArgs must be null before setting");
837 TemplateArgsForBuildingRC[Index] = Output.getArgument();
838 }
839 }
840
841
842
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
877 clang::Decl::ClassTemplateSpecialization) {
880 false, std::nullopt,
881 true,
882 nullptr,
883 true);
884 for (auto It : OuterLevelArgs)
886 }
887
889 if (E.isInvalid())
890 return nullptr;
891
892 auto Conjunction =
894 BinaryOperatorKind::BO_LAnd, E.get(), IsDeducible);
895 if (Conjunction.isInvalid())
896 return nullptr;
897 return Conjunction.getAs<Expr>();
898}
899
900
901
902
903Expr *buildIsDeducibleConstraint(Sema &SemaRef,
908
909 if (auto *PrimaryTemplate =
910 AliasTemplate->getInstantiatedFromMemberTemplate();
911 PrimaryTemplate && TemplateParams.size() > 0) {
913
914
915 unsigned AdjustDepth = PrimaryTemplate->getTemplateDepth();
917 for (auto *TP : TemplateParams) {
918
919
921 Args.setKind(TemplateSubstitutionKind::Rewrite);
923 NamedDecl *NewParam = transformTemplateParameter(
924 SemaRef, AliasTemplate->getDeclContext(), TP, Args,
925 TransformedTemplateArgs.size(),
927
930 TransformedTemplateArgs.push_back(NewTemplateArgument);
931 }
932
934 Args.setKind(TemplateSubstitutionKind::Rewrite);
939 };
940
945 true)),
946
948 ReturnType),
949 };
952 TypeTrait::BTT_IsDeducible, IsDeducibleTypeTraitArgs,
954}
955
956std::pair<TemplateDecl *, llvm::ArrayRef>
958
960 ->getUnderlyingType()
961 .getSingleStepDesugaredType(SemaRef.Context);
965
966
967
968 Template = TST->getTemplateName().getAsTemplateDecl();
969 AliasRhsTemplateArgs = TST->template_arguments();
970 } else if (const auto *RT = RhsType->getAs<RecordType>()) {
971
972
973
974 if (const auto *CTSD = llvm::dyn_cast(
975 RT->getAsCXXRecordDecl())) {
976 Template = CTSD->getSpecializedTemplate();
977 AliasRhsTemplateArgs = CTSD->getTemplateArgs().asArray();
978 }
979 } else {
980 assert(false && "unhandled RHS type of the alias");
981 }
982 return {Template, AliasRhsTemplateArgs};
983}
984
985
986
988BuildDeductionGuideForTypeAlias(Sema &SemaRef,
995 if (BuildingDeductionGuides.isInvalid())
996 return nullptr;
997
998 auto &Context = SemaRef.Context;
999 auto [Template, AliasRhsTemplateArgs] =
1000 getRHSTemplateDeclAndArgs(SemaRef, AliasTemplate);
1001
1003
1007
1008 FReturnType = InjectedCNT->getInjectedTST();
1009 else if (const auto *ET = RType->getAs<ElaboratedType>())
1010
1012 assert(FReturnType && "expected to see a return type");
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1034
1037
1038
1039
1040
1041
1042
1045 AliasRhsTemplateArgs, TDeduceInfo, DeduceResults,
1046 false);
1047
1050
1051
1052 for (unsigned Index = 0; Index < DeduceResults.size(); ++Index) {
1053 if (const auto &D = DeduceResults[Index]; .isNull())
1054 DeducedArgs.push_back(D);
1055 else
1056 NonDeducedTemplateParamsInFIndex.push_back(Index);
1057 }
1058 auto DeducedAliasTemplateParams =
1059 TemplateParamsReferencedInTemplateArgumentList(
1060 AliasTemplate->getTemplateParameters(), DeducedArgs);
1061
1064
1065
1066
1067
1068
1069
1070
1071
1073
1074
1076 AliasTemplate->getTemplateParameters()->size());
1077
1078 for (unsigned AliasTemplateParamIdx : DeducedAliasTemplateParams) {
1079 auto *TP =
1080 AliasTemplate->getTemplateParameters()->getParam(AliasTemplateParamIdx);
1081
1082
1084 Args.setKind(TemplateSubstitutionKind::Rewrite);
1086 NamedDecl *NewParam = transformTemplateParameter(
1087 SemaRef, AliasTemplate->getDeclContext(), TP, Args,
1088 FPrimeTemplateParams.size(), getDepthAndIndex(TP).first);
1089 FPrimeTemplateParams.push_back(NewParam);
1090
1093 TransformedDeducedAliasArgs[AliasTemplateParamIdx] = NewTemplateArgument;
1094 }
1095 unsigned FirstUndeducedParamIdx = FPrimeTemplateParams.size();
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1113 Args.setKind(TemplateSubstitutionKind::Rewrite);
1115 for (unsigned Index = 0; Index < DeduceResults.size(); ++Index) {
1116 const auto &D = DeduceResults[Index];
1117 if (D.isNull()) {
1118
1119 continue;
1120 }
1125 assert(TemplateArgsForBuildingFPrime[Index].isNull() &&
1126 "InstantiatedArgs must be null before setting");
1127 TemplateArgsForBuildingFPrime[Index] = Output.getArgument();
1128 }
1129 }
1130
1131
1132
1133
1134 for (unsigned FTemplateParamIdx : NonDeducedTemplateParamsInFIndex) {
1137 Args.setKind(TemplateSubstitutionKind::Rewrite);
1138
1139
1141 NamedDecl *NewParam = transformTemplateParameter(
1142 SemaRef, F->getDeclContext(), TP, Args, FPrimeTemplateParams.size(),
1144 FPrimeTemplateParams.push_back(NewParam);
1145
1146 assert(TemplateArgsForBuildingFPrime[FTemplateParamIdx].isNull() &&
1147 "The argument must be null before setting");
1148 TemplateArgsForBuildingFPrime[FTemplateParamIdx] =
1150 }
1151
1152 auto *TemplateArgListForBuildingFPrime =
1154
1156 F, TemplateArgListForBuildingFPrime, AliasTemplate->getLocation(),
1158 auto *GG = cast(FPrime);
1159
1160 Expr *IsDeducible = buildIsDeducibleConstraint(
1161 SemaRef, AliasTemplate, FPrime->getReturnType(), FPrimeTemplateParams);
1162 Expr *RequiresClause =
1163 buildAssociatedConstraints(SemaRef, F, AliasTemplate, DeduceResults,
1164 FirstUndeducedParamIdx, IsDeducible);
1165
1166 auto *FPrimeTemplateParamList = TemplateParameterList::Create(
1167 Context, AliasTemplate->getTemplateParameters()->getTemplateLoc(),
1168 AliasTemplate->getTemplateParameters()->getLAngleLoc(),
1169 FPrimeTemplateParams,
1170 AliasTemplate->getTemplateParameters()->getRAngleLoc(),
1171 RequiresClause);
1172 auto *Result = cast(buildDeductionGuide(
1173 SemaRef, AliasTemplate, FPrimeTemplateParamList,
1174 GG->getCorrespondingConstructor(), GG->getExplicitSpecifier(),
1175 GG->getTypeSourceInfo(), AliasTemplate->getBeginLoc(),
1178 cast(Result->getTemplatedDecl())
1179 ->setDeductionCandidateKind(GG->getDeductionCandidateKind());
1180 return Result;
1181 }
1182 return nullptr;
1183}
1184
1185void DeclareImplicitDeductionGuidesForTypeAlias(
1188 return;
1189 auto &Context = SemaRef.Context;
1190
1191
1192
1193 if (hasDeclaredDeductionGuides(
1196 return;
1197 auto [Template, AliasRhsTemplateArgs] =
1198 getRHSTemplateDeclAndArgs(SemaRef, AliasTemplate);
1199 if (!Template)
1200 return;
1205 Guides.suppressDiagnostics();
1206
1207 for (auto *G : Guides) {
1208 if (auto *DG = dyn_cast(G)) {
1209
1214
1215
1216 for (unsigned I = 0, N = DG->getNumParams(); I != N; ++I) {
1217 const auto *P = DG->getParamDecl(I);
1220 SemaRef.Context, G->getDeclContext(),
1221 DG->getParamDecl(I)->getBeginLoc(), P->getLocation(), nullptr,
1225 }
1226 auto *Transformed = cast(buildDeductionGuide(
1227 SemaRef, AliasTemplate, nullptr,
1228 nullptr, DG->getExplicitSpecifier(), FunctionType,
1231
1232
1233
1234
1235 auto *Constraint = buildIsDeducibleConstraint(
1236 SemaRef, AliasTemplate, Transformed->getReturnType(), {});
1237 if (auto *RC = DG->getTrailingRequiresClause()) {
1238 auto Conjunction =
1240 BinaryOperatorKind::BO_LAnd, RC, Constraint);
1241 if (!Conjunction.isInvalid())
1242 Constraint = Conjunction.getAs<Expr>();
1243 }
1244 Transformed->setTrailingRequiresClause(Constraint);
1245 }
1247 if (!F)
1248 continue;
1249
1250
1251
1253 ->getDeductionCandidateKind() == DeductionCandidate::Aggregate)
1254 continue;
1255
1256 BuildDeductionGuideForTypeAlias(SemaRef, AliasTemplate, F, Loc);
1257 }
1258}
1259
1260
1265 getRHSTemplateDeclAndArgs(SemaRef, AliasTemplate).first;
1266 if (!RHSTemplate)
1267 return nullptr;
1268
1271 ExtractTypeForDeductionGuide TypeAliasTransformer(SemaRef, TypedefDecls);
1273 QualType Type = TypeAliasTransformer.TransformType(P);
1274 if (Type.isNull())
1275 return nullptr;
1276 NewParamTypes.push_back(Type);
1277 }
1278
1280 RHSTemplate, NewParamTypes, Loc);
1281 if (!RHSDeductionGuide)
1282 return nullptr;
1283
1285 TD->setDeclContext(RHSDeductionGuide->getTemplatedDecl());
1286
1287 return BuildDeductionGuideForTypeAlias(SemaRef, AliasTemplate,
1288 RHSDeductionGuide, Loc);
1289}
1290
1291}
1292
1296 llvm::FoldingSetNodeID ID;
1297 ID.AddPointer(Template);
1298 for (auto &T : ParamTypes)
1299 T.getCanonicalType().Profile(ID);
1300 unsigned Hash = ID.ComputeHash();
1301
1306 }
1307
1308 if (auto *AliasTemplate = llvm::dyn_cast(Template)) {
1309 if (auto *FTD = DeclareAggregateDeductionGuideForTypeAlias(
1311 auto *GD = cast(FTD->getTemplatedDecl());
1314 return FTD;
1315 }
1316 }
1317
1321 DefRecord->getDescribedClassTemplate())
1322 Template = DescribedTemplate;
1323 }
1324
1327 return nullptr;
1328
1329 ConvertConstructorToDeductionGuideTransform Transform(
1330 *this, cast(Template));
1332 return nullptr;
1333
1334
1335
1337 -1);
1338
1339
1341 *this, Loc, Template,
1343 if (BuildingDeductionGuides.isInvalid())
1344 return nullptr;
1345
1347 Transform.NestedPattern ? Transform.NestedPattern : Transform.Template;
1349
1350 auto *FTD = cast(
1351 Transform.buildSimpleDeductionGuide(ParamTypes));
1352 SavedContext.pop();
1353 auto *GD = cast(FTD->getTemplatedDecl());
1356 return FTD;
1357}
1358
1361 if (auto *AliasTemplate = llvm::dyn_cast(Template)) {
1362 DeclareImplicitDeductionGuidesForTypeAlias(*this, AliasTemplate, Loc);
1363 return;
1364 }
1368 DefRecord->getDescribedClassTemplate())
1369 Template = DescribedTemplate;
1370 }
1371
1374 return;
1375
1376 ConvertConstructorToDeductionGuideTransform Transform(
1377 *this, cast(Template));
1379 return;
1380
1381 if (hasDeclaredDeductionGuides(Transform.DeductionGuideName, DC))
1382 return;
1383
1384
1385
1387
1388
1390 *this, Loc, Template,
1392 if (BuildingDeductionGuides.isInvalid())
1393 return;
1394
1395
1396
1397
1398
1400 Transform.NestedPattern ? Transform.NestedPattern : Transform.Template;
1403 bool AddedAny = false;
1405 D = D->getUnderlyingDecl();
1407 continue;
1408
1410
1411
1412
1413
1414 if (ProcessedCtors.count(D))
1415 continue;
1416
1417 auto *FTD = dyn_cast(D);
1418 auto *CD =
1419 dyn_cast_or_null(FTD ? FTD->getTemplatedDecl() : D);
1420
1421
1423 continue;
1424
1425
1427 return !P || P->hasUnparsedDefaultArg();
1428 }))
1429 continue;
1430
1431 ProcessedCtors.insert(D);
1432 Transform.transformConstructor(FTD, CD);
1433 AddedAny = true;
1434 }
1435
1436
1437
1438
1439
1440 if (!AddedAny)
1441 Transform.buildSimpleDeductionGuide({});
1442
1443
1444
1445 cast(
1446 cast(
1447 Transform.buildSimpleDeductionGuide(Transform.DeducedType))
1448 ->getTemplatedDecl())
1450
1451 SavedContext.pop();
1452}
Defines the clang::ASTContext interface.
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Defines the C++ template declaration subclasses.
Defines the clang::Expr interface and subclasses for C++ expressions.
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
Defines the clang::SourceLocation class and associated facilities.
Defines various enumerations that describe declaration and type specifiers.
Defines the clang::TypeLoc interface and its subclasses.
Defines enumerations for the type traits support.
C Language Family Type Representation.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
TranslationUnitDecl * getTranslationUnitDecl() const
DeclarationNameTable DeclarationNames
QualType getTypeDeclType(const TypeDecl *Decl, const TypeDecl *PrevDecl=nullptr) const
Return the unique reference to the type for the specified type declaration.
QualType getDecayedType(QualType T) const
Return the uniqued reference to the decayed version of the given type.
QualType getDeducedTemplateSpecializationType(TemplateName Template, QualType DeducedType, bool IsDependent) const
C++17 deduced class template specialization type.
TypeSourceInfo * getTrivialTypeSourceInfo(QualType T, SourceLocation Loc=SourceLocation()) const
Allocate a TypeSourceInfo where all locations have been initialized to a given location,...
TemplateArgument getInjectedTemplateArg(NamedDecl *ParamDecl) const
QualType getLogicalOperationType() const
The result type of logical operations, '<', '>', '!=', etc.
QualType getTypedefType(const TypedefNameDecl *Decl, QualType Underlying=QualType()) const
Return the unique reference to the type for the specified typedef-name decl.
static BinaryOperator * Create(const ASTContext &C, Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy, ExprValueKind VK, ExprObjectKind OK, SourceLocation opLoc, FPOptionsOverride FPFeatures)
Represents a C++ constructor within a class.
ExplicitSpecifier getExplicitSpecifier()
Represents a C++ deduction guide declaration.
static CXXDeductionGuideDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, ExplicitSpecifier ES, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, SourceLocation EndLocation, CXXConstructorDecl *Ctor=nullptr, DeductionCandidate Kind=DeductionCandidate::Normal, Expr *TrailingRequiresClause=nullptr)
Represents a C++ struct/union/class.
CXXRecordDecl * getDefinition() const
Declaration of a class template.
CXXRecordDecl * getTemplatedDecl() const
Get the underlying class declarations of the template.
ClassTemplateDecl * getInstantiatedFromMemberTemplate() const
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
DeclContext * getParent()
getParent - Returns the containing DeclContext.
bool Equals(const DeclContext *DC) const
Determine whether this declaration context is equivalent to the declaration context DC.
bool isDependentContext() const
Determines whether this context is dependent on a template parameter.
lookup_result lookup(DeclarationName Name) const
lookup - Find the declarations (if any) with the given Name in this context.
void addDecl(Decl *D)
Add the declaration D into this context.
Decl::Kind getDeclKind() const
A reference to a declared variable, function, enum, etc.
NamedDecl * getFoundDecl()
Get the NamedDecl through which this reference occurred.
Decl - This represents one declaration (or definition), e.g.
SourceLocation getEndLoc() const LLVM_READONLY
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
unsigned getTemplateDepth() const
Determine the number of levels of template parameter surrounding this declaration.
bool isInvalidDecl() const
SourceLocation getLocation() const
DeclContext * getDeclContext()
void setDeclContext(DeclContext *DC)
setDeclContext - Set both the semantic and lexical DeclContext to DC.
DeclContext * getLexicalDeclContext()
getLexicalDeclContext - The declaration context where this Decl was lexically declared (LexicalDC).
virtual Decl * getCanonicalDecl()
Retrieves the "canonical" declaration of the given declaration.
The name of a declaration.
SourceLocation getInnerLocStart() const
Return start of source range ignoring outer template declarations.
SourceLocation getBeginLoc() const LLVM_READONLY
Expr * getTrailingRequiresClause()
Get the constraint-expression introduced by the trailing requires-clause in the function/member decla...
TypeSourceInfo * getTypeSourceInfo() const
Common base class for placeholders for types that get replaced by placeholder type deduction: C++11 a...
Recursive AST visitor that supports extension via dynamic dispatch.
virtual bool TraverseTemplateName(TemplateName Template)
Recursively visit a template name and dispatch to the appropriate method.
Represents a type that was referred to using an elaborated type keyword, e.g., struct S,...
Store information needed for an explicit specifier.
This represents one expression.
Represents difference between two FPOptions values.
bool isFunctionTemplateSpecialization() const
Determine whether this function is a function template specialization.
FunctionTemplateDecl * getDescribedFunctionTemplate() const
Retrieves the function template that is described by this function declaration.
QualType getReturnType() const
ArrayRef< ParmVarDecl * > parameters() const
Represents a prototype with parameter type info, e.g.
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx)
bool isVariadic() const
Whether this function prototype is variadic.
Declaration of a template function.
FunctionDecl * getTemplatedDecl() const
Get the underlying function declaration of the template.
static FunctionTemplateDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName Name, TemplateParameterList *Params, NamedDecl *Decl)
Create a function template node.
unsigned getNumParams() const
SourceLocation getLocalRangeEnd() const
void setLocalRangeBegin(SourceLocation L)
void setLParenLoc(SourceLocation Loc)
void setParam(unsigned i, ParmVarDecl *VD)
ArrayRef< ParmVarDecl * > getParams() const
void setRParenLoc(SourceLocation Loc)
void setLocalRangeEnd(SourceLocation L)
void setExceptionSpecRange(SourceRange R)
SourceLocation getLocalRangeBegin() const
SourceLocation getLParenLoc() const
SourceLocation getRParenLoc() const
FunctionType - C99 6.7.5.3 - Function Declarators.
const TypeClass * getTypePtr() const
The injected class name of a C++ class template or class template partial specialization.
A stack-allocated class that identifies which local variable declaration instantiations are present i...
void InstantiatedLocal(const Decl *D, Decl *Inst)
Represents the results of name lookup.
Data structure that captures multiple levels of template argument lists for use in template instantia...
void addOuterRetainedLevel()
Add an outermost level that we are not substituting.
void addOuterTemplateArguments(Decl *AssociatedDecl, ArgList Args, bool Final)
Add a new outmost level to the multi-level template argument list.
void setKind(TemplateSubstitutionKind K)
unsigned getNumSubstitutedLevels() const
Determine the number of substituted levels in this template argument list.
void addOuterRetainedLevels(unsigned Num)
This represents a decl that may have a name.
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
NonTypeTemplateParmDecl - Declares a non-type template parameter, e.g., "Size" in.
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.
Represents a parameter to a function.
unsigned getFunctionScopeIndex() const
Returns the index of this parameter in its prototype or method scope.
SourceRange getDefaultArgRange() const
Retrieve the source range that covers the entire default argument.
void setScopeInfo(unsigned scopeDepth, unsigned parameterIndex)
static ParmVarDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S, Expr *DefArg)
bool hasDefaultArg() const
Determines whether this parameter has a default argument, either parsed or not.
unsigned getFunctionScopeDepth() const
A (possibly-)qualified type.
QualType getNonLValueExprType(const ASTContext &Context) const
Determine the type of a (typically non-lvalue) expression with the specified result type.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
bool isMemberSpecialization() const
Determines whether this template was a specialization of a member template.
Scope - A scope is a transient data structure that is used while parsing the program.
RAII object used to change the argument pack substitution index within a Sema object.
Sema - This implements semantic analysis and AST building for C.
bool SubstTypeConstraint(TemplateTypeParmDecl *Inst, const TypeConstraint *TC, const MultiLevelTemplateArgumentList &TemplateArgs, bool EvaluateConstraint)
LocalInstantiationScope * CurrentInstantiationScope
The current instantiation scope used to store local variables.
TemplateArgumentLoc getTrivialTemplateArgumentLoc(const TemplateArgument &Arg, QualType NTTPType, SourceLocation Loc, NamedDecl *TemplateParam=nullptr)
Allocate a TemplateArgumentLoc where all locations have been initialized to the given location.
Scope * getCurScope() const
Retrieve the parser's current scope.
@ LookupOrdinaryName
Ordinary name lookup, which finds ordinary names (functions, variables, typedefs, etc....
FunctionTemplateDecl * DeclareAggregateDeductionGuideFromInitList(TemplateDecl *Template, MutableArrayRef< QualType > ParamTypes, SourceLocation Loc)
FunctionDecl * InstantiateFunctionDeclaration(FunctionTemplateDecl *FTD, const TemplateArgumentList *Args, SourceLocation Loc, CodeSynthesisContext::SynthesisKind CSC=CodeSynthesisContext::ExplicitTemplateArgumentSubstitution)
Instantiate (or find existing instantiation of) a function template with a given set of template argu...
QualType BuildFunctionType(QualType T, MutableArrayRef< QualType > ParamTypes, SourceLocation Loc, DeclarationName Entity, const FunctionProtoType::ExtProtoInfo &EPI)
Build a function type.
ExprResult SubstExpr(Expr *E, const MultiLevelTemplateArgumentList &TemplateArgs)
TypeSourceInfo * CheckPackExpansion(TypeSourceInfo *Pattern, SourceLocation EllipsisLoc, std::optional< unsigned > NumExpansions)
Construct a pack expansion type from the pattern of the pack expansion.
ExprResult SubstConstraintExprWithoutSatisfaction(Expr *E, const MultiLevelTemplateArgumentList &TemplateArgs)
ASTContext & getASTContext() const
TypeSourceInfo * SubstType(TypeSourceInfo *T, const MultiLevelTemplateArgumentList &TemplateArgs, SourceLocation Loc, DeclarationName Entity, bool AllowDeducedTST=false)
Perform substitution on the type T with a given set of template arguments.
TemplateParameterList * GetTemplateParameterList(TemplateDecl *TD)
Returns the template parameter list with all default template argument information.
llvm::DenseMap< unsigned, CXXDeductionGuideDecl * > AggregateDeductionCandidates
MultiLevelTemplateArgumentList getTemplateInstantiationArgs(const NamedDecl *D, const DeclContext *DC=nullptr, bool Final=false, std::optional< ArrayRef< TemplateArgument > > Innermost=std::nullopt, bool RelativeToPrimary=false, const FunctionDecl *Pattern=nullptr, bool ForConstraintInstantiation=false, bool SkipForSpecialization=false, bool ForDefaultArgumentSubstitution=false)
Retrieve the template argument list(s) that should be used to instantiate the definition of the given...
void DeclareImplicitDeductionGuides(TemplateDecl *Template, SourceLocation Loc)
Declare implicit deduction guides for a class template if we've not already done so.
Decl * SubstDecl(Decl *D, DeclContext *Owner, const MultiLevelTemplateArgumentList &TemplateArgs)
bool isCompleteType(SourceLocation Loc, QualType T, CompleteTypeKind Kind=CompleteTypeKind::Default)
bool SubstTemplateArgument(const TemplateArgumentLoc &Input, const MultiLevelTemplateArgumentList &TemplateArgs, TemplateArgumentLoc &Output, SourceLocation Loc={}, const DeclarationName &Entity={})
bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, bool InUnqualifiedLookup=false)
Perform qualified name lookup into a given context.
TemplateDeductionResult DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial, ArrayRef< TemplateArgument > TemplateArgs, sema::TemplateDeductionInfo &Info)
ExprResult BuildBinOp(Scope *S, SourceLocation OpLoc, BinaryOperatorKind Opc, Expr *LHSExpr, Expr *RHSExpr)
DeclContextLookupResult LookupConstructors(CXXRecordDecl *Class)
Look up the constructors for the given class.
Encodes a location in the source.
A trivial tuple used to represent a source range.
SourceLocation getBegin() const
A convenient class for passing around template argument information.
static TemplateArgumentList * CreateCopy(ASTContext &Context, ArrayRef< TemplateArgument > Args)
Create a new template argument list that copies the given set of template arguments.
Location wrapper for a TemplateArgument.
const TemplateArgument & getArgument() const
Represents a template argument.
The base class of all kinds of template declarations (e.g., class, function, etc.).
NamedDecl * getTemplatedDecl() const
Get the underlying, templated declaration.
TemplateParameterList * getTemplateParameters() const
Get the list of template parameters.
Represents a C++ template name within the type system.
TemplateDecl * getAsTemplateDecl(bool IgnoreDeduced=false) const
Retrieve the underlying template declaration that this template name refers to, if known.
Stores a list of template parameters for a TemplateDecl and its derived classes.
NamedDecl * getParam(unsigned Idx)
Expr * getRequiresClause()
The constraint-expression of the associated requires-clause.
SourceLocation getTemplateLoc() const
Represents a type template specialization; the template must be a class template, a type alias templa...
ArrayRef< TemplateArgument > template_arguments() const
TemplateTemplateParmDecl - Declares a template template parameter, e.g., "T" in.
Declaration of a template type parameter.
bool wasDeclaredWithTypename() const
Whether this template type parameter was declared with the 'typename' keyword.
SourceLocation getDefaultArgumentLoc() const
Retrieves the location of the default argument declaration.
const TemplateArgumentLoc & getDefaultArgument() const
Retrieve the default argument, if any.
bool hasTypeConstraint() const
Determine whether this template parameter has a type-constraint.
const TypeConstraint * getTypeConstraint() const
Returns the type constraint associated with this template parameter (if any).
static TemplateTypeParmDecl * Create(const ASTContext &C, DeclContext *DC, SourceLocation KeyLoc, SourceLocation NameLoc, unsigned D, unsigned P, IdentifierInfo *Id, bool Typename, bool ParameterPack, bool HasTypeConstraint=false, std::optional< unsigned > NumExpanded=std::nullopt)
bool hasDefaultArgument() const
Determine whether this template parameter has a default argument.
bool isExpandedParameterPack() const
Whether this parameter is a template type parameter pack that has a known list of different type-cons...
bool isParameterPack() const
Returns whether this is a parameter pack.
unsigned getNumExpansionParameters() const
Retrieves the number of parameters in an expanded parameter pack.
unsigned getIndex() const
unsigned getDepth() const
A semantic tree transformation that allows one to transform one abstract syntax tree into another.
QualType RebuildTemplateSpecializationType(TemplateName Template, SourceLocation TemplateLoc, TemplateArgumentListInfo &Args)
Build a new template specialization type.
QualType TransformType(QualType T)
Transforms the given type into another type.
static TypeAliasDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, TypeSourceInfo *TInfo)
Declaration of an alias template.
SourceLocation getBeginLoc() const LLVM_READONLY
TyLocType push(QualType T)
Pushes space for a new TypeLoc of the given type.
TypeSpecTypeLoc pushTypeSpec(QualType T)
Pushes space for a typespec TypeLoc.
TypeSourceInfo * getTypeSourceInfo(ASTContext &Context, QualType T)
Creates a TypeSourceInfo for the given type.
T getAs() const
Convert to the specified TypeLoc type, returning a null TypeLoc if this TypeLoc is not of the desired...
T castAs() const
Convert to the specified TypeLoc type, asserting that this TypeLoc is of the desired type.
T getAsAdjusted() const
Convert to the specified TypeLoc type, returning a null TypeLoc if this TypeLoc is not of the desired...
SourceLocation getBeginLoc() const
Get the begin source location.
A container of type source information.
TypeLoc getTypeLoc() const
Return the TypeLoc wrapper for the type source info.
QualType getType() const
Return the type wrapped by this type source info.
SourceLocation getNameLoc() const
void setNameLoc(SourceLocation Loc)
static TypeTraitExpr * Create(const ASTContext &C, QualType T, SourceLocation Loc, TypeTrait Kind, ArrayRef< TypeSourceInfo * > Args, SourceLocation RParenLoc, bool Value)
Create a new type trait expression.
The base class of the type hierarchy.
bool isRValueReferenceType() const
const T * castAs() const
Member-template castAs.
bool isInstantiationDependentType() const
Determine whether this type is an instantiation-dependent type, meaning that the type involves a temp...
bool isLValueReferenceType() const
bool isFunctionType() const
const T * getAs() const
Member-template getAs'.
static TypedefDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, TypeSourceInfo *TInfo)
Base class for declarations which introduce a typedef-name.
TypeSourceInfo * getTypeSourceInfo() const
Wrapper for source info for typedefs.
TypedefNameDecl * getTypedefNameDecl() const
StorageClass getStorageClass() const
Returns the storage class as written in the source.
Provides information about an attempted template argument deduction, whose success or failure was des...
The JSON file list parser is used to communicate input to InstallAPI.
@ Rewrite
We are substituting template parameters for (typically) other template parameters in order to rewrite...
@ OK_Ordinary
An ordinary object is located at an address in memory.
std::pair< unsigned, unsigned > getDepthAndIndex(const NamedDecl *ND)
Retrieve the depth and index of a template parameter.
@ VK_PRValue
A pr-value expression (in the C++11 taxonomy) produces a temporary value.
@ VK_XValue
An x-value expression is a reference to an object with independent storage but which can be "moved",...
@ VK_LValue
An l-value expression is a reference to an object with independent storage.
const FunctionProtoType * T
DeclarationNameInfo - A collector data type for bundling together a DeclarationName and the correspon...
Extra information about a function prototype.
unsigned HasTrailingReturn
@ BuildingDeductionGuides
We are building deduction guides for a class.
A stack object to be created when performing template instantiation.