clang: lib/Sema/SemaConcept.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

29#include "llvm/ADT/DenseMap.h"

30#include "llvm/ADT/PointerUnion.h"

31#include "llvm/ADT/StringExtras.h"

32#include "llvm/Support/SaveAndRestore.h"

33#include "llvm/Support/TimeProfiler.h"

34

35using namespace clang;

36using namespace sema;

37

38namespace {

39class LogicalBinOp {

40 SourceLocation Loc;

42 const Expr *LHS = nullptr;

43 const Expr *RHS = nullptr;

44

45public:

46 LogicalBinOp(const Expr *E) {

47 if (auto *BO = dyn_cast(E)) {

49 LHS = BO->getLHS();

50 RHS = BO->getRHS();

51 Loc = BO->getExprLoc();

52 } else if (auto *OO = dyn_cast(E)) {

53

54 if (OO->getNumArgs() == 2) {

55 Op = OO->getOperator();

56 LHS = OO->getArg(0);

57 RHS = OO->getArg(1);

58 Loc = OO->getOperatorLoc();

59 }

60 }

61 }

62

63 bool isAnd() const { return Op == OO_AmpAmp; }

64 bool isOr() const { return Op == OO_PipePipe; }

65 explicit operator bool() const { return isAnd() || isOr(); }

66

67 const Expr *getLHS() const { return LHS; }

68 const Expr *getRHS() const { return RHS; }

70

72 return recreateBinOp(SemaRef, LHS, const_cast<Expr *>(getRHS()));

73 }

74

77 assert((isAnd() || isOr()) && "Not the right kind of op?");

78 assert((!LHS.isInvalid() && !RHS.isInvalid()) && "not good expressions?");

79

80 if (!LHS.isUsable() || !RHS.isUsable())

82

83

84

89 }

90};

91}

92

94 Token NextToken, bool *PossibleNonPrimary,

95 bool IsTrailingRequiresClause) {

96

97

98

100

101 if (LogicalBinOp BO = ConstraintExpression) {

103 PossibleNonPrimary) &&

105 PossibleNonPrimary);

106 } else if (auto *C = dyn_cast(ConstraintExpression))

108 PossibleNonPrimary);

109

111

112 auto CheckForNonPrimary = [&] {

113 if (!PossibleNonPrimary)

114 return;

115

116 *PossibleNonPrimary =

117

118

119

120

121

122

123

124

125

126

127 (NextToken.is(tok::l_paren) &&

128 (IsTrailingRequiresClause ||

131 !dyn_cast_if_present(getCurFunction())) ||

134

135

136

137

138

140 true,

142 };

143

144

146 CheckForNonPrimary();

147 return true;

148 }

149

152 diag::err_non_bool_atomic_constraint)

154 CheckForNonPrimary();

155 return false;

156 }

157

158 if (PossibleNonPrimary)

159 *PossibleNonPrimary = false;

160 return true;

161}

162

163namespace {

164struct SatisfactionStackRAII {

165 Sema &SemaRef;

166 bool Inserted = false;

167 SatisfactionStackRAII(Sema &SemaRef, const NamedDecl *ND,

168 const llvm::FoldingSetNodeID &FSNID)

169 : SemaRef(SemaRef) {

170 if (ND) {

172 Inserted = true;

173 }

174 }

175 ~SatisfactionStackRAII() {

176 if (Inserted)

178 }

179};

180}

181

183 Sema &S, llvm::FoldingSetNodeID &ID, const NamedDecl *Templ, const Expr *E,

186 if (MLTAL) {

187 for (const auto &List : *MLTAL)

188 for (const auto &TemplateArg : List.Args)

191 }

193 S.Diag(E->getExprLoc(), diag::err_constraint_depends_on_self)

195 return true;

196 }

197 return false;

198}

199

200

201

202

203static unsigned

205 bool SkipForSpecialization = false) {

208 std::nullopt,

209 true,

210 nullptr,

211 true, SkipForSpecialization);

213}

214

215namespace {

216class AdjustConstraintDepth : public TreeTransform {

217 unsigned TemplateDepth = 0;

218

219public:

220 using inherited = TreeTransform;

221 AdjustConstraintDepth(Sema &SemaRef, unsigned TemplateDepth)

222 : inherited(SemaRef), TemplateDepth(TemplateDepth) {}

223

224 using inherited::TransformTemplateTypeParmType;

225 QualType TransformTemplateTypeParmType(TypeLocBuilder &TLB,

226 TemplateTypeParmTypeLoc TL, bool) {

227 const TemplateTypeParmType *T = TL.getTypePtr();

228

229 TemplateTypeParmDecl *NewTTPDecl = nullptr;

230 if (TemplateTypeParmDecl *OldTTPDecl = T->getDecl())

231 NewTTPDecl = cast_or_null(

232 TransformDecl(TL.getNameLoc(), OldTTPDecl));

233

234 QualType Result = getSema().Context.getTemplateTypeParmType(

235 T->getDepth() + TemplateDepth, T->getIndex(), T->isParameterPack(),

236 NewTTPDecl);

237 TemplateTypeParmTypeLoc NewTL = TLB.push(Result);

240 }

241

242 bool AlreadyTransformed(QualType T) {

243 if (T.isNull())

244 return true;

245

248 return false;

249 return true;

250 }

251};

252}

253

254namespace {

255

256

257class HashParameterMapping : public RecursiveASTVisitor {

258 using inherited = RecursiveASTVisitor;

259 friend inherited;

260

261 Sema &SemaRef;

262 const MultiLevelTemplateArgumentList &TemplateArgs;

263 llvm::FoldingSetNodeID &ID;

264 llvm::SmallVector<TemplateArgument, 10> UsedTemplateArgs;

265

266 UnsignedOrNone OuterPackSubstIndex;

267

268 bool shouldVisitTemplateInstantiations() const { return true; }

269

270public:

271 HashParameterMapping(Sema &SemaRef,

272 const MultiLevelTemplateArgumentList &TemplateArgs,

273 llvm::FoldingSetNodeID &ID,

274 UnsignedOrNone OuterPackSubstIndex)

275 : SemaRef(SemaRef), TemplateArgs(TemplateArgs), ID(ID),

276 OuterPackSubstIndex(OuterPackSubstIndex) {}

277

278 bool VisitTemplateTypeParmType(TemplateTypeParmType *T) {

279

280

281 if (T->getDepth() >= TemplateArgs.getNumLevels())

282 return true;

283

284

285

287 return true;

288

289 TemplateArgument Arg = TemplateArgs(T->getDepth(), T->getIndex());

290

293 "Missing argument pack");

294

296 }

297

298 UsedTemplateArgs.push_back(

300 return true;

301 }

302

303 bool VisitDeclRefExpr(DeclRefExpr *E) {

304 NamedDecl *D = E->getDecl();

305 NonTypeTemplateParmDecl *NTTP = dyn_cast(D);

306 if (!NTTP)

307 return TraverseDecl(D);

308

310 return true;

311

313 return true;

314

315 TemplateArgument Arg = TemplateArgs(NTTP->getDepth(), NTTP->getPosition());

318 "Missing argument pack");

320 }

321

322 UsedTemplateArgs.push_back(

324 return true;

325 }

326

327 bool VisitTypedefType(TypedefType *TT) {

328 return inherited::TraverseType(TT->desugar());

329 }

330

331 bool TraverseDecl(Decl *D) {

332 if (auto *VD = dyn_cast(D)) {

333 if (auto *Var = dyn_cast(VD))

334 TraverseStmt(Var->getInit());

335 return TraverseType(VD->getType());

336 }

337

338 return inherited::TraverseDecl(D);

339 }

340

341 bool TraverseCallExpr(CallExpr *CE) {

342 inherited::TraverseStmt(CE->getCallee());

343

344 for (Expr *Arg : CE->arguments())

345 inherited::TraverseStmt(Arg);

346

347 return true;

348 }

349

350 bool TraverseTypeLoc(TypeLoc TL, bool TraverseQualifier = true) {

351

353 }

354

355 bool TraverseTagType(const TagType *T, bool TraverseQualifier) {

356

357

358

359

360 return true;

361 }

362

363 bool TraverseInjectedClassNameType(InjectedClassNameType *T,

364 bool TraverseQualifier) {

365 return TraverseTemplateArguments(T->getTemplateArgs(SemaRef.Context));

366 }

367

368 bool TraverseTemplateArgument(const TemplateArgument &Arg) {

370

371 Sema::ArgPackSubstIndexRAII _1(SemaRef, std::nullopt);

372 llvm::SaveAndRestore _2(OuterPackSubstIndex,

373 std::nullopt);

374 return inherited::TraverseTemplateArgument(Arg);

375 }

376

377 Sema::ArgPackSubstIndexRAII _1(SemaRef, OuterPackSubstIndex);

378 return inherited::TraverseTemplateArgument(Arg);

379 }

380

381 bool TraverseSizeOfPackExpr(SizeOfPackExpr *SOPE) {

382 return TraverseDecl(SOPE->getPack());

383 }

384

385 bool VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *E) {

387 }

388

390 if (auto *TTP = dyn_cast_if_present(

391 Template.getAsTemplateDecl());

392 TTP && TTP->getDepth() < TemplateArgs.getNumLevels()) {

394 TTP->getPosition()))

395 return true;

396

397 TemplateArgument Arg = TemplateArgs(TTP->getDepth(), TTP->getPosition());

400 "Missing argument pack");

402 }

404 "Null template template argument");

405 UsedTemplateArgs.push_back(

407 }

408 return inherited::TraverseTemplateName(Template);

409 }

410

411 void VisitConstraint(const NormalizedConstraintWithParamMapping &Constraint) {

413 for (const auto &List : TemplateArgs)

414 for (const TemplateArgument &Arg : List.Args)

417 return;

418 }

419

420 llvm::ArrayRef Mapping =

422 for (auto &ArgLoc : Mapping) {

423 TemplateArgument Canonical =

425

426 UsedTemplateArgs.push_back(Canonical);

427 TraverseTemplateArgument(Canonical);

428 }

429

430 for (auto &Used : UsedTemplateArgs) {

431 llvm::FoldingSetNodeID R;

433 ID.AddNodeID(R);

434 }

435 }

436};

437

438class ConstraintSatisfactionChecker {

439 Sema &S;

441 SourceLocation TemplateNameLoc;

442 UnsignedOrNone PackSubstitutionIndex;

443 ConstraintSatisfaction &Satisfaction;

444 bool BuildExpression;

445

446private:

448 EvaluateAtomicConstraint(const Expr *AtomicExpr,

449 const MultiLevelTemplateArgumentList &MLTAL);

450

451 UnsignedOrNone EvaluateFoldExpandedConstraintSize(

452 const FoldExpandedConstraint &FE,

453 const MultiLevelTemplateArgumentList &MLTAL);

454

455

456 std::optional SubstitutionInTemplateArguments(

457 const NormalizedConstraintWithParamMapping &Constraint,

458 const MultiLevelTemplateArgumentList &MLTAL,

459 llvm::SmallVector &SubstitutedOuterMost);

460

461 ExprResult EvaluateSlow(const AtomicConstraint &Constraint,

462 const MultiLevelTemplateArgumentList &MLTAL);

463

465 const MultiLevelTemplateArgumentList &MLTAL);

466

467 ExprResult EvaluateSlow(const FoldExpandedConstraint &Constraint,

468 const MultiLevelTemplateArgumentList &MLTAL);

