xref: /freebsd/contrib/llvm-project/clang/include/clang/AST/ExprConcepts.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
1 //===- ExprConcepts.h - C++2a Concepts expressions --------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 /// \file
10 /// Defines Expressions and AST nodes for C++2a concepts.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef LLVM_CLANG_AST_EXPRCONCEPTS_H
15 #define LLVM_CLANG_AST_EXPRCONCEPTS_H
16 
17 #include "clang/AST/ASTConcept.h"
18 #include "clang/AST/ASTContext.h"
19 #include "clang/AST/Decl.h"
20 #include "clang/AST/DeclTemplate.h"
21 #include "clang/AST/DeclarationName.h"
22 #include "clang/AST/Expr.h"
23 #include "clang/AST/NestedNameSpecifier.h"
24 #include "clang/AST/TemplateBase.h"
25 #include "clang/AST/Type.h"
26 #include "clang/Basic/SourceLocation.h"
27 #include "llvm/ADT/STLFunctionalExtras.h"
28 #include "llvm/Support/ErrorHandling.h"
29 #include "llvm/Support/TrailingObjects.h"
30 #include <string>
31 #include <utility>
32 
33 namespace clang {
34 class ASTStmtReader;
35 class ASTStmtWriter;
36 
37 /// \brief Represents the specialization of a concept - evaluates to a prvalue
38 /// of type bool.
39 ///
40 /// According to C++2a [expr.prim.id]p3 an id-expression that denotes the
41 /// specialization of a concept results in a prvalue of type bool.
42 class ConceptSpecializationExpr final : public Expr {
43   friend class ASTReader;
44   friend class ASTStmtReader;
45 
46 private:
47   ConceptReference *ConceptRef;
48 
49   /// \brief The Implicit Concept Specialization Decl, which holds the template
50   /// arguments for this specialization.
51   ImplicitConceptSpecializationDecl *SpecDecl;
52 
53   /// \brief Information about the satisfaction of the named concept with the
54   /// given arguments. If this expression is value dependent, this is to be
55   /// ignored.
56   ASTConstraintSatisfaction *Satisfaction;
57 
58   ConceptSpecializationExpr(const ASTContext &C, ConceptReference *ConceptRef,
59                             ImplicitConceptSpecializationDecl *SpecDecl,
60                             const ConstraintSatisfaction *Satisfaction);
61 
62   ConceptSpecializationExpr(const ASTContext &C, ConceptReference *ConceptRef,
63                             ImplicitConceptSpecializationDecl *SpecDecl,
64                             const ConstraintSatisfaction *Satisfaction,
65                             bool Dependent,
66                             bool ContainsUnexpandedParameterPack);
67   ConceptSpecializationExpr(EmptyShell Empty);
68 
69 public:
70   static ConceptSpecializationExpr *
71   Create(const ASTContext &C, ConceptReference *ConceptRef,
72          ImplicitConceptSpecializationDecl *SpecDecl,
73          const ConstraintSatisfaction *Satisfaction);
74 
75   static ConceptSpecializationExpr *
76   Create(const ASTContext &C, ConceptReference *ConceptRef,
77          ImplicitConceptSpecializationDecl *SpecDecl,
78          const ConstraintSatisfaction *Satisfaction, bool Dependent,
79          bool ContainsUnexpandedParameterPack);
80 
getTemplateArguments()81   ArrayRef<TemplateArgument> getTemplateArguments() const {
82     return SpecDecl->getTemplateArguments();
83   }
84 
getConceptReference()85   ConceptReference *getConceptReference() const { return ConceptRef; }
86 
getNamedConcept()87   ConceptDecl *getNamedConcept() const { return ConceptRef->getNamedConcept(); }
88 
89   // FIXME: Several of the following functions can be removed. Instead the
90   // caller can directly work with the ConceptReference.
hasExplicitTemplateArgs()91   bool hasExplicitTemplateArgs() const {
92     return ConceptRef->hasExplicitTemplateArgs();
93   }
94 
getConceptNameLoc()95   SourceLocation getConceptNameLoc() const {
96     return ConceptRef->getConceptNameLoc();
97   }
getTemplateArgsAsWritten()98   const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const {
99     return ConceptRef->getTemplateArgsAsWritten();
100   }
101 
getNestedNameSpecifierLoc()102   const NestedNameSpecifierLoc &getNestedNameSpecifierLoc() const {
103     return ConceptRef->getNestedNameSpecifierLoc();
104   }
105 
getTemplateKWLoc()106   SourceLocation getTemplateKWLoc() const {
107     return ConceptRef->getTemplateKWLoc();
108   }
109 
getFoundDecl()110   NamedDecl *getFoundDecl() const { return ConceptRef->getFoundDecl(); }
111 
getConceptNameInfo()112   const DeclarationNameInfo &getConceptNameInfo() const {
113     return ConceptRef->getConceptNameInfo();
114   }
115 
getSpecializationDecl()116   const ImplicitConceptSpecializationDecl *getSpecializationDecl() const {
117     assert(SpecDecl && "Template Argument Decl not initialized");
118     return SpecDecl;
119   }
120 
121   /// \brief Whether or not the concept with the given arguments was satisfied
122   /// when the expression was created.
123   /// The expression must not be dependent.
isSatisfied()124   bool isSatisfied() const {
125     assert(!isValueDependent() &&
126            "isSatisfied called on a dependent ConceptSpecializationExpr");
127     return Satisfaction->IsSatisfied;
128   }
129 
130   /// \brief Get elaborated satisfaction info about the template arguments'
131   /// satisfaction of the named concept.
132   /// The expression must not be dependent.
getSatisfaction()133   const ASTConstraintSatisfaction &getSatisfaction() const {
134     assert(!isValueDependent() &&
135            "getSatisfaction called on dependent ConceptSpecializationExpr");
136     return *Satisfaction;
137   }
138 
classof(const Stmt * T)139   static bool classof(const Stmt *T) {
140     return T->getStmtClass() == ConceptSpecializationExprClass;
141   }
142 
getBeginLoc()143   SourceLocation getBeginLoc() const LLVM_READONLY {
144     return ConceptRef->getBeginLoc();
145   }
146 
getEndLoc()147   SourceLocation getEndLoc() const LLVM_READONLY {
148     return ConceptRef->getEndLoc();
149   }
150 
getExprLoc()151   SourceLocation getExprLoc() const LLVM_READONLY {
152     return ConceptRef->getLocation();
153   }
154 
155   // Iterators
children()156   child_range children() {
157     return child_range(child_iterator(), child_iterator());
158   }
children()159   const_child_range children() const {
160     return const_child_range(const_child_iterator(), const_child_iterator());
161   }
162 };
163 
164 namespace concepts {
165 
166 /// \brief A static requirement that can be used in a requires-expression to
167 /// check properties of types and expression.
168 class Requirement {
169 public:
170   // Note - simple and compound requirements are both represented by the same
171   // class (ExprRequirement).
172   enum RequirementKind { RK_Type, RK_Simple, RK_Compound, RK_Nested };
173 private:
174   const RequirementKind Kind;
175   // FIXME: use RequirementDependence to model dependence?
176   LLVM_PREFERRED_TYPE(bool)
177   bool Dependent : 1;
178   LLVM_PREFERRED_TYPE(bool)
179   bool ContainsUnexpandedParameterPack : 1;
180   LLVM_PREFERRED_TYPE(bool)
181   bool Satisfied : 1;
182 public:
183   struct SubstitutionDiagnostic {
184     StringRef SubstitutedEntity;
185     // FIXME: Store diagnostics semantically and not as prerendered strings.
186     //  Fixing this probably requires serialization of PartialDiagnostic
187     //  objects.
188     SourceLocation DiagLoc;
189     StringRef DiagMessage;
190   };
191 
192   Requirement(RequirementKind Kind, bool IsDependent,
193               bool ContainsUnexpandedParameterPack, bool IsSatisfied = true) :
Kind(Kind)194       Kind(Kind), Dependent(IsDependent),
195       ContainsUnexpandedParameterPack(ContainsUnexpandedParameterPack),
196       Satisfied(IsSatisfied) {}
197 
getKind()198   RequirementKind getKind() const { return Kind; }
199 
isSatisfied()200   bool isSatisfied() const {
201     assert(!Dependent &&
202            "isSatisfied can only be called on non-dependent requirements.");
203     return Satisfied;
204   }
205 
setSatisfied(bool IsSatisfied)206   void setSatisfied(bool IsSatisfied) {
207     assert(!Dependent &&
208            "setSatisfied can only be called on non-dependent requirements.");
209     Satisfied = IsSatisfied;
210   }
211 
setDependent(bool IsDependent)212   void setDependent(bool IsDependent) { Dependent = IsDependent; }
isDependent()213   bool isDependent() const { return Dependent; }
214 
setContainsUnexpandedParameterPack(bool Contains)215   void setContainsUnexpandedParameterPack(bool Contains) {
216     ContainsUnexpandedParameterPack = Contains;
217   }
containsUnexpandedParameterPack()218   bool containsUnexpandedParameterPack() const {
219     return ContainsUnexpandedParameterPack;
220   }
221 };
222 
223 /// \brief A requires-expression requirement which queries the existence of a
224 /// type name or type template specialization ('type' requirements).
225 class TypeRequirement : public Requirement {
226 public:
227   enum SatisfactionStatus {
228       SS_Dependent,
229       SS_SubstitutionFailure,
230       SS_Satisfied
231   };
232 private:
233   llvm::PointerUnion<SubstitutionDiagnostic *, TypeSourceInfo *> Value;
234   SatisfactionStatus Status;
235 public:
236   friend ASTStmtReader;
237   friend ASTStmtWriter;
238 
239   /// \brief Construct a type requirement from a type. If the given type is not
240   /// dependent, this indicates that the type exists and the requirement will be
241   /// satisfied. Otherwise, the SubstitutionDiagnostic constructor is to be
242   /// used.
243   TypeRequirement(TypeSourceInfo *T);
244 
245   /// \brief Construct a type requirement when the nested name specifier is
246   /// invalid due to a bad substitution. The requirement is unsatisfied.
TypeRequirement(SubstitutionDiagnostic * Diagnostic)247   TypeRequirement(SubstitutionDiagnostic *Diagnostic) :
248       Requirement(RK_Type, false, false, false), Value(Diagnostic),
249       Status(SS_SubstitutionFailure) {}
250 
getSatisfactionStatus()251   SatisfactionStatus getSatisfactionStatus() const { return Status; }
setSatisfactionStatus(SatisfactionStatus Status)252   void setSatisfactionStatus(SatisfactionStatus Status) {
253     this->Status = Status;
254   }
255 
isSubstitutionFailure()256   bool isSubstitutionFailure() const {
257     return Status == SS_SubstitutionFailure;
258   }
259 
getSubstitutionDiagnostic()260   SubstitutionDiagnostic *getSubstitutionDiagnostic() const {
261     assert(Status == SS_SubstitutionFailure &&
262            "Attempted to get substitution diagnostic when there has been no "
263            "substitution failure.");
264     return cast<SubstitutionDiagnostic *>(Value);
265   }
266 
getType()267   TypeSourceInfo *getType() const {
268     assert(!isSubstitutionFailure() &&
269            "Attempted to get type when there has been a substitution failure.");
270     return cast<TypeSourceInfo *>(Value);
271   }
272 
classof(const Requirement * R)273   static bool classof(const Requirement *R) {
274     return R->getKind() == RK_Type;
275   }
276 };
277 
278 /// \brief A requires-expression requirement which queries the validity and
279 /// properties of an expression ('simple' and 'compound' requirements).
280 class ExprRequirement : public Requirement {
281 public:
282   enum SatisfactionStatus {
283       SS_Dependent,
284       SS_ExprSubstitutionFailure,
285       SS_NoexceptNotMet,
286       SS_TypeRequirementSubstitutionFailure,
287       SS_ConstraintsNotSatisfied,
288       SS_Satisfied
289   };
290   class ReturnTypeRequirement {
291       llvm::PointerIntPair<
292           llvm::PointerUnion<TemplateParameterList *, SubstitutionDiagnostic *>,
293           1, bool>
294           TypeConstraintInfo;
295   public:
296       friend ASTStmtReader;
297       friend ASTStmtWriter;
298 
299       /// \brief No return type requirement was specified.
ReturnTypeRequirement()300       ReturnTypeRequirement() : TypeConstraintInfo(nullptr, false) {}
301 
302       /// \brief A return type requirement was specified but it was a
303       /// substitution failure.
ReturnTypeRequirement(SubstitutionDiagnostic * SubstDiag)304       ReturnTypeRequirement(SubstitutionDiagnostic *SubstDiag) :
305           TypeConstraintInfo(SubstDiag, false) {}
306 
307       /// \brief A 'type constraint' style return type requirement.
308       /// \param TPL an invented template parameter list containing a single
309       /// type parameter with a type-constraint.
310       // TODO: Can we maybe not save the whole template parameter list and just
311       //  the type constraint? Saving the whole TPL makes it easier to handle in
312       //  serialization but is less elegant.
313       ReturnTypeRequirement(TemplateParameterList *TPL, bool IsDependent);
314       ReturnTypeRequirement(TemplateParameterList *TPL);
315 
isDependent()316       bool isDependent() const {
317         return TypeConstraintInfo.getInt();
318       }
319 
containsUnexpandedParameterPack()320       bool containsUnexpandedParameterPack() const {
321         if (!isTypeConstraint())
322           return false;
323         return getTypeConstraintTemplateParameterList()
324                 ->containsUnexpandedParameterPack();
325       }
326 
isEmpty()327       bool isEmpty() const {
328         return TypeConstraintInfo.getPointer().isNull();
329       }
330 
isSubstitutionFailure()331       bool isSubstitutionFailure() const {
332         return !isEmpty() &&
333                isa<SubstitutionDiagnostic *>(TypeConstraintInfo.getPointer());
334       }
335 
isTypeConstraint()336       bool isTypeConstraint() const {
337         return !isEmpty() &&
338                isa<TemplateParameterList *>(TypeConstraintInfo.getPointer());
339       }
340 
getSubstitutionDiagnostic()341       SubstitutionDiagnostic *getSubstitutionDiagnostic() const {
342         assert(isSubstitutionFailure());
343         return cast<SubstitutionDiagnostic *>(TypeConstraintInfo.getPointer());
344       }
345 
346       const TypeConstraint *getTypeConstraint() const;
347 
getTypeConstraintTemplateParameterList()348       TemplateParameterList *getTypeConstraintTemplateParameterList() const {
349         assert(isTypeConstraint());
350         return cast<TemplateParameterList *>(TypeConstraintInfo.getPointer());
351       }
352   };
353 private:
354   llvm::PointerUnion<Expr *, SubstitutionDiagnostic *> Value;
355   SourceLocation NoexceptLoc; // May be empty if noexcept wasn't specified.
356   ReturnTypeRequirement TypeReq;
357   ConceptSpecializationExpr *SubstitutedConstraintExpr;
358   SatisfactionStatus Status;
359 public:
360   friend ASTStmtReader;
361   friend ASTStmtWriter;
362 
363   /// \brief Construct a compound requirement.
364   /// \param E the expression which is checked by this requirement.
365   /// \param IsSimple whether this was a simple requirement in source.
366   /// \param NoexceptLoc the location of the noexcept keyword, if it was
367   /// specified, otherwise an empty location.
368   /// \param Req the requirement for the type of the checked expression.
369   /// \param Status the satisfaction status of this requirement.
370   ExprRequirement(
371       Expr *E, bool IsSimple, SourceLocation NoexceptLoc,
372       ReturnTypeRequirement Req, SatisfactionStatus Status,
373       ConceptSpecializationExpr *SubstitutedConstraintExpr = nullptr);
374 
375   /// \brief Construct a compound requirement whose expression was a
376   /// substitution failure. The requirement is not satisfied.
377   /// \param E the diagnostic emitted while instantiating the original
378   /// expression.
379   /// \param IsSimple whether this was a simple requirement in source.
380   /// \param NoexceptLoc the location of the noexcept keyword, if it was
381   /// specified, otherwise an empty location.
382   /// \param Req the requirement for the type of the checked expression (omit
383   /// if no requirement was specified).
384   ExprRequirement(SubstitutionDiagnostic *E, bool IsSimple,
385                   SourceLocation NoexceptLoc, ReturnTypeRequirement Req = {});
386 
isSimple()387   bool isSimple() const { return getKind() == RK_Simple; }
isCompound()388   bool isCompound() const { return getKind() == RK_Compound; }
389 
hasNoexceptRequirement()390   bool hasNoexceptRequirement() const { return NoexceptLoc.isValid(); }
getNoexceptLoc()391   SourceLocation getNoexceptLoc() const { return NoexceptLoc; }
392 
getSatisfactionStatus()393   SatisfactionStatus getSatisfactionStatus() const { return Status; }
394 
isExprSubstitutionFailure()395   bool isExprSubstitutionFailure() const {
396     return Status == SS_ExprSubstitutionFailure;
397   }
398 
getReturnTypeRequirement()399   const ReturnTypeRequirement &getReturnTypeRequirement() const {
400     return TypeReq;
401   }
402 
403   ConceptSpecializationExpr *
getReturnTypeRequirementSubstitutedConstraintExpr()404   getReturnTypeRequirementSubstitutedConstraintExpr() const {
405     assert(Status >= SS_TypeRequirementSubstitutionFailure);
406     return SubstitutedConstraintExpr;
407   }
408 
getExprSubstitutionDiagnostic()409   SubstitutionDiagnostic *getExprSubstitutionDiagnostic() const {
410     assert(isExprSubstitutionFailure() &&
411            "Attempted to get expression substitution diagnostic when there has "
412            "been no expression substitution failure");
413     return cast<SubstitutionDiagnostic *>(Value);
414   }
415 
getExpr()416   Expr *getExpr() const {
417     assert(!isExprSubstitutionFailure() &&
418            "ExprRequirement has no expression because there has been a "
419            "substitution failure.");
420     return cast<Expr *>(Value);
421   }
422 
classof(const Requirement * R)423   static bool classof(const Requirement *R) {
424     return R->getKind() == RK_Compound || R->getKind() == RK_Simple;
425   }
426 };
427 
428 /// \brief A requires-expression requirement which is satisfied when a general
429 /// constraint expression is satisfied ('nested' requirements).
430 class NestedRequirement : public Requirement {
431   Expr *Constraint = nullptr;
432   const ASTConstraintSatisfaction *Satisfaction = nullptr;
433   bool HasInvalidConstraint = false;
434   StringRef InvalidConstraintEntity;
435 
436 public:
437   friend ASTStmtReader;
438   friend ASTStmtWriter;
439 
NestedRequirement(Expr * Constraint)440   NestedRequirement(Expr *Constraint)
441       : Requirement(RK_Nested, /*IsDependent=*/true,
442                     Constraint->containsUnexpandedParameterPack()),
443         Constraint(Constraint) {
444     assert(Constraint->isInstantiationDependent() &&
445            "Nested requirement with non-dependent constraint must be "
446            "constructed with a ConstraintSatisfaction object");
447   }
448 
NestedRequirement(ASTContext & C,Expr * Constraint,const ConstraintSatisfaction & Satisfaction)449   NestedRequirement(ASTContext &C, Expr *Constraint,
450                     const ConstraintSatisfaction &Satisfaction)
451       : Requirement(RK_Nested, Constraint->isInstantiationDependent(),
452                     Constraint->containsUnexpandedParameterPack(),
453                     Satisfaction.IsSatisfied),
454         Constraint(Constraint),
455         Satisfaction(ASTConstraintSatisfaction::Create(C, Satisfaction)) {}
456 
NestedRequirement(StringRef InvalidConstraintEntity,const ASTConstraintSatisfaction * Satisfaction)457   NestedRequirement(StringRef InvalidConstraintEntity,
458                     const ASTConstraintSatisfaction *Satisfaction)
459       : Requirement(RK_Nested,
460                     /*IsDependent=*/false,
461                     /*ContainsUnexpandedParameterPack*/ false,
462                     Satisfaction->IsSatisfied),
463         Satisfaction(Satisfaction), HasInvalidConstraint(true),
464         InvalidConstraintEntity(InvalidConstraintEntity) {}
465 
NestedRequirement(ASTContext & C,StringRef InvalidConstraintEntity,const ConstraintSatisfaction & Satisfaction)466   NestedRequirement(ASTContext &C, StringRef InvalidConstraintEntity,
467                     const ConstraintSatisfaction &Satisfaction)
468       : NestedRequirement(InvalidConstraintEntity,
469                           ASTConstraintSatisfaction::Create(C, Satisfaction)) {}
470 
hasInvalidConstraint()471   bool hasInvalidConstraint() const { return HasInvalidConstraint; }
472 
getInvalidConstraintEntity()473   StringRef getInvalidConstraintEntity() {
474     assert(hasInvalidConstraint());
475     return InvalidConstraintEntity;
476   }
477 
getConstraintExpr()478   Expr *getConstraintExpr() const {
479     assert(!hasInvalidConstraint() &&
480            "getConstraintExpr() may not be called "
481            "on nested requirements with invalid constraint.");
482     return Constraint;
483   }
484 
getConstraintSatisfaction()485   const ASTConstraintSatisfaction &getConstraintSatisfaction() const {
486     return *Satisfaction;
487   }
488 
classof(const Requirement * R)489   static bool classof(const Requirement *R) {
490     return R->getKind() == RK_Nested;
491   }
492 };
493 } // namespace concepts
494 
495 /// C++2a [expr.prim.req]:
496 ///     A requires-expression provides a concise way to express requirements on
497 ///     template arguments. A requirement is one that can be checked by name
498 ///     lookup (6.4) or by checking properties of types and expressions.
499 ///     [...]
500 ///     A requires-expression is a prvalue of type bool [...]
501 class RequiresExpr final : public Expr,
502     llvm::TrailingObjects<RequiresExpr, ParmVarDecl *,
503                           concepts::Requirement *> {
504   friend TrailingObjects;
505   friend class ASTStmtReader;
506 
507   unsigned NumLocalParameters;
508   unsigned NumRequirements;
509   RequiresExprBodyDecl *Body;
510   SourceLocation LParenLoc;
511   SourceLocation RParenLoc;
512   SourceLocation RBraceLoc;
513 
numTrailingObjects(OverloadToken<ParmVarDecl * >)514   unsigned numTrailingObjects(OverloadToken<ParmVarDecl *>) const {
515     return NumLocalParameters;
516   }
517 
518   RequiresExpr(ASTContext &C, SourceLocation RequiresKWLoc,
519                RequiresExprBodyDecl *Body, SourceLocation LParenLoc,
520                ArrayRef<ParmVarDecl *> LocalParameters,
521                SourceLocation RParenLoc,
522                ArrayRef<concepts::Requirement *> Requirements,
523                SourceLocation RBraceLoc);
524   RequiresExpr(ASTContext &C, EmptyShell Empty, unsigned NumLocalParameters,
525                unsigned NumRequirements);
526 
527 public:
528   static RequiresExpr *Create(ASTContext &C, SourceLocation RequiresKWLoc,
529                               RequiresExprBodyDecl *Body,
530                               SourceLocation LParenLoc,
531                               ArrayRef<ParmVarDecl *> LocalParameters,
532                               SourceLocation RParenLoc,
533                               ArrayRef<concepts::Requirement *> Requirements,
534                               SourceLocation RBraceLoc);
535   static RequiresExpr *
536   Create(ASTContext &C, EmptyShell Empty, unsigned NumLocalParameters,
537          unsigned NumRequirements);
538 
getLocalParameters()539   ArrayRef<ParmVarDecl *> getLocalParameters() const {
540     return getTrailingObjects<ParmVarDecl *>(NumLocalParameters);
541   }
542 
getBody()543   RequiresExprBodyDecl *getBody() const { return Body; }
544 
getRequirements()545   ArrayRef<concepts::Requirement *> getRequirements() const {
546     return getTrailingObjects<concepts::Requirement *>(NumRequirements);
547   }
548 
549   /// \brief Whether or not the requires clause is satisfied.
550   /// The expression must not be dependent.
isSatisfied()551   bool isSatisfied() const {
552     assert(!isValueDependent()
553            && "isSatisfied called on a dependent RequiresExpr");
554     return RequiresExprBits.IsSatisfied;
555   }
556 
setSatisfied(bool IsSatisfied)557   void setSatisfied(bool IsSatisfied) {
558     assert(!isValueDependent() &&
559            "setSatisfied called on a dependent RequiresExpr");
560     RequiresExprBits.IsSatisfied = IsSatisfied;
561   }
562 
getRequiresKWLoc()563   SourceLocation getRequiresKWLoc() const {
564     return RequiresExprBits.RequiresKWLoc;
565   }
566 
getLParenLoc()567   SourceLocation getLParenLoc() const { return LParenLoc; }
getRParenLoc()568   SourceLocation getRParenLoc() const { return RParenLoc; }
getRBraceLoc()569   SourceLocation getRBraceLoc() const { return RBraceLoc; }
570 
classof(const Stmt * T)571   static bool classof(const Stmt *T) {
572     return T->getStmtClass() == RequiresExprClass;
573   }
574 
getBeginLoc()575   SourceLocation getBeginLoc() const LLVM_READONLY {
576     return RequiresExprBits.RequiresKWLoc;
577   }
getEndLoc()578   SourceLocation getEndLoc() const LLVM_READONLY {
579     return RBraceLoc;
580   }
581 
582   // Iterators
children()583   child_range children() {
584     return child_range(child_iterator(), child_iterator());
585   }
children()586   const_child_range children() const {
587     return const_child_range(const_child_iterator(), const_child_iterator());
588   }
589 };
590 
591 } // namespace clang
592 
593 #endif // LLVM_CLANG_AST_EXPRCONCEPTS_H
594