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

1

2

3

4

5

6

7

8

9

10

11

12

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

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

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

30#include

31

32using namespace clang;

33using namespace sema;

34

35namespace {

36class LogicalBinOp {

39 const Expr *LHS = nullptr;

40 const Expr *RHS = nullptr;

41

42public:

43 LogicalBinOp(const Expr *E) {

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

46 LHS = BO->getLHS();

47 RHS = BO->getRHS();

48 Loc = BO->getExprLoc();

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

50

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

52 Op = OO->getOperator();

53 LHS = OO->getArg(0);

54 RHS = OO->getArg(1);

55 Loc = OO->getOperatorLoc();

56 }

57 }

58 }

59

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

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

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

63

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

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

67

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

70 }

71

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

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

76

79

80

81

86 }

87};

88}

89

91 Token NextToken, bool *PossibleNonPrimary,

92 bool IsTrailingRequiresClause) {

93

94

95

97

98 if (LogicalBinOp BO = ConstraintExpression) {

100 PossibleNonPrimary) &&

102 PossibleNonPrimary);

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

105 PossibleNonPrimary);

106

108

109 auto CheckForNonPrimary = [&] {

110 if (!PossibleNonPrimary)

111 return;

112

113 *PossibleNonPrimary =

114

115

116

117

118

119

120

121

122

123

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

125 (IsTrailingRequiresClause ||

127 isa(ConstraintExpression) &&

128 !dyn_cast_if_present(getCurFunction())) ||

131

132

133

134

135

137 true,

139 };

140

141

143 CheckForNonPrimary();

144 return true;

145 }

146

149 diag::err_non_bool_atomic_constraint) << Type

151 CheckForNonPrimary();

152 return false;

153 }

154

155 if (PossibleNonPrimary)

156 *PossibleNonPrimary = false;

157 return true;

158}

159

160namespace {

161struct SatisfactionStackRAII {

162 Sema &SemaRef;

163 bool Inserted = false;

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

165 const llvm::FoldingSetNodeID &FSNID)

166 : SemaRef(SemaRef) {

167 if (ND) {

169 Inserted = true;

170 }

171 }

172 ~SatisfactionStackRAII() {

173 if (Inserted)

175 }

176};

177}

178

179template

183 const ConstraintEvaluator &Evaluator);

184

185template

190 const ConstraintEvaluator &Evaluator) {

191 size_t EffectiveDetailEndIndex = Satisfaction.Details.size();

192

195

198

199 bool IsLHSSatisfied = Satisfaction.IsSatisfied;

200

201 if (Op == clang::OO_PipePipe && IsLHSSatisfied)

202

203

204

205

206

207

208

209 return LHSRes;

210

211 if (Op == clang::OO_AmpAmp && !IsLHSSatisfied)

212

213

214

215

216

217

218

219 return LHSRes;

220

225

226 bool IsRHSSatisfied = Satisfaction.IsSatisfied;

227

228

229

230

231

232

233

234

235 if (Op == clang::OO_PipePipe && IsRHSSatisfied) {

236 auto EffectiveDetailEnd = Satisfaction.Details.begin();

237 std::advance(EffectiveDetailEnd, EffectiveDetailEndIndex);

238 Satisfaction.Details.erase(EffectiveDetailEnd, Satisfaction.Details.end());

239 }

240

243

248}

249

250template

254 const ConstraintEvaluator &Evaluator) {

255 bool Conjunction = FE->getOperator() == BinaryOperatorKind::BO_LAnd;

256 size_t EffectiveDetailEndIndex = Satisfaction.Details.size();

257

261 Evaluator);

262 if (Out.isInvalid())

264

265

266

267

268

269 if (Conjunction != Satisfaction.IsSatisfied)

270 return Out;

271 }

272 std::optional NumExpansions =

273 Evaluator.EvaluateFoldExpandedConstraintSize(FE);

274 if (!NumExpansions)

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

279 Satisfaction, Evaluator);

282 bool IsRHSSatisfied = Satisfaction.IsSatisfied;

283 if (!Conjunction && IsRHSSatisfied) {

284 auto EffectiveDetailEnd = Satisfaction.Details.begin();

285 std::advance(EffectiveDetailEnd, EffectiveDetailEndIndex);

286 Satisfaction.Details.erase(EffectiveDetailEnd,

287 Satisfaction.Details.end());

288 }

289 if (Out.isUnset())

290 Out = Res;

291 else if (!Res.isUnset()) {

295 }

296 if (Conjunction != IsRHSSatisfied)

297 return Out;

298 }

299

302 Satisfaction, Evaluator);

303 if (Out.isInvalid())

305

306 if (Out.isUnset())

307 Out = Res;

308 else if (!Res.isUnset()) {

312 }

313 }

314

315 if (Out.isUnset()) {

318 }

319 return Out;

320}

321

322template

326 const ConstraintEvaluator &Evaluator) {

328

329 if (LogicalBinOp BO = ConstraintExpr)

331 S, BO.getLHS(), BO.getOp(), BO.getRHS(), Satisfaction, Evaluator);

332

333 if (auto *C = dyn_cast(ConstraintExpr)) {

334

335

337 Evaluator);

338 }

339

340 if (auto *FE = dyn_cast(ConstraintExpr);

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

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

345 }

346

347

349 Evaluator.EvaluateAtomicConstraint(ConstraintExpr);

350

351 if (SubstitutedAtomicExpr.isInvalid())

353

354 if (!SubstitutedAtomicExpr.isUsable())

