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

204 auto DeductionGuideName =

206 OriginalTemplate);

207

211

212

213 auto *Guide =

215 TInfo->getType(), TInfo, LocEnd, Ctor);

216 Guide->setImplicit(IsImplicit);

217 Guide->setParams(Params);

218

219 for (auto *Param : Params)

220 Param->setDeclContext(Guide);

221 for (auto *TD : MaterializedTypedefs)

222 TD->setDeclContext(Guide);

223 if (isa(DC))

225

226 if (!TemplateParams) {

228 return Guide;

229 }

230

232 SemaRef.Context, DC, Loc, DeductionGuideName, TemplateParams, Guide);

233 GuideTemplate->setImplicit(IsImplicit);

234 Guide->setDescribedFunctionTemplate(GuideTemplate);

235

236 if (isa(DC))

237 GuideTemplate->setAccess(AS_public);

238

239 DC->addDecl(GuideTemplate);

240 return GuideTemplate;

241}

242

243

247 bool EvaluateConstraint) {

248

249

256 : std::nullopt);

259 EvaluateConstraint);

265 NewTTP->setDefaultArgument(SemaRef.Context, InstantiatedDefaultArg);

266 }

268 return NewTTP;

269}

270

271template

272NonTypeTemplateOrTemplateTemplateParmDecl *

274 NonTypeTemplateOrTemplateTemplateParmDecl *OldParam,

276 unsigned NewDepth) {

277

278

279 auto *NewParam = cast(

280 SemaRef.SubstDecl(OldParam, DC, Args));

281 NewParam->setPosition(NewIndex);

282 NewParam->setDepth(NewDepth);

283 return NewParam;

284}

285

289 unsigned NewIndex, unsigned NewDepth,

290 bool EvaluateConstraint = true) {

291 if (auto *TTP = dyn_cast(TemplateParam))

292 return transformTemplateTypeParam(

293 SemaRef, DC, TTP, Args, NewDepth, NewIndex,

294 EvaluateConstraint);

295 if (auto *TTP = dyn_cast(TemplateParam))

296 return transformTemplateParam(SemaRef, DC, TTP, Args, NewIndex, NewDepth);

297 if (auto *NTTP = dyn_cast(TemplateParam))

298 return transformTemplateParam(SemaRef, DC, NTTP, Args, NewIndex, NewDepth);

299 llvm_unreachable("Unhandled template parameter types");

300}

301

302

303

304struct ConvertConstructorToDeductionGuideTransform {

305 ConvertConstructorToDeductionGuideTransform(Sema &S,

307 : SemaRef(S), Template(Template) {

308

309

313 break;

315 NestedPattern = Pattern;

316 }

317

318 if (NestedPattern)

320 }

321

322 Sema &SemaRef;

325

330

332

333

334

336

337

338

340

341

345

347

348

349

350

351

352

353

354

357 if (FTD) {

361 AllParams.reserve(TemplateParams->size() + InnerParams->size());

362 AllParams.insert(AllParams.begin(), TemplateParams->begin(),

363 TemplateParams->end());

364 SubstArgs.reserve(InnerParams->size());

365 Depth1Args.reserve(InnerParams->size());

366

367

368

369 for (NamedDecl *Param : *InnerParams) {

371 Args.setKind(TemplateSubstitutionKind::Rewrite);

374 if (NestedPattern)

377 NamedDecl *NewParam = transformTemplateParameter(

378 SemaRef, DC, Param, Args, Index + Depth1IndexAdjustment, Depth - 1);

379 if (!NewParam)

380 return nullptr;

381

382

384

385 if (NestedPattern) {

387 NewParam = transformTemplateParameter(

388 SemaRef, DC, NewParam, OuterInstantiationArgs, Index,

390 false);

391 }

392

394 "Unexpected template parameter depth");

395

396 AllParams.push_back(NewParam);

398 }

399

400

401 Expr *RequiresClause = nullptr;

402 if (Expr *InnerRC = InnerParams->getRequiresClause()) {

404 Args.setKind(TemplateSubstitutionKind::Rewrite);

407 if (NestedPattern)

410 if (E.isInvalid())

411 return nullptr;

412 RequiresClause = E.getAs<Expr>();

413 }

414

415 TemplateParams = TemplateParameterList::Create(

416 SemaRef.Context, InnerParams->getTemplateLoc(),

417 InnerParams->getLAngleLoc(), AllParams, InnerParams->getRAngleLoc(),

418 RequiresClause);

419 }