469

471 const MultiLevelTemplateArgumentList &MLTAL);

472

473 ExprResult EvaluateSlow(const ConceptIdConstraint &Constraint,

474 const MultiLevelTemplateArgumentList &MLTAL,

475 unsigned int Size);

476

478 const MultiLevelTemplateArgumentList &MLTAL);

479

481 const MultiLevelTemplateArgumentList &MLTAL);

482

483public:

484 ConstraintSatisfactionChecker(Sema &SemaRef, const NamedDecl *Template,

485 SourceLocation TemplateNameLoc,

486 UnsignedOrNone PackSubstitutionIndex,

487 ConstraintSatisfaction &Satisfaction,

488 bool BuildExpression)

489 : S(SemaRef), Template(Template), TemplateNameLoc(TemplateNameLoc),

490 PackSubstitutionIndex(PackSubstitutionIndex),

491 Satisfaction(Satisfaction), BuildExpression(BuildExpression) {}

492

494 const MultiLevelTemplateArgumentList &MLTAL);

495};

496

497StringRef allocateStringFromConceptDiagnostic(const Sema &S,

500 DiagString = ": ";

503}

504

505}

506

507ExprResult ConstraintSatisfactionChecker::EvaluateAtomicConstraint(

512

513 llvm::FoldingSetNodeID ID;

516 Satisfaction.IsSatisfied = false;

517 Satisfaction.ContainsErrors = true;

519 }

520 SatisfactionStackRAII StackRAII(S, Template, ID);

521

522

524 {

529

531 if (Inst.isInvalid())

533

534

536 SubstitutedExpression =

538

539 if (SubstitutedExpression.isInvalid() || Trap.hasErrorOccurred()) {

540

541

542

543 if (!Trap.hasErrorOccurred())

544

545

547

550 Info.takeSFINAEDiagnostic(SubstDiag);

551

552

553

554

555

556

557 Satisfaction.Details.emplace_back(

559 SubstDiag.first,

560 allocateStringFromConceptDiagnostic(S, SubstDiag.second)});

561 Satisfaction.IsSatisfied = false;

563 }

564 }

565

568

569

570

571

572

573

574

575

576

577

578

579 if (!SubstitutedExpression.get()->isPRValue())

581 S.Context, SubstitutedExpression.get()->getType(), CK_LValueToRValue,

582 SubstitutedExpression.get(),

584

585 return SubstitutedExpression;

586}

587

588std::optional

589ConstraintSatisfactionChecker::SubstitutionInTemplateArguments(

593

595 return std::move(MLTAL);

596

597

598

601

607

609 if (Inst.isInvalid())

610 return std::nullopt;

611

616 : PackSubstitutionIndex);

617

620 SubstArgs, true)) {

621 Satisfaction.IsSatisfied = false;

622 return std::nullopt;

623 }

624

629 TD->getLocation(), SubstArgs,

630 {},

631 false, CTAI))

632 return std::nullopt;

635

636

638 SubstitutedOutermost =

639 llvm::to_vector_of(MLTAL.getOutermost());

640 unsigned Offset = 0;

641 for (unsigned I = 0, MappedIndex = 0; I < Used.size(); I++) {

646 if (I < SubstitutedOutermost.size()) {

647 SubstitutedOutermost[I] = Arg;

648 Offset = I + 1;

649 } else {

650 SubstitutedOutermost.push_back(Arg);

651 Offset = SubstitutedOutermost.size();

652 }

653 }

654 if (Offset < SubstitutedOutermost.size())

655 SubstitutedOutermost.erase(SubstitutedOutermost.begin() + Offset);

656

659 false);

660 return std::move(SubstitutedTemplateArgs);

661}

662

663ExprResult ConstraintSatisfactionChecker::EvaluateSlow(

666

668 std::optional SubstitutedArgs =

669 SubstitutionInTemplateArguments(Constraint, MLTAL, SubstitutedOutermost);

670 if (!SubstitutedArgs) {

671 Satisfaction.IsSatisfied = false;

673 }

674

676 ExprResult SubstitutedAtomicExpr = EvaluateAtomicConstraint(

678

679 if (SubstitutedAtomicExpr.isInvalid())

681

682 if (SubstitutedAtomicExpr.isUnset())

683

685

686

687

688

689

690

692 Satisfaction.IsSatisfied = false;

693 Satisfaction.ContainsErrors = true;

694

696 Satisfaction.Details.emplace_back(

698 SubstitutedAtomicExpr.get()->getBeginLoc(),

699 allocateStringFromConceptDiagnostic(S, Msg)});

700 return SubstitutedAtomicExpr;

701 }

702

704 Satisfaction.IsSatisfied = true;

705 Satisfaction.ContainsErrors = false;

706 return SubstitutedAtomicExpr;

707 }

708

713 EvalResult.Diag = &EvaluationDiags;

716 !EvaluationDiags.empty()) {

717

718

720 diag::err_non_constant_constraint_expression)

723 S.Diag(PDiag.first, PDiag.second);

725 }

726

727 assert(EvalResult.Val.isInt() &&

728 "evaluating bool expression didn't produce int");

729 Satisfaction.IsSatisfied = EvalResult.Val.getInt().getBoolValue();

730 if (!Satisfaction.IsSatisfied)

731 Satisfaction.Details.emplace_back(SubstitutedAtomicExpr.get());

732

733 return SubstitutedAtomicExpr;

734}

735

736ExprResult ConstraintSatisfactionChecker::Evaluate(

739

740 unsigned Size = Satisfaction.Details.size();

741 llvm::FoldingSetNodeID ID;

745 : PackSubstitutionIndex;

746

749 HashParameterMapping(S, MLTAL, ID, OuterPackSubstIndex)

750 .VisitConstraint(Constraint);

751

754 auto &Cached = Iter->second.Satisfaction;

755 Satisfaction.ContainsErrors = Cached.ContainsErrors;

756 Satisfaction.IsSatisfied = Cached.IsSatisfied;

757 Satisfaction.Details.insert(Satisfaction.Details.begin() + Size,

758 Cached.Details.begin(), Cached.Details.end());

759 return Iter->second.SubstExpr;

760 }

761

762 ExprResult E = EvaluateSlow(Constraint, MLTAL);

763

765 Cache.Satisfaction.ContainsErrors = Satisfaction.ContainsErrors;

766 Cache.Satisfaction.IsSatisfied = Satisfaction.IsSatisfied;

767 Cache.Satisfaction.Details.insert(Cache.Satisfaction.Details.end(),

768 Satisfaction.Details.begin() + Size,

769 Satisfaction.Details.end());

770 Cache.SubstExpr = E;

772

773 return E;

774}

775

777ConstraintSatisfactionChecker::EvaluateFoldExpandedConstraintSize(

780

782

785 assert(!Unexpanded.empty() && "Pack expansion without parameter packs?");

786 bool Expand = true;

787 bool RetainExpansion = false;

791 false, Expand, RetainExpansion,

792 NumExpansions, false) ||

793 !Expand || RetainExpansion)

794 return std::nullopt;

795

796 if (NumExpansions && S.getLangOpts().BracketDepth < *NumExpansions)

797 return std::nullopt;

798 return NumExpansions;

799}

800

801ExprResult ConstraintSatisfactionChecker::EvaluateSlow(

804

807 unsigned EffectiveDetailEndIndex = Satisfaction.Details.size();

808

810

812 std::optional SubstitutedArgs =

813 SubstitutionInTemplateArguments(

815 MLTAL, SubstitutedOutermost);

816 if (!SubstitutedArgs) {

817 Satisfaction.IsSatisfied = false;

819 }

820

823 EvaluateFoldExpandedConstraintSize(Constraint, *SubstitutedArgs);

824 if (!NumExpansions)

826

827 if (*NumExpansions == 0) {

828 Satisfaction.IsSatisfied = Conjunction;

830 }

831

832 for (unsigned I = 0; I < *NumExpansions; I++) {

834 Satisfaction.IsSatisfied = false;

835 Satisfaction.ContainsErrors = false;

837 ConstraintSatisfactionChecker(S, Template, TemplateNameLoc,

839 false)

841 if (BuildExpression && Expr.isUsable()) {

842 if (Out.isUnset())

844 else

846 Conjunction ? BinaryOperatorKind::BO_LAnd

847 : BinaryOperatorKind::BO_LOr,

851 } else {

852 assert(!BuildExpression || !Satisfaction.IsSatisfied);

853 }

854 if (!Conjunction && Satisfaction.IsSatisfied) {

855 Satisfaction.Details.erase(Satisfaction.Details.begin() +

856 EffectiveDetailEndIndex,

857 Satisfaction.Details.end());

858 break;

859 }

860 if (Satisfaction.IsSatisfied != Conjunction)

861 return Out;

862 }

863

864 return Out;

865}

866

867ExprResult ConstraintSatisfactionChecker::Evaluate(

870

871 llvm::FoldingSetNodeID ID;

873 HashParameterMapping(S, MLTAL, ID, std::nullopt).VisitConstraint(Constraint);

874

877

878 auto &Cached = Iter->second.Satisfaction;

879 Satisfaction.ContainsErrors = Cached.ContainsErrors;

880 Satisfaction.IsSatisfied = Cached.IsSatisfied;

881 Satisfaction.Details.insert(Satisfaction.Details.end(),

882 Cached.Details.begin(), Cached.Details.end());

883 return Iter->second.SubstExpr;

884 }

885

886 unsigned Size = Satisfaction.Details.size();

887

888 ExprResult E = EvaluateSlow(Constraint, MLTAL);

890 Cache.Satisfaction.ContainsErrors = Satisfaction.ContainsErrors;

891 Cache.Satisfaction.IsSatisfied = Satisfaction.IsSatisfied;

892 Cache.Satisfaction.Details.insert(Cache.Satisfaction.Details.end(),

893 Satisfaction.Details.begin() + Size,

894 Satisfaction.Details.end());

895 Cache.SubstExpr = E;

897 return E;

898}

899

900ExprResult ConstraintSatisfactionChecker::EvaluateSlow(

904

906 std::optional SubstitutedArgs =

907 SubstitutionInTemplateArguments(Constraint, MLTAL, SubstitutedOutermost);

908

909 if (!SubstitutedArgs) {

910 Satisfaction.IsSatisfied = false;

911

913 }

914

918 : PackSubstitutionIndex);

919

927

930 Trap.hasErrorOccurred()) {

931 Satisfaction.IsSatisfied = false;

932 if (!Trap.hasErrorOccurred())

934

937 Info.takeSFINAEDiagnostic(SubstDiag);

938

939

940

941

942

943

944 Satisfaction.Details.insert(

945 Satisfaction.Details.begin() + Size,

947 SubstDiag.first,

948 allocateStringFromConceptDiagnostic(S, SubstDiag.second)});

950 }

951

954

958 false);

959

960 if (SubstitutedConceptId.isInvalid() || Trap.hasErrorOccurred())

962

963 if (Size != Satisfaction.Details.size()) {

964 Satisfaction.Details.insert(

965 Satisfaction.Details.begin() + Size,

969 }

970 return SubstitutedConceptId;

971}

972

973ExprResult ConstraintSatisfactionChecker::Evaluate(

976

978

982 : PackSubstitutionIndex;

983

988

989

990

991

992

996 if (InstTemplate.isInvalid())

998

999 unsigned Size = Satisfaction.Details.size();

1000

1002

1004 Satisfaction.Details.insert(Satisfaction.Details.begin() + Size, ConceptId);

1005 return E;

1006 }