355

357

358

359

360

361

362

366

369 DiagString = ": ";

371 unsigned MessageSize = DiagString.size();

372 char *Mem = new (S.Context) char[MessageSize];

373 memcpy(Mem, DiagString.c_str(), MessageSize);

374 Satisfaction.Details.emplace_back(

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

377 StringRef(Mem, MessageSize)});

378 return SubstitutedAtomicExpr;

379 }

380

385 EvalResult.Diag = &EvaluationDiags;

388 !EvaluationDiags.empty()) {

389

390

392 diag::err_non_constant_constraint_expression)

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

397 }

398

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

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

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

404

405 return SubstitutedAtomicExpr;

406}

407

408static bool

413 for (const auto &List : MLTAL)

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

416

417

418

419

420

421

422

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

426 return true;

427 }

428

429 return false;

430}

431

436

437 struct ConstraintEvaluator {

443

446 S, Sema::ExpressionEvaluationContext::ConstantEvaluated,

448

449

451 {

456 const_cast<NamedDecl *>(Template), Info,

460

461 llvm::FoldingSetNodeID ID;

462 if (Template &&

467 }

468

469 SatisfactionStackRAII StackRAII(S, Template, ID);

470

471

473 SubstitutedExpression =

475

477

478

479

481

482

484

488

489

490

491

492

493

495 DiagString = ": ";

496 SubstDiag.second.EmitToString(S.getDiagnostics(), DiagString);

497 unsigned MessageSize = DiagString.size();

498 char *Mem = new (S.Context) char[MessageSize];

499 memcpy(Mem, DiagString.c_str(), MessageSize);

500 Satisfaction.Details.emplace_back(

502 SubstDiag.first, StringRef(Mem, MessageSize)});

505 }

506 }

507

510

511

512

513

514

515

516

517

518

519

520

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

524 CK_LValueToRValue, SubstitutedExpression.get(),

526

527 return SubstitutedExpression;

528 }

529

530 std::optional

531 EvaluateFoldExpandedConstraintSize(const CXXFoldExpr *FE) const {

532

533

535

537

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

541 bool Expand = true;

542 bool RetainExpansion = false;

543 std::optional OrigNumExpansions = FE->getNumExpansions(),

544 NumExpansions = OrigNumExpansions;

547 MLTAL, Expand, RetainExpansion, NumExpansions) ||

548 !Expand || RetainExpansion)

549 return std::nullopt;

550

551 if (NumExpansions && S.getLangOpts().BracketDepth < NumExpansions) {

553 clang::diag::err_fold_expression_limit_exceeded)

554 << *NumExpansions << S.getLangOpts().BracketDepth

557 return std::nullopt;

558 }

559 return NumExpansions;

560 }

561 };

562

564 S, ConstraintExpr, Satisfaction,

565 ConstraintEvaluator{S, Template, TemplateNameLoc, MLTAL, Satisfaction});

566}

567

573 if (ConstraintExprs.empty()) {

575 return false;

576 }

577

579

581 return false;

582 }

583

590 const_cast<NamedDecl *>(Template), TemplateArgs, TemplateIDRange);

592 return true;

593

594 for (const Expr *ConstraintExpr : ConstraintExprs) {

596 S, Template, TemplateIDRange.getBegin(), TemplateArgsLists,

597 ConstraintExpr, Satisfaction);

599 return true;

600

601 Converted.push_back(Res.get());

603

604

605 Converted.append(ConstraintExprs.size() - Converted.size(), nullptr);

606

607

608

609

610 return false;

611 }

612 }

613 return false;

614}

615

621 if (ConstraintExprs.empty()) {

623 return false;

624 }

625 if (!Template) {

626 return ::CheckConstraintSatisfaction(

627 *this, nullptr, ConstraintExprs, ConvertedConstraints,

628 TemplateArgsLists, TemplateIDRange, OutSatisfaction);

629 }

630

631

634 return true;

635 }

636

637

638

639

640

642 for (auto List : TemplateArgsLists)

643 FlattenedArgs.insert(FlattenedArgs.end(), List.Args.begin(),

644 List.Args.end());

645

646 llvm::FoldingSetNodeID ID;

648 void *InsertPos;

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

650 OutSatisfaction = *Cached;

651 return false;

652 }

653

654 auto Satisfaction =

655 std::make_unique(Template, FlattenedArgs);

657 ConvertedConstraints, TemplateArgsLists,

658 TemplateIDRange, *Satisfaction)) {

659 OutSatisfaction = *Satisfaction;

660 return true;

661 }

662

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

664

665

666

667

668

669

670

671

672 OutSatisfaction = *Cached;

673 return false;

674 }

675

676

677 OutSatisfaction = *Satisfaction;

678

679

680

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

682 return false;

683}

684

687

688 struct ConstraintEvaluator {

692 }

693

694 std::optional

695 EvaluateFoldExpandedConstraintSize(const CXXFoldExpr *FE) const {

696 return 0;

697 }

698 };

699

701 ConstraintEvaluator{*this})

703}

704

