1 //===--- StmtCXX.cpp - Classes for representing C++ statements ------------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file implements the subclesses of Stmt class declared in StmtCXX.h
11 //===----------------------------------------------------------------------===//
13 #include "clang/AST/StmtCXX.h"
15 #include "clang/AST/ASTContext.h"
17 using namespace clang
;
19 QualType
CXXCatchStmt::getCaughtType() const {
21 return ExceptionDecl
->getType();
25 CXXTryStmt
*CXXTryStmt::Create(const ASTContext
&C
, SourceLocation tryLoc
,
26 CompoundStmt
*tryBlock
,
27 ArrayRef
<Stmt
*> handlers
) {
28 const size_t Size
= totalSizeToAlloc
<Stmt
*>(handlers
.size() + 1);
29 void *Mem
= C
.Allocate(Size
, alignof(CXXTryStmt
));
30 return new (Mem
) CXXTryStmt(tryLoc
, tryBlock
, handlers
);
33 CXXTryStmt
*CXXTryStmt::Create(const ASTContext
&C
, EmptyShell Empty
,
34 unsigned numHandlers
) {
35 const size_t Size
= totalSizeToAlloc
<Stmt
*>(numHandlers
+ 1);
36 void *Mem
= C
.Allocate(Size
, alignof(CXXTryStmt
));
37 return new (Mem
) CXXTryStmt(Empty
, numHandlers
);
40 CXXTryStmt::CXXTryStmt(SourceLocation tryLoc
, CompoundStmt
*tryBlock
,
41 ArrayRef
<Stmt
*> handlers
)
42 : Stmt(CXXTryStmtClass
), TryLoc(tryLoc
), NumHandlers(handlers
.size()) {
43 Stmt
**Stmts
= getStmts();
45 std::copy(handlers
.begin(), handlers
.end(), Stmts
+ 1);
48 CXXForRangeStmt::CXXForRangeStmt(Stmt
*Init
, DeclStmt
*Range
,
49 DeclStmt
*BeginStmt
, DeclStmt
*EndStmt
,
50 Expr
*Cond
, Expr
*Inc
, DeclStmt
*LoopVar
,
51 Stmt
*Body
, SourceLocation FL
,
52 SourceLocation CAL
, SourceLocation CL
,
54 : Stmt(CXXForRangeStmtClass
), ForLoc(FL
), CoawaitLoc(CAL
), ColonLoc(CL
),
56 SubExprs
[INIT
] = Init
;
57 SubExprs
[RANGE
] = Range
;
58 SubExprs
[BEGINSTMT
] = BeginStmt
;
59 SubExprs
[ENDSTMT
] = EndStmt
;
60 SubExprs
[COND
] = Cond
;
62 SubExprs
[LOOPVAR
] = LoopVar
;
63 SubExprs
[BODY
] = Body
;
66 Expr
*CXXForRangeStmt::getRangeInit() {
67 DeclStmt
*RangeStmt
= getRangeStmt();
68 VarDecl
*RangeDecl
= dyn_cast_or_null
<VarDecl
>(RangeStmt
->getSingleDecl());
69 assert(RangeDecl
&& "for-range should have a single var decl");
70 return RangeDecl
->getInit();
73 const Expr
*CXXForRangeStmt::getRangeInit() const {
74 return const_cast<CXXForRangeStmt
*>(this)->getRangeInit();
77 VarDecl
*CXXForRangeStmt::getLoopVariable() {
78 Decl
*LV
= cast
<DeclStmt
>(getLoopVarStmt())->getSingleDecl();
79 assert(LV
&& "No loop variable in CXXForRangeStmt");
80 return cast
<VarDecl
>(LV
);
83 const VarDecl
*CXXForRangeStmt::getLoopVariable() const {
84 return const_cast<CXXForRangeStmt
*>(this)->getLoopVariable();
87 CoroutineBodyStmt
*CoroutineBodyStmt::Create(
88 const ASTContext
&C
, CoroutineBodyStmt::CtorArgs
const &Args
) {
89 std::size_t Size
= totalSizeToAlloc
<Stmt
*>(
90 CoroutineBodyStmt::FirstParamMove
+ Args
.ParamMoves
.size());
92 void *Mem
= C
.Allocate(Size
, alignof(CoroutineBodyStmt
));
93 return new (Mem
) CoroutineBodyStmt(Args
);
96 CoroutineBodyStmt
*CoroutineBodyStmt::Create(const ASTContext
&C
, EmptyShell
,
98 std::size_t Size
= totalSizeToAlloc
<Stmt
*>(
99 CoroutineBodyStmt::FirstParamMove
+ NumParams
);
101 void *Mem
= C
.Allocate(Size
, alignof(CoroutineBodyStmt
));
102 auto *Result
= new (Mem
) CoroutineBodyStmt(CtorArgs());
103 Result
->NumParams
= NumParams
;
104 auto *ParamBegin
= Result
->getStoredStmts() + SubStmt::FirstParamMove
;
105 std::uninitialized_fill(ParamBegin
, ParamBegin
+ NumParams
,
106 static_cast<Stmt
*>(nullptr));
110 CoroutineBodyStmt::CoroutineBodyStmt(CoroutineBodyStmt::CtorArgs
const &Args
)
111 : Stmt(CoroutineBodyStmtClass
), NumParams(Args
.ParamMoves
.size()) {
112 Stmt
**SubStmts
= getStoredStmts();
113 SubStmts
[CoroutineBodyStmt::Body
] = Args
.Body
;
114 SubStmts
[CoroutineBodyStmt::Promise
] = Args
.Promise
;
115 SubStmts
[CoroutineBodyStmt::InitSuspend
] = Args
.InitialSuspend
;
116 SubStmts
[CoroutineBodyStmt::FinalSuspend
] = Args
.FinalSuspend
;
117 SubStmts
[CoroutineBodyStmt::OnException
] = Args
.OnException
;
118 SubStmts
[CoroutineBodyStmt::OnFallthrough
] = Args
.OnFallthrough
;
119 SubStmts
[CoroutineBodyStmt::Allocate
] = Args
.Allocate
;
120 SubStmts
[CoroutineBodyStmt::Deallocate
] = Args
.Deallocate
;
121 SubStmts
[CoroutineBodyStmt::ResultDecl
] = Args
.ResultDecl
;
122 SubStmts
[CoroutineBodyStmt::ReturnValue
] = Args
.ReturnValue
;
123 SubStmts
[CoroutineBodyStmt::ReturnStmt
] = Args
.ReturnStmt
;
124 SubStmts
[CoroutineBodyStmt::ReturnStmtOnAllocFailure
] =
125 Args
.ReturnStmtOnAllocFailure
;
126 std::copy(Args
.ParamMoves
.begin(), Args
.ParamMoves
.end(),
127 const_cast<Stmt
**>(getParamMoves().data()));