1007

1008

1009

1010

1011 if (Satisfaction.IsSatisfied)

1012 return E;

1013

1014 llvm::FoldingSetNodeID ID;

1017 HashParameterMapping(S, MLTAL, ID, OuterPackSubstIndex)

1018 .VisitConstraint(Constraint);

1019

1022

1023 auto &Cached = Iter->second.Satisfaction;

1024 Satisfaction.ContainsErrors = Cached.ContainsErrors;

1025 Satisfaction.IsSatisfied = Cached.IsSatisfied;

1026 Satisfaction.Details.insert(Satisfaction.Details.begin() + Size,

1027 Cached.Details.begin(), Cached.Details.end());

1028 return Iter->second.SubstExpr;

1029 }

1030

1031 ExprResult CE = EvaluateSlow(Constraint, MLTAL, Size);

1033 return E;

1035 Cache.Satisfaction.ContainsErrors = Satisfaction.ContainsErrors;

1036 Cache.Satisfaction.IsSatisfied = Satisfaction.IsSatisfied;

1037 Cache.Satisfaction.Details.insert(Cache.Satisfaction.Details.end(),

1038 Satisfaction.Details.begin() + Size,

1039 Satisfaction.Details.end());

1040 Cache.SubstExpr = CE;

1042 return CE;

1043}

1044

1045ExprResult ConstraintSatisfactionChecker::Evaluate(

1048

1049 unsigned EffectiveDetailEndIndex = Satisfaction.Details.size();

1050

1051 bool Conjunction =

1053

1055

1056 if (Conjunction && (!Satisfaction.IsSatisfied || Satisfaction.ContainsErrors))

1057 return LHS;

1058

1059 if (!Conjunction && !LHS.isInvalid() && Satisfaction.IsSatisfied &&

1060 !Satisfaction.ContainsErrors)

1061 return LHS;

1062

1063 Satisfaction.ContainsErrors = false;

1064 Satisfaction.IsSatisfied = false;

1065

1067

1068 if (!Conjunction && !RHS.isInvalid() && Satisfaction.IsSatisfied &&

1069 !Satisfaction.ContainsErrors)

1070 Satisfaction.Details.erase(Satisfaction.Details.begin() +

1071 EffectiveDetailEndIndex,

1072 Satisfaction.Details.end());

1073

1074 if (!BuildExpression)

1076

1078 return RHS;

1079

1081 return LHS;

1082

1084 Conjunction ? BinaryOperatorKind::BO_LAnd

1085 : BinaryOperatorKind::BO_LOr,

1088}

1089

1090ExprResult ConstraintSatisfactionChecker::Evaluate(

1093 switch (Constraint.getKind()) {

1096

1099 MLTAL);

1100

1103 MLTAL);

1104

1107 }

1108 llvm_unreachable("Unknown ConstraintKind enum");

1109}

1110

1116 Expr **ConvertedExpr, const ConceptReference *TopLevelConceptId = nullptr) {

1117

1118 if (ConvertedExpr)

1119 *ConvertedExpr = nullptr;

1120

1121 if (AssociatedConstraints.empty()) {

1123 return false;

1124 }

1125

1127

1129 return false;

1130 }

1131

1135

1136 struct SynthesisContextPair {

1142 : Inst(S, InstantiationRange.getBegin(),

1144 TemplateArgs, InstantiationRange),

1145 NSC(S) {}

1146 };

1147 std::optional SynthesisContext;

1148 if (!TopLevelConceptId)

1149 SynthesisContext.emplace(S, const_cast<NamedDecl *>(Template), Args,

1150 TemplateIDRange);

1151

1154 if (C) {

1156 return true;

1157 }

1158

1159 if (TopLevelConceptId)

1164

1165 ExprResult Res = ConstraintSatisfactionChecker(

1168 ConvertedExpr != nullptr)

1169 .Evaluate(*C, TemplateArgsLists);

1170

1172 return true;

1173

1174 if (Res.isUsable() && ConvertedExpr)

1175 *ConvertedExpr = Res.get();

1176

1177 return false;

1178}

1179

1186 llvm::TimeTraceScope TimeScope(

1187 "CheckConstraintSatisfaction", [TemplateIDRange, this] {

1189 });

1190 if (AssociatedConstraints.empty()) {

1192 return false;

1193 }

1196 return ::CheckConstraintSatisfaction(

1197 *this, nullptr, AssociatedConstraints, TemplateArgsLists,

1198 TemplateIDRange, OutSatisfaction, ConvertedExpr, TopLevelConceptId);

1199 }

1200

1201

1202 if (Template->isInvalidDecl()) {

1204 return true;

1205 }

1206

1207

1208

1209

1210

1212 for (auto List : TemplateArgsLists)

1214 FlattenedArgs.emplace_back(Context.getCanonicalTemplateArgument(Arg));

1215

1217 if (TopLevelConceptId)

1219

1220 llvm::FoldingSetNodeID ID;

1222 void *InsertPos;

1223 if (auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) {

1224 OutSatisfaction = *Cached;

1225 return false;

1226 }

1227

1228 auto Satisfaction =

1229 std::make_unique(Owner, FlattenedArgs);

1231 *this, Template, AssociatedConstraints, TemplateArgsLists,

1232 TemplateIDRange, *Satisfaction, ConvertedExpr, TopLevelConceptId)) {

1233 OutSatisfaction = std::move(*Satisfaction);

1234 return true;

1235 }

1236

1237 if (auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) {

1238

1239

1240

1241

1242

1243

1244

1245

1246 OutSatisfaction = *Cached;

1247 return false;

1248 }

1249

1250

1251 OutSatisfaction = *Satisfaction;

1252

1253

1254

1255 SatisfactionCache.InsertNode(Satisfaction.release());

1256 return false;

1257}

1258

1263

1264

1265

1266

1267

1268

1269

1272

1275 if (llvm::none_of(

1277 return !ArgLoc.getArgument().isDependent() &&

1278 ArgLoc.getArgument().isConceptOrConceptTemplateParameter();

1279 })) {

1280 return Concept->getConstraintExpr();

1281 }

1282

1286 true,

1287 nullptr,

1288 true);

1290 MLTAL);

1291}

1292

1296

1300 return true;

1301

1303 Constraints.emplace_back(Res.get());

1304

1307 true);

1308

1313}

1314

1315bool Sema::SetupConstraintScope(

1320 "Use LambdaScopeForCallOperatorInstantiationRAII to handle lambda "

1321 "instantiations");

1324 InstantiatingTemplate Inst(

1329 if (Inst.isInvalid())

1330 return true;

1331

1332

1333

1334

1335

1336

1339 false);

1340 if (addInstantiatedParametersToScope(

1342 return true;

1343 }

1344

1345

1346

1349 if (addInstantiatedParametersToScope(FD, FromMemTempl->getTemplatedDecl(),

1351 return true;

1352 }

1353

1354 return false;

1355 }

1356

1359 FunctionDecl *InstantiatedFrom =

1363

1366 Sema::InstantiatingTemplate::ConstraintsCheck{}, InstantiatedFrom,

1367 TemplateArgs ? *TemplateArgs : ArrayRef{},

1368 SourceRange());

1369 if (Inst.isInvalid())

1370 return true;

1371

1372

1373

1374 if (addInstantiatedParametersToScope(FD, InstantiatedFrom, Scope, MLTAL))

1375 return true;

1376 }

1377

1378 return false;

1379}

1380

1381

1382

1383std::optional

1384Sema::SetupConstraintCheckingTemplateArgumentsAndScope(

1387 MultiLevelTemplateArgumentList MLTAL;

1388

1389

1390

1391

1392 MLTAL =

1394 false, std::nullopt,

1395 true,

1396 nullptr,

1397 true);

1398

1400 return MLTAL;

1401 if (SetupConstraintScope(FD, TemplateArgs, MLTAL, Scope))

1402 return std::nullopt;

1403

1404 return MLTAL;

1405}

1406

1410 bool ForOverloadResolution) {

1411

1412

1413

1414

1419 return false;

1420 }

1421

1422

1423

1424

1425

1426

1427

1428

1429 if (const auto *MD = dyn_cast(FD);

1432 Satisfaction, UsageLoc,

1433 true);

1434

1436

1440 else

1442 }

1443

1444 ContextRAII SavedContext{*this, CtxToSave};

1446 std::optional MLTAL =

1447 SetupConstraintCheckingTemplateArgumentsAndScope(

1449

1450 if (!MLTAL)

1451 return true;

1452

1455 if (auto *Method = dyn_cast(FD)) {

1456 ThisQuals = Method->getMethodQualifiers();

1458 }

1460

1463 ForOverloadResolution);

1464

1468 Satisfaction);

1469}

1470

1473 const Expr *ConstrExpr) {

1476 std::nullopt,

1477 true,

1478 nullptr, true,

1479 false);

1480

1482 return ConstrExpr;

1483

1490 return nullptr;

1491

1492

1493

1494

1495

1496 std::optional ScopeForParameters;

1499 ScopeForParameters.emplace(S, true);

1503 FD = Template->getInstantiatedFromMemberTemplate()->getTemplatedDecl();

1504 for (auto *PVD : FD->parameters()) {

1505 if (ScopeForParameters->getInstantiationOfIfExists(PVD))

1506 continue;

1507 if (!PVD->isParameterPack()) {

1508 ScopeForParameters->InstantiatedLocal(PVD, PVD);

1509 continue;

1510 }

1511

1512

1513

1514

1515

1516

1517

1518

1519

1520

1521

1522

1523

1524

1525

1526

1527 ScopeForParameters->MakeInstantiatedLocalArgPack(PVD);

1528 ScopeForParameters->InstantiatedLocalPackArg(PVD, PVD);

1529 }

1530 }

1531

1532 std::optionalSema::CXXThisScopeRAII ThisScope;

1533

1534

1535

1536

1537

1538

1539

1540

1541 std::optionalSema::ContextRAII ContextScope;

1543 if (!DeclInfo.getDecl())

1548 }();

1549 if (auto *RD = dyn_cast(DC)) {

1552 false);

1553 }

1558 const_cast<clang::Expr *>(ConstrExpr), MLTAL);

1559 if (!SubstConstr.isUsable())

1560 return nullptr;

1561 return SubstConstr.get();

1562}

1563

1565 const Expr *OldConstr,

1567 const Expr *NewConstr) {

1568 if (OldConstr == NewConstr)

1569 return true;

1570

1571 if (Old && New.isInvalid() && New.ContainsDecl(Old) &&

1573 if (const Expr *SubstConstr =

1575 OldConstr))

1576 OldConstr = SubstConstr;

1577 else

1578 return false;

1579 if (const Expr *SubstConstr =

1581 NewConstr))

1582 NewConstr = SubstConstr;

1583 else

1584 return false;

1585 }

1586

1587 llvm::FoldingSetNodeID ID1, ID2;

1588 OldConstr->Profile(ID1, Context, true);

1589 NewConstr->Profile(ID2, Context, true);

1590 return ID1 == ID2;

1591}

1592

1595

1596

1597

1598

1600 "Non-function templates don't need to be checked");

1601

1604

1608 AC.ConstraintExpr))

1609 return true;

1610

1611 return false;

1612}

1613

1621 TemplateIDRange, Satisfaction))

1622 return true;

1623

1626 TemplateArgString = " ";

1630