705bool Sema::addInstantiatedCapturesToScope(

709 const auto *LambdaClass = cast(Function)->getParent();

710 const auto *LambdaPattern = cast(PatternDecl)->getParent();

711

712 unsigned Instantiated = 0;

713

714 auto AddSingleCapture = [&](const ValueDecl *CapturedPattern,

715 unsigned Index) {

716 ValueDecl *CapturedVar = LambdaClass->getCapture(Index)->getCapturedVar();

718 Scope.InstantiatedLocal(CapturedPattern, CapturedVar);

719 };

720

721 for (const LambdaCapture &CapturePattern : LambdaPattern->captures()) {

722 if (!CapturePattern.capturesVariable()) {

723 Instantiated++;

724 continue;

725 }

726 ValueDecl *CapturedPattern = CapturePattern.getCapturedVar();

727

729 Instantiated++;

730 continue;

731 }

732

734 AddSingleCapture(CapturedPattern, Instantiated++);

735 } else {

736 Scope.MakeInstantiatedLocalArgPack(CapturedPattern);

739 dyn_cast(CapturedPattern)->getInit(), Unexpanded);

740 auto NumArgumentsInExpansion =

742 if (!NumArgumentsInExpansion)

743 continue;

744 for (unsigned Arg = 0; Arg < *NumArgumentsInExpansion; ++Arg)

745 AddSingleCapture(CapturedPattern, Instantiated++);

746 }

747 }

748 return false;

749}

750

751bool Sema::SetupConstraintScope(

756 "Use LambdaScopeForCallOperatorInstantiationRAII to handle lambda "

757 "instantiations");

760 InstantiatingTemplate Inst(

765 if (Inst.isInvalid())

766 return true;

767

768

769

770

771

772

775 false);

776 if (addInstantiatedParametersToScope(

778 return true;

779 }

780

781

782

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

787 return true;

788 }

789

790 return false;

791 }

792

799

800 InstantiatingTemplate Inst(

805 if (Inst.isInvalid())

806 return true;

807

808

809

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

811 return true;

812 }

813

814 return false;

815}

816

817

818

819std::optional

820Sema::SetupConstraintCheckingTemplateArgumentsAndScope(

824

825

826

827

828 MLTAL =

830 false, std::nullopt,

831 true,

832 nullptr,

833 true);

834

836 return MLTAL;

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

838 return std::nullopt;

839

840 return MLTAL;

841}

842

846 bool ForOverloadResolution) {

847

848

849

850

855 return false;

856 }

857

858

859

860

861

862

863

864

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

868 Satisfaction, UsageLoc,

869 true);

870

872

876 else

878 }

879

880 ContextRAII SavedContext{*this, CtxToSave};

882 std::optional MLTAL =

883 SetupConstraintCheckingTemplateArgumentsAndScope(

885

886 if (!MLTAL)

887 return true;

888

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

892 ThisQuals = Method->getMethodQualifiers();

894 }

896

899 ForOverloadResolution);

900

904 Satisfaction);

905}

906

907

908

909

910

911static unsigned

913 bool SkipForSpecialization = false) {

916 std::nullopt,

917 true,

918 nullptr,

919 true, SkipForSpecialization);

921}

922

923namespace {

924 class AdjustConstraintDepth : public TreeTransform {

925 unsigned TemplateDepth = 0;

926 public:

928 AdjustConstraintDepth(Sema &SemaRef, unsigned TemplateDepth)

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

930

931 using inherited::TransformTemplateTypeParmType;

935

938 NewTTPDecl = cast_or_null(

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

940

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

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

943 NewTTPDecl);

946 return Result;

947 }

948 };

949}

950

953 const Expr *ConstrExpr) {

956 std::nullopt,

957 true,

958 nullptr, true,

959 false);

960

962 return ConstrExpr;

963

965

971 return nullptr;

972

973

974

975

976

977 std::optional ScopeForParameters;

980 ScopeForParameters.emplace(S, true);

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

984 ScopeForParameters->InstantiatedLocal(PVD, PVD);

985 continue;

986 }

987

988

989

990

991

992

993

994

995

996

997

998

999

1000

1001

1002

1003 ScopeForParameters->MakeInstantiatedLocalArgPack(PVD);

1004 ScopeForParameters->InstantiatedLocalPackArg(PVD, PVD);

1005 }

1006 }

1007

1008 std::optionalSema::CXXThisScopeRAII ThisScope;

1009

1010

1011

1012

1013

1014

1015

1016

1017 std::optionalSema::ContextRAII ContextScope;

1019 if (!DeclInfo.getDecl())

1024 }();

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

1027 ContextScope.emplace(S, const_cast<DeclContext *>(cast(RD)),

1028 false);

1029 }

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

1036 return nullptr;

1037 return SubstConstr.get();

1038}

1039

1041 const Expr *OldConstr,

1043 const Expr *NewConstr) {

1044 if (OldConstr == NewConstr)

1045 return true;

1046

1049 if (const Expr *SubstConstr =

1051 OldConstr))

1052 OldConstr = SubstConstr;

1053 else

1054 return false;

1055 if (const Expr *SubstConstr =

1057 NewConstr))

1058 NewConstr = SubstConstr;

1059 else

1060 return false;

1061 }

1062

1063 llvm::FoldingSetNodeID ID1, ID2;

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

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

1066 return ID1 == ID2;

1067}

1068

1071

1072

1073

1074

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

1077

1080

1082 for (const Expr *Constraint : ACs)

1084 Constraint))

1085 return true;

1086

1087 return false;

1088}

1089

1097 TemplateIDRange, Satisfaction))

1098 return true;

1099

1102 TemplateArgString = " ";

1106

1108 diag::err_template_arg_list_constraints_not_satisfied)

1110 << TemplateArgString << TemplateIDRange;

1112 return true;

1113 }

1114 return false;

1115}

1116

1121

1123

1124

1127 if (TemplateAC.empty()) {

1129 return false;

1130 }