420

421

422

423

425 Args.setKind(TemplateSubstitutionKind::Rewrite);

426 if (FTD) {

429 }

430

434 assert(FPTL && "no prototype for constructor declaration");

435

436

437

438

442 QualType NewType = transformFunctionProtoType(TLB, FPTL, Params, Args,

443 MaterializedTypedefs);

444 if (NewType.isNull())

445 return nullptr;

447

448 return buildDeductionGuide(

451 true, MaterializedTypedefs);

452 }

453

454

457

458

462 DeductionGuideName, EPI);

464 if (NestedPattern)

465 TSI = SemaRef.SubstType(TSI, OuterInstantiationArgs, Loc,

466 DeductionGuideName);

467

468 if (!TSI)

469 return nullptr;

470

473

474

476 for (auto T : ParamTypes) {

478 if (NestedPattern)

479 TSI = SemaRef.SubstType(TSI, OuterInstantiationArgs, Loc,

481 if (!TSI)

482 return nullptr;

483

488 FPTL.setParam(Params.size(), NewParam);

489 Params.push_back(NewParam);

490 }

491

492 return buildDeductionGuide(

495 }

496

497private:

498 QualType transformFunctionProtoType(

505

506

507 for (auto *OldParam : TL.getParams()) {

509

510

511

512

513

514

515

516

517

518 if (NestedPattern) {

519 NewParam = transformFunctionTypeParam(

520 NewParam, OuterInstantiationArgs, MaterializedTypedefs,

521 true);

522 if (!NewParam)

524 }

525

526

527

528 NewParam =

529 transformFunctionTypeParam(NewParam, Args, MaterializedTypedefs,

530 false);

531 if (!NewParam)

533 ParamTypes.push_back(NewParam->getType());

534 Params.push_back(NewParam);

535 }

536

537

538

539

540

541

542

543

544

545

548

549

550

554

556 ReturnType, ParamTypes, TL.getBeginLoc(), DeductionGuideName, EPI);

557 if (Result.isNull())

559

566 for (unsigned I = 0, E = NewTL.getNumParams(); I != E; ++I)

567 NewTL.setParam(I, Params[I]);

568

569 return Result;

570 }

571

575 bool TransformingOuterPatterns) {

579

581 NewDI =

582 SemaRef.SubstType(PackTL.getPatternLoc(), Args,

584 if (!NewDI)

585 return nullptr;

586 NewDI =

588 PackTL.getTypePtr()->getNumExpansions());

589 } else

592 if (!NewDI)

593 return nullptr;

594

595

596

597

598

599 NewDI = ExtractTypeForDeductionGuide(

600 SemaRef, MaterializedTypedefs, NestedPattern,

601 TransformingOuterPatterns ? &Args : nullptr)

602 .transform(NewDI);

603

604

605

608

609

611 NewDefArg = new (SemaRef.Context)

617 }

618

619 auto NewType = NewDI->getType();

622

630 return NewParam;

631 }

632};

633

634

635

641 llvm::BitVector ReferencedTemplateParams;

642

643 TemplateParamsReferencedFinder(

645 : TemplateParamList(TemplateParamList),

646 ReferencedTemplateParams(TemplateParamList->size()) {}

647

649

650

652 return true;

653 }

654

655 bool VisitDeclRefExpr(DeclRefExpr *DRE) override {

657 return true;

658 }

659

662 MarkAppeared(TD);

664 }

665

666 void MarkAppeared(NamedDecl *ND) {

670 Mark(Depth, Index);

671 }

672 }

673 void Mark(unsigned Depth, unsigned Index) {

674 if (Index < TemplateParamList->size() &&

676 ReferencedTemplateParams.set(Index);

677 }

678 };