1632 diag::err_template_arg_list_constraints_not_satisfied)

1634 << TemplateArgString << TemplateIDRange;

1636 return true;

1637 }

1638 return false;

1639}

1640

1646 Template->getAssociatedConstraints(TemplateAC);

1647 if (TemplateAC.empty()) {

1649 return false;

1650 }

1651

1653

1655

1656

1657

1658

1660 {

1661

1662

1663

1664

1666 SemaRef, PointOfInstantiation,

1668 PointOfInstantiation);

1669 if (Inst.isInvalid())

1670 return true;

1672 FD, FD,

1673 false, {}, true,

1674 nullptr, true);

1675 }

1676

1679 Template, TemplateAC, MLTAL, PointOfInstantiation, Satisfaction);

1680}

1681

1686

1688

1690 return ::CheckFunctionConstraintsWithoutInstantiation(

1691 *this, PointOfInstantiation, Decl->getDescribedFunctionTemplate(),

1692 TemplateArgs, Satisfaction);

1693

1694

1695

1697 Template->getAssociatedConstraints(TemplateAC);

1698 if (TemplateAC.empty()) {

1700 return false;

1701 }

1702

1703

1704

1707

1708 std::optional MLTAL =

1709 SetupConstraintCheckingTemplateArgumentsAndScope(Decl, TemplateArgs,

1711

1712 if (!MLTAL)

1713 return true;

1714

1717 if (auto *Method = dyn_cast(Decl)) {

1718 ThisQuals = Method->getMethodQualifiers();

1720 }

1721

1725

1727 PointOfInstantiation, Satisfaction);

1728}

1729

1734 "Diagnose() can only be used on an unsatisfied requirement");

1737 llvm_unreachable("Diagnosing a dependent requirement");

1738 break;

1741 if (!SubstDiag->DiagMessage.empty())

1742 S.Diag(SubstDiag->DiagLoc,

1743 diag::note_expr_requirement_expr_substitution_error)

1744 << (int)First << SubstDiag->SubstitutedEntity

1745 << SubstDiag->DiagMessage;

1746 else

1747 S.Diag(SubstDiag->DiagLoc,

1748 diag::note_expr_requirement_expr_unknown_substitution_error)

1749 << (int)First << SubstDiag->SubstitutedEntity;

1750 break;

1751 }

1753 S.Diag(Req->getNoexceptLoc(), diag::note_expr_requirement_noexcept_not_met)

1755 break;

1757 auto *SubstDiag =

1759 if (!SubstDiag->DiagMessage.empty())

1760 S.Diag(SubstDiag->DiagLoc,

1761 diag::note_expr_requirement_type_requirement_substitution_error)

1762 << (int)First << SubstDiag->SubstitutedEntity

1763 << SubstDiag->DiagMessage;

1764 else

1766 SubstDiag->DiagLoc,

1768 note_expr_requirement_type_requirement_unknown_substitution_error)

1769 << (int)First << SubstDiag->SubstitutedEntity;

1770 break;

1771 }

1776 break;

1777 }

1779 llvm_unreachable("We checked this above");

1780 }

1781}

1782

1787 "Diagnose() can only be used on an unsatisfied requirement");

1790 llvm_unreachable("Diagnosing a dependent requirement");

1791 return;

1794 if (!SubstDiag->DiagMessage.empty())

1795 S.Diag(SubstDiag->DiagLoc, diag::note_type_requirement_substitution_error)

1796 << (int)First << SubstDiag->SubstitutedEntity

1797 << SubstDiag->DiagMessage;

1798 else

1799 S.Diag(SubstDiag->DiagLoc,

1800 diag::note_type_requirement_unknown_substitution_error)

1801 << (int)First << SubstDiag->SubstitutedEntity;

1802 return;

1803 }

1804 default:

1805 llvm_unreachable("Unknown satisfaction status");

1806 return;

1807 }

1808}

1809

1813 if (Concept->getTemplateArgsAsWritten()->NumTemplateArgs == 1) {

1815 Loc,

1817 note_single_arg_concept_specialization_constraint_evaluated_to_false)

1819 << Concept->getTemplateArgsAsWritten()->arguments()[0].getArgument()

1820 << Concept->getNamedConcept();

1821 } else {

1822 S.Diag(Loc, diag::note_concept_specialization_constraint_evaluated_to_false)

1824 }

1825}

1826

1830

1836 Loc = {};

1838 }

1839}

1840

1850

1852 const Expr *SubstExpr,

1855 if (const BinaryOperator *BO = dyn_cast(SubstExpr)) {

1856 switch (BO->getOpcode()) {

1857

1858

1859

1860 case BO_LOr:

1861

1864 false);

1865 return;

1866 case BO_LAnd: {

1867 bool LHSSatisfied =

1868 BO->getLHS()->EvaluateKnownConstInt(S.Context).getBoolValue();

1869 if (LHSSatisfied) {

1870

1872 return;

1873 }

1874

1876

1877

1878 bool RHSSatisfied =

1879 BO->getRHS()->EvaluateKnownConstInt(S.Context).getBoolValue();

1880 if (!RHSSatisfied)

1882 false);

1883 return;

1884 }

1885 case BO_GE:

1886 case BO_LE:

1887 case BO_GT:

1888 case BO_LT:

1889 case BO_EQ:

1890 case BO_NE:

1891 if (BO->getLHS()->getType()->isIntegerType() &&

1892 BO->getRHS()->getType()->isIntegerType()) {

1895 BO->getLHS()->EvaluateAsInt(SimplifiedLHS, S.Context,

1897 true);

1898 BO->getRHS()->EvaluateAsInt(SimplifiedRHS, S.Context,

1900 true);

1901 if (!SimplifiedLHS.Diag && !SimplifiedRHS.Diag) {

1903 diag::note_atomic_constraint_evaluated_to_false_elaborated)

1908 return;

1909 }

1910 }

1911 break;

1912

1913 default:

1914 break;

1915 }

1916 } else if (auto *RE = dyn_cast(SubstExpr)) {

1917

1919 if (!Req->isDependent() && !Req->isSatisfied()) {

1920 if (auto *E = dyn_castconcepts::ExprRequirement(Req))

1922 else if (auto *T = dyn_castconcepts::TypeRequirement(Req))

1924 else

1927 break;

1928 }

1929 return;

1930 } else if (auto *CSE = dyn_cast(SubstExpr)) {

1931

1933 return;

1934 } else if (auto *TTE = dyn_cast(SubstExpr);

1935 TTE && TTE->getTrait() == clang::TypeTrait::BTT_IsDeducible) {

1936 assert(TTE->getNumArgs() == 2);

1938 diag::note_is_deducible_constraint_evaluated_to_false)

1939 << TTE->getArg(0)->getType() << TTE->getArg(1)->getType();

1940 return;

1941 }

1942

1944 diag::note_atomic_constraint_evaluated_to_false)

1947}

1948

1952 if (auto *Diag =

1954 .template dyn_cast<const ConstraintSubstitutionDiagnostic *>()) {

1955 if (Req)

1956 S.Diag(Diag->first, diag::note_nested_requirement_substitution_error)

1958 else

1959 S.Diag(Diag->first, diag::note_substituted_constraint_expr_is_ill_formed)

1960 << Diag->second;

1961 return;

1962 }

1963 if (const auto *Concept = dyn_cast<const ConceptReference *>(Record)) {

1965 Loc = Concept->getBeginLoc();

1967 return;

1968 }

1971}

1972

1976

1978 "Attempted to diagnose a satisfied constraint");

1980}

1981

1984

1987

1989 "Attempted to diagnose a satisfied constraint");

1990

1993}

1994

1995namespace {

1996

1997class SubstituteParameterMappings {

1998 Sema &SemaRef;

1999

2002

2003 bool InFoldExpr;

2004

2005 SubstituteParameterMappings(Sema &SemaRef,

2008 bool InFoldExpr)

2009 : SemaRef(SemaRef), MLTAL(MLTAL), ArgsAsWritten(ArgsAsWritten),

2010 InFoldExpr(InFoldExpr) {}

2011

2013

2015

2017

2018public:

2019 SubstituteParameterMappings(Sema &SemaRef, bool InFoldExpr = false)

2020 : SemaRef(SemaRef), MLTAL(nullptr), ArgsAsWritten(nullptr),

2021 InFoldExpr(InFoldExpr) {}

2022

2023 bool substitute(NormalizedConstraint &N);

2024};

2025

2026void SubstituteParameterMappings::buildParameterMapping(

2030

2031 llvm::SmallBitVector OccurringIndices(TemplateParams->size());

2032 llvm::SmallBitVector OccurringIndicesForSubsumption(TemplateParams->size());

2033

2037 false,

2038 0, OccurringIndices);

2039

2042 0, OccurringIndicesForSubsumption);

2043

2044 } else if (N.getKind() ==

2048 false,

2049 0, OccurringIndices);

2052 .getConceptId()

2053 ->getTemplateArgsAsWritten();

2054 if (Args)

2056 0, OccurringIndices);

2057 }

2058 unsigned Size = OccurringIndices.count();

2059

2060

2061

2062

2066 for (unsigned I = 0, J = 0, C = TemplateParams->size(); I != C; ++I) {

2067 SourceLocation Loc = ArgsAsWritten->NumTemplateArgs > I

2068 ? ArgsAsWritten->arguments()[I].getLocation()

2070

2071

2072 if (OccurringIndices[I]) {

2076 UsedParams.push_back(Param);

2077 J++;

2078 }

2079 }

2084 nullptr);

2086 std::move(OccurringIndices), std::move(OccurringIndicesForSubsumption),

2088}

2089

2090bool SubstituteParameterMappings::substitute(

2093 buildParameterMapping(N);

2094

2095

2097 return false;

2098

2102 InstLocBegin = ArgsAsWritten->getLAngleLoc();

2103 InstLocEnd = ArgsAsWritten->getRAngleLoc();

2104 } else {

2105 auto SR = Arguments[0].getSourceRange();

2106 InstLocBegin = SR.getBegin();

2107 InstLocEnd = SR.getEnd();

2108 }

2111 SemaRef, InstLocBegin,

2114 {InstLocBegin, InstLocEnd});

2115 if (Inst.isInvalid())

2116 return true;

2117

2118

2119

2120

2121

2125 !InFoldExpr))

2126 return true;

2128 auto *TD =

2131 TD->getLocation(), SubstArgs,

2132 {},

2133 false, CTAI))

2134 return true;

2135

2138

2139 for (unsigned I = 0; I < CTAI.SugaredConverted.size(); ++I) {

2141

2142 if (I < SubstArgs.size())

2143 Loc = SubstArgs.arguments()[I].getLocation();

2144

2147 }

2148

2154 return false;

2155}

2156

2159

2161 return true;

2162

2164 assert(CSE);

2166

2168 if (llvm::ArrayRef Arguments = ArgsAsWritten->arguments();

2170 InstLocBegin = ArgsAsWritten->getLAngleLoc();

2171 InstLocEnd = ArgsAsWritten->getRAngleLoc();

2172 } else {

2173 auto SR = Arguments[0].getSourceRange();

2174 InstLocBegin = SR.getBegin();

2175 InstLocEnd = SR.getEnd();

2176 }

2178

2180 SemaRef, InstLocBegin,

2183 {InstLocBegin, InstLocEnd});

2184 if (Inst.isInvalid())

2185 return true;

2186

2188

2189

2190

2191

2193 CSE->getTemplateArgsAsWritten();