1131

1132

1133

1136

1137 std::optional MLTAL =

1138 SetupConstraintCheckingTemplateArgumentsAndScope(Decl, TemplateArgs,

1140

1141 if (!MLTAL)

1142 return true;

1143

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

1147 ThisQuals = Method->getMethodQualifiers();

1148 Record = Method->getParent();

1149 }

1150

1154

1157 PointOfInstantiation, Satisfaction);

1158}

1159

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

1167 llvm_unreachable("Diagnosing a dependent requirement");

1168 break;

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

1172 S.Diag(SubstDiag->DiagLoc,

1173 diag::note_expr_requirement_expr_substitution_error)

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

1175 << SubstDiag->DiagMessage;

1176 else

1177 S.Diag(SubstDiag->DiagLoc,

1178 diag::note_expr_requirement_expr_unknown_substitution_error)

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

1180 break;

1181 }

1184 diag::note_expr_requirement_noexcept_not_met)

1186 break;

1188 auto *SubstDiag =

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

1191 S.Diag(SubstDiag->DiagLoc,

1192 diag::note_expr_requirement_type_requirement_substitution_error)

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

1194 << SubstDiag->DiagMessage;

1195 else

1196 S.Diag(SubstDiag->DiagLoc,

1197 diag::note_expr_requirement_type_requirement_unknown_substitution_error)

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

1199 break;

1200 }

1205

1206

1209 diag::note_expr_requirement_constraints_not_satisfied_simple)

1212 } else {

1214 diag::note_expr_requirement_constraints_not_satisfied)

1215 << (int)First << ConstraintExpr;

1216 }

1218 break;

1219 }

1221 llvm_unreachable("We checked this above");

1222 }

1223}

1224

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

1232 llvm_unreachable("Diagnosing a dependent requirement");

1233 return;

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

1237 S.Diag(SubstDiag->DiagLoc,

1238 diag::note_type_requirement_substitution_error) << (int)First

1239 << SubstDiag->SubstitutedEntity << SubstDiag->DiagMessage;

1240 else

1241 S.Diag(SubstDiag->DiagLoc,

1242 diag::note_type_requirement_unknown_substitution_error)

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

1244 return;

1245 }

1246 default:

1247 llvm_unreachable("Unknown satisfaction status");

1248 return;

1249 }

1250}

1252 Expr *SubstExpr,

1253 bool First = true);

1254

1258 using SubstitutionDiagnostic = std::pair<SourceLocation, StringRef>;

1260 if (auto *SubstDiag = Record.dyn_cast<SubstitutionDiagnostic *>())

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

1263 << SubstDiag->second;

1264 else

1268 }

1269}

1270

1272 Expr *SubstExpr,

1275 if (BinaryOperator *BO = dyn_cast(SubstExpr)) {

1276 switch (BO->getOpcode()) {

1277

1278

1279

1280 case BO_LOr:

1281

1284 false);

1285 return;

1286 case BO_LAnd: {

1287 bool LHSSatisfied =

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

1289 if (LHSSatisfied) {

1290

1292 return;

1293 }

1294

1296

1297

1298 bool RHSSatisfied =

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

1300 if (!RHSSatisfied)

1302 false);

1303 return;

1304 }

1305 case BO_GE:

1306 case BO_LE:

1307 case BO_GT:

1308 case BO_LT:

1309 case BO_EQ:

1310 case BO_NE:

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

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

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

1317 true);

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

1320 true);

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

1323 diag::note_atomic_constraint_evaluated_to_false_elaborated)

1328 return;

1329 }

1330 }

1331 break;

1332

1333 default:

1334 break;

1335 }

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

1337 if (CSE->getTemplateArgsAsWritten()->NumTemplateArgs == 1) {

1339 CSE->getSourceRange().getBegin(),

1340 diag::

1341 note_single_arg_concept_specialization_constraint_evaluated_to_false)

1343 << CSE->getTemplateArgsAsWritten()->arguments()[0].getArgument()

1344 << CSE->getNamedConcept();

1345 } else {

1347 diag::note_concept_specialization_constraint_evaluated_to_false)

1348 << (int)First << CSE;

1349 }

1351 return;

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

1353

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

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

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

1360 else

1362 S, castconcepts::NestedRequirement(Req), First);

1363 break;

1364 }

1365 return;

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

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

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

1370 diag::note_is_deducible_constraint_evaluated_to_false)

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

1372 return;

1373 }

1374

1376 diag::note_atomic_constraint_evaluated_to_false)

1378}

1379

1380template

1382 Sema &S, const llvm::PointerUnion<Expr *, SubstitutionDiagnostic *> &Record,

1383 bool First = true) {

1384 if (auto *Diag = Record.template dyn_cast<SubstitutionDiagnostic *>()) {

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

1386 << Diag->second;

1387 return;

1388 }

1389

1391}

1392

1393void

1397 "Attempted to diagnose a satisfied constraint");

1401 }

1402}

1403

1408 "Attempted to diagnose a satisfied constraint");

1409 for (auto &Record : Satisfaction) {

1412 }

1413}

1414

1418

1419

1420

1421 ConstrainedDecl = cast(ConstrainedDecl->getCanonicalDecl());

1422

1423 auto CacheEntry = NormalizationCache.find(ConstrainedDecl);

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

1425 auto Normalized =

1426 NormalizedConstraint::fromConstraintExprs(*this, ConstrainedDecl,

1427 AssociatedConstraints);

1428 CacheEntry =