679 TemplateParamsReferencedFinder Finder(TemplateParamsList);

680 Finder.TraverseTemplateArguments(DeducedArgs);

681

683 for (unsigned Index = 0; Index < TemplateParamsList->size(); ++Index) {

684 if (Finder.ReferencedTemplateParams[Index])

685 Results.push_back(Index);

686 }

687 return Results;

688}

689

691

692

693 assert(Name.getNameKind() ==

694 DeclarationName::NameKind::CXXDeductionGuideName &&

695 "name must be a deduction guide name");

696 auto Existing = DC->lookup(Name);

697 for (auto *D : Existing)

699 return true;

700 return false;

701}

702

703

704

705

706

707

708

709

710

715 unsigned FirstUndeducedParamIdx, Expr *IsDeducible) {

717 if (!RC)

718 return IsDeducible;

719

722

723

724

725

726

727

728

729

730

731

732

733

734

735

736

737

738

739

740 unsigned AdjustDepth = 0;

741 if (auto *PrimaryTemplate =

742 AliasTemplate->getInstantiatedFromMemberTemplate())

743 AdjustDepth = PrimaryTemplate->getTemplateDepth();

744

745

746

748

749 for (auto *TP : *AliasTemplate->getTemplateParameters()) {

750

751

753 Args.setKind(TemplateSubstitutionKind::Rewrite);

755 NamedDecl *NewParam = transformTemplateParameter(

756 SemaRef, AliasTemplate->getDeclContext(), TP, Args,

757 AdjustedAliasTemplateArgs.size(),

759

762 AdjustedAliasTemplateArgs.push_back(NewTemplateArgument);

763 }

764

765

768

770 Args.setKind(TemplateSubstitutionKind::Rewrite);

772

773 for (unsigned Index = 0; Index < DeduceResults.size(); ++Index) {

774 const auto &D = DeduceResults[Index];

775 if (D.isNull()) {

778 Args.setKind(TemplateSubstitutionKind::Rewrite);

780

782 transformTemplateParameter(SemaRef, F->getDeclContext(), TP, Args,

783 FirstUndeducedParamIdx,

785 FirstUndeducedParamIdx += 1;

786 assert(TemplateArgsForBuildingRC[Index].isNull());

787 TemplateArgsForBuildingRC[Index] =

789 continue;

790 }

795 assert(TemplateArgsForBuildingRC[Index].isNull() &&

796 "InstantiatedArgs must be null before setting");

797 TemplateArgsForBuildingRC[Index] = Output.getArgument();

798 }

799 }

800

801

802

806

807

808

809

810

811

812

813

814

815

816

817

818

819

820

821

822

823

824

825

826

827

828

829

830

831

832

833

834

835

837 clang::Decl::ClassTemplateSpecialization) {

840 false, std::nullopt,

841 true,

842 nullptr,

843 true);

844 for (auto It : OuterLevelArgs)

846 }

847

849 if (E.isInvalid())

850 return nullptr;

851

852 auto Conjunction =

854 BinaryOperatorKind::BO_LAnd, E.get(), IsDeducible);

855 if (Conjunction.isInvalid())

856 return nullptr;

857 return Conjunction.getAs<Expr>();

858}

859

860

861

862

863Expr *buildIsDeducibleConstraint(Sema &SemaRef,

868

869 if (auto *PrimaryTemplate =

870 AliasTemplate->getInstantiatedFromMemberTemplate();

871 PrimaryTemplate && TemplateParams.size() > 0) {

873

874

875 unsigned AdjustDepth = PrimaryTemplate->getTemplateDepth();

877 for (auto *TP : TemplateParams) {

878

879

881 Args.setKind(TemplateSubstitutionKind::Rewrite);

883 NamedDecl *NewParam = transformTemplateParameter(

884 SemaRef, AliasTemplate->getDeclContext(), TP, Args,

885 TransformedTemplateArgs.size(),

887

890 TransformedTemplateArgs.push_back(NewTemplateArgument);

891 }

892

894 Args.setKind(TemplateSubstitutionKind::Rewrite);

899 };

900

905 true)),

906

908 ReturnType),

909 };