2196 !InFoldExpr))

2197 return true;

2200 CSE->getConceptNameInfo().getLoc(), Out,

2201 {},

2202 false, CTAI,

2203 false))

2204 return true;

2205 auto TemplateArgs = *MLTAL;

2208 return SubstituteParameterMappings(SemaRef, &TemplateArgs, ArgsAsWritten,

2209 InFoldExpr)

2211}

2212

2216 if (!MLTAL) {

2217 assert(!ArgsAsWritten);

2218 return false;

2219 }

2221 }

2224 if (!MLTAL) {

2226 assert(!ArgsAsWritten);

2228 }

2231 return SubstituteParameterMappings(SemaRef, true)

2233 }

2236 if (MLTAL) {

2237 assert(ArgsAsWritten);

2238 return substitute(CC);

2239 }

2240 assert(!ArgsAsWritten);

2246 true,

2247 nullptr,

2248 true);

2249

2250 return SubstituteParameterMappings(

2253 }

2256 if (substitute(Compound.getLHS()))

2257 return true;

2258 return substitute(Compound.getRHS());

2259 }

2260 }

2261 llvm_unreachable("Unknown ConstraintKind enum");

2262}

2263

2264}

2265

2268 assert(ACs.size() != 0);

2269 auto *Conjunction =

2270 fromConstraintExpr(S, D, ACs[0].ConstraintExpr, ACs[0].ArgPackSubstIndex);

2271 if (!Conjunction)

2272 return nullptr;

2273 for (unsigned I = 1; I < ACs.size(); ++I) {

2274 auto *Next = fromConstraintExpr(S, D, ACs[I].ConstraintExpr,

2275 ACs[I].ArgPackSubstIndex);

2277 return nullptr;

2279 Conjunction, Next);

2280 }

2281 return Conjunction;

2282}

2283

2286 assert(E != nullptr);

2287

2288

2289

2290

2291

2293

2294 llvm::FoldingSetNodeID ID;

2296 return nullptr;

2297 }

2298 SatisfactionStackRAII StackRAII(S, D, ID);

2299

2300

2301

2302

2303

2304

2305 if (LogicalBinOp BO = E) {

2306 auto *LHS = fromConstraintExpr(S, D, BO.getLHS(), SubstIndex);

2307 if (!LHS)

2308 return nullptr;

2309 auto *RHS = fromConstraintExpr(S, D, BO.getRHS(), SubstIndex);

2310 if (!RHS)

2311 return nullptr;

2312

2315 } else if (auto *CSE = dyn_cast(E)) {

2317 {

2318 Sema::NonSFINAEContext _(S);

2319 Sema::InstantiatingTemplate Inst(

2321 Sema::InstantiatingTemplate::ConstraintNormalization{},

2322

2324 if (Inst.isInvalid())

2325 return nullptr;

2326

2327

2328

2329

2330

2331

2332

2333

2334

2335

2336

2337

2339

2343 return nullptr;

2344

2345 SubNF = NormalizedConstraint::fromAssociatedConstraints(

2346 S, CD, AssociatedConstraint(Res.get(), SubstIndex));

2347

2348 if (!SubNF)

2349 return nullptr;

2350 }

2351

2354 CSE, SubstIndex);

2355

2356 } else if (auto *FE = dyn_cast(E);

2358 (FE->getOperator() == BinaryOperatorKind::BO_LAnd ||

2359 FE->getOperator() == BinaryOperatorKind::BO_LOr)) {

2360

2361

2362

2364 FE->getOperator() == BinaryOperatorKind::BO_LAnd

2367

2368 if (FE->getInit()) {

2369 auto *LHS = fromConstraintExpr(S, D, FE->getLHS(), SubstIndex);

2370 auto *RHS = fromConstraintExpr(S, D, FE->getRHS(), SubstIndex);

2371 if (!LHS || !RHS)

2372 return nullptr;

2373

2374 if (FE->isRightFold())

2377 else

2380

2383 (FE->getOperator() == BinaryOperatorKind::BO_LAnd ? CCK_Conjunction

2385 RHS);

2386 }

2387 auto *Sub = fromConstraintExpr(S, D, FE->getPattern(), SubstIndex);

2388 if (!Sub)

2389 return nullptr;

2391 D, Kind, Sub);

2392 }

2394}

2395

2399 if (!ConstrainedDeclOrNestedReq) {

2400 auto *Normalized = NormalizedConstraint::fromAssociatedConstraints(

2401 *this, nullptr, AssociatedConstraints);

2402 if (!Normalized ||

2403 SubstituteParameterMappings(*this).substitute(*Normalized))

2404 return nullptr;

2405

2406 return Normalized;

2407 }

2408

2409

2411 ConstrainedDeclOrNestedReq.dyn_cast<const NamedDecl *>();

2412 auto CacheEntry = NormalizationCache.find(ConstrainedDeclOrNestedReq);

2413 if (CacheEntry == NormalizationCache.end()) {

2414 auto *Normalized = NormalizedConstraint::fromAssociatedConstraints(

2415 *this, ND, AssociatedConstraints);

2416 if (!Normalized) {

2417 NormalizationCache.try_emplace(ConstrainedDeclOrNestedReq, nullptr);

2418 return nullptr;

2419 }

2420

2421 bool Failed = SubstituteParameterMappings(*this).substitute(*Normalized);

2422 CacheEntry =

2423 NormalizationCache.try_emplace(ConstrainedDeclOrNestedReq, Normalized)

2424 .first;

2425 if (Failed)

2426 return nullptr;

2427 }

2428 return CacheEntry->second;

2429}

2430

2433

2434

2435

2436

2437

2440 APacks);

2442 BPacks);

2443

2446 if (!ADI)

2447 continue;

2450 });

2451 if (It != BPacks.end())

2452 return true;

2453 }

2454 return false;

2455}

2456

2462#ifndef NDEBUG

2463 if (const auto *FD1 = dyn_cast(D1)) {

2464 auto IsExpectedEntity = [](const FunctionDecl *FD) {

2468 };

2469 const auto *FD2 = dyn_cast(D2);

2470 assert(IsExpectedEntity(FD1) && FD2 && IsExpectedEntity(FD2) &&

2471 "use non-instantiated function declaration for constraints partial "

2472 "ordering");

2473 }

2474#endif

2475

2476 if (AC1.empty()) {

2477 Result = AC2.empty();

2478 return false;

2479 }

2480 if (AC2.empty()) {

2481

2483 return false;

2484 }

2485

2486 std::pair<const NamedDecl *, const NamedDecl *> Key{D1, D2};

2487 auto CacheEntry = SubsumptionCache.find(Key);

2488 if (CacheEntry != SubsumptionCache.end()) {

2489 Result = CacheEntry->second;

2490 return false;

2491 }

2492

2495

2496 for (size_t I = 0; I != AC1.size() && I != AC2.size(); ++I) {

2497 if (Depth2 > Depth1) {

2498 AC1[I].ConstraintExpr =

2499 AdjustConstraintDepth(*this, Depth2 - Depth1)

2500 .TransformExpr(const_cast<Expr *>(AC1[I].ConstraintExpr))

2501 .get();

2502 } else if (Depth1 > Depth2) {

2503 AC2[I].ConstraintExpr =

2504 AdjustConstraintDepth(*this, Depth1 - Depth2)

2505 .TransformExpr(const_cast<Expr *>(AC2[I].ConstraintExpr))

2506 .get();

2507 }

2508 }

2509

2511 std::optional Subsumes = SC.Subsumes(D1, AC1, D2, AC2);

2512 if (!Subsumes) {

2513

2514 return true;

2515 }

2517 SubsumptionCache.try_emplace(Key, *Subsumes);

2518 return false;

2519}

2520

2525

2526 return false;

2527

2528 if (AC1.empty() || AC2.empty())

2529 return false;

2530

2531 const Expr *AmbiguousAtomic1 = nullptr, *AmbiguousAtomic2 = nullptr;

2532 auto IdenticalExprEvaluator = [&](const AtomicConstraint &A,

2535 return false;

2537 if (EA == EB)

2538 return true;

2539

2540

2541

2542 llvm::FoldingSetNodeID IDA, IDB;

2544 EB->Profile(IDB, Context, true);

2545 if (IDA != IDB)

2546 return false;

2547

2548 AmbiguousAtomic1 = EA;

2549 AmbiguousAtomic2 = EB;

2550 return true;

2551 };

2552

2553 {

2555 if (!Normalized1)

2556 return false;

2557

2559 if (!Normalized2)

2560 return false;

2561

2563

2564 bool Is1AtLeastAs2Normally = SC.Subsumes(Normalized1, Normalized2);

2565 bool Is2AtLeastAs1Normally = SC.Subsumes(Normalized2, Normalized1);

2566

2568 bool Is1AtLeastAs2 = SC2.Subsumes(Normalized1, Normalized2);

2569 bool Is2AtLeastAs1 = SC2.Subsumes(Normalized2, Normalized1);

2570

2571 if (Is1AtLeastAs2 == Is1AtLeastAs2Normally &&

2572 Is2AtLeastAs1 == Is2AtLeastAs1Normally)

2573

2574 return false;

2575 }

2576

2577 assert(AmbiguousAtomic1 && AmbiguousAtomic2);

2578

2579 Diag(AmbiguousAtomic1->getBeginLoc(), diag::note_ambiguous_atomic_constraints)

2581 Diag(AmbiguousAtomic2->getBeginLoc(),

2582 diag::note_ambiguous_atomic_constraints_similar_expression)

2583 << AmbiguousAtomic2->getSourceRange();

2584 return true;

2585}

2586

2587

2588

2589

2590

2591

2594 : SemaRef(SemaRef), Callable(Callable), NextID(1) {}

2595

2596uint16_t SubsumptionChecker::getNewLiteralId() {

2597 assert((unsigned(NextID) + 1 < std::numeric_limits<uint16_t>::max()) &&

2598 "too many constraints!");

2599 return NextID++;

2600}

2601

2602auto SubsumptionChecker::find(const AtomicConstraint *Ori) -> Literal {

2603 auto &Elems = AtomicMap[Ori->getConstraintExpr()];

2604

2605

2606

2607

2608

2609

2610

2611

2612

2613

2614

2615

2616

2617

2618 llvm::FoldingSetNodeID ID;

2619 ID.AddBoolean(Ori->hasParameterMapping());

2620 if (Ori->hasParameterMapping()) {

2621 const auto &Mapping = Ori->getParameterMapping();

2623 Ori->mappingOccurenceListForSubsumption();

2624 for (auto [Idx, TAL] : llvm::enumerate(Mapping)) {

2625 if (Indexes[Idx])

2629 }

2630 }

2631 auto It = Elems.find(ID);

2632 if (It == Elems.end()) {

2633 It = Elems

2634 .insert({ID,

2635 MappedAtomicConstraint{

2636 Ori, {getNewLiteralId(), Literal::Atomic}}})

2637 .first;

2638 ReverseMap[It->second.ID.Value] = Ori;

2639 }

2640 return It->getSecond().ID;

2641}

2642

2644 auto &Elems = FoldMap[Ori->getPattern()];

2645

2646 FoldExpendedConstraintKey K;

2647 K.Kind = Ori->getFoldOperator();

2648

2649 auto It = llvm::find_if(Elems, [&K](const FoldExpendedConstraintKey &Other) {

2650 return K.Kind == Other.Kind;

2651 });