1429 NormalizationCache

1430 .try_emplace(ConstrainedDecl,

1431 Normalized

1433 std::move(*Normalized))

1434 : nullptr)

1435 .first;

1436 }

1437 return CacheEntry->second;

1438}

1439

1444 AssociatedConstraints);

1445}

1446

1447static bool

1452

1455 ArgsAsWritten))

1456 return true;

1458 ArgsAsWritten);

1459 }

1460

1465 ArgsAsWritten);

1466 }

1467

1469

1472 if (Atomic.ParameterMapping) {

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

1475 0, OccurringIndices);

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

1479 if (OccurringIndices[I])

1480 new (&(TempArgs)[J++])

1482 TemplateParams->begin()[I],

1483

1484

1485

1486

1487

1488

1489

1490

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

1494 Atomic.ParameterMapping.emplace(TempArgs, OccurringIndices.count());

1495 }

1497 ArgsAsWritten->arguments().empty()

1499 : ArgsAsWritten->arguments().front().getSourceRange().getBegin();

1501 ArgsAsWritten->arguments().empty()

1503 : ArgsAsWritten->arguments().front().getSourceRange().getEnd();

1505 S, InstLocBegin,

1507 Atomic.ConstraintDecl, {InstLocBegin, InstLocEnd});

1508 if (Inst.isInvalid())

1509 return true;

1511 return true;

1512

1515 std::copy(SubstArgs.arguments().begin(), SubstArgs.arguments().end(),

1516 TempArgs);

1517 Atomic.ParameterMapping.emplace(TempArgs, SubstArgs.size());

1518 return false;

1519}

1520

1526 true,

1527 nullptr,

1528 true);

1529

1532}

1533

1540 Kind}} {}

1541

1544 if (Other.isAtomic()) {

1546 } else if (Other.isFoldExpanded()) {

1548 Other.getFoldExpandedConstraint()->Kind,

1550 Other.getFoldExpandedConstraint()->Pattern);

1551 } else {

1553 new (C)

1556 Other.getCompoundKind());

1557 }

1558}

1559

1561 assert(isCompound() && "getLHS called on a non-compound constraint.");

1562 return cast(Constraint).getPointer()->LHS;

1563}

1564

1566 assert(isCompound() && "getRHS called on a non-compound constraint.");

1567 return cast(Constraint).getPointer()->RHS;

1568}

1569

1570std::optional

1571NormalizedConstraint::fromConstraintExprs(Sema &S, NamedDecl *D,

1573 assert(E.size() != 0);

1574 auto Conjunction = fromConstraintExpr(S, D, E[0]);

1575 if (!Conjunction)

1576 return std::nullopt;

1577 for (unsigned I = 1; I < E.size(); ++I) {

1578 auto Next = fromConstraintExpr(S, D, E[I]);

1579 if (!Next)

1580 return std::nullopt;

1583 }

1584 return Conjunction;

1585}

1586

1587std::optional

1588NormalizedConstraint::fromConstraintExpr(Sema &S, NamedDecl *D, const Expr *E) {

1589 assert(E != nullptr);

1590

1591

1592

1593

1594

1596

1597

1598

1599

1600

1601

1602 if (LogicalBinOp BO = E) {

1603 auto LHS = fromConstraintExpr(S, D, BO.getLHS());

1604 if (!LHS)

1605 return std::nullopt;

1606 auto RHS = fromConstraintExpr(S, D, BO.getRHS());

1607 if (!RHS)

1608 return std::nullopt;

1609

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

1614 {

1616 S, CSE->getExprLoc(),

1619 if (Inst.isInvalid())

1620 return std::nullopt;

1621

1622

1623

1624

1625

1626

1627

1628

1629

1630 ConceptDecl *CD = CSE->getNamedConcept();

1633 if (!SubNF)

1634 return std::nullopt;

1635 }

1636

1637 std::optional New;

1638 New.emplace(S.Context, *SubNF);

1639

1641 return std::nullopt;

1642

1643 return New;

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

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

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

1648

1649

1650

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

1655

1656 if (FE->getInit()) {

1657 auto LHS = fromConstraintExpr(S, D, FE->getLHS());

1658 auto RHS = fromConstraintExpr(S, D, FE->getRHS());

1659 if (!LHS || !RHS)

1660 return std::nullopt;

1661

1662 if (FE->isRightFold())

1664 Kind, std::move(*RHS), FE->getPattern()}};

1665 else

1667 Kind, std::move(*LHS), FE->getPattern()}};

1668

1670 S.Context, std::move(*LHS), std::move(*RHS),

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

1673 }

1674 auto Sub = fromConstraintExpr(S, D, FE->getPattern());

1675 if (!Sub)

1676 return std::nullopt;

1678 Kind, std::move(*Sub), FE->getPattern()}};

1679 }

1680

1682}

1683

1686

1687

1688

1689

1690

1694

1696 std::pair<unsigned, unsigned> DepthAndIndex = getDepthAndIndex(APack);

1699 });

1700 if (it != BPacks.end())

1701 return true;

1702 }

1703 return false;

1704}

1705

1709

1712

1716 LCNF.reserve(LCNF.size() + RCNF.size());

1717 while (!RCNF.empty())

1718 LCNF.push_back(RCNF.pop_back_val());

1719 return LCNF;

1720 }

1721

1722

1724 Res.reserve(LCNF.size() * RCNF.size());

1725 for (auto &LDisjunction : LCNF)