912 TypeTrait::BTT_IsDeducible, IsDeducibleTypeTraitArgs,

914}

915

916std::pair<TemplateDecl *, llvm::ArrayRef>

918

920 ->getUnderlyingType()

921 .getSingleStepDesugaredType(SemaRef.Context);

925

926

927

928 Template = TST->getTemplateName().getAsTemplateDecl();

929 AliasRhsTemplateArgs = TST->template_arguments();

930 } else if (const auto *RT = RhsType->getAs<RecordType>()) {

931

932

933

934 if (const auto *CTSD = llvm::dyn_cast(

935 RT->getAsCXXRecordDecl())) {

936 Template = CTSD->getSpecializedTemplate();

937 AliasRhsTemplateArgs = CTSD->getTemplateArgs().asArray();

938 }

939 } else {

940 assert(false && "unhandled RHS type of the alias");

941 }

942 return {Template, AliasRhsTemplateArgs};

943}

944

945

946

948BuildDeductionGuideForTypeAlias(Sema &SemaRef,

955 if (BuildingDeductionGuides.isInvalid())

956 return nullptr;

957

958 auto &Context = SemaRef.Context;

959 auto [Template, AliasRhsTemplateArgs] =

960 getRHSTemplateDeclAndArgs(SemaRef, AliasTemplate);

961

963

967

968 FReturnType = InjectedCNT->getInjectedTST();

969 else if (const auto *ET = RType->getAs<ElaboratedType>())

970

972 assert(FReturnType && "expected to see a return type");

973

974

975

976

977

978

979

980

981

982

983

984

985

986

987

988

989

990

991

992

994

997

998

999

1000

1001

1002

1005 AliasRhsTemplateArgs, TDeduceInfo, DeduceResults,

1006 false);

1007

1010

1011

1012 for (unsigned Index = 0; Index < DeduceResults.size(); ++Index) {

1013 if (const auto &D = DeduceResults[Index]; D.isNull())

1014 DeducedArgs.push_back(D);

1015 else

1016 NonDeducedTemplateParamsInFIndex.push_back(Index);

1017 }

1018 auto DeducedAliasTemplateParams =

1019 TemplateParamsReferencedInTemplateArgumentList(

1020 AliasTemplate->getTemplateParameters(), DeducedArgs);

1021

1024

1025

1026

1027

1028

1029

1030

1031

1033

1034

1036 AliasTemplate->getTemplateParameters()->size());

1037

1038 for (unsigned AliasTemplateParamIdx : DeducedAliasTemplateParams) {

1039 auto *TP =

1040 AliasTemplate->getTemplateParameters()->getParam(AliasTemplateParamIdx);

1041

1042

1044 Args.setKind(TemplateSubstitutionKind::Rewrite);

1046 NamedDecl *NewParam = transformTemplateParameter(

1047 SemaRef, AliasTemplate->getDeclContext(), TP, Args,

1048 FPrimeTemplateParams.size(), getDepthAndIndex(TP).first);

1049 FPrimeTemplateParams.push_back(NewParam);

1050

1053 TransformedDeducedAliasArgs[AliasTemplateParamIdx] = NewTemplateArgument;

1054 }

1055 unsigned FirstUndeducedParamIdx = FPrimeTemplateParams.size();

1056

1057

1058

1059

1060

1061

1062

1063

1064

1065

1066

1067

1068

1069

1070

1071

1073 Args.setKind(TemplateSubstitutionKind::Rewrite);

1075 for (unsigned Index = 0; Index < DeduceResults.size(); ++Index) {

1076 const auto &D = DeduceResults[Index];

1077 if (D.isNull()) {

1078

1079 continue;

1080 }

1085 assert(TemplateArgsForBuildingFPrime[Index].isNull() &&

1086 "InstantiatedArgs must be null before setting");

1087 TemplateArgsForBuildingFPrime[Index] = Output.getArgument();

1088 }

1089 }

1090

1091

1092

1093