2652 if (It == Elems.end()) {

2653 K.ID = {getNewLiteralId(), Literal::FoldExpanded};

2654 It = Elems.insert(Elems.end(), std::move(K));

2655 ReverseMap[It->ID.Value] = Ori;

2656 }

2657 return It->ID;

2658}

2659

2661 return SubsumptionChecker::Normalize(C);

2662}

2664 return SubsumptionChecker::Normalize(C);

2665}

2666

2667

2668

2669

2670

2671

2672

2673

2674

2675

2676

2677

2678

2679

2680template

2682 FormulaType Res;

2683

2684 auto Add = [&, this](Clause C) {

2685

2686 llvm::sort(C);

2687 C.erase(llvm::unique(C), C.end());

2688 AddUniqueClauseToFormula(Res, std::move(C));

2689 };

2690

2693 return {{find(&static_cast<const AtomicConstraint &>(NC))}};

2694

2696 return {{find(&static_cast<const FoldExpandedConstraint &>(NC))}};

2697

2699 return Normalize(

2700 static_cast<const ConceptIdConstraint &>(NC).getNormalizedConstraint());

2701

2703 const auto &Compound = static_cast<const CompoundConstraint &>(NC);

2705 SemaRef.runWithSufficientStackSpace(SourceLocation(), [&] {

2706 Left = Normalize(Compound.getLHS());

2707 Right = Normalize(Compound.getRHS());

2708 });

2709

2710 if (Compound.getCompoundKind() == FormulaType::Kind) {

2711 unsigned SizeLeft = Left.size();

2712 Res = std::move(Left);

2713 Res.reserve(SizeLeft + Right.size());

2714 std::for_each(std::make_move_iterator(Right.begin()),

2715 std::make_move_iterator(Right.end()), Add);

2716 return Res;

2717 }

2718

2719 Res.reserve(Left.size() * Right.size());

2720 for (const auto &LTransform : Left) {

2721 for (const auto &RTransform : Right) {

2722 Clause Combined;

2723 Combined.reserve(LTransform.size() + RTransform.size());

2724 llvm::copy(LTransform, std::back_inserter(Combined));

2725 llvm::copy(RTransform, std::back_inserter(Combined));

2726 Add(std::move(Combined));

2727 }

2728 }

2729 return Res;

2730 }

2731 }

2732 llvm_unreachable("Unknown ConstraintKind enum");

2733}

2734

2735void SubsumptionChecker::AddUniqueClauseToFormula(Formula &F, Clause C) {

2736 for (auto &Other : F) {

2737 if (llvm::equal(C, Other))

2738 return;

2739 }

2740 F.push_back(C);

2741}

2742

2747 SemaRef.getNormalizedAssociatedConstraints(DP, P);

2748 if (!PNormalized)

2749 return std::nullopt;

2750

2752 SemaRef.getNormalizedAssociatedConstraints(DQ, Q);

2753 if (!QNormalized)

2754 return std::nullopt;

2755

2756 return Subsumes(PNormalized, QNormalized);

2757}

2758

2761

2762 DNFFormula DNFP = DNF(*P);

2763 CNFFormula CNFQ = CNF(*Q);

2764 return Subsumes(DNFP, CNFQ);

2765}

2766

2768 const CNFFormula &QCNF) {

2769 for (const auto &Pi : PDNF) {

2770 for (const auto &Qj : QCNF) {

2771

2772

2773

2774

2775

2776 if (!DNFSubsumes(Pi, Qj))

2777 return false;

2778 }

2779 }

2780 return true;

2781}

2782

2783bool SubsumptionChecker::DNFSubsumes(const Clause &P, const Clause &Q) {

2784

2785 return llvm::any_of(P, [&](Literal LP) {

2786 return llvm::any_of(Q, [this, LP](Literal LQ) { return Subsumes(LP, LQ); });

2787 });

2788}

2789

2792 std::pair<const FoldExpandedConstraint *, const FoldExpandedConstraint *> Key{

2793 A, B};

2794

2795 auto It = FoldSubsumptionCache.find(Key);

2796 if (It == FoldSubsumptionCache.end()) {

2797

2798

2799

2800

2801 bool DoesSubsume =

2805 It = FoldSubsumptionCache.try_emplace(std::move(Key), DoesSubsume).first;

2806 }

2807 return It->second;

2808}

2809

2811 if (A.Kind != B.Kind)

2812 return false;

2813 switch (A.Kind) {

2814 case Literal::Atomic:

2815 if (!Callable)

2816 return A.Value == B.Value;

2818 *static_cast<const AtomicConstraint *>(ReverseMap[A.Value]),

2819 *static_cast<const AtomicConstraint *>(ReverseMap[B.Value]));

2820 case Literal::FoldExpanded:

2822 static_cast<const FoldExpandedConstraint *>(ReverseMap[A.Value]),

2823 static_cast<const FoldExpandedConstraint *>(ReverseMap[B.Value]));

2824 }

2825 llvm_unreachable("unknown literal kind");

2826}

This file provides AST data structures related to concepts.

This file provides some common utility functions for processing Lambda related AST Constructs.

Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....

Defines Expressions and AST nodes for C++2a concepts.

static bool Evaluate(APValue &Result, EvalInfo &Info, const Expr *E)

FormatToken * Next

The next token in the unwrapped line.

static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)

Produce a diagnostic highlighting some portion of a literal.

llvm::MachO::Records Records

llvm::MachO::Record Record

Defines and computes precedence levels for binary/ternary operators.

static std::string toString(const clang::SanitizerSet &Sanitizers)

Produce a string containing comma-separated names of sanitizers in Sanitizers set.

static void diagnoseUnsatisfiedConstraintExpr(Sema &S, const UnsatisfiedConstraintRecord &Record, SourceLocation Loc, bool First, concepts::NestedRequirement *Req=nullptr)

Definition SemaConcept.cpp:1949

static ExprResult SubstituteConceptsInConstraintExpression(Sema &S, const NamedDecl *D, const ConceptSpecializationExpr *CSE, UnsignedOrNone SubstIndex)

Definition SemaConcept.cpp:1260

static void DiagnoseUnsatisfiedConstraint(Sema &S, ArrayRef< UnsatisfiedConstraintRecord > Records, SourceLocation Loc, bool First=true, concepts::NestedRequirement *Req=nullptr)

Definition SemaConcept.cpp:1831

static const Expr * SubstituteConstraintExpressionWithoutSatisfaction(Sema &S, const Sema::TemplateCompareNewDeclInfo &DeclInfo, const Expr *ConstrExpr)

Definition SemaConcept.cpp:1471

static void diagnoseWellFormedUnsatisfiedConstraintExpr(Sema &S, const Expr *SubstExpr, bool First)

Definition SemaConcept.cpp:1851

static bool DiagRecursiveConstraintEval(Sema &S, llvm::FoldingSetNodeID &ID, const NamedDecl *Templ, const Expr *E, const MultiLevelTemplateArgumentList *MLTAL=nullptr)

Definition SemaConcept.cpp:182

static bool CheckConstraintSatisfaction(Sema &S, const NamedDecl *Template, ArrayRef< AssociatedConstraint > AssociatedConstraints, const MultiLevelTemplateArgumentList &TemplateArgsLists, SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction, Expr **ConvertedExpr, const ConceptReference *TopLevelConceptId=nullptr)

Definition SemaConcept.cpp:1111

static void diagnoseUnsatisfiedRequirement(Sema &S, concepts::ExprRequirement *Req, bool First)

Definition SemaConcept.cpp:1730

static void diagnoseUnsatisfiedConceptIdExpr(Sema &S, const ConceptReference *Concept, SourceLocation Loc, bool First)

Definition SemaConcept.cpp:1810

static bool CheckFunctionConstraintsWithoutInstantiation(Sema &SemaRef, SourceLocation PointOfInstantiation, FunctionTemplateDecl *Template, ArrayRef< TemplateArgument > TemplateArgs, ConstraintSatisfaction &Satisfaction)

Definition SemaConcept.cpp:1641

static unsigned CalculateTemplateDepthForConstraints(Sema &S, const NamedDecl *ND, bool SkipForSpecialization=false)

Definition SemaConcept.cpp:204

TemplateArgument getCanonicalTemplateArgument(const TemplateArgument &Arg) const

Retrieve the "canonical" template argument.

llvm::StringRef backupStr(llvm::StringRef S) const

const Expr * getConstraintExpr() const

static AtomicConstraint * Create(ASTContext &Ctx, const Expr *ConstraintExpr, const NamedDecl *ConstraintDecl, UnsignedOrNone PackIndex)

AtomicExpr - Variadic atomic builtins: __atomic_exchange, __atomic_fetch_*, __atomic_load,...

SourceLocation getBeginLoc() const LLVM_READONLY

A builtin binary operation expression such as "x + y" or "x <= y".

static OverloadedOperatorKind getOverloadedOperator(Opcode Opc)

Retrieve the overloaded operator kind that corresponds to the given binary opcode.

StringRef getOpcodeStr() const

static BinaryOperator * Create(const ASTContext &C, Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy, ExprValueKind VK, ExprObjectKind OK, SourceLocation opLoc, FPOptionsOverride FPFeatures)

static Opcode getOverloadedOpcode(OverloadedOperatorKind OO)

Retrieve the binary opcode that corresponds to the given overloaded operator.

Represents a C++ conversion function within a class.

Represents a C++ struct/union/class.

Represents a C++ nested-name-specifier or a global scope specifier.

void Adopt(NestedNameSpecifierLoc Other)

Adopt an existing nested-name-specifier (with source-range information).

const NormalizedConstraint & getLHS() const

static CompoundConstraint * CreateConjunction(ASTContext &Ctx, NormalizedConstraint *LHS, NormalizedConstraint *RHS)

CompoundConstraintKind getCompoundKind() const

const NormalizedConstraint & getRHS() const

static CompoundConstraint * Create(ASTContext &Ctx, NormalizedConstraint *LHS, CompoundConstraintKind CCK, NormalizedConstraint *RHS)

Declaration of a C++20 concept.

ConceptDecl * getCanonicalDecl() override

Retrieves the "canonical" declaration of the given declaration.

const NormalizedConstraint & getNormalizedConstraint() const

const ConceptSpecializationExpr * getConceptSpecializationExpr() const

static ConceptIdConstraint * Create(ASTContext &Ctx, const ConceptReference *ConceptId, NormalizedConstraint *SubConstraint, const NamedDecl *ConstraintDecl, const ConceptSpecializationExpr *CSE, UnsignedOrNone PackIndex)

const ConceptReference * getConceptId() const

A reference to a concept and its template args, as it appears in the code.

const NestedNameSpecifierLoc & getNestedNameSpecifierLoc() const

NamedDecl * getFoundDecl() const

const DeclarationNameInfo & getConceptNameInfo() const

SourceLocation getBeginLoc() const LLVM_READONLY

const ASTTemplateArgumentListInfo * getTemplateArgsAsWritten() const

TemplateDecl * getNamedConcept() const

SourceLocation getTemplateKWLoc() const

Represents the specialization of a concept - evaluates to a prvalue of type bool.

SourceLocation getBeginLoc() const LLVM_READONLY

SourceLocation getExprLoc() const LLVM_READONLY

ArrayRef< TemplateArgument > getTemplateArguments() const

const ASTTemplateArgumentListInfo * getTemplateArgsAsWritten() const

ConceptReference * getConceptReference() const

const ASTConstraintSatisfaction & getSatisfaction() const