1726 for (auto &RDisjunction : RCNF) {

1727 NormalForm::value_type Combined;

1728 Combined.reserve(LDisjunction.size() + RDisjunction.size());

1729 std::copy(LDisjunction.begin(), LDisjunction.end(),

1730 std::back_inserter(Combined));

1731 std::copy(RDisjunction.begin(), RDisjunction.end(),

1732 std::back_inserter(Combined));

1733 Res.emplace_back(Combined);

1734 }

1735 return Res;

1736}

1737

1741

1744

1748 LDNF.reserve(LDNF.size() + RDNF.size());

1749 while (!RDNF.empty())

1750 LDNF.push_back(RDNF.pop_back_val());

1751 return LDNF;

1752 }

1753

1754

1756 Res.reserve(LDNF.size() * RDNF.size());

1757 for (auto &LConjunction : LDNF) {

1758 for (auto &RConjunction : RDNF) {

1759 NormalForm::value_type Combined;

1760 Combined.reserve(LConjunction.size() + RConjunction.size());

1761 std::copy(LConjunction.begin(), LConjunction.end(),

1762 std::back_inserter(Combined));

1763 std::copy(RConjunction.begin(), RConjunction.end(),

1764 std::back_inserter(Combined));

1765 Res.emplace_back(Combined);

1766 }

1767 }

1768 return Res;

1769}

1770

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

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

1781 };

1782 const auto *FD2 = dyn_cast(D2);

1783 (void)IsExpectedEntity;

1784 (void)FD1;

1785 (void)FD2;

1786 assert(IsExpectedEntity(FD1) && FD2 && IsExpectedEntity(FD2) &&

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

1788 "ordering");

1789 }

1790

1791 if (AC1.empty()) {

1792 Result = AC2.empty();

1793 return false;

1794 }

1795 if (AC2.empty()) {

1796

1798 return false;

1799 }

1800

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

1802 auto CacheEntry = SubsumptionCache.find(Key);

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

1804 Result = CacheEntry->second;

1805 return false;

1806 }

1807

1810

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

1812 if (Depth2 > Depth1) {

1813 AC1[I] = AdjustConstraintDepth(*this, Depth2 - Depth1)

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

1815 .get();

1816 } else if (Depth1 > Depth2) {

1817 AC2[I] = AdjustConstraintDepth(*this, Depth1 - Depth2)

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

1819 .get();

1820 }

1821 }

1822

1824 *this, D1, AC1, D2, AC2, Result,

1827 }))

1828 return true;

1829 SubsumptionCache.try_emplace(Key, Result);

1830 return false;

1831}

1832

1836

1837 return false;

1838

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

1840 return false;

1841

1842 auto NormalExprEvaluator =

1845 };

1846

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

1848 auto IdenticalExprEvaluator =

1851 return false;

1853 if (EA == EB)

1854 return true;

1855

1856

1857

1858 llvm::FoldingSetNodeID IDA, IDB;

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

1861 if (IDA != IDB)

1862 return false;

1863

1864 AmbiguousAtomic1 = EA;

1865 AmbiguousAtomic2 = EB;

1866 return true;

1867 };

1868

1869 {

1870

1873 if (!Normalized1)

1874 return false;

1877

1879 if (!Normalized2)

1880 return false;

1883

1884 bool Is1AtLeastAs2Normally =

1886 bool Is2AtLeastAs1Normally =

1888 bool Is1AtLeastAs2 = clang::subsumes(DNF1, CNF2, IdenticalExprEvaluator);

1889 bool Is2AtLeastAs1 = clang::subsumes(DNF2, CNF1, IdenticalExprEvaluator);

1890 if (Is1AtLeastAs2 == Is1AtLeastAs2Normally &&

1891 Is2AtLeastAs1 == Is2AtLeastAs1Normally)

1892

1893 return false;

1894 }

1895

1896

1897 assert(AmbiguousAtomic1 && AmbiguousAtomic2);

1898

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

1901 Diag(AmbiguousAtomic2->getBeginLoc(),

1902 diag::note_ambiguous_atomic_constraints_similar_expression)

1903 << AmbiguousAtomic2->getSourceRange();

1904 return true;

1905}

1906

1911 Requirement(IsSimple ? RK_Simple : RK_Compound, Status == SS_Dependent,

1912 Status == SS_Dependent &&

1913 (E->containsUnexpandedParameterPack() ||

1914 Req.containsUnexpandedParameterPack()),

1915 Status == SS_Satisfied), Value(E), NoexceptLoc(NoexceptLoc),

1916 TypeReq(Req), SubstitutedConstraintExpr(SubstitutedConstraintExpr),

1917 Status(Status) {

1918 assert((!IsSimple || (Req.isEmpty() && NoexceptLoc.isInvalid())) &&

1919 "Simple requirement must not have a return type requirement or a "

1920 "noexcept specification");

1922 (SubstitutedConstraintExpr != nullptr));

1923}

1924

1928 Requirement(IsSimple ? RK_Simple : RK_Compound, Req.isDependent(),

1929 Req.containsUnexpandedParameterPack(), false),

1930 Value(ExprSubstDiag), NoexceptLoc(NoexceptLoc), TypeReq(Req),

1931 Status(SS_ExprSubstitutionFailure) {

1932 assert((!IsSimple || (Req.isEmpty() && NoexceptLoc.isInvalid())) &&

1933 "Simple requirement must not have a return type requirement or a "

1934 "noexcept specification");

1935}

1936