1094 for (unsigned FTemplateParamIdx : NonDeducedTemplateParamsInFIndex) {

1097 Args.setKind(TemplateSubstitutionKind::Rewrite);

1098

1099

1101 NamedDecl *NewParam = transformTemplateParameter(

1102 SemaRef, F->getDeclContext(), TP, Args, FPrimeTemplateParams.size(),

1104 FPrimeTemplateParams.push_back(NewParam);

1105

1106 assert(TemplateArgsForBuildingFPrime[FTemplateParamIdx].isNull() &&

1107 "The argument must be null before setting");

1108 TemplateArgsForBuildingFPrime[FTemplateParamIdx] =

1110 }

1111

1112 auto *TemplateArgListForBuildingFPrime =

1114

1116 F, TemplateArgListForBuildingFPrime, AliasTemplate->getLocation(),

1118 auto *GG = cast(FPrime);

1119

1120 Expr *IsDeducible = buildIsDeducibleConstraint(

1121 SemaRef, AliasTemplate, FPrime->getReturnType(), FPrimeTemplateParams);

1122 Expr *RequiresClause =

1123 buildAssociatedConstraints(SemaRef, F, AliasTemplate, DeduceResults,

1124 FirstUndeducedParamIdx, IsDeducible);

1125

1126 auto *FPrimeTemplateParamList = TemplateParameterList::Create(

1127 Context, AliasTemplate->getTemplateParameters()->getTemplateLoc(),

1128 AliasTemplate->getTemplateParameters()->getLAngleLoc(),

1129 FPrimeTemplateParams,

1130 AliasTemplate->getTemplateParameters()->getRAngleLoc(),

1131 RequiresClause);

1132 auto *Result = cast(buildDeductionGuide(

1133 SemaRef, AliasTemplate, FPrimeTemplateParamList,

1134 GG->getCorrespondingConstructor(), GG->getExplicitSpecifier(),

1135 GG->getTypeSourceInfo(), AliasTemplate->getBeginLoc(),

1138 cast(Result->getTemplatedDecl())

1139 ->setDeductionCandidateKind(GG->getDeductionCandidateKind());

1140 return Result;

1141 }

1142 return nullptr;

1143}

1144

1145void DeclareImplicitDeductionGuidesForTypeAlias(

1148 return;

1149 auto &Context = SemaRef.Context;

1150

1151

1152

1153 if (hasDeclaredDeductionGuides(

1156 return;

1157 auto [Template, AliasRhsTemplateArgs] =

1158 getRHSTemplateDeclAndArgs(SemaRef, AliasTemplate);

1159 if (!Template)

1160 return;

1165 Guides.suppressDiagnostics();

1166

1167 for (auto *G : Guides) {

1168 if (auto *DG = dyn_cast(G)) {

1169

1174

1175

1176 for (unsigned I = 0, N = DG->getNumParams(); I != N; ++I) {

1177 const auto *P = DG->getParamDecl(I);

1180 SemaRef.Context, G->getDeclContext(),

1181 DG->getParamDecl(I)->getBeginLoc(), P->getLocation(), nullptr,

1185 }

1186 auto *Transformed = cast(buildDeductionGuide(

1187 SemaRef, AliasTemplate, nullptr,

1188 nullptr, DG->getExplicitSpecifier(), FunctionType,

1191

1192

1193

1194

1195 auto *Constraint = buildIsDeducibleConstraint(

1196 SemaRef, AliasTemplate, Transformed->getReturnType(), {});

1197 if (auto *RC = DG->getTrailingRequiresClause()) {

1198 auto Conjunction =

1200 BinaryOperatorKind::BO_LAnd, RC, Constraint);

1201 if (!Conjunction.isInvalid())

1202 Constraint = Conjunction.getAs<Expr>();

1203 }

1204 Transformed->setTrailingRequiresClause(Constraint);

1205 }

1207 if (!F)

1208 continue;

1209

1210

1211

1213 ->getDeductionCandidateKind() == DeductionCandidate::Aggregate)

1214 continue;

1215

1216 BuildDeductionGuideForTypeAlias(SemaRef, AliasTemplate, F, Loc);

1217 }

1218}

1219

1220

1225 getRHSTemplateDeclAndArgs(SemaRef, AliasTemplate).first;

1226 if (!RHSTemplate)

1227 return nullptr;

1228

1231 ExtractTypeForDeductionGuide TypeAliasTransformer(SemaRef, TypedefDecls);

1233 QualType Type = TypeAliasTransformer.TransformType(P);

1234 if (Type.isNull())

1235 return nullptr;

1236 NewParamTypes.push_back(Type);

1237 }

1238

1240 RHSTemplate, NewParamTypes, Loc);

1241 if (!RHSDeductionGuide)

1242 return nullptr;

1243

1245 TD->setDeclContext(RHSDeductionGuide->getTemplatedDecl());

1246

1247 return BuildDeductionGuideForTypeAlias(SemaRef, AliasTemplate,

1248 RHSDeductionGuide, Loc);

1249}