Get elaborated satisfaction info about the template arguments' satisfaction of the named concept.

ConceptDecl * getNamedConcept() const

The result of a constraint satisfaction check, containing the necessary information to diagnose an un...

void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &C)

llvm::SmallVector< UnsatisfiedConstraintRecord, 4 > Details

The substituted constraint expr, if the template arguments could be substituted into them,...

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 isTransparentContext() const

isTransparentContext - Determines whether this context is a "transparent" context,...

bool isDependentContext() const

Determines whether this context is dependent on a template parameter.

DeclContext * getNonTransparentContext()

Decl - This represents one declaration (or definition), e.g.

FriendObjectKind getFriendObjectKind() const

Determines whether this declaration is the object of a friend declaration and, if so,...

bool isFunctionOrFunctionTemplate() const

Whether this declaration is a function or function template.

FunctionDecl * getAsFunction() LLVM_READONLY

Returns the function itself, or the templated function if this is a function template.

SourceLocation getLocation() const

DeclContext * getLexicalDeclContext()

getLexicalDeclContext - The declaration context where this Decl was lexically declared (LexicalDC).

const AssociatedConstraint & getTrailingRequiresClause() const

Get the constraint-expression introduced by the trailing requires-clause in the function/member decla...

RAII object that enters a new expression evaluation context.

This represents one expression.

@ SE_NoSideEffects

Strictly evaluate the expression.

bool isValueDependent() const

Determines whether the value of this expression depends on.

bool isTypeDependent() const

Determines whether the type of this expression depends on.

Expr * IgnoreParenImpCasts() LLVM_READONLY

Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...

bool containsErrors() const

Whether this expression contains subexpressions which had errors.

bool EvaluateAsConstantExpr(EvalResult &Result, const ASTContext &Ctx, ConstantExprKind Kind=ConstantExprKind::Normal) const

Evaluate an expression that is required to be a constant expression.

SourceLocation getExprLoc() const LLVM_READONLY

getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...

Represents difference between two FPOptions values.

static bool AreCompatibleForSubsumption(const FoldExpandedConstraint &A, const FoldExpandedConstraint &B)

Definition SemaConcept.cpp:2431

FoldOperatorKind getFoldOperator() const

const Expr * getPattern() const

static FoldExpandedConstraint * Create(ASTContext &Ctx, const Expr *Pattern, const NamedDecl *ConstraintDecl, FoldOperatorKind OpKind, NormalizedConstraint *Constraint)

const NormalizedConstraint & getNormalizedPattern() const

Represents a function declaration or definition.

FunctionTemplateDecl * getDescribedFunctionTemplate() const

Retrieves the function template that is described by this function declaration.

SourceLocation getPointOfInstantiation() const

Retrieve the (first) point of instantiation of a function template specialization or a member of a cl...

ArrayRef< ParmVarDecl * > parameters() const

FunctionTemplateDecl * getPrimaryTemplate() const

Retrieve the primary template that this function template specialization either specializes or was in...

const TemplateArgumentList * getTemplateSpecializationArgs() const

Retrieve the template arguments used to produce this function template specialization from the primar...

bool isTemplateInstantiation() const

Determines if the given function was instantiated from a function template.

TemplatedKind

The kind of templated function a FunctionDecl can be.

@ TK_MemberSpecialization

@ TK_DependentNonTemplate

@ TK_FunctionTemplateSpecialization

TemplatedKind getTemplatedKind() const

What kind of templated function this is.

FunctionDecl * getInstantiatedFromDecl() const

FunctionDecl * getInstantiatedFromMemberFunction() const

If this function is an instantiation of a member function of a class template specialization,...

Declaration of a template function.

FunctionDecl * getTemplatedDecl() const

Get the underlying function declaration of the template.

FunctionTemplateDecl * getInstantiatedFromMemberTemplate() const

static ImplicitCastExpr * Create(const ASTContext &Context, QualType T, CastKind Kind, Expr *Operand, const CXXCastPath *BasePath, ExprValueKind Cat, FPOptionsOverride FPO)

const TypeClass * getTypePtr() const

A stack-allocated class that identifies which local variable declaration instantiations are present i...

Data structure that captures multiple levels of template argument lists for use in template instantia...

bool hasTemplateArgument(unsigned Depth, unsigned Index) const

Determine whether there is a non-NULL template argument at the given depth and index.

const ArgList & getInnermost() const

Retrieve the innermost template argument list.

void addOuterTemplateArguments(Decl *AssociatedDecl, ArgList Args, bool Final)

Add a new outmost level to the multi-level template argument list.

unsigned getNumLevels() const

Determine the number of levels in this template argument list.

unsigned getNumSubstitutedLevels() const

Determine the number of substituted levels in this template argument list.

void replaceOutermostTemplateArguments(Decl *AssociatedDecl, ArgList Args)

const ArgList & getOutermost() const

Retrieve the outermost template argument list.

bool isAnyArgInstantiationDependent() const

This represents a decl that may have a name.

unsigned getPosition() const

Get the position of the template parameter within its parameter list.

bool isParameterPack() const

Whether this parameter is a non-type template parameter pack.

unsigned getIndex() const

Get the index of the template parameter within its parameter list.

unsigned getDepth() const

Get the nesting depth of the template parameter.

UnsignedOrNone getPackSubstitutionIndex() const

const NamedDecl * getConstraintDecl() const

bool hasMatchingParameterMapping(ASTContext &C, const NormalizedConstraint &Other) const

const OccurenceList & mappingOccurenceList() const

const OccurenceList & mappingOccurenceListForSubsumption() const

TemplateParameterList * getUsedTemplateParamList() const

llvm::MutableArrayRef< TemplateArgumentLoc > getParameterMapping() const

bool hasParameterMapping() const

void updateParameterMapping(OccurenceList Indexes, OccurenceList IndexesForSubsumption, llvm::MutableArrayRef< TemplateArgumentLoc > Args, TemplateParameterList *ParamList)

A (possibly-)qualified type.

QualType getCanonicalType() const

The collection of all-type qualifiers we support.

A class that does preorder or postorder depth-first traversal on the entire Clang AST and visits each...

Scope - A scope is a transient data structure that is used while parsing the program.

PartialDiagnostic PDiag(unsigned DiagID=0)

Build a partial diagnostic.

SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)

Emit a diagnostic.

RAII object used to change the argument pack substitution index within a Sema object.

RAII object used to temporarily allow the C++ 'this' expression to be used, with the given qualifiers...

RAII class used to determine whether SFINAE has trapped any errors that occur during template argumen...

SourceLocation getLocation() const

const DeclContext * getDeclContext() const

const NamedDecl * getDecl() const

const DeclContext * getLexicalDeclContext() const

Sema - This implements semantic analysis and AST building for C.

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.

ExprResult SubstConceptTemplateArguments(const ConceptSpecializationExpr *CSE, const Expr *ConstraintExpr, const MultiLevelTemplateArgumentList &MLTAL)

Substitute concept template arguments in the constraint expression of a concept-id.

llvm::DenseMap< llvm::FoldingSetNodeID, UnsubstitutedConstraintSatisfactionCacheResult > UnsubstitutedConstraintSatisfactionCache

Cache the satisfaction of an atomic constraint.

bool ConstraintExpressionDependsOnEnclosingTemplate(const FunctionDecl *Friend, unsigned TemplateDepth, const Expr *Constraint)

void MarkUsedTemplateParametersForSubsumptionParameterMapping(const Expr *E, unsigned Depth, llvm::SmallBitVector &Used)

Mark which template parameters are named in a given expression.

DiagnosticsEngine & getDiagnostics() const

void DiagnoseTypeTraitDetails(const Expr *E)

If E represents a built-in type trait, or a known standard type trait, try to print more information ...

bool CheckParameterPacksForExpansion(SourceLocation EllipsisLoc, SourceRange PatternRange, ArrayRef< UnexpandedParameterPack > Unexpanded, const MultiLevelTemplateArgumentList &TemplateArgs, bool FailOnPackProducingTemplates, bool &ShouldExpand, bool &RetainExpansion, UnsignedOrNone &NumExpansions, bool Diagnose=true)

Determine whether we could expand a pack expansion with the given set of parameter packs into separat...

ExprResult SubstConstraintExprWithoutSatisfaction(Expr *E, const MultiLevelTemplateArgumentList &TemplateArgs)

bool CheckConstraintExpression(const Expr *CE, Token NextToken=Token(), bool *PossibleNonPrimary=nullptr, bool IsTrailingRequiresClause=false)

Check whether the given expression is a valid constraint expression.

Definition SemaConcept.cpp:93

ASTContext & getASTContext() const

ExprResult CheckConceptTemplateId(const CXXScopeSpec &SS, SourceLocation TemplateKWLoc, const DeclarationNameInfo &ConceptNameInfo, NamedDecl *FoundDecl, TemplateDecl *NamedConcept, const TemplateArgumentListInfo *TemplateArgs, bool DoCheckConstraintSatisfaction=true)

llvm::PointerUnion< const NamedDecl *, const concepts::NestedRequirement * > ConstrainedDeclOrNestedRequirement

bool SubstTemplateArguments(ArrayRef< TemplateArgumentLoc > Args, const MultiLevelTemplateArgumentList &TemplateArgs, TemplateArgumentListInfo &Outputs)

bool CheckConstraintSatisfaction(ConstrainedDeclOrNestedRequirement Entity, ArrayRef< AssociatedConstraint > AssociatedConstraints, const MultiLevelTemplateArgumentList &TemplateArgLists, SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction, const ConceptReference *TopLevelConceptId=nullptr, Expr **ConvertedExpr=nullptr)

Check whether the given list of constraint expressions are satisfied (as if in a 'conjunction') given...

Definition SemaConcept.cpp:1180

const NormalizedConstraint * getNormalizedAssociatedConstraints(ConstrainedDeclOrNestedRequirement Entity, ArrayRef< AssociatedConstraint > AssociatedConstraints)

Definition SemaConcept.cpp:2396

bool FriendConstraintsDependOnEnclosingTemplate(const FunctionDecl *FD)

Definition SemaConcept.cpp:1593

bool EnsureTemplateArgumentListConstraints(TemplateDecl *Template, const MultiLevelTemplateArgumentList &TemplateArgs, SourceRange TemplateIDRange)

Ensure that the given template arguments satisfy the constraints associated with the given template,...

Definition SemaConcept.cpp:1614

const LangOptions & getLangOpts() const

void collectUnexpandedParameterPacks(TemplateArgument Arg, SmallVectorImpl< UnexpandedParameterPack > &Unexpanded)

Collect the set of unexpanded parameter packs within the given template argument.

TemplateArgument getPackSubstitutedTemplateArgument(TemplateArgument Arg) const

bool AreConstraintExpressionsEqual(const NamedDecl *Old, const Expr *OldConstr, const TemplateCompareNewDeclInfo &New, const Expr *NewConstr)

Definition SemaConcept.cpp:1564

sema::FunctionScopeInfo * getCurFunction() const

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 DiagnoseUnsatisfiedConstraint(const ConstraintSatisfaction &Satisfaction, SourceLocation Loc={}, bool First=true)

Emit diagnostics explaining why a constraint expression was deemed unsatisfied.

Definition SemaConcept.cpp:1973

bool CheckFunctionConstraints(const FunctionDecl *FD, ConstraintSatisfaction &Satisfaction, SourceLocation UsageLoc=SourceLocation(), bool ForOverloadResolution=false)