1939 TypeConstraintInfo(TPL, false) {

1940 assert(TPL->size() == 1);

1942 cast(TPL->getParam(0))->getTypeConstraint();

1943 assert(TC &&

1944 "TPL must have a template type parameter with a type constraint");

1945 auto *Constraint =

1948 Constraint->getTemplateArgsAsWritten() &&

1950 Constraint->getTemplateArgsAsWritten()->arguments().drop_front(1));

1951 TypeConstraintInfo.setInt(Dependent ? true : false);

1952}

1953

1957

1958

1959

1960 true),

1962 Status(T->getType()->isInstantiationDependentType() ? SS_Dependent

1964

1967 assert(isCompound() && "getCompoundKind on a non-compound constraint..");

1968 return cast(Constraint).getInt();

1969}

1970

1972 assert(isAtomic() && "getAtomicConstraint called on non-atomic constraint.");

1973 return cast<AtomicConstraint *>(Constraint);

1974}

1975

1978 assert(isFoldExpanded() &&

1979 "getFoldExpandedConstraint called on non-fold-expanded constraint.");

1980 return cast<FoldExpandedConstraint *>(Constraint);

1981}

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 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::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 bool CheckConstraintSatisfaction(Sema &S, const NamedDecl *Template, ArrayRef< const Expr * > ConstraintExprs, llvm::SmallVectorImpl< Expr * > &Converted, const MultiLevelTemplateArgumentList &TemplateArgsLists, SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction)

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

static ExprResult calculateConstraintSatisfaction(Sema &S, const Expr *ConstraintExpr, ConstraintSatisfaction &Satisfaction, const ConstraintEvaluator &Evaluator)

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

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

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

static bool substituteParameterMappings(Sema &S, NormalizedConstraint &N, ConceptDecl *Concept, const MultiLevelTemplateArgumentList &MLTAL, const ASTTemplateArgumentListInfo *ArgsAsWritten)

static void diagnoseUnsatisfiedConstraintExpr(Sema &S, const llvm::PointerUnion< Expr *, SubstitutionDiagnostic * > &Record, bool First=true)

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

static bool isInvalid(LocType Loc, bool *Invalid)

__DEVICE__ void * memcpy(void *__a, const void *__b, size_t __c)

Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...

QualType getReferenceQualifiedType(const Expr *e) const

getReferenceQualifiedType - Given an expr, will return the type for that expression,...

bool hasSameUnqualifiedType(QualType T1, QualType T2) const

Determine whether the given types are equivalent after cvr-qualifiers have been removed.

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 folding of a pack over an operator.

SourceLocation getBeginLoc() const LLVM_READONLY

Expr * getInit() const

Get the operand that doesn't contain a pack, for a binary fold.

std::optional< unsigned > getNumExpansions() const

SourceLocation getEllipsisLoc() const

bool isLeftFold() const

Does this produce a left-associated sequence of operators?

bool isRightFold() const

Does this produce a right-associated sequence of operators?

Expr * getPattern() const

Get the pattern, that is, the operand that contains an unexpanded pack.

BinaryOperatorKind getOperator() const

Represents a C++ struct/union/class.

Declaration of a C++20 concept.

Expr * getConstraintExpr() const

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

SourceLocation getBeginLoc() const LLVM_READONLY

ArrayRef< TemplateArgument > getTemplateArguments() const

const ASTTemplateArgumentListInfo * getTemplateArgsAsWritten() 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...

std::pair< SourceLocation, StringRef > SubstitutionDiagnostic

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

llvm::SmallVector< Detail, 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.

bool isParameterPack() const

Whether this declaration is a parameter pack.

FunctionDecl * getAsFunction() LLVM_READONLY

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

bool isInvalidDecl() const

SourceLocation getLocation() const

DeclContext * getLexicalDeclContext()

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

virtual Decl * getCanonicalDecl()

Retrieves the "canonical" declaration of the given declaration.

virtual SourceRange getSourceRange() const LLVM_READONLY

Source range that this declaration covers.

Expr * getTrailingRequiresClause()

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 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, e.g.

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.

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

Describes the capture of a variable or of this, or of a C++1y init-capture.

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

const ArgList & getInnermost() const

Retrieve the innermost 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.

const ArgList & getOutermost() const

Retrieve the outermost template argument list.

bool isAnyArgInstantiationDependent() const

This represents a decl that may have a name.

void EmitToString(DiagnosticsEngine &Diags, SmallVectorImpl< char > &Buf) const

A (possibly-)qualified type.

The collection of all-type qualifiers we support.

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

SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, bool DeferHint=false)

Emit a diagnostic.

PartialDiagnostic PDiag(unsigned DiagID=0)

Build a partial 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...

bool hasErrorOccurred() const

Determine whether any SFINAE errors have been trapped.

SourceLocation getLocation() const

bool ContainsDecl(const NamedDecl *ND) const

const DeclContext * getDeclContext() const

const NamedDecl * getDecl() const

const DeclContext * getLexicalDeclContext() const

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

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

bool CheckParameterPacksForExpansion(SourceLocation EllipsisLoc, SourceRange PatternRange, ArrayRef< UnexpandedParameterPack > Unexpanded, const MultiLevelTemplateArgumentList &TemplateArgs, bool &ShouldExpand, bool &RetainExpansion, std::optional< unsigned > &NumExpansions)

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

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

DiagnosticsEngine & getDiagnostics() const

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.

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

std::optional< unsigned > getNumArgumentsInExpansionFromUnexpanded(llvm::ArrayRef< UnexpandedParameterPack > Unexpanded, const MultiLevelTemplateArgumentList &TemplateArgs)

