File indexing completed on 2026-05-10 08:36:35
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef LLVM_CLANG_AST_EXPRCONCEPTS_H
0015 #define LLVM_CLANG_AST_EXPRCONCEPTS_H
0016
0017 #include "clang/AST/ASTConcept.h"
0018 #include "clang/AST/ASTContext.h"
0019 #include "clang/AST/Decl.h"
0020 #include "clang/AST/DeclTemplate.h"
0021 #include "clang/AST/DeclarationName.h"
0022 #include "clang/AST/Expr.h"
0023 #include "clang/AST/NestedNameSpecifier.h"
0024 #include "clang/AST/TemplateBase.h"
0025 #include "clang/AST/Type.h"
0026 #include "clang/Basic/SourceLocation.h"
0027 #include "llvm/ADT/STLFunctionalExtras.h"
0028 #include "llvm/Support/ErrorHandling.h"
0029 #include "llvm/Support/TrailingObjects.h"
0030 #include <string>
0031 #include <utility>
0032
0033 namespace clang {
0034 class ASTStmtReader;
0035 class ASTStmtWriter;
0036
0037
0038
0039
0040
0041
0042 class ConceptSpecializationExpr final : public Expr {
0043 friend class ASTReader;
0044 friend class ASTStmtReader;
0045
0046 private:
0047 ConceptReference *ConceptRef;
0048
0049
0050
0051 ImplicitConceptSpecializationDecl *SpecDecl;
0052
0053
0054
0055
0056 ASTConstraintSatisfaction *Satisfaction;
0057
0058 ConceptSpecializationExpr(const ASTContext &C, ConceptReference *ConceptRef,
0059 ImplicitConceptSpecializationDecl *SpecDecl,
0060 const ConstraintSatisfaction *Satisfaction);
0061
0062 ConceptSpecializationExpr(const ASTContext &C, ConceptReference *ConceptRef,
0063 ImplicitConceptSpecializationDecl *SpecDecl,
0064 const ConstraintSatisfaction *Satisfaction,
0065 bool Dependent,
0066 bool ContainsUnexpandedParameterPack);
0067 ConceptSpecializationExpr(EmptyShell Empty);
0068
0069 public:
0070 static ConceptSpecializationExpr *
0071 Create(const ASTContext &C, ConceptReference *ConceptRef,
0072 ImplicitConceptSpecializationDecl *SpecDecl,
0073 const ConstraintSatisfaction *Satisfaction);
0074
0075 static ConceptSpecializationExpr *
0076 Create(const ASTContext &C, ConceptReference *ConceptRef,
0077 ImplicitConceptSpecializationDecl *SpecDecl,
0078 const ConstraintSatisfaction *Satisfaction, bool Dependent,
0079 bool ContainsUnexpandedParameterPack);
0080
0081 ArrayRef<TemplateArgument> getTemplateArguments() const {
0082 return SpecDecl->getTemplateArguments();
0083 }
0084
0085 ConceptReference *getConceptReference() const { return ConceptRef; }
0086
0087 ConceptDecl *getNamedConcept() const { return ConceptRef->getNamedConcept(); }
0088
0089
0090
0091 bool hasExplicitTemplateArgs() const {
0092 return ConceptRef->hasExplicitTemplateArgs();
0093 }
0094
0095 SourceLocation getConceptNameLoc() const {
0096 return ConceptRef->getConceptNameLoc();
0097 }
0098 const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const {
0099 return ConceptRef->getTemplateArgsAsWritten();
0100 }
0101
0102 const NestedNameSpecifierLoc &getNestedNameSpecifierLoc() const {
0103 return ConceptRef->getNestedNameSpecifierLoc();
0104 }
0105
0106 SourceLocation getTemplateKWLoc() const {
0107 return ConceptRef->getTemplateKWLoc();
0108 }
0109
0110 NamedDecl *getFoundDecl() const { return ConceptRef->getFoundDecl(); }
0111
0112 const DeclarationNameInfo &getConceptNameInfo() const {
0113 return ConceptRef->getConceptNameInfo();
0114 }
0115
0116 const ImplicitConceptSpecializationDecl *getSpecializationDecl() const {
0117 assert(SpecDecl && "Template Argument Decl not initialized");
0118 return SpecDecl;
0119 }
0120
0121
0122
0123
0124 bool isSatisfied() const {
0125 assert(!isValueDependent() &&
0126 "isSatisfied called on a dependent ConceptSpecializationExpr");
0127 return Satisfaction->IsSatisfied;
0128 }
0129
0130
0131
0132
0133 const ASTConstraintSatisfaction &getSatisfaction() const {
0134 assert(!isValueDependent() &&
0135 "getSatisfaction called on dependent ConceptSpecializationExpr");
0136 return *Satisfaction;
0137 }
0138
0139 static bool classof(const Stmt *T) {
0140 return T->getStmtClass() == ConceptSpecializationExprClass;
0141 }
0142
0143 SourceLocation getBeginLoc() const LLVM_READONLY {
0144 return ConceptRef->getBeginLoc();
0145 }
0146
0147 SourceLocation getEndLoc() const LLVM_READONLY {
0148 return ConceptRef->getEndLoc();
0149 }
0150
0151 SourceLocation getExprLoc() const LLVM_READONLY {
0152 return ConceptRef->getLocation();
0153 }
0154
0155
0156 child_range children() {
0157 return child_range(child_iterator(), child_iterator());
0158 }
0159 const_child_range children() const {
0160 return const_child_range(const_child_iterator(), const_child_iterator());
0161 }
0162 };
0163
0164 namespace concepts {
0165
0166
0167
0168 class Requirement {
0169 public:
0170
0171
0172 enum RequirementKind { RK_Type, RK_Simple, RK_Compound, RK_Nested };
0173 private:
0174 const RequirementKind Kind;
0175
0176 LLVM_PREFERRED_TYPE(bool)
0177 bool Dependent : 1;
0178 LLVM_PREFERRED_TYPE(bool)
0179 bool ContainsUnexpandedParameterPack : 1;
0180 LLVM_PREFERRED_TYPE(bool)
0181 bool Satisfied : 1;
0182 public:
0183 struct SubstitutionDiagnostic {
0184 StringRef SubstitutedEntity;
0185
0186
0187
0188 SourceLocation DiagLoc;
0189 StringRef DiagMessage;
0190 };
0191
0192 Requirement(RequirementKind Kind, bool IsDependent,
0193 bool ContainsUnexpandedParameterPack, bool IsSatisfied = true) :
0194 Kind(Kind), Dependent(IsDependent),
0195 ContainsUnexpandedParameterPack(ContainsUnexpandedParameterPack),
0196 Satisfied(IsSatisfied) {}
0197
0198 RequirementKind getKind() const { return Kind; }
0199
0200 bool isSatisfied() const {
0201 assert(!Dependent &&
0202 "isSatisfied can only be called on non-dependent requirements.");
0203 return Satisfied;
0204 }
0205
0206 void setSatisfied(bool IsSatisfied) {
0207 assert(!Dependent &&
0208 "setSatisfied can only be called on non-dependent requirements.");
0209 Satisfied = IsSatisfied;
0210 }
0211
0212 void setDependent(bool IsDependent) { Dependent = IsDependent; }
0213 bool isDependent() const { return Dependent; }
0214
0215 void setContainsUnexpandedParameterPack(bool Contains) {
0216 ContainsUnexpandedParameterPack = Contains;
0217 }
0218 bool containsUnexpandedParameterPack() const {
0219 return ContainsUnexpandedParameterPack;
0220 }
0221 };
0222
0223
0224
0225 class TypeRequirement : public Requirement {
0226 public:
0227 enum SatisfactionStatus {
0228 SS_Dependent,
0229 SS_SubstitutionFailure,
0230 SS_Satisfied
0231 };
0232 private:
0233 llvm::PointerUnion<SubstitutionDiagnostic *, TypeSourceInfo *> Value;
0234 SatisfactionStatus Status;
0235 public:
0236 friend ASTStmtReader;
0237 friend ASTStmtWriter;
0238
0239
0240
0241
0242
0243 TypeRequirement(TypeSourceInfo *T);
0244
0245
0246
0247 TypeRequirement(SubstitutionDiagnostic *Diagnostic) :
0248 Requirement(RK_Type, false, false, false), Value(Diagnostic),
0249 Status(SS_SubstitutionFailure) {}
0250
0251 SatisfactionStatus getSatisfactionStatus() const { return Status; }
0252 void setSatisfactionStatus(SatisfactionStatus Status) {
0253 this->Status = Status;
0254 }
0255
0256 bool isSubstitutionFailure() const {
0257 return Status == SS_SubstitutionFailure;
0258 }
0259
0260 SubstitutionDiagnostic *getSubstitutionDiagnostic() const {
0261 assert(Status == SS_SubstitutionFailure &&
0262 "Attempted to get substitution diagnostic when there has been no "
0263 "substitution failure.");
0264 return cast<SubstitutionDiagnostic *>(Value);
0265 }
0266
0267 TypeSourceInfo *getType() const {
0268 assert(!isSubstitutionFailure() &&
0269 "Attempted to get type when there has been a substitution failure.");
0270 return cast<TypeSourceInfo *>(Value);
0271 }
0272
0273 static bool classof(const Requirement *R) {
0274 return R->getKind() == RK_Type;
0275 }
0276 };
0277
0278
0279
0280 class ExprRequirement : public Requirement {
0281 public:
0282 enum SatisfactionStatus {
0283 SS_Dependent,
0284 SS_ExprSubstitutionFailure,
0285 SS_NoexceptNotMet,
0286 SS_TypeRequirementSubstitutionFailure,
0287 SS_ConstraintsNotSatisfied,
0288 SS_Satisfied
0289 };
0290 class ReturnTypeRequirement {
0291 llvm::PointerIntPair<
0292 llvm::PointerUnion<TemplateParameterList *, SubstitutionDiagnostic *>,
0293 1, bool>
0294 TypeConstraintInfo;
0295 public:
0296 friend ASTStmtReader;
0297 friend ASTStmtWriter;
0298
0299
0300 ReturnTypeRequirement() : TypeConstraintInfo(nullptr, false) {}
0301
0302
0303
0304 ReturnTypeRequirement(SubstitutionDiagnostic *SubstDiag) :
0305 TypeConstraintInfo(SubstDiag, false) {}
0306
0307
0308
0309
0310
0311
0312
0313 ReturnTypeRequirement(TemplateParameterList *TPL);
0314
0315 bool isDependent() const {
0316 return TypeConstraintInfo.getInt();
0317 }
0318
0319 bool containsUnexpandedParameterPack() const {
0320 if (!isTypeConstraint())
0321 return false;
0322 return getTypeConstraintTemplateParameterList()
0323 ->containsUnexpandedParameterPack();
0324 }
0325
0326 bool isEmpty() const {
0327 return TypeConstraintInfo.getPointer().isNull();
0328 }
0329
0330 bool isSubstitutionFailure() const {
0331 return !isEmpty() &&
0332 isa<SubstitutionDiagnostic *>(TypeConstraintInfo.getPointer());
0333 }
0334
0335 bool isTypeConstraint() const {
0336 return !isEmpty() &&
0337 isa<TemplateParameterList *>(TypeConstraintInfo.getPointer());
0338 }
0339
0340 SubstitutionDiagnostic *getSubstitutionDiagnostic() const {
0341 assert(isSubstitutionFailure());
0342 return cast<SubstitutionDiagnostic *>(TypeConstraintInfo.getPointer());
0343 }
0344
0345 const TypeConstraint *getTypeConstraint() const;
0346
0347 TemplateParameterList *getTypeConstraintTemplateParameterList() const {
0348 assert(isTypeConstraint());
0349 return cast<TemplateParameterList *>(TypeConstraintInfo.getPointer());
0350 }
0351 };
0352 private:
0353 llvm::PointerUnion<Expr *, SubstitutionDiagnostic *> Value;
0354 SourceLocation NoexceptLoc;
0355 ReturnTypeRequirement TypeReq;
0356 ConceptSpecializationExpr *SubstitutedConstraintExpr;
0357 SatisfactionStatus Status;
0358 public:
0359 friend ASTStmtReader;
0360 friend ASTStmtWriter;
0361
0362
0363
0364
0365
0366
0367
0368
0369 ExprRequirement(
0370 Expr *E, bool IsSimple, SourceLocation NoexceptLoc,
0371 ReturnTypeRequirement Req, SatisfactionStatus Status,
0372 ConceptSpecializationExpr *SubstitutedConstraintExpr = nullptr);
0373
0374
0375
0376
0377
0378
0379
0380
0381
0382
0383 ExprRequirement(SubstitutionDiagnostic *E, bool IsSimple,
0384 SourceLocation NoexceptLoc, ReturnTypeRequirement Req = {});
0385
0386 bool isSimple() const { return getKind() == RK_Simple; }
0387 bool isCompound() const { return getKind() == RK_Compound; }
0388
0389 bool hasNoexceptRequirement() const { return NoexceptLoc.isValid(); }
0390 SourceLocation getNoexceptLoc() const { return NoexceptLoc; }
0391
0392 SatisfactionStatus getSatisfactionStatus() const { return Status; }
0393
0394 bool isExprSubstitutionFailure() const {
0395 return Status == SS_ExprSubstitutionFailure;
0396 }
0397
0398 const ReturnTypeRequirement &getReturnTypeRequirement() const {
0399 return TypeReq;
0400 }
0401
0402 ConceptSpecializationExpr *
0403 getReturnTypeRequirementSubstitutedConstraintExpr() const {
0404 assert(Status >= SS_TypeRequirementSubstitutionFailure);
0405 return SubstitutedConstraintExpr;
0406 }
0407
0408 SubstitutionDiagnostic *getExprSubstitutionDiagnostic() const {
0409 assert(isExprSubstitutionFailure() &&
0410 "Attempted to get expression substitution diagnostic when there has "
0411 "been no expression substitution failure");
0412 return cast<SubstitutionDiagnostic *>(Value);
0413 }
0414
0415 Expr *getExpr() const {
0416 assert(!isExprSubstitutionFailure() &&
0417 "ExprRequirement has no expression because there has been a "
0418 "substitution failure.");
0419 return cast<Expr *>(Value);
0420 }
0421
0422 static bool classof(const Requirement *R) {
0423 return R->getKind() == RK_Compound || R->getKind() == RK_Simple;
0424 }
0425 };
0426
0427
0428
0429 class NestedRequirement : public Requirement {
0430 Expr *Constraint = nullptr;
0431 const ASTConstraintSatisfaction *Satisfaction = nullptr;
0432 bool HasInvalidConstraint = false;
0433 StringRef InvalidConstraintEntity;
0434
0435 public:
0436 friend ASTStmtReader;
0437 friend ASTStmtWriter;
0438
0439 NestedRequirement(Expr *Constraint)
0440 : Requirement(RK_Nested, true,
0441 Constraint->containsUnexpandedParameterPack()),
0442 Constraint(Constraint) {
0443 assert(Constraint->isInstantiationDependent() &&
0444 "Nested requirement with non-dependent constraint must be "
0445 "constructed with a ConstraintSatisfaction object");
0446 }
0447
0448 NestedRequirement(ASTContext &C, Expr *Constraint,
0449 const ConstraintSatisfaction &Satisfaction)
0450 : Requirement(RK_Nested, Constraint->isInstantiationDependent(),
0451 Constraint->containsUnexpandedParameterPack(),
0452 Satisfaction.IsSatisfied),
0453 Constraint(Constraint),
0454 Satisfaction(ASTConstraintSatisfaction::Create(C, Satisfaction)) {}
0455
0456 NestedRequirement(StringRef InvalidConstraintEntity,
0457 const ASTConstraintSatisfaction *Satisfaction)
0458 : Requirement(RK_Nested,
0459 false,
0460 false,
0461 Satisfaction->IsSatisfied),
0462 Satisfaction(Satisfaction), HasInvalidConstraint(true),
0463 InvalidConstraintEntity(InvalidConstraintEntity) {}
0464
0465 NestedRequirement(ASTContext &C, StringRef InvalidConstraintEntity,
0466 const ConstraintSatisfaction &Satisfaction)
0467 : NestedRequirement(InvalidConstraintEntity,
0468 ASTConstraintSatisfaction::Create(C, Satisfaction)) {}
0469
0470 bool hasInvalidConstraint() const { return HasInvalidConstraint; }
0471
0472 StringRef getInvalidConstraintEntity() {
0473 assert(hasInvalidConstraint());
0474 return InvalidConstraintEntity;
0475 }
0476
0477 Expr *getConstraintExpr() const {
0478 assert(!hasInvalidConstraint() &&
0479 "getConstraintExpr() may not be called "
0480 "on nested requirements with invalid constraint.");
0481 return Constraint;
0482 }
0483
0484 const ASTConstraintSatisfaction &getConstraintSatisfaction() const {
0485 return *Satisfaction;
0486 }
0487
0488 static bool classof(const Requirement *R) {
0489 return R->getKind() == RK_Nested;
0490 }
0491 };
0492 }
0493
0494
0495
0496
0497
0498
0499
0500 class RequiresExpr final : public Expr,
0501 llvm::TrailingObjects<RequiresExpr, ParmVarDecl *,
0502 concepts::Requirement *> {
0503 friend TrailingObjects;
0504 friend class ASTStmtReader;
0505
0506 unsigned NumLocalParameters;
0507 unsigned NumRequirements;
0508 RequiresExprBodyDecl *Body;
0509 SourceLocation LParenLoc;
0510 SourceLocation RParenLoc;
0511 SourceLocation RBraceLoc;
0512
0513 unsigned numTrailingObjects(OverloadToken<ParmVarDecl *>) const {
0514 return NumLocalParameters;
0515 }
0516
0517 unsigned numTrailingObjects(OverloadToken<concepts::Requirement *>) const {
0518 return NumRequirements;
0519 }
0520
0521 RequiresExpr(ASTContext &C, SourceLocation RequiresKWLoc,
0522 RequiresExprBodyDecl *Body, SourceLocation LParenLoc,
0523 ArrayRef<ParmVarDecl *> LocalParameters,
0524 SourceLocation RParenLoc,
0525 ArrayRef<concepts::Requirement *> Requirements,
0526 SourceLocation RBraceLoc);
0527 RequiresExpr(ASTContext &C, EmptyShell Empty, unsigned NumLocalParameters,
0528 unsigned NumRequirements);
0529
0530 public:
0531 static RequiresExpr *Create(ASTContext &C, SourceLocation RequiresKWLoc,
0532 RequiresExprBodyDecl *Body,
0533 SourceLocation LParenLoc,
0534 ArrayRef<ParmVarDecl *> LocalParameters,
0535 SourceLocation RParenLoc,
0536 ArrayRef<concepts::Requirement *> Requirements,
0537 SourceLocation RBraceLoc);
0538 static RequiresExpr *
0539 Create(ASTContext &C, EmptyShell Empty, unsigned NumLocalParameters,
0540 unsigned NumRequirements);
0541
0542 ArrayRef<ParmVarDecl *> getLocalParameters() const {
0543 return {getTrailingObjects<ParmVarDecl *>(), NumLocalParameters};
0544 }
0545
0546 RequiresExprBodyDecl *getBody() const { return Body; }
0547
0548 ArrayRef<concepts::Requirement *> getRequirements() const {
0549 return {getTrailingObjects<concepts::Requirement *>(), NumRequirements};
0550 }
0551
0552
0553
0554 bool isSatisfied() const {
0555 assert(!isValueDependent()
0556 && "isSatisfied called on a dependent RequiresExpr");
0557 return RequiresExprBits.IsSatisfied;
0558 }
0559
0560 void setSatisfied(bool IsSatisfied) {
0561 assert(!isValueDependent() &&
0562 "setSatisfied called on a dependent RequiresExpr");
0563 RequiresExprBits.IsSatisfied = IsSatisfied;
0564 }
0565
0566 SourceLocation getRequiresKWLoc() const {
0567 return RequiresExprBits.RequiresKWLoc;
0568 }
0569
0570 SourceLocation getLParenLoc() const { return LParenLoc; }
0571 SourceLocation getRParenLoc() const { return RParenLoc; }
0572 SourceLocation getRBraceLoc() const { return RBraceLoc; }
0573
0574 static bool classof(const Stmt *T) {
0575 return T->getStmtClass() == RequiresExprClass;
0576 }
0577
0578 SourceLocation getBeginLoc() const LLVM_READONLY {
0579 return RequiresExprBits.RequiresKWLoc;
0580 }
0581 SourceLocation getEndLoc() const LLVM_READONLY {
0582 return RBraceLoc;
0583 }
0584
0585
0586 child_range children() {
0587 return child_range(child_iterator(), child_iterator());
0588 }
0589 const_child_range children() const {
0590 return const_child_range(const_child_iterator(), const_child_iterator());
0591 }
0592 };
0593
0594 }
0595
0596 #endif