1250

1251}

1252

1256 llvm::FoldingSetNodeID ID;

1257 ID.AddPointer(Template);

1258 for (auto &T : ParamTypes)

1259 T.getCanonicalType().Profile(ID);

1260 unsigned Hash = ID.ComputeHash();

1261

1266 }

1267

1268 if (auto *AliasTemplate = llvm::dyn_cast(Template)) {

1269 if (auto *FTD = DeclareAggregateDeductionGuideForTypeAlias(

1271 auto *GD = cast(FTD->getTemplatedDecl());

1274 return FTD;

1275 }

1276 }

1277

1281 DefRecord->getDescribedClassTemplate())

1282 Template = DescribedTemplate;

1283 }

1284

1287 return nullptr;

1288

1289 ConvertConstructorToDeductionGuideTransform Transform(

1290 *this, cast(Template));

1292 return nullptr;

1293

1294

1295

1297 -1);

1298

1299

1301 *this, Loc, Template,

1303 if (BuildingDeductionGuides.isInvalid())

1304 return nullptr;

1305

1307 Transform.NestedPattern ? Transform.NestedPattern : Transform.Template;

1309

1310 auto *FTD = cast(

1311 Transform.buildSimpleDeductionGuide(ParamTypes));

1312 SavedContext.pop();

1313 auto *GD = cast(FTD->getTemplatedDecl());

1316 return FTD;

1317}

1318

1321 if (auto *AliasTemplate = llvm::dyn_cast(Template)) {

1322 DeclareImplicitDeductionGuidesForTypeAlias(*this, AliasTemplate, Loc);

1323 return;

1324 }

1328 DefRecord->getDescribedClassTemplate())

1329 Template = DescribedTemplate;

1330 }

1331

1334 return;

1335

1336 ConvertConstructorToDeductionGuideTransform Transform(

1337 *this, cast(Template));

1339 return;

1340

1341 if (hasDeclaredDeductionGuides(Transform.DeductionGuideName, DC))

1342 return;

1343

1344

1345

1347

1348

1350 *this, Loc, Template,

1352 if (BuildingDeductionGuides.isInvalid())

1353 return;

1354

1355

1356

1357

1358

1360 Transform.NestedPattern ? Transform.NestedPattern : Transform.Template;

1363 bool AddedAny = false;

1365 D = D->getUnderlyingDecl();

1367 continue;

1368

1370

1371

1372

1373

1374 if (ProcessedCtors.count(D))

1375 continue;

1376

1377 auto *FTD = dyn_cast(D);

1378 auto *CD =

1379 dyn_cast_or_null(FTD ? FTD->getTemplatedDecl() : D);

1380

1381

1383 continue;

1384

1385

1387 return !P || P->hasUnparsedDefaultArg();

1388 }))

1389 continue;

1390

1391 ProcessedCtors.insert(D);

1392 Transform.transformConstructor(FTD, CD);

1393 AddedAny = true;

1394 }

1395

1396

1397

1398

1399

1400 if (!AddedAny)

1401 Transform.buildSimpleDeductionGuide({});

1402

1403

1404

1405 cast(

1406 cast(

1407 Transform.buildSimpleDeductionGuide(Transform.DeducedType))

1408 ->getTemplatedDecl())

1410

1411 SavedContext.pop();

1412}

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.

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

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.

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.

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.

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...

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.