Check whether the given function decl's trailing requires clause is satisfied, if any.

Definition SemaConcept.cpp:1407

TemplateNameKindForDiagnostics getTemplateNameKindForDiagnostics(TemplateName Name)

SourceManager & getSourceManager() const

bool isSFINAEContext() const

UnsignedOrNone ArgPackSubstIndex

The current index into pack expansion arguments that will be used for substitution of parameter packs...

void PushSatisfactionStackEntry(const NamedDecl *D, const llvm::FoldingSetNodeID &ID)

void PopSatisfactionStackEntry()

ExprResult SubstConstraintExpr(Expr *E, const MultiLevelTemplateArgumentList &TemplateArgs)

void MarkUsedTemplateParameters(const Expr *E, bool OnlyDeduced, unsigned Depth, llvm::SmallBitVector &Used)

Mark which template parameters are used in a given expression.

@ ConstantEvaluated

The current context is "potentially evaluated" in C++11 terms, but the expression is evaluated at com...

@ Unevaluated

The current expression and its subexpressions occur within an unevaluated operand (C++11 [expr]p7),...

bool SatisfactionStackContains(const NamedDecl *D, const llvm::FoldingSetNodeID &ID) const

bool IsAtLeastAsConstrained(const NamedDecl *D1, MutableArrayRef< AssociatedConstraint > AC1, const NamedDecl *D2, MutableArrayRef< AssociatedConstraint > AC2, bool &Result)

Check whether the given declaration's associated constraints are at least as constrained than another...

Definition SemaConcept.cpp:2457

TemplateArgumentLoc getIdentityTemplateArgumentLoc(NamedDecl *Param, SourceLocation Location)

Get a template argument mapping the given template parameter to itself, e.g.

bool CheckFunctionTemplateConstraints(SourceLocation PointOfInstantiation, FunctionDecl *Decl, ArrayRef< TemplateArgument > TemplateArgs, ConstraintSatisfaction &Satisfaction)

Definition SemaConcept.cpp:1682

bool SubstTemplateArgumentsInParameterMapping(ArrayRef< TemplateArgumentLoc > Args, SourceLocation BaseLoc, const MultiLevelTemplateArgumentList &TemplateArgs, TemplateArgumentListInfo &Out, bool BuildPackExpansionTypes)

std::string getTemplateArgumentBindingsText(const TemplateParameterList *Params, const TemplateArgumentList &Args)

Produces a formatted string that describes the binding of template parameters to template arguments.

bool MaybeEmitAmbiguousAtomicConstraintsDiagnostic(const NamedDecl *D1, ArrayRef< AssociatedConstraint > AC1, const NamedDecl *D2, ArrayRef< AssociatedConstraint > AC2)

If D1 was not at least as constrained as D2, but would've been if a pair of atomic constraints involv...

Definition SemaConcept.cpp:2521

bool CheckTemplateArgumentList(TemplateDecl *Template, SourceLocation TemplateLoc, TemplateArgumentListInfo &TemplateArgs, const DefaultArguments &DefaultArgs, bool PartialTemplateArgs, CheckTemplateArgumentInfo &CTAI, bool UpdateArgsWithConversions=true, bool *ConstraintsNotSatisfied=nullptr)

Check that the given template arguments can be provided to the given template, converting the argumen...

NamedDecl * getPack() const

Retrieve the parameter pack.

Encodes a location in the source.

bool isValid() const

Return true if this is a valid SourceLocation object.

A trivial tuple used to represent a source range.

SourceLocation getBegin() const

std::string printToString(const SourceManager &SM) const

SourceRange getSourceRange() const LLVM_READONLY

SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...

void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, bool Canonical, bool ProfileLambdaExpr=false) const

Produce a unique representation of the given statement.

SourceLocation getBeginLoc() const LLVM_READONLY

Expr * getReplacement() const

SubsumptionChecker establishes subsumption between two set of constraints.

std::optional< bool > Subsumes(const NamedDecl *DP, ArrayRef< AssociatedConstraint > P, const NamedDecl *DQ, ArrayRef< AssociatedConstraint > Q)

Definition SemaConcept.cpp:2743

SubsumptionChecker(Sema &SemaRef, SubsumptionCallable Callable={})

Definition SemaConcept.cpp:2592

llvm::function_ref< bool( const AtomicConstraint &, const AtomicConstraint &)> SubsumptionCallable

A convenient class for passing around template argument information.

ArrayRef< TemplateArgumentLoc > arguments() const

Location wrapper for a TemplateArgument.

Represents a template argument.

void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) const

Used to insert TemplateArguments into FoldingSets.

TemplateName getAsTemplate() const

Retrieve the template name for a template name argument.

bool containsUnexpandedParameterPack() const

Whether this template argument contains an unexpanded parameter pack.

@ Pack

The template argument is actually a parameter pack.

ArgKind getKind() const

Return the kind of stored template argument.

bool isPackExpansion() const

Determine whether this template argument is a pack expansion.

The base class of all kinds of template declarations (e.g., class, function, etc.).

void getAssociatedConstraints(llvm::SmallVectorImpl< AssociatedConstraint > &AC) const

Get the total constraint-expression associated with this template, including constraint-expressions d...

TemplateParameterList * getTemplateParameters() const

Get the list of template parameters.

bool isNull() const

Determine whether this template name is NULL.

Stores a list of template parameters for a TemplateDecl and its derived classes.

static TemplateParameterList * Create(const ASTContext &C, SourceLocation TemplateLoc, SourceLocation LAngleLoc, ArrayRef< NamedDecl * > Params, SourceLocation RAngleLoc, Expr *RequiresClause)

SourceLocation getLAngleLoc() const

SourceLocation getTemplateLoc() const

Token - This structure provides full information about a lexed token.

bool is(tok::TokenKind K) const

is/isNot - Predicates to check if this token is a specific kind, as in "if (Tok.is(tok::l_brace)) {....

tok::TokenKind getKind() const

A semantic tree transformation that allows one to transform one abstract syntax tree into another.

TyLocType push(QualType T)

Pushes space for a new TypeLoc of the given type.

QualType getType() const

Get the type for which this source info wrapper provides information.

SourceLocation getNameLoc() const

void setNameLoc(SourceLocation Loc)

The base class of the type hierarchy.

bool isInstantiationDependentType() const

Determine whether this type is an instantiation-dependent type, meaning that the type involves a temp...

bool isSpecificBuiltinType(unsigned K) const

Test for a particular builtin type.

bool isDependentType() const

Whether this type is a dependent type, meaning that its definition somehow depends on a template para...

bool containsUnexpandedParameterPack() const

Whether this type is or contains an unexpanded parameter pack, used to support C++0x variadic templat...

bool isVariablyModifiedType() const

Whether this type is a variably-modified type (C99 6.7.5).

bool isFunctionType() const

SubstitutionDiagnostic * getSubstitutionDiagnostic() const

A requires-expression requirement which queries the validity and properties of an expression ('simple...

SubstitutionDiagnostic * getExprSubstitutionDiagnostic() const

ConceptSpecializationExpr * getReturnTypeRequirementSubstitutedConstraintExpr() const

@ SS_ConstraintsNotSatisfied

@ SS_TypeRequirementSubstitutionFailure

@ SS_ExprSubstitutionFailure

const ReturnTypeRequirement & getReturnTypeRequirement() const

SatisfactionStatus getSatisfactionStatus() const

SourceLocation getNoexceptLoc() const

A requires-expression requirement which is satisfied when a general constraint expression is satisfie...

const ASTConstraintSatisfaction & getConstraintSatisfaction() const

bool hasInvalidConstraint() const

Expr * getConstraintExpr() const

StringRef getInvalidConstraintEntity()

A static requirement that can be used in a requires-expression to check properties of types and expre...

A requires-expression requirement which queries the existence of a type name or type template special...

SubstitutionDiagnostic * getSubstitutionDiagnostic() const

SatisfactionStatus getSatisfactionStatus() const

Provides information about an attempted template argument deduction, whose success or failure was des...

__inline void unsigned int _2

uint32_t Literal

Literals are represented as positive integers.

bool Sub(InterpState &S, CodePtr OpPC)

bool Add(InterpState &S, CodePtr OpPC)

The JSON file list parser is used to communicate input to InstallAPI.

OverloadedOperatorKind

Enumeration specifying the different kinds of C++ overloaded operators.

@ OO_None

Not an overloaded operator.

bool isa(CodeGen::Address addr)

if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))

@ TemplateName

The identifier is a template name. FIXME: Add an annotation for that.

@ OK_Ordinary

An ordinary object is located at an address in memory.

llvm::PointerUnion< const Expr *, const ConceptReference *, const ConstraintSubstitutionDiagnostic * > UnsatisfiedConstraintRecord

std::pair< llvm::PointerUnion< const TemplateTypeParmType *, NamedDecl *, const TemplateSpecializationType *, const SubstBuiltinTemplatePackType * >, SourceLocation > UnexpandedParameterPack

nullptr

This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...

bool isLambdaCallOperator(const CXXMethodDecl *MD)

@ Result

The result type of a method or function.

std::pair< unsigned, unsigned > getDepthAndIndex(const NamedDecl *ND)

Retrieve the depth and index of a template parameter.

const FunctionProtoType * T

@ Template

We are parsing a template declaration.

@ Concept

The name was classified as a concept name.

std::pair< SourceLocation, StringRef > ConstraintSubstitutionDiagnostic

Unsatisfied constraint expressions if the template arguments could be substituted into them,...

prec::Level getBinOpPrecedence(tok::TokenKind Kind, bool GreaterThanIsOperator, bool CPlusPlus11)

Return the precedence of the specified binary operator token.

bool isLambdaConversionOperator(CXXConversionDecl *C)

std::pair< SourceLocation, PartialDiagnostic > PartialDiagnosticAt

A partial diagnostic along with the source location where this diagnostic occurs.

@ VK_PRValue

A pr-value expression (in the C++11 taxonomy) produces a temporary value.

U cast(CodeGen::Address addr)

ActionResult< Expr * > ExprResult

@ Other

Other implicit parameter.

The result of a constraint satisfaction check, containing the necessary information to diagnose an un...

ArrayRef< UnsatisfiedConstraintRecord > records() const

Represents an explicit template argument list in C++, e.g., the "" in "sort".

SourceLocation RAngleLoc

The source location of the right angle bracket ('>').

SourceLocation LAngleLoc

The source location of the left angle bracket ('<').

ArrayRef< TemplateArgumentLoc > arguments() const

EvalResult is a struct with detailed info about an evaluated expression.

APValue Val

Val - This is the value the expression can be folded to.

SmallVectorImpl< PartialDiagnosticAt > * Diag

Diag - If this is non-null, it will be filled in with a stack of notes indicating why evaluation fail...

A normalized constraint, as defined in C++ [temp.constr.normal], is either an atomic constraint,...

NormalizedConstraint(const Expr *ConstraintExpr, const NamedDecl *ConstraintDecl, UnsignedOrNone PackIndex)

SourceRange getSourceRange() const

ConstraintKind getKind() const

SourceLocation getBeginLoc() const

llvm::SmallBitVector OccurenceList

SmallVector< TemplateArgument, 4 > SugaredConverted

The checked, converted argument will be added to the end of these vectors.

A stack object to be created when performing template instantiation.

bool isInvalid() const

Determines whether we have exceeded the maximum recursive template instantiations.

constexpr unsigned toInternalRepresentation() const