Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:36:42

0001 //===--- StmtCXX.h - Classes for representing C++ statements ----*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 // This file defines the C++ statement AST node classes.
0010 //
0011 //===----------------------------------------------------------------------===//
0012 
0013 #ifndef LLVM_CLANG_AST_STMTCXX_H
0014 #define LLVM_CLANG_AST_STMTCXX_H
0015 
0016 #include "clang/AST/DeclarationName.h"
0017 #include "clang/AST/Expr.h"
0018 #include "clang/AST/NestedNameSpecifier.h"
0019 #include "clang/AST/Stmt.h"
0020 #include "llvm/Support/Compiler.h"
0021 
0022 namespace clang {
0023 
0024 class VarDecl;
0025 
0026 /// CXXCatchStmt - This represents a C++ catch block.
0027 ///
0028 class CXXCatchStmt : public Stmt {
0029   SourceLocation CatchLoc;
0030   /// The exception-declaration of the type.
0031   VarDecl *ExceptionDecl;
0032   /// The handler block.
0033   Stmt *HandlerBlock;
0034 
0035 public:
0036   CXXCatchStmt(SourceLocation catchLoc, VarDecl *exDecl, Stmt *handlerBlock)
0037   : Stmt(CXXCatchStmtClass), CatchLoc(catchLoc), ExceptionDecl(exDecl),
0038     HandlerBlock(handlerBlock) {}
0039 
0040   CXXCatchStmt(EmptyShell Empty)
0041   : Stmt(CXXCatchStmtClass), ExceptionDecl(nullptr), HandlerBlock(nullptr) {}
0042 
0043   SourceLocation getBeginLoc() const LLVM_READONLY { return CatchLoc; }
0044   SourceLocation getEndLoc() const LLVM_READONLY {
0045     return HandlerBlock->getEndLoc();
0046   }
0047 
0048   SourceLocation getCatchLoc() const { return CatchLoc; }
0049   VarDecl *getExceptionDecl() const { return ExceptionDecl; }
0050   QualType getCaughtType() const;
0051   Stmt *getHandlerBlock() const { return HandlerBlock; }
0052 
0053   static bool classof(const Stmt *T) {
0054     return T->getStmtClass() == CXXCatchStmtClass;
0055   }
0056 
0057   child_range children() { return child_range(&HandlerBlock, &HandlerBlock+1); }
0058 
0059   const_child_range children() const {
0060     return const_child_range(&HandlerBlock, &HandlerBlock + 1);
0061   }
0062 
0063   friend class ASTStmtReader;
0064 };
0065 
0066 /// CXXTryStmt - A C++ try block, including all handlers.
0067 ///
0068 class CXXTryStmt final : public Stmt,
0069                          private llvm::TrailingObjects<CXXTryStmt, Stmt *> {
0070 
0071   friend TrailingObjects;
0072   friend class ASTStmtReader;
0073 
0074   SourceLocation TryLoc;
0075   unsigned NumHandlers;
0076   size_t numTrailingObjects(OverloadToken<Stmt *>) const { return NumHandlers; }
0077 
0078   CXXTryStmt(SourceLocation tryLoc, CompoundStmt *tryBlock,
0079              ArrayRef<Stmt *> handlers);
0080   CXXTryStmt(EmptyShell Empty, unsigned numHandlers)
0081     : Stmt(CXXTryStmtClass), NumHandlers(numHandlers) { }
0082 
0083   Stmt *const *getStmts() const { return getTrailingObjects<Stmt *>(); }
0084   Stmt **getStmts() { return getTrailingObjects<Stmt *>(); }
0085 
0086 public:
0087   static CXXTryStmt *Create(const ASTContext &C, SourceLocation tryLoc,
0088                             CompoundStmt *tryBlock, ArrayRef<Stmt *> handlers);
0089 
0090   static CXXTryStmt *Create(const ASTContext &C, EmptyShell Empty,
0091                             unsigned numHandlers);
0092 
0093   SourceLocation getBeginLoc() const LLVM_READONLY { return getTryLoc(); }
0094 
0095   SourceLocation getTryLoc() const { return TryLoc; }
0096   SourceLocation getEndLoc() const {
0097     return getStmts()[NumHandlers]->getEndLoc();
0098   }
0099 
0100   CompoundStmt *getTryBlock() {
0101     return cast<CompoundStmt>(getStmts()[0]);
0102   }
0103   const CompoundStmt *getTryBlock() const {
0104     return cast<CompoundStmt>(getStmts()[0]);
0105   }
0106 
0107   unsigned getNumHandlers() const { return NumHandlers; }
0108   CXXCatchStmt *getHandler(unsigned i) {
0109     return cast<CXXCatchStmt>(getStmts()[i + 1]);
0110   }
0111   const CXXCatchStmt *getHandler(unsigned i) const {
0112     return cast<CXXCatchStmt>(getStmts()[i + 1]);
0113   }
0114 
0115   static bool classof(const Stmt *T) {
0116     return T->getStmtClass() == CXXTryStmtClass;
0117   }
0118 
0119   child_range children() {
0120     return child_range(getStmts(), getStmts() + getNumHandlers() + 1);
0121   }
0122 
0123   const_child_range children() const {
0124     return const_child_range(getStmts(), getStmts() + getNumHandlers() + 1);
0125   }
0126 };
0127 
0128 /// CXXForRangeStmt - This represents C++0x [stmt.ranged]'s ranged for
0129 /// statement, represented as 'for (range-declarator : range-expression)'
0130 /// or 'for (init-statement range-declarator : range-expression)'.
0131 ///
0132 /// This is stored in a partially-desugared form to allow full semantic
0133 /// analysis of the constituent components. The original syntactic components
0134 /// can be extracted using getLoopVariable and getRangeInit.
0135 class CXXForRangeStmt : public Stmt {
0136   SourceLocation ForLoc;
0137   enum { INIT, RANGE, BEGINSTMT, ENDSTMT, COND, INC, LOOPVAR, BODY, END };
0138   // SubExprs[RANGE] is an expression or declstmt.
0139   // SubExprs[COND] and SubExprs[INC] are expressions.
0140   Stmt *SubExprs[END];
0141   SourceLocation CoawaitLoc;
0142   SourceLocation ColonLoc;
0143   SourceLocation RParenLoc;
0144 
0145   friend class ASTStmtReader;
0146 public:
0147   CXXForRangeStmt(Stmt *InitStmt, DeclStmt *Range, DeclStmt *Begin,
0148                   DeclStmt *End, Expr *Cond, Expr *Inc, DeclStmt *LoopVar,
0149                   Stmt *Body, SourceLocation FL, SourceLocation CAL,
0150                   SourceLocation CL, SourceLocation RPL);
0151   CXXForRangeStmt(EmptyShell Empty) : Stmt(CXXForRangeStmtClass, Empty) { }
0152 
0153   Stmt *getInit() { return SubExprs[INIT]; }
0154   VarDecl *getLoopVariable();
0155   Expr *getRangeInit();
0156 
0157   const Stmt *getInit() const { return SubExprs[INIT]; }
0158   const VarDecl *getLoopVariable() const;
0159   const Expr *getRangeInit() const;
0160 
0161 
0162   DeclStmt *getRangeStmt() { return cast<DeclStmt>(SubExprs[RANGE]); }
0163   DeclStmt *getBeginStmt() {
0164     return cast_or_null<DeclStmt>(SubExprs[BEGINSTMT]);
0165   }
0166   DeclStmt *getEndStmt() { return cast_or_null<DeclStmt>(SubExprs[ENDSTMT]); }
0167   Expr *getCond() { return cast_or_null<Expr>(SubExprs[COND]); }
0168   Expr *getInc() { return cast_or_null<Expr>(SubExprs[INC]); }
0169   DeclStmt *getLoopVarStmt() { return cast<DeclStmt>(SubExprs[LOOPVAR]); }
0170   Stmt *getBody() { return SubExprs[BODY]; }
0171 
0172   const DeclStmt *getRangeStmt() const {
0173     return cast<DeclStmt>(SubExprs[RANGE]);
0174   }
0175   const DeclStmt *getBeginStmt() const {
0176     return cast_or_null<DeclStmt>(SubExprs[BEGINSTMT]);
0177   }
0178   const DeclStmt *getEndStmt() const {
0179     return cast_or_null<DeclStmt>(SubExprs[ENDSTMT]);
0180   }
0181   const Expr *getCond() const {
0182     return cast_or_null<Expr>(SubExprs[COND]);
0183   }
0184   const Expr *getInc() const {
0185     return cast_or_null<Expr>(SubExprs[INC]);
0186   }
0187   const DeclStmt *getLoopVarStmt() const {
0188     return cast<DeclStmt>(SubExprs[LOOPVAR]);
0189   }
0190   const Stmt *getBody() const { return SubExprs[BODY]; }
0191 
0192   void setInit(Stmt *S) { SubExprs[INIT] = S; }
0193   void setRangeInit(Expr *E) { SubExprs[RANGE] = reinterpret_cast<Stmt*>(E); }
0194   void setRangeStmt(Stmt *S) { SubExprs[RANGE] = S; }
0195   void setBeginStmt(Stmt *S) { SubExprs[BEGINSTMT] = S; }
0196   void setEndStmt(Stmt *S) { SubExprs[ENDSTMT] = S; }
0197   void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast<Stmt*>(E); }
0198   void setInc(Expr *E) { SubExprs[INC] = reinterpret_cast<Stmt*>(E); }
0199   void setLoopVarStmt(Stmt *S) { SubExprs[LOOPVAR] = S; }
0200   void setBody(Stmt *S) { SubExprs[BODY] = S; }
0201 
0202   SourceLocation getForLoc() const { return ForLoc; }
0203   SourceLocation getCoawaitLoc() const { return CoawaitLoc; }
0204   SourceLocation getColonLoc() const { return ColonLoc; }
0205   SourceLocation getRParenLoc() const { return RParenLoc; }
0206 
0207   SourceLocation getBeginLoc() const LLVM_READONLY { return ForLoc; }
0208   SourceLocation getEndLoc() const LLVM_READONLY {
0209     return SubExprs[BODY]->getEndLoc();
0210   }
0211 
0212   static bool classof(const Stmt *T) {
0213     return T->getStmtClass() == CXXForRangeStmtClass;
0214   }
0215 
0216   // Iterators
0217   child_range children() {
0218     return child_range(&SubExprs[0], &SubExprs[END]);
0219   }
0220 
0221   const_child_range children() const {
0222     return const_child_range(&SubExprs[0], &SubExprs[END]);
0223   }
0224 };
0225 
0226 /// Representation of a Microsoft __if_exists or __if_not_exists
0227 /// statement with a dependent name.
0228 ///
0229 /// The __if_exists statement can be used to include a sequence of statements
0230 /// in the program only when a particular dependent name does not exist. For
0231 /// example:
0232 ///
0233 /// \code
0234 /// template<typename T>
0235 /// void call_foo(T &t) {
0236 ///   __if_exists (T::foo) {
0237 ///     t.foo(); // okay: only called when T::foo exists.
0238 ///   }
0239 /// }
0240 /// \endcode
0241 ///
0242 /// Similarly, the __if_not_exists statement can be used to include the
0243 /// statements when a particular name does not exist.
0244 ///
0245 /// Note that this statement only captures __if_exists and __if_not_exists
0246 /// statements whose name is dependent. All non-dependent cases are handled
0247 /// directly in the parser, so that they don't introduce a new scope. Clang
0248 /// introduces scopes in the dependent case to keep names inside the compound
0249 /// statement from leaking out into the surround statements, which would
0250 /// compromise the template instantiation model. This behavior differs from
0251 /// Visual C++ (which never introduces a scope), but is a fairly reasonable
0252 /// approximation of the VC++ behavior.
0253 class MSDependentExistsStmt : public Stmt {
0254   SourceLocation KeywordLoc;
0255   bool IsIfExists;
0256   NestedNameSpecifierLoc QualifierLoc;
0257   DeclarationNameInfo NameInfo;
0258   Stmt *SubStmt;
0259 
0260   friend class ASTReader;
0261   friend class ASTStmtReader;
0262 
0263 public:
0264   MSDependentExistsStmt(SourceLocation KeywordLoc, bool IsIfExists,
0265                         NestedNameSpecifierLoc QualifierLoc,
0266                         DeclarationNameInfo NameInfo,
0267                         CompoundStmt *SubStmt)
0268   : Stmt(MSDependentExistsStmtClass),
0269     KeywordLoc(KeywordLoc), IsIfExists(IsIfExists),
0270     QualifierLoc(QualifierLoc), NameInfo(NameInfo),
0271     SubStmt(reinterpret_cast<Stmt *>(SubStmt)) { }
0272 
0273   /// Retrieve the location of the __if_exists or __if_not_exists
0274   /// keyword.
0275   SourceLocation getKeywordLoc() const { return KeywordLoc; }
0276 
0277   /// Determine whether this is an __if_exists statement.
0278   bool isIfExists() const { return IsIfExists; }
0279 
0280   /// Determine whether this is an __if_exists statement.
0281   bool isIfNotExists() const { return !IsIfExists; }
0282 
0283   /// Retrieve the nested-name-specifier that qualifies this name, if
0284   /// any.
0285   NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; }
0286 
0287   /// Retrieve the name of the entity we're testing for, along with
0288   /// location information
0289   DeclarationNameInfo getNameInfo() const { return NameInfo; }
0290 
0291   /// Retrieve the compound statement that will be included in the
0292   /// program only if the existence of the symbol matches the initial keyword.
0293   CompoundStmt *getSubStmt() const {
0294     return reinterpret_cast<CompoundStmt *>(SubStmt);
0295   }
0296 
0297   SourceLocation getBeginLoc() const LLVM_READONLY { return KeywordLoc; }
0298   SourceLocation getEndLoc() const LLVM_READONLY {
0299     return SubStmt->getEndLoc();
0300   }
0301 
0302   child_range children() {
0303     return child_range(&SubStmt, &SubStmt+1);
0304   }
0305 
0306   const_child_range children() const {
0307     return const_child_range(&SubStmt, &SubStmt + 1);
0308   }
0309 
0310   static bool classof(const Stmt *T) {
0311     return T->getStmtClass() == MSDependentExistsStmtClass;
0312   }
0313 };
0314 
0315 /// Represents the body of a coroutine. This wraps the normal function
0316 /// body and holds the additional semantic context required to set up and tear
0317 /// down the coroutine frame.
0318 class CoroutineBodyStmt final
0319     : public Stmt,
0320       private llvm::TrailingObjects<CoroutineBodyStmt, Stmt *> {
0321   enum SubStmt {
0322     Body,          ///< The body of the coroutine.
0323     Promise,       ///< The promise statement.
0324     InitSuspend,   ///< The initial suspend statement, run before the body.
0325     FinalSuspend,  ///< The final suspend statement, run after the body.
0326     OnException,   ///< Handler for exceptions thrown in the body.
0327     OnFallthrough, ///< Handler for control flow falling off the body.
0328     Allocate,      ///< Coroutine frame memory allocation.
0329     Deallocate,    ///< Coroutine frame memory deallocation.
0330     ResultDecl,    ///< Declaration holding the result of get_return_object.
0331     ReturnValue,   ///< Return value for thunk function: p.get_return_object().
0332     ReturnStmt,    ///< Return statement for the thunk function.
0333     ReturnStmtOnAllocFailure, ///< Return statement if allocation failed.
0334     FirstParamMove ///< First offset for move construction of parameter copies.
0335   };
0336   unsigned NumParams;
0337 
0338   friend class ASTStmtReader;
0339   friend class ASTReader;
0340   friend TrailingObjects;
0341 
0342   Stmt **getStoredStmts() { return getTrailingObjects<Stmt *>(); }
0343 
0344   Stmt *const *getStoredStmts() const { return getTrailingObjects<Stmt *>(); }
0345 
0346 public:
0347 
0348   struct CtorArgs {
0349     Stmt *Body = nullptr;
0350     Stmt *Promise = nullptr;
0351     Expr *InitialSuspend = nullptr;
0352     Expr *FinalSuspend = nullptr;
0353     Stmt *OnException = nullptr;
0354     Stmt *OnFallthrough = nullptr;
0355     Expr *Allocate = nullptr;
0356     Expr *Deallocate = nullptr;
0357     Stmt *ResultDecl = nullptr;
0358     Expr *ReturnValue = nullptr;
0359     Stmt *ReturnStmt = nullptr;
0360     Stmt *ReturnStmtOnAllocFailure = nullptr;
0361     ArrayRef<Stmt *> ParamMoves;
0362   };
0363 
0364 private:
0365 
0366   CoroutineBodyStmt(CtorArgs const& Args);
0367 
0368 public:
0369   static CoroutineBodyStmt *Create(const ASTContext &C, CtorArgs const &Args);
0370   static CoroutineBodyStmt *Create(const ASTContext &C, EmptyShell,
0371                                    unsigned NumParams);
0372 
0373   bool hasDependentPromiseType() const {
0374     return getPromiseDecl()->getType()->isDependentType();
0375   }
0376 
0377   /// Retrieve the body of the coroutine as written. This will be either
0378   /// a CompoundStmt. If the coroutine is in function-try-block, we will
0379   /// wrap the CXXTryStmt into a CompoundStmt to keep consistency.
0380   CompoundStmt *getBody() const {
0381     return cast<CompoundStmt>(getStoredStmts()[SubStmt::Body]);
0382   }
0383 
0384   Stmt *getPromiseDeclStmt() const {
0385     return getStoredStmts()[SubStmt::Promise];
0386   }
0387   VarDecl *getPromiseDecl() const {
0388     return cast<VarDecl>(cast<DeclStmt>(getPromiseDeclStmt())->getSingleDecl());
0389   }
0390 
0391   Stmt *getInitSuspendStmt() const {
0392     return getStoredStmts()[SubStmt::InitSuspend];
0393   }
0394   Stmt *getFinalSuspendStmt() const {
0395     return getStoredStmts()[SubStmt::FinalSuspend];
0396   }
0397 
0398   Stmt *getExceptionHandler() const {
0399     return getStoredStmts()[SubStmt::OnException];
0400   }
0401   Stmt *getFallthroughHandler() const {
0402     return getStoredStmts()[SubStmt::OnFallthrough];
0403   }
0404 
0405   Expr *getAllocate() const {
0406     return cast_or_null<Expr>(getStoredStmts()[SubStmt::Allocate]);
0407   }
0408   Expr *getDeallocate() const {
0409     return cast_or_null<Expr>(getStoredStmts()[SubStmt::Deallocate]);
0410   }
0411   Stmt *getResultDecl() const { return getStoredStmts()[SubStmt::ResultDecl]; }
0412   Expr *getReturnValueInit() const {
0413     return cast<Expr>(getStoredStmts()[SubStmt::ReturnValue]);
0414   }
0415   Expr *getReturnValue() const {
0416     auto *RS = dyn_cast_or_null<clang::ReturnStmt>(getReturnStmt());
0417     return RS ? RS->getRetValue() : nullptr;
0418   }
0419   Stmt *getReturnStmt() const { return getStoredStmts()[SubStmt::ReturnStmt]; }
0420   Stmt *getReturnStmtOnAllocFailure() const {
0421     return getStoredStmts()[SubStmt::ReturnStmtOnAllocFailure];
0422   }
0423   ArrayRef<Stmt const *> getParamMoves() const {
0424     return {getStoredStmts() + SubStmt::FirstParamMove, NumParams};
0425   }
0426 
0427   SourceLocation getBeginLoc() const LLVM_READONLY {
0428     return getBody() ? getBody()->getBeginLoc()
0429                      : getPromiseDecl()->getBeginLoc();
0430   }
0431   SourceLocation getEndLoc() const LLVM_READONLY {
0432     return getBody() ? getBody()->getEndLoc() : getPromiseDecl()->getEndLoc();
0433   }
0434 
0435   child_range children() {
0436     return child_range(getStoredStmts(),
0437                        getStoredStmts() + SubStmt::FirstParamMove + NumParams);
0438   }
0439 
0440   const_child_range children() const {
0441     return const_child_range(getStoredStmts(), getStoredStmts() +
0442                                                    SubStmt::FirstParamMove +
0443                                                    NumParams);
0444   }
0445 
0446   child_range childrenExclBody() {
0447     return child_range(getStoredStmts() + SubStmt::Body + 1,
0448                        getStoredStmts() + SubStmt::FirstParamMove + NumParams);
0449   }
0450 
0451   const_child_range childrenExclBody() const {
0452     return const_child_range(getStoredStmts() + SubStmt::Body + 1,
0453                              getStoredStmts() + SubStmt::FirstParamMove +
0454                                  NumParams);
0455   }
0456 
0457   static bool classof(const Stmt *T) {
0458     return T->getStmtClass() == CoroutineBodyStmtClass;
0459   }
0460 };
0461 
0462 /// Represents a 'co_return' statement in the C++ Coroutines TS.
0463 ///
0464 /// This statament models the initialization of the coroutine promise
0465 /// (encapsulating the eventual notional return value) from an expression
0466 /// (or braced-init-list), followed by termination of the coroutine.
0467 ///
0468 /// This initialization is modeled by the evaluation of the operand
0469 /// followed by a call to one of:
0470 ///   <promise>.return_value(<operand>)
0471 ///   <promise>.return_void()
0472 /// which we name the "promise call".
0473 class CoreturnStmt : public Stmt {
0474   SourceLocation CoreturnLoc;
0475 
0476   enum SubStmt { Operand, PromiseCall, Count };
0477   Stmt *SubStmts[SubStmt::Count];
0478 
0479   bool IsImplicit : 1;
0480 
0481   friend class ASTStmtReader;
0482 public:
0483   CoreturnStmt(SourceLocation CoreturnLoc, Stmt *Operand, Stmt *PromiseCall,
0484                bool IsImplicit = false)
0485       : Stmt(CoreturnStmtClass), CoreturnLoc(CoreturnLoc),
0486         IsImplicit(IsImplicit) {
0487     SubStmts[SubStmt::Operand] = Operand;
0488     SubStmts[SubStmt::PromiseCall] = PromiseCall;
0489   }
0490 
0491   CoreturnStmt(EmptyShell) : CoreturnStmt({}, {}, {}) {}
0492 
0493   SourceLocation getKeywordLoc() const { return CoreturnLoc; }
0494 
0495   /// Retrieve the operand of the 'co_return' statement. Will be nullptr
0496   /// if none was specified.
0497   Expr *getOperand() const { return static_cast<Expr*>(SubStmts[Operand]); }
0498 
0499   /// Retrieve the promise call that results from this 'co_return'
0500   /// statement. Will be nullptr if either the coroutine has not yet been
0501   /// finalized or the coroutine has no eventual return type.
0502   Expr *getPromiseCall() const {
0503     return static_cast<Expr*>(SubStmts[PromiseCall]);
0504   }
0505 
0506   bool isImplicit() const { return IsImplicit; }
0507   void setIsImplicit(bool value = true) { IsImplicit = value; }
0508 
0509   SourceLocation getBeginLoc() const LLVM_READONLY { return CoreturnLoc; }
0510   SourceLocation getEndLoc() const LLVM_READONLY {
0511     return getOperand() ? getOperand()->getEndLoc() : getBeginLoc();
0512   }
0513 
0514   child_range children() {
0515     return child_range(SubStmts, SubStmts + SubStmt::Count);
0516   }
0517 
0518   const_child_range children() const {
0519     return const_child_range(SubStmts, SubStmts + SubStmt::Count);
0520   }
0521 
0522   static bool classof(const Stmt *T) {
0523     return T->getStmtClass() == CoreturnStmtClass;
0524   }
0525 };
0526 
0527 }  // end namespace clang
0528 
0529 #endif