bool FriendConstraintsDependOnEnclosingTemplate(const FunctionDecl *FD)

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

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

const LangOptions & getLangOpts() const

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

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

bool CheckConstraintSatisfaction(const NamedDecl *Template, ArrayRef< const Expr * > ConstraintExprs, const MultiLevelTemplateArgumentList &TemplateArgLists, SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction)

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

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

sema::FunctionScopeInfo * getCurFunction() const

std::optional< sema::TemplateDeductionInfo * > isSFINAEContext() const

Determines whether we are currently in a context where template argument substitution failures are no...

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

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

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

ExprResult PerformContextuallyConvertToBool(Expr *From)

PerformContextuallyConvertToBool - Perform a contextual conversion of the expression From to bool (C+...

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.

TemplateNameKindForDiagnostics getTemplateNameKindForDiagnostics(TemplateName Name)

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

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

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

ExprResult BuildEmptyCXXFoldExpr(SourceLocation EllipsisLoc, BinaryOperatorKind Operator)

TemplateArgumentLoc getIdentityTemplateArgumentLoc(NamedDecl *Param, SourceLocation Location)

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

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

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

void DiagnoseUnsatisfiedConstraint(const ConstraintSatisfaction &Satisfaction, bool First=true)

Emit diagnostics explaining why a constraint expression was deemed unsatisfied.

const NormalizedConstraint * getNormalizedAssociatedConstraints(NamedDecl *ConstrainedDecl, ArrayRef< const Expr * > AssociatedConstraints)

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

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

A convenient class for passing around template argument information.

llvm::ArrayRef< TemplateArgumentLoc > arguments() const

Location wrapper for a TemplateArgument.

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

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

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

TemplateParameterList * getTemplateParameters() const

Get the list of template parameters.

Represents a C++ template name within the type system.

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

NamedDecl * getParam(unsigned Idx)

static bool anyInstantiationDependentTemplateArguments(ArrayRef< TemplateArgumentLoc > Args)

Declaration of a template type parameter.

Wrapper for template type parameters.

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.

Models the abbreviated syntax to constrain a template type parameter: template <convertible_to<string...

Expr * getImmediatelyDeclaredConstraint() const

Get the immediately-declared constraint expression introduced by this type-constraint,...

TyLocType push(QualType T)

Pushes space for a new TypeLoc of the given type.

A container of type source information.

SourceLocation getNameLoc() const

void setNameLoc(SourceLocation Loc)

The base class of the type hierarchy.

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

Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...

bool isInitCapture() const

Whether this variable is the implicit variable for a lambda init-capture.

ReturnTypeRequirement()

No return type requirement was specified.

bool isTypeConstraint() 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

ExprRequirement(Expr *E, bool IsSimple, SourceLocation NoexceptLoc, ReturnTypeRequirement Req, SatisfactionStatus Status, ConceptSpecializationExpr *SubstitutedConstraintExpr=nullptr)

Construct a compound requirement.

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

const ASTConstraintSatisfaction & getConstraintSatisfaction() const

StringRef getInvalidConstraintEntity()

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

bool containsUnexpandedParameterPack() const

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

SubstitutionDiagnostic * getSubstitutionDiagnostic() const

SatisfactionStatus getSatisfactionStatus() const

TypeRequirement(TypeSourceInfo *T)

Construct a type requirement from a type.

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

void takeSFINAEDiagnostic(PartialDiagnosticAt &PD)

Take ownership of the SFINAE diagnostic.

bool Sub(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.

NormalForm makeCNF(const NormalizedConstraint &Normalized)

NormalForm makeDNF(const NormalizedConstraint &Normalized)

@ OK_Ordinary

An ordinary object is located at an address in memory.

bool subsumes(const NormalForm &PDNF, const NormalForm &QCNF, const AtomicSubsumptionEvaluator &E)

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 NormalizedConstraint * getNormalizedAssociatedConstraints(Sema &S, NamedDecl *ConstrainedDecl, ArrayRef< const Expr * > AssociatedConstraints)

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

Return the precedence of the specified binary operator token.

bool isLambdaConversionOperator(CXXConversionDecl *C)

@ VK_PRValue

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

const FunctionProtoType * T

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

std::pair< SourceLocation, PartialDiagnostic > PartialDiagnosticAt

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

@ Other

Other implicit parameter.

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

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

SourceLocation getLAngleLoc() const

llvm::ArrayRef< TemplateArgumentLoc > arguments() const

unsigned NumTemplateArgs

The number of template arguments in TemplateArgs.

SourceLocation getRAngleLoc() const

bool subsumes(ASTContext &C, const AtomicConstraint &Other) const

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

const Expr * ConstraintExpr

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

NormalizedConstraint Constraint

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

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

llvm::PointerUnion< AtomicConstraint *, FoldExpandedConstraint *, CompoundConstraint > Constraint

bool isFoldExpanded() const

NormalizedConstraint & getRHS() const

llvm::PointerIntPair< NormalizedConstraintPair *, 1, CompoundConstraintKind > CompoundConstraint

CompoundConstraintKind getCompoundKind() const

NormalizedConstraint(AtomicConstraint *C)

AtomicConstraint * getAtomicConstraint() const

FoldExpandedConstraint * getFoldExpandedConstraint() const

NormalizedConstraint & getLHS() const

A stack object to be created when performing template instantiation.

bool isInvalid() const

Determines whether we have exceeded the maximum recursive template instantiations.