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 (E.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 (E.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]; D.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.