blob: e9a2c58f1a17cecefb0126a655146d0bc5fe4a4e [file] [log] [blame]
Eugene Zelenko1eab6c12017-11-14 23:35:42 +00001//===- Stmt.cpp - Statement AST Node Implementation -----------------------===//
Chris Lattnerf42cce72006-10-25 04:09:21 +00002//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// 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
Chris Lattnerf42cce72006-10-25 04:09:21 +00006//
7//===----------------------------------------------------------------------===//
8//
9// This file implements the Stmt class and statement subclasses.
10//
11//===----------------------------------------------------------------------===//
12
Eugene Zelenko7855e772018-04-03 00:11:50 +000013#include "clang/AST/Stmt.h"
Benjamin Kramer444a1302012-12-01 17:12:56 +000014#include "clang/AST/ASTContext.h"
15#include "clang/AST/ASTDiagnostic.h"
Eugene Zelenko1eab6c12017-11-14 23:35:42 +000016#include "clang/AST/Decl.h"
17#include "clang/AST/DeclGroup.h"
Eugene Zelenko7855e772018-04-03 00:11:50 +000018#include "clang/AST/Expr.h"
Chris Lattner29375652006-12-04 18:06:35 +000019#include "clang/AST/ExprCXX.h"
Steve Naroff021ca182008-05-29 21:12:08 +000020#include "clang/AST/ExprObjC.h"
Alexey Bataev1a3320e2015-08-25 14:24:04 +000021#include "clang/AST/ExprOpenMP.h"
Chris Lattnerf0b64d72009-04-26 01:32:48 +000022#include "clang/AST/StmtCXX.h"
23#include "clang/AST/StmtObjC.h"
Alexey Bataev5ec3eb12013-07-19 03:13:43 +000024#include "clang/AST/StmtOpenMP.h"
Sebastian Redl54c04d42008-12-22 19:15:10 +000025#include "clang/AST/Type.h"
Jordan Rosea7d03842013-02-08 22:30:41 +000026#include "clang/Basic/CharInfo.h"
Eugene Zelenko1eab6c12017-11-14 23:35:42 +000027#include "clang/Basic/LLVM.h"
28#include "clang/Basic/SourceLocation.h"
Chris Lattner1a8f3942010-04-23 16:29:58 +000029#include "clang/Basic/TargetInfo.h"
Benjamin Kramer444a1302012-12-01 17:12:56 +000030#include "clang/Lex/Token.h"
Eugene Zelenko1eab6c12017-11-14 23:35:42 +000031#include "llvm/ADT/SmallVector.h"
Chad Rosier14836ba2012-08-24 17:05:45 +000032#include "llvm/ADT/StringExtras.h"
Eugene Zelenko1eab6c12017-11-14 23:35:42 +000033#include "llvm/ADT/StringRef.h"
34#include "llvm/Support/Casting.h"
35#include "llvm/Support/Compiler.h"
36#include "llvm/Support/ErrorHandling.h"
37#include "llvm/Support/MathExtras.h"
Chandler Carruthbfb154a2011-07-04 06:13:27 +000038#include "llvm/Support/raw_ostream.h"
Eugene Zelenko1eab6c12017-11-14 23:35:42 +000039#include <algorithm>
40#include <cassert>
41#include <cstring>
42#include <string>
43#include <utility>
44
Chris Lattnerf42cce72006-10-25 04:09:21 +000045using namespace clang;
46
Steve Narofff84d11f2007-05-23 21:48:04 +000047static struct StmtClassNameTable {
Chris Lattner4d15a0d2007-08-25 01:42:24 +000048 const char *Name;
49 unsigned Counter;
50 unsigned Size;
Alexis Hunt656bb312010-05-05 15:24:00 +000051} StmtClassInfo[Stmt::lastStmtConstant+1];
Chris Lattner4d15a0d2007-08-25 01:42:24 +000052
53static StmtClassNameTable &getStmtInfoTableEntry(Stmt::StmtClass E) {
54 static bool Initialized = false;
55 if (Initialized)
56 return StmtClassInfo[E];
57
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +000058 // Initialize the table on the first use.
Chris Lattner4d15a0d2007-08-25 01:42:24 +000059 Initialized = true;
Alexis Huntabb2ac82010-05-18 06:22:21 +000060#define ABSTRACT_STMT(STMT)
Douglas Gregorbe35ce92008-11-14 12:46:07 +000061#define STMT(CLASS, PARENT) \
62 StmtClassInfo[(unsigned)Stmt::CLASS##Class].Name = #CLASS; \
63 StmtClassInfo[(unsigned)Stmt::CLASS##Class].Size = sizeof(CLASS);
Alexis Hunt656bb312010-05-05 15:24:00 +000064#include "clang/AST/StmtNodes.inc"
Nico Weberde565e32008-08-05 23:15:29 +000065
Chris Lattner4d15a0d2007-08-25 01:42:24 +000066 return StmtClassInfo[E];
67}
68
Craig Topper37932912013-08-18 10:09:15 +000069void *Stmt::operator new(size_t bytes, const ASTContext& C,
Craig Topper5a050012013-08-18 17:45:38 +000070 unsigned alignment) {
Benjamin Kramerea70eb32012-12-01 15:09:41 +000071 return ::operator new(bytes, C, alignment);
72}
73
Steve Narofff1e53692007-03-23 22:27:02 +000074const char *Stmt::getStmtClassName() const {
John McCall925b16622010-10-26 08:39:16 +000075 return getStmtInfoTableEntry((StmtClass) StmtBits.sClass).Name;
Steve Narofff1e53692007-03-23 22:27:02 +000076}
Steve Narofff84d11f2007-05-23 21:48:04 +000077
Bruno Ricci65034b82018-12-04 16:04:19 +000078// Check that no statement / expression class is polymorphic. LLVM style RTTI
79// should be used instead. If absolutely needed an exception can still be added
80// here by defining the appropriate macro (but please don't do this).
81#define STMT(CLASS, PARENT) \
82 static_assert(!std::is_polymorphic<CLASS>::value, \
83 #CLASS " should not be polymorphic!");
84#include "clang/AST/StmtNodes.inc"
85
Steve Narofff84d11f2007-05-23 21:48:04 +000086void Stmt::PrintStats() {
Chris Lattner4d15a0d2007-08-25 01:42:24 +000087 // Ensure the table is primed.
88 getStmtInfoTableEntry(Stmt::NullStmtClass);
Nico Weberde565e32008-08-05 23:15:29 +000089
Steve Narofff84d11f2007-05-23 21:48:04 +000090 unsigned sum = 0;
Chandler Carruthbfb154a2011-07-04 06:13:27 +000091 llvm::errs() << "\n*** Stmt/Expr Stats:\n";
Alexis Hunt656bb312010-05-05 15:24:00 +000092 for (int i = 0; i != Stmt::lastStmtConstant+1; i++) {
Craig Topper36250ad2014-05-12 05:36:57 +000093 if (StmtClassInfo[i].Name == nullptr) continue;
Chris Lattner4d15a0d2007-08-25 01:42:24 +000094 sum += StmtClassInfo[i].Counter;
Steve Narofff84d11f2007-05-23 21:48:04 +000095 }
Chandler Carruthbfb154a2011-07-04 06:13:27 +000096 llvm::errs() << " " << sum << " stmts/exprs total.\n";
Steve Narofff84d11f2007-05-23 21:48:04 +000097 sum = 0;
Alexis Hunt656bb312010-05-05 15:24:00 +000098 for (int i = 0; i != Stmt::lastStmtConstant+1; i++) {
Craig Topper36250ad2014-05-12 05:36:57 +000099 if (StmtClassInfo[i].Name == nullptr) continue;
Douglas Gregora30d0462009-05-26 14:40:08 +0000100 if (StmtClassInfo[i].Counter == 0) continue;
Chandler Carruthbfb154a2011-07-04 06:13:27 +0000101 llvm::errs() << " " << StmtClassInfo[i].Counter << " "
102 << StmtClassInfo[i].Name << ", " << StmtClassInfo[i].Size
103 << " each (" << StmtClassInfo[i].Counter*StmtClassInfo[i].Size
104 << " bytes)\n";
Chris Lattner4d15a0d2007-08-25 01:42:24 +0000105 sum += StmtClassInfo[i].Counter*StmtClassInfo[i].Size;
Steve Narofff84d11f2007-05-23 21:48:04 +0000106 }
Chandler Carruthbfb154a2011-07-04 06:13:27 +0000107
108 llvm::errs() << "Total bytes = " << sum << "\n";
Steve Narofff84d11f2007-05-23 21:48:04 +0000109}
110
111void Stmt::addStmtClass(StmtClass s) {
Chris Lattner4d15a0d2007-08-25 01:42:24 +0000112 ++getStmtInfoTableEntry(s).Counter;
Steve Narofff84d11f2007-05-23 21:48:04 +0000113}
114
Daniel Dunbar62905572012-03-05 21:42:49 +0000115bool Stmt::StatisticsEnabled = false;
116void Stmt::EnableStatistics() {
117 StatisticsEnabled = true;
Steve Narofff84d11f2007-05-23 21:48:04 +0000118}
119
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000120/// Skip no-op (attributed, compound) container stmts and skip captured
Alexander Musmana5f070a2014-10-01 06:03:56 +0000121/// stmt at the top, if \a IgnoreCaptured is true.
122Stmt *Stmt::IgnoreContainers(bool IgnoreCaptured) {
123 Stmt *S = this;
124 if (IgnoreCaptured)
125 if (auto CapS = dyn_cast_or_null<CapturedStmt>(S))
126 S = CapS->getCapturedStmt();
127 while (true) {
128 if (auto AS = dyn_cast_or_null<AttributedStmt>(S))
129 S = AS->getSubStmt();
130 else if (auto CS = dyn_cast_or_null<CompoundStmt>(S)) {
131 if (CS->size() != 1)
132 break;
133 S = CS->body_back();
134 } else
135 break;
136 }
137 return S;
138}
139
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000140/// Strip off all label-like statements.
Chandler Carrutha626d642011-09-10 00:02:34 +0000141///
Richard Smithc202b282012-04-14 00:33:13 +0000142/// This will strip off label statements, case statements, attributed
143/// statements and default statements recursively.
Chandler Carrutha626d642011-09-10 00:02:34 +0000144const Stmt *Stmt::stripLabelLikeStatements() const {
145 const Stmt *S = this;
146 while (true) {
Eugene Zelenko7855e772018-04-03 00:11:50 +0000147 if (const auto *LS = dyn_cast<LabelStmt>(S))
Chandler Carrutha626d642011-09-10 00:02:34 +0000148 S = LS->getSubStmt();
Eugene Zelenko7855e772018-04-03 00:11:50 +0000149 else if (const auto *SC = dyn_cast<SwitchCase>(S))
Chandler Carrutha626d642011-09-10 00:02:34 +0000150 S = SC->getSubStmt();
Eugene Zelenko7855e772018-04-03 00:11:50 +0000151 else if (const auto *AS = dyn_cast<AttributedStmt>(S))
Richard Smithc202b282012-04-14 00:33:13 +0000152 S = AS->getSubStmt();
Chandler Carrutha626d642011-09-10 00:02:34 +0000153 else
154 return S;
155 }
156}
157
John McCallbd066782011-02-09 08:16:59 +0000158namespace {
Eugene Zelenko1eab6c12017-11-14 23:35:42 +0000159
John McCallbd066782011-02-09 08:16:59 +0000160 struct good {};
161 struct bad {};
John McCallf75152f2011-02-09 08:31:17 +0000162
163 // These silly little functions have to be static inline to suppress
164 // unused warnings, and they have to be defined to suppress other
165 // warnings.
Eugene Zelenko7855e772018-04-03 00:11:50 +0000166 static good is_good(good) { return good(); }
John McCallbd066782011-02-09 08:16:59 +0000167
168 typedef Stmt::child_range children_t();
Nick Lewyckybae992f2011-02-09 08:42:57 +0000169 template <class T> good implements_children(children_t T::*) {
170 return good();
171 }
Eli Friedmandc41d792013-09-10 22:57:15 +0000172 LLVM_ATTRIBUTE_UNUSED
Eugene Zelenko7855e772018-04-03 00:11:50 +0000173 static bad implements_children(children_t Stmt::*) {
Nick Lewyckybae992f2011-02-09 08:42:57 +0000174 return bad();
175 }
John McCallbd066782011-02-09 08:16:59 +0000176
Stephen Kellyf2ceec42018-08-09 21:08:08 +0000177 typedef SourceLocation getBeginLoc_t() const;
178 template <class T> good implements_getBeginLoc(getBeginLoc_t T::*) {
Nick Lewyckybae992f2011-02-09 08:42:57 +0000179 return good();
180 }
Eli Friedmandc41d792013-09-10 22:57:15 +0000181 LLVM_ATTRIBUTE_UNUSED
Stephen Kellyf2ceec42018-08-09 21:08:08 +0000182 static bad implements_getBeginLoc(getBeginLoc_t Stmt::*) { return bad(); }
Erik Verbruggen11a2ecc2012-12-25 14:51:39 +0000183
184 typedef SourceLocation getLocEnd_t() const;
Stephen Kelly1c301dc2018-08-09 21:09:38 +0000185 template <class T> good implements_getEndLoc(getLocEnd_t T::*) {
Erik Verbruggen11a2ecc2012-12-25 14:51:39 +0000186 return good();
187 }
Eli Friedmandc41d792013-09-10 22:57:15 +0000188 LLVM_ATTRIBUTE_UNUSED
Stephen Kelly1c301dc2018-08-09 21:09:38 +0000189 static bad implements_getEndLoc(getLocEnd_t Stmt::*) { return bad(); }
John McCallbd066782011-02-09 08:16:59 +0000190
191#define ASSERT_IMPLEMENTS_children(type) \
Eli Friedmandc41d792013-09-10 22:57:15 +0000192 (void) is_good(implements_children(&type::children))
Stephen Kellyf2ceec42018-08-09 21:08:08 +0000193#define ASSERT_IMPLEMENTS_getBeginLoc(type) \
194 (void)is_good(implements_getBeginLoc(&type::getBeginLoc))
Stephen Kelly1c301dc2018-08-09 21:09:38 +0000195#define ASSERT_IMPLEMENTS_getEndLoc(type) \
196 (void)is_good(implements_getEndLoc(&type::getEndLoc))
Eugene Zelenko1eab6c12017-11-14 23:35:42 +0000197
198} // namespace
John McCallbd066782011-02-09 08:16:59 +0000199
200/// Check whether the various Stmt classes implement their member
201/// functions.
Eli Friedmandc41d792013-09-10 22:57:15 +0000202LLVM_ATTRIBUTE_UNUSED
John McCallbd066782011-02-09 08:16:59 +0000203static inline void check_implementations() {
204#define ABSTRACT_STMT(type)
Stephen Kellyf2ceec42018-08-09 21:08:08 +0000205#define STMT(type, base) \
206 ASSERT_IMPLEMENTS_children(type); \
207 ASSERT_IMPLEMENTS_getBeginLoc(type); \
Stephen Kelly1c301dc2018-08-09 21:09:38 +0000208 ASSERT_IMPLEMENTS_getEndLoc(type);
John McCallbd066782011-02-09 08:16:59 +0000209#include "clang/AST/StmtNodes.inc"
210}
211
212Stmt::child_range Stmt::children() {
213 switch (getStmtClass()) {
214 case Stmt::NoStmtClass: llvm_unreachable("statement without class");
215#define ABSTRACT_STMT(type)
216#define STMT(type, base) \
217 case Stmt::type##Class: \
218 return static_cast<type*>(this)->children();
219#include "clang/AST/StmtNodes.inc"
220 }
221 llvm_unreachable("unknown statement kind!");
John McCallbd066782011-02-09 08:16:59 +0000222}
223
Erik Verbruggen11a2ecc2012-12-25 14:51:39 +0000224// Amusing macro metaprogramming hack: check whether a class provides
225// a more specific implementation of getSourceRange.
226//
227// See also Expr.cpp:getExprLoc().
228namespace {
Eugene Zelenko1eab6c12017-11-14 23:35:42 +0000229
Erik Verbruggen11a2ecc2012-12-25 14:51:39 +0000230 /// This implementation is used when a class provides a custom
231 /// implementation of getSourceRange.
232 template <class S, class T>
233 SourceRange getSourceRangeImpl(const Stmt *stmt,
234 SourceRange (T::*v)() const) {
235 return static_cast<const S*>(stmt)->getSourceRange();
236 }
237
238 /// This implementation is used when a class doesn't provide a custom
239 /// implementation of getSourceRange. Overload resolution should pick it over
240 /// the implementation above because it's more specialized according to
241 /// function template partial ordering.
242 template <class S>
243 SourceRange getSourceRangeImpl(const Stmt *stmt,
244 SourceRange (Stmt::*v)() const) {
Stephen Kellyf2ceec42018-08-09 21:08:08 +0000245 return SourceRange(static_cast<const S *>(stmt)->getBeginLoc(),
Stephen Kelly1c301dc2018-08-09 21:09:38 +0000246 static_cast<const S *>(stmt)->getEndLoc());
Erik Verbruggen11a2ecc2012-12-25 14:51:39 +0000247 }
Eugene Zelenko1eab6c12017-11-14 23:35:42 +0000248
249} // namespace
Erik Verbruggen11a2ecc2012-12-25 14:51:39 +0000250
John McCallbd066782011-02-09 08:16:59 +0000251SourceRange Stmt::getSourceRange() const {
252 switch (getStmtClass()) {
253 case Stmt::NoStmtClass: llvm_unreachable("statement without class");
254#define ABSTRACT_STMT(type)
255#define STMT(type, base) \
256 case Stmt::type##Class: \
Erik Verbruggen11a2ecc2012-12-25 14:51:39 +0000257 return getSourceRangeImpl<type>(this, &type::getSourceRange);
John McCallbd066782011-02-09 08:16:59 +0000258#include "clang/AST/StmtNodes.inc"
259 }
260 llvm_unreachable("unknown statement kind!");
John McCallbd066782011-02-09 08:16:59 +0000261}
262
Stephen Kelly724e9e52018-08-09 20:05:03 +0000263SourceLocation Stmt::getBeginLoc() const {
264 // llvm::errs() << "getBeginLoc() for " << getStmtClassName() << "\n";
Daniel Dunbarb0ab5e92012-03-09 15:39:19 +0000265 switch (getStmtClass()) {
266 case Stmt::NoStmtClass: llvm_unreachable("statement without class");
267#define ABSTRACT_STMT(type)
Stephen Kellyf2ceec42018-08-09 21:08:08 +0000268#define STMT(type, base) \
269 case Stmt::type##Class: \
270 return static_cast<const type *>(this)->getBeginLoc();
Daniel Dunbarb0ab5e92012-03-09 15:39:19 +0000271#include "clang/AST/StmtNodes.inc"
272 }
273 llvm_unreachable("unknown statement kind");
274}
275
Stephen Kelly02a67ba2018-08-09 20:05:47 +0000276SourceLocation Stmt::getEndLoc() const {
Daniel Dunbarb0ab5e92012-03-09 15:39:19 +0000277 switch (getStmtClass()) {
278 case Stmt::NoStmtClass: llvm_unreachable("statement without class");
279#define ABSTRACT_STMT(type)
Stephen Kelly1c301dc2018-08-09 21:09:38 +0000280#define STMT(type, base) \
281 case Stmt::type##Class: \
282 return static_cast<const type *>(this)->getEndLoc();
Daniel Dunbarb0ab5e92012-03-09 15:39:19 +0000283#include "clang/AST/StmtNodes.inc"
284 }
285 llvm_unreachable("unknown statement kind");
286}
287
George Karpenkov5eb4cc62018-09-15 02:01:47 +0000288int64_t Stmt::getID(const ASTContext &Context) const {
Artem Dergachev057647d2018-12-03 22:19:05 +0000289 return Context.getAllocator().identifyKnownAlignedObject<Stmt>(this);
George Karpenkov5eb4cc62018-09-15 02:01:47 +0000290}
291
Benjamin Kramer07420902017-12-24 16:24:20 +0000292CompoundStmt::CompoundStmt(ArrayRef<Stmt *> Stmts, SourceLocation LB,
293 SourceLocation RB)
Bruno Ricci41d11c02018-10-27 18:43:27 +0000294 : Stmt(CompoundStmtClass), RBraceLoc(RB) {
Nico Webera2a0eb92012-12-29 20:03:39 +0000295 CompoundStmtBits.NumStmts = Stmts.size();
Benjamin Kramer07420902017-12-24 16:24:20 +0000296 setStmts(Stmts);
Bruno Ricci41d11c02018-10-27 18:43:27 +0000297 CompoundStmtBits.LBraceLoc = LB;
Benjamin Kramere2a929d2012-07-04 17:03:41 +0000298}
299
Benjamin Kramer07420902017-12-24 16:24:20 +0000300void CompoundStmt::setStmts(ArrayRef<Stmt *> Stmts) {
Craig Topper9ee84ad2015-12-04 05:01:44 +0000301 assert(CompoundStmtBits.NumStmts == Stmts.size() &&
302 "NumStmts doesn't fit in bits of CompoundStmtBits.NumStmts!");
Douglas Gregora9af1d12009-04-17 00:04:06 +0000303
Benjamin Kramer07420902017-12-24 16:24:20 +0000304 std::copy(Stmts.begin(), Stmts.end(), body_begin());
305}
306
307CompoundStmt *CompoundStmt::Create(const ASTContext &C, ArrayRef<Stmt *> Stmts,
308 SourceLocation LB, SourceLocation RB) {
309 void *Mem =
310 C.Allocate(totalSizeToAlloc<Stmt *>(Stmts.size()), alignof(CompoundStmt));
311 return new (Mem) CompoundStmt(Stmts, LB, RB);
312}
313
314CompoundStmt *CompoundStmt::CreateEmpty(const ASTContext &C,
315 unsigned NumStmts) {
316 void *Mem =
317 C.Allocate(totalSizeToAlloc<Stmt *>(NumStmts), alignof(CompoundStmt));
318 CompoundStmt *New = new (Mem) CompoundStmt(EmptyShell());
319 New->CompoundStmtBits.NumStmts = NumStmts;
320 return New;
Douglas Gregora9af1d12009-04-17 00:04:06 +0000321}
Steve Narofff84d11f2007-05-23 21:48:04 +0000322
Richard Smitha6e8d5e2019-02-15 00:27:53 +0000323const Expr *ValueStmt::getExprStmt() const {
324 const Stmt *S = this;
325 do {
326 if (const auto *E = dyn_cast<Expr>(S))
327 return E;
328
329 if (const auto *LS = dyn_cast<LabelStmt>(S))
330 S = LS->getSubStmt();
331 else if (const auto *AS = dyn_cast<AttributedStmt>(S))
332 S = AS->getSubStmt();
333 else
334 llvm_unreachable("unknown kind of ValueStmt");
335 } while (isa<ValueStmt>(S));
336
337 return nullptr;
338}
339
Chris Lattnereefa10e2007-05-28 06:56:27 +0000340const char *LabelStmt::getName() const {
Chris Lattnerc8e630e2011-02-17 07:39:24 +0000341 return getDecl()->getIdentifier()->getNameStart();
Chris Lattnereefa10e2007-05-28 06:56:27 +0000342}
343
Craig Toppere6960e22013-08-22 05:28:54 +0000344AttributedStmt *AttributedStmt::Create(const ASTContext &C, SourceLocation Loc,
Alexander Kornienko20f6fc62012-07-09 10:04:07 +0000345 ArrayRef<const Attr*> Attrs,
346 Stmt *SubStmt) {
Aaron Ballmanf3d9b092014-05-13 14:55:01 +0000347 assert(!Attrs.empty() && "Attrs should not be empty");
Benjamin Kramer917fdbe2017-12-24 16:24:11 +0000348 void *Mem = C.Allocate(totalSizeToAlloc<const Attr *>(Attrs.size()),
Benjamin Kramerc3f89252016-10-20 14:27:22 +0000349 alignof(AttributedStmt));
Alexander Kornienko20f6fc62012-07-09 10:04:07 +0000350 return new (Mem) AttributedStmt(Loc, Attrs, SubStmt);
351}
352
Craig Toppere6960e22013-08-22 05:28:54 +0000353AttributedStmt *AttributedStmt::CreateEmpty(const ASTContext &C,
354 unsigned NumAttrs) {
Alexander Kornienko20f6fc62012-07-09 10:04:07 +0000355 assert(NumAttrs > 0 && "NumAttrs should be greater than zero");
Benjamin Kramer917fdbe2017-12-24 16:24:11 +0000356 void *Mem = C.Allocate(totalSizeToAlloc<const Attr *>(NumAttrs),
Benjamin Kramerc3f89252016-10-20 14:27:22 +0000357 alignof(AttributedStmt));
Alexander Kornienko20f6fc62012-07-09 10:04:07 +0000358 return new (Mem) AttributedStmt(EmptyShell(), NumAttrs);
359}
360
Craig Topperc571c812013-08-22 06:02:26 +0000361std::string AsmStmt::generateAsmString(const ASTContext &C) const {
Eugene Zelenko7855e772018-04-03 00:11:50 +0000362 if (const auto *gccAsmStmt = dyn_cast<GCCAsmStmt>(this))
Chad Rosierf70b7e22012-08-28 18:21:14 +0000363 return gccAsmStmt->generateAsmString(C);
Eugene Zelenko7855e772018-04-03 00:11:50 +0000364 if (const auto *msAsmStmt = dyn_cast<MSAsmStmt>(this))
Chad Rosierf70b7e22012-08-28 18:21:14 +0000365 return msAsmStmt->generateAsmString(C);
Chad Rosierbbbe9ab2012-08-28 17:43:23 +0000366 llvm_unreachable("unknown asm statement kind!");
367}
368
369StringRef AsmStmt::getOutputConstraint(unsigned i) const {
Eugene Zelenko7855e772018-04-03 00:11:50 +0000370 if (const auto *gccAsmStmt = dyn_cast<GCCAsmStmt>(this))
Chad Rosierf70b7e22012-08-28 18:21:14 +0000371 return gccAsmStmt->getOutputConstraint(i);
Eugene Zelenko7855e772018-04-03 00:11:50 +0000372 if (const auto *msAsmStmt = dyn_cast<MSAsmStmt>(this))
Chad Rosierf70b7e22012-08-28 18:21:14 +0000373 return msAsmStmt->getOutputConstraint(i);
Chad Rosierbbbe9ab2012-08-28 17:43:23 +0000374 llvm_unreachable("unknown asm statement kind!");
375}
376
377const Expr *AsmStmt::getOutputExpr(unsigned i) const {
Eugene Zelenko7855e772018-04-03 00:11:50 +0000378 if (const auto *gccAsmStmt = dyn_cast<GCCAsmStmt>(this))
Chad Rosierf70b7e22012-08-28 18:21:14 +0000379 return gccAsmStmt->getOutputExpr(i);
Eugene Zelenko7855e772018-04-03 00:11:50 +0000380 if (const auto *msAsmStmt = dyn_cast<MSAsmStmt>(this))
Chad Rosierf70b7e22012-08-28 18:21:14 +0000381 return msAsmStmt->getOutputExpr(i);
Chad Rosierbbbe9ab2012-08-28 17:43:23 +0000382 llvm_unreachable("unknown asm statement kind!");
383}
384
385StringRef AsmStmt::getInputConstraint(unsigned i) const {
Eugene Zelenko7855e772018-04-03 00:11:50 +0000386 if (const auto *gccAsmStmt = dyn_cast<GCCAsmStmt>(this))
Chad Rosierf70b7e22012-08-28 18:21:14 +0000387 return gccAsmStmt->getInputConstraint(i);
Eugene Zelenko7855e772018-04-03 00:11:50 +0000388 if (const auto *msAsmStmt = dyn_cast<MSAsmStmt>(this))
Chad Rosierf70b7e22012-08-28 18:21:14 +0000389 return msAsmStmt->getInputConstraint(i);
Chad Rosierbbbe9ab2012-08-28 17:43:23 +0000390 llvm_unreachable("unknown asm statement kind!");
391}
392
393const Expr *AsmStmt::getInputExpr(unsigned i) const {
Eugene Zelenko7855e772018-04-03 00:11:50 +0000394 if (const auto *gccAsmStmt = dyn_cast<GCCAsmStmt>(this))
Chad Rosierf70b7e22012-08-28 18:21:14 +0000395 return gccAsmStmt->getInputExpr(i);
Eugene Zelenko7855e772018-04-03 00:11:50 +0000396 if (const auto *msAsmStmt = dyn_cast<MSAsmStmt>(this))
Chad Rosierf70b7e22012-08-28 18:21:14 +0000397 return msAsmStmt->getInputExpr(i);
Chad Rosierbbbe9ab2012-08-28 17:43:23 +0000398 llvm_unreachable("unknown asm statement kind!");
399}
400
401StringRef AsmStmt::getClobber(unsigned i) const {
Eugene Zelenko7855e772018-04-03 00:11:50 +0000402 if (const auto *gccAsmStmt = dyn_cast<GCCAsmStmt>(this))
Chad Rosierf70b7e22012-08-28 18:21:14 +0000403 return gccAsmStmt->getClobber(i);
Eugene Zelenko7855e772018-04-03 00:11:50 +0000404 if (const auto *msAsmStmt = dyn_cast<MSAsmStmt>(this))
Chad Rosierf70b7e22012-08-28 18:21:14 +0000405 return msAsmStmt->getClobber(i);
Chad Rosierbbbe9ab2012-08-28 17:43:23 +0000406 llvm_unreachable("unknown asm statement kind!");
407}
408
Chad Rosiera1b5c8c2012-08-28 00:24:05 +0000409/// getNumPlusOperands - Return the number of output operands that have a "+"
410/// constraint.
411unsigned AsmStmt::getNumPlusOperands() const {
412 unsigned Res = 0;
413 for (unsigned i = 0, e = getNumOutputs(); i != e; ++i)
414 if (isOutputPlusConstraint(i))
415 ++Res;
416 return Res;
417}
418
Akira Hatanaka987f1862014-08-22 06:05:21 +0000419char GCCAsmStmt::AsmStringPiece::getModifier() const {
420 assert(isOperand() && "Only Operands can have modifiers.");
421 return isLetter(Str[0]) ? Str[0] : '\0';
422}
423
Chad Rosier6100ae12012-08-27 23:47:56 +0000424StringRef GCCAsmStmt::getClobber(unsigned i) const {
425 return getClobberStringLiteral(i)->getString();
426}
427
Chad Rosierde70e0e2012-08-25 00:11:56 +0000428Expr *GCCAsmStmt::getOutputExpr(unsigned i) {
Ted Kremenek5778acf2008-10-27 18:40:21 +0000429 return cast<Expr>(Exprs[i]);
430}
Chris Lattner72bbf172009-03-10 04:59:06 +0000431
432/// getOutputConstraint - Return the constraint string for the specified
433/// output operand. All output constraints are known to be non-empty (either
434/// '=' or '+').
Chad Rosierde70e0e2012-08-25 00:11:56 +0000435StringRef GCCAsmStmt::getOutputConstraint(unsigned i) const {
Anders Carlsson66de0812010-01-30 20:38:10 +0000436 return getOutputConstraintLiteral(i)->getString();
Ted Kremenek5778acf2008-10-27 18:40:21 +0000437}
Chris Lattner72bbf172009-03-10 04:59:06 +0000438
Chad Rosierde70e0e2012-08-25 00:11:56 +0000439Expr *GCCAsmStmt::getInputExpr(unsigned i) {
Ted Kremenek5778acf2008-10-27 18:40:21 +0000440 return cast<Expr>(Exprs[i + NumOutputs]);
441}
Eugene Zelenko1eab6c12017-11-14 23:35:42 +0000442
Chad Rosierde70e0e2012-08-25 00:11:56 +0000443void GCCAsmStmt::setInputExpr(unsigned i, Expr *E) {
Chris Lattner93ede022011-02-21 22:09:29 +0000444 Exprs[i + NumOutputs] = E;
445}
446
Jennifer Yu954ec092019-05-30 01:05:46 +0000447AddrLabelExpr *GCCAsmStmt::getLabelExpr(unsigned i) const {
448 return cast<AddrLabelExpr>(Exprs[i + NumInputs]);
449}
450
451StringRef GCCAsmStmt::getLabelName(unsigned i) const {
452 return getLabelExpr(i)->getLabel()->getName();
453}
454
Chris Lattner72bbf172009-03-10 04:59:06 +0000455/// getInputConstraint - Return the specified input constraint. Unlike output
456/// constraints, these can be empty.
Chad Rosierde70e0e2012-08-25 00:11:56 +0000457StringRef GCCAsmStmt::getInputConstraint(unsigned i) const {
Anders Carlsson66de0812010-01-30 20:38:10 +0000458 return getInputConstraintLiteral(i)->getString();
Ted Kremenek5778acf2008-10-27 18:40:21 +0000459}
460
Craig Topperc571c812013-08-22 06:02:26 +0000461void GCCAsmStmt::setOutputsAndInputsAndClobbers(const ASTContext &C,
462 IdentifierInfo **Names,
463 StringLiteral **Constraints,
464 Stmt **Exprs,
465 unsigned NumOutputs,
466 unsigned NumInputs,
Jennifer Yu954ec092019-05-30 01:05:46 +0000467 unsigned NumLabels,
Craig Topperc571c812013-08-22 06:02:26 +0000468 StringLiteral **Clobbers,
469 unsigned NumClobbers) {
Douglas Gregorf994f062009-04-17 20:57:14 +0000470 this->NumOutputs = NumOutputs;
471 this->NumInputs = NumInputs;
Anders Carlsson98323d22010-01-30 23:19:41 +0000472 this->NumClobbers = NumClobbers;
Jennifer Yu954ec092019-05-30 01:05:46 +0000473 this->NumLabels = NumLabels;
474 assert(!(NumOutputs && NumLabels) && "asm goto cannot have outputs");
Anders Carlsson98323d22010-01-30 23:19:41 +0000475
Jennifer Yu954ec092019-05-30 01:05:46 +0000476 unsigned NumExprs = NumOutputs + NumInputs + NumLabels;
Chad Rosier42032fa2012-08-07 23:12:23 +0000477
Anders Carlsson98323d22010-01-30 23:19:41 +0000478 C.Deallocate(this->Names);
479 this->Names = new (C) IdentifierInfo*[NumExprs];
480 std::copy(Names, Names + NumExprs, this->Names);
Chad Rosier42032fa2012-08-07 23:12:23 +0000481
Anders Carlsson98323d22010-01-30 23:19:41 +0000482 C.Deallocate(this->Exprs);
483 this->Exprs = new (C) Stmt*[NumExprs];
484 std::copy(Exprs, Exprs + NumExprs, this->Exprs);
Chad Rosier42032fa2012-08-07 23:12:23 +0000485
Anders Carlsson98323d22010-01-30 23:19:41 +0000486 C.Deallocate(this->Constraints);
487 this->Constraints = new (C) StringLiteral*[NumExprs];
488 std::copy(Constraints, Constraints + NumExprs, this->Constraints);
Chad Rosier42032fa2012-08-07 23:12:23 +0000489
Anders Carlsson98323d22010-01-30 23:19:41 +0000490 C.Deallocate(this->Clobbers);
491 this->Clobbers = new (C) StringLiteral*[NumClobbers];
492 std::copy(Clobbers, Clobbers + NumClobbers, this->Clobbers);
Douglas Gregorf994f062009-04-17 20:57:14 +0000493}
494
Chris Lattnerd7d5fdf2009-03-10 06:33:24 +0000495/// getNamedOperand - Given a symbolic operand reference like %[foo],
496/// translate this into a numeric value needed to reference the same operand.
497/// This returns -1 if the operand name is invalid.
Chad Rosierde70e0e2012-08-25 00:11:56 +0000498int GCCAsmStmt::getNamedOperand(StringRef SymbolicName) const {
Chris Lattnerd7d5fdf2009-03-10 06:33:24 +0000499 unsigned NumPlusOperands = 0;
Mike Stump11289f42009-09-09 15:08:12 +0000500
Chris Lattnerd7d5fdf2009-03-10 06:33:24 +0000501 // Check if this is an output operand.
502 for (unsigned i = 0, e = getNumOutputs(); i != e; ++i) {
503 if (getOutputName(i) == SymbolicName)
504 return i;
Chris Lattnerd7d5fdf2009-03-10 06:33:24 +0000505 }
Mike Stump11289f42009-09-09 15:08:12 +0000506
Chris Lattnerd7d5fdf2009-03-10 06:33:24 +0000507 for (unsigned i = 0, e = getNumInputs(); i != e; ++i)
508 if (getInputName(i) == SymbolicName)
509 return getNumOutputs() + NumPlusOperands + i;
510
Jennifer Yu954ec092019-05-30 01:05:46 +0000511 for (unsigned i = 0, e = getNumLabels(); i != e; ++i)
512 if (getLabelName(i) == SymbolicName)
513 return i + getNumInputs();
514
Chris Lattnerd7d5fdf2009-03-10 06:33:24 +0000515 // Not found.
516 return -1;
517}
518
Chris Lattner35b58362009-03-10 23:21:44 +0000519/// AnalyzeAsmString - Analyze the asm string of the current asm, decomposing
520/// it into pieces. If the asm string is erroneous, emit errors and return
521/// true, otherwise return false.
Chad Rosierde70e0e2012-08-25 00:11:56 +0000522unsigned GCCAsmStmt::AnalyzeAsmString(SmallVectorImpl<AsmStringPiece>&Pieces,
Craig Topperc571c812013-08-22 06:02:26 +0000523 const ASTContext &C, unsigned &DiagOffs) const {
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000524 StringRef Str = getAsmString()->getString();
Benjamin Kramer35b077e2010-08-17 12:54:38 +0000525 const char *StrStart = Str.begin();
526 const char *StrEnd = Str.end();
Chris Lattnera41b8472009-03-10 23:51:40 +0000527 const char *CurPtr = StrStart;
Mike Stump11289f42009-09-09 15:08:12 +0000528
Chris Lattner35b58362009-03-10 23:21:44 +0000529 // "Simple" inline asms have no constraints or operands, just convert the asm
530 // string to escape $'s.
531 if (isSimple()) {
532 std::string Result;
Chris Lattnera41b8472009-03-10 23:51:40 +0000533 for (; CurPtr != StrEnd; ++CurPtr) {
534 switch (*CurPtr) {
Chris Lattner35b58362009-03-10 23:21:44 +0000535 case '$':
536 Result += "$$";
537 break;
538 default:
Chris Lattnera41b8472009-03-10 23:51:40 +0000539 Result += *CurPtr;
Chris Lattner35b58362009-03-10 23:21:44 +0000540 break;
541 }
542 }
543 Pieces.push_back(AsmStringPiece(Result));
Chris Lattnera41b8472009-03-10 23:51:40 +0000544 return 0;
Chris Lattner35b58362009-03-10 23:21:44 +0000545 }
546
547 // CurStringPiece - The current string that we are building up as we scan the
548 // asm string.
549 std::string CurStringPiece;
Mike Stump11289f42009-09-09 15:08:12 +0000550
Douglas Gregore8bbc122011-09-02 00:18:52 +0000551 bool HasVariants = !C.getTargetInfo().hasNoAsmVariants();
Chad Rosier42032fa2012-08-07 23:12:23 +0000552
Richard Smithd18ab802016-05-16 22:52:23 +0000553 unsigned LastAsmStringToken = 0;
554 unsigned LastAsmStringOffset = 0;
555
Eugene Zelenko1eab6c12017-11-14 23:35:42 +0000556 while (true) {
Chris Lattner35b58362009-03-10 23:21:44 +0000557 // Done with the string?
Chris Lattnera41b8472009-03-10 23:51:40 +0000558 if (CurPtr == StrEnd) {
Chris Lattner35b58362009-03-10 23:21:44 +0000559 if (!CurStringPiece.empty())
560 Pieces.push_back(AsmStringPiece(CurStringPiece));
Chris Lattnera41b8472009-03-10 23:51:40 +0000561 return 0;
Chris Lattner35b58362009-03-10 23:21:44 +0000562 }
Mike Stump11289f42009-09-09 15:08:12 +0000563
Chris Lattnera41b8472009-03-10 23:51:40 +0000564 char CurChar = *CurPtr++;
Chris Lattnerda081a82010-04-05 18:44:00 +0000565 switch (CurChar) {
566 case '$': CurStringPiece += "$$"; continue;
Chris Lattner1a8f3942010-04-23 16:29:58 +0000567 case '{': CurStringPiece += (HasVariants ? "$(" : "{"); continue;
568 case '|': CurStringPiece += (HasVariants ? "$|" : "|"); continue;
569 case '}': CurStringPiece += (HasVariants ? "$)" : "}"); continue;
Chris Lattnerda081a82010-04-05 18:44:00 +0000570 case '%':
571 break;
572 default:
Chris Lattner35b58362009-03-10 23:21:44 +0000573 CurStringPiece += CurChar;
574 continue;
575 }
Chad Rosier42032fa2012-08-07 23:12:23 +0000576
Chris Lattner35b58362009-03-10 23:21:44 +0000577 // Escaped "%" character in asm string.
Chris Lattner3fa25c62009-03-11 00:06:36 +0000578 if (CurPtr == StrEnd) {
579 // % at end of string is invalid (no escape).
580 DiagOffs = CurPtr-StrStart-1;
581 return diag::err_asm_invalid_escape;
582 }
Michael Zuckerman2460bad2016-10-31 15:27:54 +0000583 // Handle escaped char and continue looping over the asm string.
Chris Lattnera41b8472009-03-10 23:51:40 +0000584 char EscapedChar = *CurPtr++;
Michael Zuckerman2460bad2016-10-31 15:27:54 +0000585 switch (EscapedChar) {
586 default:
587 break;
588 case '%': // %% -> %
589 case '{': // %{ -> {
590 case '}': // %} -> }
591 CurStringPiece += EscapedChar;
Chris Lattner35b58362009-03-10 23:21:44 +0000592 continue;
Michael Zuckerman2460bad2016-10-31 15:27:54 +0000593 case '=': // %= -> Generate a unique ID.
Chris Lattner35b58362009-03-10 23:21:44 +0000594 CurStringPiece += "${:uid}";
595 continue;
596 }
Mike Stump11289f42009-09-09 15:08:12 +0000597
Chris Lattner35b58362009-03-10 23:21:44 +0000598 // Otherwise, we have an operand. If we have accumulated a string so far,
599 // add it to the Pieces list.
600 if (!CurStringPiece.empty()) {
601 Pieces.push_back(AsmStringPiece(CurStringPiece));
602 CurStringPiece.clear();
603 }
Mike Stump11289f42009-09-09 15:08:12 +0000604
Akira Hatanaka987f1862014-08-22 06:05:21 +0000605 // Handle operands that have asmSymbolicName (e.g., %x[foo]) and those that
606 // don't (e.g., %x4). 'x' following the '%' is the constraint modifier.
607
608 const char *Begin = CurPtr - 1; // Points to the character following '%'.
609 const char *Percent = Begin - 1; // Points to '%'.
610
Jordan Rosea7d03842013-02-08 22:30:41 +0000611 if (isLetter(EscapedChar)) {
Benjamin Kramere87c38b2011-07-05 11:13:37 +0000612 if (CurPtr == StrEnd) { // Premature end.
613 DiagOffs = CurPtr-StrStart-1;
614 return diag::err_asm_invalid_escape;
615 }
Chris Lattnera41b8472009-03-10 23:51:40 +0000616 EscapedChar = *CurPtr++;
Chris Lattner35b58362009-03-10 23:21:44 +0000617 }
Mike Stump11289f42009-09-09 15:08:12 +0000618
Akira Hatanaka987f1862014-08-22 06:05:21 +0000619 const TargetInfo &TI = C.getTargetInfo();
620 const SourceManager &SM = C.getSourceManager();
621 const LangOptions &LO = C.getLangOpts();
622
623 // Handle operands that don't have asmSymbolicName (e.g., %x4).
Jordan Rosea7d03842013-02-08 22:30:41 +0000624 if (isDigit(EscapedChar)) {
Chris Lattner35b58362009-03-10 23:21:44 +0000625 // %n - Assembler operand n
Chris Lattner99d892b2009-03-11 22:52:17 +0000626 unsigned N = 0;
Mike Stump11289f42009-09-09 15:08:12 +0000627
Chris Lattner99d892b2009-03-11 22:52:17 +0000628 --CurPtr;
Jordan Rosea7d03842013-02-08 22:30:41 +0000629 while (CurPtr != StrEnd && isDigit(*CurPtr))
Chris Lattner84f3afa2009-03-11 23:09:16 +0000630 N = N*10 + ((*CurPtr++)-'0');
Mike Stump11289f42009-09-09 15:08:12 +0000631
Jennifer Yu954ec092019-05-30 01:05:46 +0000632 unsigned NumOperands = getNumOutputs() + getNumPlusOperands() +
633 getNumInputs() + getNumLabels();
Chris Lattner14311922009-03-11 00:23:13 +0000634 if (N >= NumOperands) {
635 DiagOffs = CurPtr-StrStart-1;
636 return diag::err_asm_invalid_operand_number;
637 }
638
Akira Hatanaka987f1862014-08-22 06:05:21 +0000639 // Str contains "x4" (Operand without the leading %).
640 std::string Str(Begin, CurPtr - Begin);
641
642 // (BeginLoc, EndLoc) represents the range of the operand we are currently
643 // processing. Unlike Str, the range includes the leading '%'.
Richard Smithd18ab802016-05-16 22:52:23 +0000644 SourceLocation BeginLoc = getAsmString()->getLocationOfByte(
645 Percent - StrStart, SM, LO, TI, &LastAsmStringToken,
646 &LastAsmStringOffset);
647 SourceLocation EndLoc = getAsmString()->getLocationOfByte(
648 CurPtr - StrStart, SM, LO, TI, &LastAsmStringToken,
649 &LastAsmStringOffset);
Akira Hatanaka987f1862014-08-22 06:05:21 +0000650
Benjamin Kramer3204b152015-05-29 19:42:19 +0000651 Pieces.emplace_back(N, std::move(Str), BeginLoc, EndLoc);
Chris Lattner35b58362009-03-10 23:21:44 +0000652 continue;
653 }
Mike Stump11289f42009-09-09 15:08:12 +0000654
Akira Hatanaka987f1862014-08-22 06:05:21 +0000655 // Handle operands that have asmSymbolicName (e.g., %x[foo]).
Chris Lattner35b58362009-03-10 23:21:44 +0000656 if (EscapedChar == '[') {
Chris Lattner3fa25c62009-03-11 00:06:36 +0000657 DiagOffs = CurPtr-StrStart-1;
Mike Stump11289f42009-09-09 15:08:12 +0000658
Chris Lattner3fa25c62009-03-11 00:06:36 +0000659 // Find the ']'.
Chris Lattnera41b8472009-03-10 23:51:40 +0000660 const char *NameEnd = (const char*)memchr(CurPtr, ']', StrEnd-CurPtr);
Craig Topper36250ad2014-05-12 05:36:57 +0000661 if (NameEnd == nullptr)
Chris Lattner3fa25c62009-03-11 00:06:36 +0000662 return diag::err_asm_unterminated_symbolic_operand_name;
663 if (NameEnd == CurPtr)
664 return diag::err_asm_empty_symbolic_operand_name;
Mike Stump11289f42009-09-09 15:08:12 +0000665
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000666 StringRef SymbolicName(CurPtr, NameEnd - CurPtr);
Mike Stump11289f42009-09-09 15:08:12 +0000667
Chris Lattner35b58362009-03-10 23:21:44 +0000668 int N = getNamedOperand(SymbolicName);
Chris Lattner3fa25c62009-03-11 00:06:36 +0000669 if (N == -1) {
670 // Verify that an operand with that name exists.
671 DiagOffs = CurPtr-StrStart;
672 return diag::err_asm_unknown_symbolic_operand_name;
673 }
Akira Hatanaka987f1862014-08-22 06:05:21 +0000674
675 // Str contains "x[foo]" (Operand without the leading %).
676 std::string Str(Begin, NameEnd + 1 - Begin);
677
678 // (BeginLoc, EndLoc) represents the range of the operand we are currently
679 // processing. Unlike Str, the range includes the leading '%'.
Richard Smithd18ab802016-05-16 22:52:23 +0000680 SourceLocation BeginLoc = getAsmString()->getLocationOfByte(
681 Percent - StrStart, SM, LO, TI, &LastAsmStringToken,
682 &LastAsmStringOffset);
683 SourceLocation EndLoc = getAsmString()->getLocationOfByte(
684 NameEnd + 1 - StrStart, SM, LO, TI, &LastAsmStringToken,
685 &LastAsmStringOffset);
Akira Hatanaka987f1862014-08-22 06:05:21 +0000686
Benjamin Kramer3204b152015-05-29 19:42:19 +0000687 Pieces.emplace_back(N, std::move(Str), BeginLoc, EndLoc);
Mike Stump11289f42009-09-09 15:08:12 +0000688
Chris Lattner3fa25c62009-03-11 00:06:36 +0000689 CurPtr = NameEnd+1;
Chris Lattner35b58362009-03-10 23:21:44 +0000690 continue;
691 }
Mike Stump11289f42009-09-09 15:08:12 +0000692
Chris Lattner0cdaa2e2009-03-10 23:57:07 +0000693 DiagOffs = CurPtr-StrStart-1;
Chris Lattnera41b8472009-03-10 23:51:40 +0000694 return diag::err_asm_invalid_escape;
Chris Lattner35b58362009-03-10 23:21:44 +0000695 }
696}
Chad Rosier3b0c2602012-08-27 20:23:31 +0000697
698/// Assemble final IR asm string (GCC-style).
Craig Topperc571c812013-08-22 06:02:26 +0000699std::string GCCAsmStmt::generateAsmString(const ASTContext &C) const {
Chad Rosier14836ba2012-08-24 17:05:45 +0000700 // Analyze the asm string to decompose it into its pieces. We know that Sema
701 // has already done this, so it is guaranteed to be successful.
Chad Rosierde70e0e2012-08-25 00:11:56 +0000702 SmallVector<GCCAsmStmt::AsmStringPiece, 4> Pieces;
Chad Rosier14836ba2012-08-24 17:05:45 +0000703 unsigned DiagOffs;
704 AnalyzeAsmString(Pieces, C, DiagOffs);
705
706 std::string AsmString;
Eugene Zelenko7855e772018-04-03 00:11:50 +0000707 for (const auto &Piece : Pieces) {
708 if (Piece.isString())
709 AsmString += Piece.getString();
710 else if (Piece.getModifier() == '\0')
711 AsmString += '$' + llvm::utostr(Piece.getOperandNo());
Chad Rosier14836ba2012-08-24 17:05:45 +0000712 else
Eugene Zelenko7855e772018-04-03 00:11:50 +0000713 AsmString += "${" + llvm::utostr(Piece.getOperandNo()) + ':' +
714 Piece.getModifier() + '}';
Chad Rosier14836ba2012-08-24 17:05:45 +0000715 }
716 return AsmString;
717}
Chris Lattner35b58362009-03-10 23:21:44 +0000718
Chad Rosier3b0c2602012-08-27 20:23:31 +0000719/// Assemble final IR asm string (MS-style).
Craig Topperc571c812013-08-22 06:02:26 +0000720std::string MSAsmStmt::generateAsmString(const ASTContext &C) const {
Chad Rosier3b0c2602012-08-27 20:23:31 +0000721 // FIXME: This needs to be translated into the IR string representation.
Chad Rosier0bca4692012-08-28 20:33:49 +0000722 return AsmStr;
Chad Rosier3b0c2602012-08-27 20:23:31 +0000723}
724
Chad Rosierfe31e622012-08-24 00:07:09 +0000725Expr *MSAsmStmt::getOutputExpr(unsigned i) {
726 return cast<Expr>(Exprs[i]);
727}
728
729Expr *MSAsmStmt::getInputExpr(unsigned i) {
730 return cast<Expr>(Exprs[i + NumOutputs]);
731}
Eugene Zelenko1eab6c12017-11-14 23:35:42 +0000732
Chad Rosierfe31e622012-08-24 00:07:09 +0000733void MSAsmStmt::setInputExpr(unsigned i, Expr *E) {
734 Exprs[i + NumOutputs] = E;
735}
736
Chris Lattner86f5e132008-01-30 05:01:46 +0000737//===----------------------------------------------------------------------===//
738// Constructors
739//===----------------------------------------------------------------------===//
740
Craig Toppere6960e22013-08-22 05:28:54 +0000741GCCAsmStmt::GCCAsmStmt(const ASTContext &C, SourceLocation asmloc,
742 bool issimple, bool isvolatile, unsigned numoutputs,
743 unsigned numinputs, IdentifierInfo **names,
744 StringLiteral **constraints, Expr **exprs,
745 StringLiteral *asmstr, unsigned numclobbers,
Jennifer Yu954ec092019-05-30 01:05:46 +0000746 StringLiteral **clobbers, unsigned numlabels,
747 SourceLocation rparenloc)
Eugene Zelenko1eab6c12017-11-14 23:35:42 +0000748 : AsmStmt(GCCAsmStmtClass, asmloc, issimple, isvolatile, numoutputs,
Jennifer Yu954ec092019-05-30 01:05:46 +0000749 numinputs, numclobbers),
750 RParenLoc(rparenloc), AsmStr(asmstr), NumLabels(numlabels) {
751 unsigned NumExprs = NumOutputs + NumInputs + NumLabels;
Chad Rosier42032fa2012-08-07 23:12:23 +0000752
Anders Carlsson98323d22010-01-30 23:19:41 +0000753 Names = new (C) IdentifierInfo*[NumExprs];
754 std::copy(names, names + NumExprs, Names);
755
756 Exprs = new (C) Stmt*[NumExprs];
757 std::copy(exprs, exprs + NumExprs, Exprs);
758
759 Constraints = new (C) StringLiteral*[NumExprs];
760 std::copy(constraints, constraints + NumExprs, Constraints);
761
762 Clobbers = new (C) StringLiteral*[NumClobbers];
763 std::copy(clobbers, clobbers + NumClobbers, Clobbers);
Anders Carlsson94ea8aa2007-11-22 01:36:19 +0000764}
765
Craig Toppere6960e22013-08-22 05:28:54 +0000766MSAsmStmt::MSAsmStmt(const ASTContext &C, SourceLocation asmloc,
Chad Rosier7dbef3e2012-08-16 00:06:53 +0000767 SourceLocation lbraceloc, bool issimple, bool isvolatile,
Chad Rosierf8037a12012-10-16 21:55:39 +0000768 ArrayRef<Token> asmtoks, unsigned numoutputs,
John McCallf413f5e2013-05-03 00:10:13 +0000769 unsigned numinputs,
Chad Rosierf8037a12012-10-16 21:55:39 +0000770 ArrayRef<StringRef> constraints, ArrayRef<Expr*> exprs,
771 StringRef asmstr, ArrayRef<StringRef> clobbers,
772 SourceLocation endloc)
Eugene Zelenko1eab6c12017-11-14 23:35:42 +0000773 : AsmStmt(MSAsmStmtClass, asmloc, issimple, isvolatile, numoutputs,
774 numinputs, clobbers.size()), LBraceLoc(lbraceloc),
775 EndLoc(endloc), NumAsmToks(asmtoks.size()) {
John McCallf413f5e2013-05-03 00:10:13 +0000776 initialize(C, asmstr, asmtoks, constraints, exprs, clobbers);
777}
Chad Rosier7dbef3e2012-08-16 00:06:53 +0000778
Craig Toppere6960e22013-08-22 05:28:54 +0000779static StringRef copyIntoContext(const ASTContext &C, StringRef str) {
Benjamin Kramer2ab0d882015-08-04 12:34:23 +0000780 return str.copy(C);
John McCallf413f5e2013-05-03 00:10:13 +0000781}
782
Craig Toppere6960e22013-08-22 05:28:54 +0000783void MSAsmStmt::initialize(const ASTContext &C, StringRef asmstr,
John McCallf413f5e2013-05-03 00:10:13 +0000784 ArrayRef<Token> asmtoks,
785 ArrayRef<StringRef> constraints,
786 ArrayRef<Expr*> exprs,
787 ArrayRef<StringRef> clobbers) {
788 assert(NumAsmToks == asmtoks.size());
789 assert(NumClobbers == clobbers.size());
790
Craig Toppercaf138e2015-12-05 07:41:42 +0000791 assert(exprs.size() == NumOutputs + NumInputs);
792 assert(exprs.size() == constraints.size());
John McCallf413f5e2013-05-03 00:10:13 +0000793
794 AsmStr = copyIntoContext(C, asmstr);
Chad Rosier99fc3812012-08-07 00:29:06 +0000795
Craig Toppercaf138e2015-12-05 07:41:42 +0000796 Exprs = new (C) Stmt*[exprs.size()];
797 std::copy(exprs.begin(), exprs.end(), Exprs);
Chad Rosierfe31e622012-08-24 00:07:09 +0000798
Craig Toppercaf138e2015-12-05 07:41:42 +0000799 AsmToks = new (C) Token[asmtoks.size()];
800 std::copy(asmtoks.begin(), asmtoks.end(), AsmToks);
Chad Rosier3ed0bd92012-08-08 19:48:07 +0000801
Craig Toppercaf138e2015-12-05 07:41:42 +0000802 Constraints = new (C) StringRef[exprs.size()];
803 std::transform(constraints.begin(), constraints.end(), Constraints,
804 [&](StringRef Constraint) {
805 return copyIntoContext(C, Constraint);
806 });
Chad Rosier3dd7bf22012-08-28 20:28:20 +0000807
Chad Rosierbaf53f92012-08-10 21:36:25 +0000808 Clobbers = new (C) StringRef[NumClobbers];
Craig Toppercaf138e2015-12-05 07:41:42 +0000809 // FIXME: Avoid the allocation/copy if at all possible.
810 std::transform(clobbers.begin(), clobbers.end(), Clobbers,
811 [&](StringRef Clobber) {
812 return copyIntoContext(C, Clobber);
813 });
Chad Rosier32503022012-06-11 20:47:18 +0000814}
815
Bruno Riccib1cc94b2018-10-27 21:12:20 +0000816IfStmt::IfStmt(const ASTContext &Ctx, SourceLocation IL, bool IsConstexpr,
817 Stmt *Init, VarDecl *Var, Expr *Cond, Stmt *Then,
818 SourceLocation EL, Stmt *Else)
819 : Stmt(IfStmtClass) {
820 bool HasElse = Else != nullptr;
821 bool HasVar = Var != nullptr;
822 bool HasInit = Init != nullptr;
823 IfStmtBits.HasElse = HasElse;
824 IfStmtBits.HasVar = HasVar;
825 IfStmtBits.HasInit = HasInit;
826
Richard Smithb130fe72016-06-23 19:16:49 +0000827 setConstexpr(IsConstexpr);
Bruno Riccib1cc94b2018-10-27 21:12:20 +0000828
829 setCond(Cond);
830 setThen(Then);
831 if (HasElse)
832 setElse(Else);
833 if (HasVar)
834 setConditionVariable(Ctx, Var);
835 if (HasInit)
836 setInit(Init);
837
838 setIfLoc(IL);
839 if (HasElse)
840 setElseLoc(EL);
Douglas Gregor27b98ea2010-06-21 23:44:13 +0000841}
842
Bruno Riccib1cc94b2018-10-27 21:12:20 +0000843IfStmt::IfStmt(EmptyShell Empty, bool HasElse, bool HasVar, bool HasInit)
844 : Stmt(IfStmtClass, Empty) {
845 IfStmtBits.HasElse = HasElse;
846 IfStmtBits.HasVar = HasVar;
847 IfStmtBits.HasInit = HasInit;
848}
Chad Rosier42032fa2012-08-07 23:12:23 +0000849
Bruno Riccib1cc94b2018-10-27 21:12:20 +0000850IfStmt *IfStmt::Create(const ASTContext &Ctx, SourceLocation IL,
851 bool IsConstexpr, Stmt *Init, VarDecl *Var, Expr *Cond,
852 Stmt *Then, SourceLocation EL, Stmt *Else) {
853 bool HasElse = Else != nullptr;
854 bool HasVar = Var != nullptr;
855 bool HasInit = Init != nullptr;
856 void *Mem = Ctx.Allocate(
857 totalSizeToAlloc<Stmt *, SourceLocation>(
858 NumMandatoryStmtPtr + HasElse + HasVar + HasInit, HasElse),
859 alignof(IfStmt));
860 return new (Mem)
861 IfStmt(Ctx, IL, IsConstexpr, Init, Var, Cond, Then, EL, Else);
862}
863
864IfStmt *IfStmt::CreateEmpty(const ASTContext &Ctx, bool HasElse, bool HasVar,
865 bool HasInit) {
866 void *Mem = Ctx.Allocate(
867 totalSizeToAlloc<Stmt *, SourceLocation>(
868 NumMandatoryStmtPtr + HasElse + HasVar + HasInit, HasElse),
869 alignof(IfStmt));
870 return new (Mem) IfStmt(EmptyShell(), HasElse, HasVar, HasInit);
871}
872
873VarDecl *IfStmt::getConditionVariable() {
874 auto *DS = getConditionVariableDeclStmt();
875 if (!DS)
876 return nullptr;
Douglas Gregor27b98ea2010-06-21 23:44:13 +0000877 return cast<VarDecl>(DS->getSingleDecl());
878}
879
Bruno Riccib1cc94b2018-10-27 21:12:20 +0000880void IfStmt::setConditionVariable(const ASTContext &Ctx, VarDecl *V) {
881 assert(hasVarStorage() &&
882 "This if statement has no storage for a condition variable!");
883
Douglas Gregor27b98ea2010-06-21 23:44:13 +0000884 if (!V) {
Bruno Riccib1cc94b2018-10-27 21:12:20 +0000885 getTrailingObjects<Stmt *>()[varOffset()] = nullptr;
Douglas Gregor27b98ea2010-06-21 23:44:13 +0000886 return;
887 }
Chad Rosier42032fa2012-08-07 23:12:23 +0000888
Daniel Dunbar62ee6412012-03-09 18:35:03 +0000889 SourceRange VarRange = V->getSourceRange();
Bruno Riccib1cc94b2018-10-27 21:12:20 +0000890 getTrailingObjects<Stmt *>()[varOffset()] = new (Ctx)
891 DeclStmt(DeclGroupRef(V), VarRange.getBegin(), VarRange.getEnd());
Douglas Gregor27b98ea2010-06-21 23:44:13 +0000892}
893
Erik Pilkington5cd57172016-08-16 17:44:11 +0000894bool IfStmt::isObjCAvailabilityCheck() const {
Bruno Riccib1cc94b2018-10-27 21:12:20 +0000895 return isa<ObjCAvailabilityCheckExpr>(getCond());
Erik Pilkington5cd57172016-08-16 17:44:11 +0000896}
897
Craig Toppere6960e22013-08-22 05:28:54 +0000898ForStmt::ForStmt(const ASTContext &C, Stmt *Init, Expr *Cond, VarDecl *condVar,
Chad Rosier42032fa2012-08-07 23:12:23 +0000899 Expr *Inc, Stmt *Body, SourceLocation FL, SourceLocation LP,
Douglas Gregor27b98ea2010-06-21 23:44:13 +0000900 SourceLocation RP)
Bruno Ricci41d11c02018-10-27 18:43:27 +0000901 : Stmt(ForStmtClass), LParenLoc(LP), RParenLoc(RP)
Douglas Gregor27b98ea2010-06-21 23:44:13 +0000902{
903 SubExprs[INIT] = Init;
904 setConditionVariable(C, condVar);
Pavel Labath515f4db2013-09-03 14:41:16 +0000905 SubExprs[COND] = Cond;
906 SubExprs[INC] = Inc;
Douglas Gregor27b98ea2010-06-21 23:44:13 +0000907 SubExprs[BODY] = Body;
Bruno Ricci41d11c02018-10-27 18:43:27 +0000908 ForStmtBits.ForLoc = FL;
Douglas Gregor27b98ea2010-06-21 23:44:13 +0000909}
910
911VarDecl *ForStmt::getConditionVariable() const {
912 if (!SubExprs[CONDVAR])
Craig Topper36250ad2014-05-12 05:36:57 +0000913 return nullptr;
Chad Rosier42032fa2012-08-07 23:12:23 +0000914
Eugene Zelenko7855e772018-04-03 00:11:50 +0000915 auto *DS = cast<DeclStmt>(SubExprs[CONDVAR]);
Douglas Gregor27b98ea2010-06-21 23:44:13 +0000916 return cast<VarDecl>(DS->getSingleDecl());
917}
918
Craig Toppere6960e22013-08-22 05:28:54 +0000919void ForStmt::setConditionVariable(const ASTContext &C, VarDecl *V) {
Douglas Gregor27b98ea2010-06-21 23:44:13 +0000920 if (!V) {
Craig Topper36250ad2014-05-12 05:36:57 +0000921 SubExprs[CONDVAR] = nullptr;
Douglas Gregor27b98ea2010-06-21 23:44:13 +0000922 return;
923 }
Chad Rosier42032fa2012-08-07 23:12:23 +0000924
Daniel Dunbar62ee6412012-03-09 18:35:03 +0000925 SourceRange VarRange = V->getSourceRange();
926 SubExprs[CONDVAR] = new (C) DeclStmt(DeclGroupRef(V), VarRange.getBegin(),
927 VarRange.getEnd());
Douglas Gregor27b98ea2010-06-21 23:44:13 +0000928}
929
Bruno Riccie2806f82018-10-29 16:12:37 +0000930SwitchStmt::SwitchStmt(const ASTContext &Ctx, Stmt *Init, VarDecl *Var,
931 Expr *Cond)
932 : Stmt(SwitchStmtClass), FirstCase(nullptr) {
933 bool HasInit = Init != nullptr;
934 bool HasVar = Var != nullptr;
935 SwitchStmtBits.HasInit = HasInit;
936 SwitchStmtBits.HasVar = HasVar;
937 SwitchStmtBits.AllEnumCasesCovered = false;
938
939 setCond(Cond);
940 setBody(nullptr);
941 if (HasInit)
942 setInit(Init);
943 if (HasVar)
944 setConditionVariable(Ctx, Var);
945
946 setSwitchLoc(SourceLocation{});
Douglas Gregor27b98ea2010-06-21 23:44:13 +0000947}
948
Bruno Riccie2806f82018-10-29 16:12:37 +0000949SwitchStmt::SwitchStmt(EmptyShell Empty, bool HasInit, bool HasVar)
950 : Stmt(SwitchStmtClass, Empty) {
951 SwitchStmtBits.HasInit = HasInit;
952 SwitchStmtBits.HasVar = HasVar;
953 SwitchStmtBits.AllEnumCasesCovered = false;
954}
Chad Rosier42032fa2012-08-07 23:12:23 +0000955
Bruno Riccie2806f82018-10-29 16:12:37 +0000956SwitchStmt *SwitchStmt::Create(const ASTContext &Ctx, Stmt *Init, VarDecl *Var,
957 Expr *Cond) {
958 bool HasInit = Init != nullptr;
959 bool HasVar = Var != nullptr;
960 void *Mem = Ctx.Allocate(
961 totalSizeToAlloc<Stmt *>(NumMandatoryStmtPtr + HasInit + HasVar),
962 alignof(SwitchStmt));
963 return new (Mem) SwitchStmt(Ctx, Init, Var, Cond);
964}
965
966SwitchStmt *SwitchStmt::CreateEmpty(const ASTContext &Ctx, bool HasInit,
967 bool HasVar) {
968 void *Mem = Ctx.Allocate(
969 totalSizeToAlloc<Stmt *>(NumMandatoryStmtPtr + HasInit + HasVar),
970 alignof(SwitchStmt));
971 return new (Mem) SwitchStmt(EmptyShell(), HasInit, HasVar);
972}
973
974VarDecl *SwitchStmt::getConditionVariable() {
975 auto *DS = getConditionVariableDeclStmt();
976 if (!DS)
977 return nullptr;
Douglas Gregor27b98ea2010-06-21 23:44:13 +0000978 return cast<VarDecl>(DS->getSingleDecl());
979}
980
Bruno Riccie2806f82018-10-29 16:12:37 +0000981void SwitchStmt::setConditionVariable(const ASTContext &Ctx, VarDecl *V) {
982 assert(hasVarStorage() &&
983 "This switch statement has no storage for a condition variable!");
984
Douglas Gregor27b98ea2010-06-21 23:44:13 +0000985 if (!V) {
Bruno Riccie2806f82018-10-29 16:12:37 +0000986 getTrailingObjects<Stmt *>()[varOffset()] = nullptr;
Douglas Gregor27b98ea2010-06-21 23:44:13 +0000987 return;
988 }
Chad Rosier42032fa2012-08-07 23:12:23 +0000989
Daniel Dunbar62ee6412012-03-09 18:35:03 +0000990 SourceRange VarRange = V->getSourceRange();
Bruno Riccie2806f82018-10-29 16:12:37 +0000991 getTrailingObjects<Stmt *>()[varOffset()] = new (Ctx)
992 DeclStmt(DeclGroupRef(V), VarRange.getBegin(), VarRange.getEnd());
Douglas Gregor27b98ea2010-06-21 23:44:13 +0000993}
994
Bruno Riccibacf7512018-10-30 13:42:41 +0000995WhileStmt::WhileStmt(const ASTContext &Ctx, VarDecl *Var, Expr *Cond,
996 Stmt *Body, SourceLocation WL)
997 : Stmt(WhileStmtClass) {
998 bool HasVar = Var != nullptr;
999 WhileStmtBits.HasVar = HasVar;
1000
1001 setCond(Cond);
1002 setBody(Body);
1003 if (HasVar)
1004 setConditionVariable(Ctx, Var);
1005
1006 setWhileLoc(WL);
Douglas Gregor27b98ea2010-06-21 23:44:13 +00001007}
1008
Bruno Riccibacf7512018-10-30 13:42:41 +00001009WhileStmt::WhileStmt(EmptyShell Empty, bool HasVar)
1010 : Stmt(WhileStmtClass, Empty) {
1011 WhileStmtBits.HasVar = HasVar;
1012}
Chad Rosier42032fa2012-08-07 23:12:23 +00001013
Bruno Riccibacf7512018-10-30 13:42:41 +00001014WhileStmt *WhileStmt::Create(const ASTContext &Ctx, VarDecl *Var, Expr *Cond,
1015 Stmt *Body, SourceLocation WL) {
1016 bool HasVar = Var != nullptr;
1017 void *Mem =
1018 Ctx.Allocate(totalSizeToAlloc<Stmt *>(NumMandatoryStmtPtr + HasVar),
1019 alignof(WhileStmt));
1020 return new (Mem) WhileStmt(Ctx, Var, Cond, Body, WL);
1021}
1022
1023WhileStmt *WhileStmt::CreateEmpty(const ASTContext &Ctx, bool HasVar) {
1024 void *Mem =
1025 Ctx.Allocate(totalSizeToAlloc<Stmt *>(NumMandatoryStmtPtr + HasVar),
1026 alignof(WhileStmt));
1027 return new (Mem) WhileStmt(EmptyShell(), HasVar);
1028}
1029
1030VarDecl *WhileStmt::getConditionVariable() {
1031 auto *DS = getConditionVariableDeclStmt();
1032 if (!DS)
1033 return nullptr;
Douglas Gregor27b98ea2010-06-21 23:44:13 +00001034 return cast<VarDecl>(DS->getSingleDecl());
1035}
1036
Bruno Riccibacf7512018-10-30 13:42:41 +00001037void WhileStmt::setConditionVariable(const ASTContext &Ctx, VarDecl *V) {
1038 assert(hasVarStorage() &&
1039 "This while statement has no storage for a condition variable!");
1040
Douglas Gregor27b98ea2010-06-21 23:44:13 +00001041 if (!V) {
Bruno Riccibacf7512018-10-30 13:42:41 +00001042 getTrailingObjects<Stmt *>()[varOffset()] = nullptr;
Douglas Gregor27b98ea2010-06-21 23:44:13 +00001043 return;
1044 }
Daniel Dunbar62ee6412012-03-09 18:35:03 +00001045
1046 SourceRange VarRange = V->getSourceRange();
Bruno Riccibacf7512018-10-30 13:42:41 +00001047 getTrailingObjects<Stmt *>()[varOffset()] = new (Ctx)
1048 DeclStmt(DeclGroupRef(V), VarRange.getBegin(), VarRange.getEnd());
Douglas Gregor27b98ea2010-06-21 23:44:13 +00001049}
1050
Ted Kremenek066dd932007-08-24 21:09:09 +00001051// IndirectGotoStmt
Chris Lattnerc8e630e2011-02-17 07:39:24 +00001052LabelDecl *IndirectGotoStmt::getConstantTarget() {
Eugene Zelenko7855e772018-04-03 00:11:50 +00001053 if (auto *E = dyn_cast<AddrLabelExpr>(getTarget()->IgnoreParenImpCasts()))
John McCall9de91602010-10-28 08:53:48 +00001054 return E->getLabel();
Craig Topper36250ad2014-05-12 05:36:57 +00001055 return nullptr;
John McCall9de91602010-10-28 08:53:48 +00001056}
Ted Kremenek066dd932007-08-24 21:09:09 +00001057
Ted Kremenek066dd932007-08-24 21:09:09 +00001058// ReturnStmt
Bruno Ricci023b1d12018-10-30 14:40:49 +00001059ReturnStmt::ReturnStmt(SourceLocation RL, Expr *E, const VarDecl *NRVOCandidate)
1060 : Stmt(ReturnStmtClass), RetExpr(E) {
1061 bool HasNRVOCandidate = NRVOCandidate != nullptr;
1062 ReturnStmtBits.HasNRVOCandidate = HasNRVOCandidate;
1063 if (HasNRVOCandidate)
1064 setNRVOCandidate(NRVOCandidate);
1065 setReturnLoc(RL);
Ted Kremenekc6501db2008-06-17 03:11:08 +00001066}
Bruno Ricci023b1d12018-10-30 14:40:49 +00001067
1068ReturnStmt::ReturnStmt(EmptyShell Empty, bool HasNRVOCandidate)
1069 : Stmt(ReturnStmtClass, Empty) {
1070 ReturnStmtBits.HasNRVOCandidate = HasNRVOCandidate;
1071}
1072
1073ReturnStmt *ReturnStmt::Create(const ASTContext &Ctx, SourceLocation RL,
1074 Expr *E, const VarDecl *NRVOCandidate) {
1075 bool HasNRVOCandidate = NRVOCandidate != nullptr;
1076 void *Mem = Ctx.Allocate(totalSizeToAlloc<const VarDecl *>(HasNRVOCandidate),
1077 alignof(ReturnStmt));
1078 return new (Mem) ReturnStmt(RL, E, NRVOCandidate);
1079}
1080
1081ReturnStmt *ReturnStmt::CreateEmpty(const ASTContext &Ctx,
1082 bool HasNRVOCandidate) {
1083 void *Mem = Ctx.Allocate(totalSizeToAlloc<const VarDecl *>(HasNRVOCandidate),
1084 alignof(ReturnStmt));
1085 return new (Mem) ReturnStmt(EmptyShell(), HasNRVOCandidate);
Ted Kremenek066dd932007-08-24 21:09:09 +00001086}
John Wiegley1c0675e2011-04-28 01:08:34 +00001087
Bruno Ricci5b30571752018-10-28 12:30:53 +00001088// CaseStmt
1089CaseStmt *CaseStmt::Create(const ASTContext &Ctx, Expr *lhs, Expr *rhs,
1090 SourceLocation caseLoc, SourceLocation ellipsisLoc,
1091 SourceLocation colonLoc) {
1092 bool CaseStmtIsGNURange = rhs != nullptr;
1093 void *Mem = Ctx.Allocate(
1094 totalSizeToAlloc<Stmt *, SourceLocation>(
1095 NumMandatoryStmtPtr + CaseStmtIsGNURange, CaseStmtIsGNURange),
1096 alignof(CaseStmt));
1097 return new (Mem) CaseStmt(lhs, rhs, caseLoc, ellipsisLoc, colonLoc);
1098}
1099
1100CaseStmt *CaseStmt::CreateEmpty(const ASTContext &Ctx,
1101 bool CaseStmtIsGNURange) {
1102 void *Mem = Ctx.Allocate(
1103 totalSizeToAlloc<Stmt *, SourceLocation>(
1104 NumMandatoryStmtPtr + CaseStmtIsGNURange, CaseStmtIsGNURange),
1105 alignof(CaseStmt));
1106 return new (Mem) CaseStmt(EmptyShell(), CaseStmtIsGNURange);
1107}
1108
Eugene Zelenko1eab6c12017-11-14 23:35:42 +00001109SEHTryStmt::SEHTryStmt(bool IsCXXTry, SourceLocation TryLoc, Stmt *TryBlock,
Warren Huntf6be4cb2014-07-25 20:52:51 +00001110 Stmt *Handler)
Eugene Zelenko1eab6c12017-11-14 23:35:42 +00001111 : Stmt(SEHTryStmtClass), IsCXXTry(IsCXXTry), TryLoc(TryLoc) {
Warren Huntf6be4cb2014-07-25 20:52:51 +00001112 Children[TRY] = TryBlock;
John Wiegley1c0675e2011-04-28 01:08:34 +00001113 Children[HANDLER] = Handler;
1114}
1115
Warren Huntf6be4cb2014-07-25 20:52:51 +00001116SEHTryStmt* SEHTryStmt::Create(const ASTContext &C, bool IsCXXTry,
Craig Toppere6960e22013-08-22 05:28:54 +00001117 SourceLocation TryLoc, Stmt *TryBlock,
Warren Huntf6be4cb2014-07-25 20:52:51 +00001118 Stmt *Handler) {
1119 return new(C) SEHTryStmt(IsCXXTry,TryLoc,TryBlock,Handler);
John Wiegley1c0675e2011-04-28 01:08:34 +00001120}
1121
1122SEHExceptStmt* SEHTryStmt::getExceptHandler() const {
1123 return dyn_cast<SEHExceptStmt>(getHandler());
1124}
1125
1126SEHFinallyStmt* SEHTryStmt::getFinallyHandler() const {
1127 return dyn_cast<SEHFinallyStmt>(getHandler());
1128}
1129
Eugene Zelenko1eab6c12017-11-14 23:35:42 +00001130SEHExceptStmt::SEHExceptStmt(SourceLocation Loc, Expr *FilterExpr, Stmt *Block)
1131 : Stmt(SEHExceptStmtClass), Loc(Loc) {
Pavel Labath515f4db2013-09-03 14:41:16 +00001132 Children[FILTER_EXPR] = FilterExpr;
John Wiegley1c0675e2011-04-28 01:08:34 +00001133 Children[BLOCK] = Block;
1134}
1135
Craig Toppere6960e22013-08-22 05:28:54 +00001136SEHExceptStmt* SEHExceptStmt::Create(const ASTContext &C, SourceLocation Loc,
1137 Expr *FilterExpr, Stmt *Block) {
John Wiegley1c0675e2011-04-28 01:08:34 +00001138 return new(C) SEHExceptStmt(Loc,FilterExpr,Block);
1139}
1140
Eugene Zelenko1eab6c12017-11-14 23:35:42 +00001141SEHFinallyStmt::SEHFinallyStmt(SourceLocation Loc, Stmt *Block)
1142 : Stmt(SEHFinallyStmtClass), Loc(Loc), Block(Block) {}
John Wiegley1c0675e2011-04-28 01:08:34 +00001143
Craig Toppere6960e22013-08-22 05:28:54 +00001144SEHFinallyStmt* SEHFinallyStmt::Create(const ASTContext &C, SourceLocation Loc,
John Wiegley1c0675e2011-04-28 01:08:34 +00001145 Stmt *Block) {
1146 return new(C)SEHFinallyStmt(Loc,Block);
1147}
Tareq A. Siraj24110cc2013-04-16 18:53:08 +00001148
Samuel Antao4af1b7b2015-12-02 17:44:43 +00001149CapturedStmt::Capture::Capture(SourceLocation Loc, VariableCaptureKind Kind,
1150 VarDecl *Var)
1151 : VarAndKind(Var, Kind), Loc(Loc) {
1152 switch (Kind) {
1153 case VCK_This:
1154 assert(!Var && "'this' capture cannot have a variable!");
1155 break;
1156 case VCK_ByRef:
1157 assert(Var && "capturing by reference must have a variable!");
1158 break;
1159 case VCK_ByCopy:
1160 assert(Var && "capturing by copy must have a variable!");
1161 assert(
1162 (Var->getType()->isScalarType() || (Var->getType()->isReferenceType() &&
1163 Var->getType()
1164 ->castAs<ReferenceType>()
1165 ->getPointeeType()
1166 ->isScalarType())) &&
1167 "captures by copy are expected to have a scalar type!");
1168 break;
1169 case VCK_VLAType:
1170 assert(!Var &&
1171 "Variable-length array type capture cannot have a variable!");
1172 break;
1173 }
1174}
1175
Chandler Carruth21c90602015-12-30 03:24:14 +00001176CapturedStmt::VariableCaptureKind
1177CapturedStmt::Capture::getCaptureKind() const {
1178 return VarAndKind.getInt();
1179}
1180
1181VarDecl *CapturedStmt::Capture::getCapturedVar() const {
1182 assert((capturesVariable() || capturesVariableByCopy()) &&
1183 "No variable available for 'this' or VAT capture");
1184 return VarAndKind.getPointer();
1185}
1186
Tareq A. Siraj24110cc2013-04-16 18:53:08 +00001187CapturedStmt::Capture *CapturedStmt::getStoredCaptures() const {
1188 unsigned Size = sizeof(CapturedStmt) + sizeof(Stmt *) * (NumCaptures + 1);
1189
1190 // Offset of the first Capture object.
Benjamin Kramerc3f89252016-10-20 14:27:22 +00001191 unsigned FirstCaptureOffset = llvm::alignTo(Size, alignof(Capture));
Tareq A. Siraj24110cc2013-04-16 18:53:08 +00001192
1193 return reinterpret_cast<Capture *>(
1194 reinterpret_cast<char *>(const_cast<CapturedStmt *>(this))
1195 + FirstCaptureOffset);
1196}
1197
Wei Pan17fbf6e2013-05-04 03:59:06 +00001198CapturedStmt::CapturedStmt(Stmt *S, CapturedRegionKind Kind,
1199 ArrayRef<Capture> Captures,
Tareq A. Siraj24110cc2013-04-16 18:53:08 +00001200 ArrayRef<Expr *> CaptureInits,
Tareq A. Siraj6dfa25a2013-04-16 19:37:38 +00001201 CapturedDecl *CD,
Tareq A. Siraj24110cc2013-04-16 18:53:08 +00001202 RecordDecl *RD)
1203 : Stmt(CapturedStmtClass), NumCaptures(Captures.size()),
Wei Pan17fbf6e2013-05-04 03:59:06 +00001204 CapDeclAndKind(CD, Kind), TheRecordDecl(RD) {
Tareq A. Siraj24110cc2013-04-16 18:53:08 +00001205 assert( S && "null captured statement");
Tareq A. Siraj6dfa25a2013-04-16 19:37:38 +00001206 assert(CD && "null captured declaration for captured statement");
Tareq A. Siraj24110cc2013-04-16 18:53:08 +00001207 assert(RD && "null record declaration for captured statement");
1208
1209 // Copy initialization expressions.
1210 Stmt **Stored = getStoredStmts();
1211 for (unsigned I = 0, N = NumCaptures; I != N; ++I)
1212 *Stored++ = CaptureInits[I];
1213
1214 // Copy the statement being captured.
1215 *Stored = S;
1216
1217 // Copy all Capture objects.
1218 Capture *Buffer = getStoredCaptures();
1219 std::copy(Captures.begin(), Captures.end(), Buffer);
1220}
1221
1222CapturedStmt::CapturedStmt(EmptyShell Empty, unsigned NumCaptures)
1223 : Stmt(CapturedStmtClass, Empty), NumCaptures(NumCaptures),
Eugene Zelenko1eab6c12017-11-14 23:35:42 +00001224 CapDeclAndKind(nullptr, CR_Default) {
Craig Topper36250ad2014-05-12 05:36:57 +00001225 getStoredStmts()[NumCaptures] = nullptr;
Tareq A. Siraj24110cc2013-04-16 18:53:08 +00001226}
1227
Craig Toppere6960e22013-08-22 05:28:54 +00001228CapturedStmt *CapturedStmt::Create(const ASTContext &Context, Stmt *S,
Wei Pan17fbf6e2013-05-04 03:59:06 +00001229 CapturedRegionKind Kind,
Tareq A. Siraj24110cc2013-04-16 18:53:08 +00001230 ArrayRef<Capture> Captures,
1231 ArrayRef<Expr *> CaptureInits,
Tareq A. Siraj6dfa25a2013-04-16 19:37:38 +00001232 CapturedDecl *CD,
Tareq A. Siraj24110cc2013-04-16 18:53:08 +00001233 RecordDecl *RD) {
1234 // The layout is
1235 //
1236 // -----------------------------------------------------------
1237 // | CapturedStmt, Init, ..., Init, S, Capture, ..., Capture |
1238 // ----------------^-------------------^----------------------
1239 // getStoredStmts() getStoredCaptures()
1240 //
1241 // where S is the statement being captured.
1242 //
1243 assert(CaptureInits.size() == Captures.size() && "wrong number of arguments");
1244
1245 unsigned Size = sizeof(CapturedStmt) + sizeof(Stmt *) * (Captures.size() + 1);
1246 if (!Captures.empty()) {
1247 // Realign for the following Capture array.
Benjamin Kramerc3f89252016-10-20 14:27:22 +00001248 Size = llvm::alignTo(Size, alignof(Capture));
Tareq A. Siraj24110cc2013-04-16 18:53:08 +00001249 Size += sizeof(Capture) * Captures.size();
1250 }
1251
1252 void *Mem = Context.Allocate(Size);
Wei Pan17fbf6e2013-05-04 03:59:06 +00001253 return new (Mem) CapturedStmt(S, Kind, Captures, CaptureInits, CD, RD);
Tareq A. Siraj24110cc2013-04-16 18:53:08 +00001254}
1255
Craig Toppere6960e22013-08-22 05:28:54 +00001256CapturedStmt *CapturedStmt::CreateDeserialized(const ASTContext &Context,
Tareq A. Siraj24110cc2013-04-16 18:53:08 +00001257 unsigned NumCaptures) {
1258 unsigned Size = sizeof(CapturedStmt) + sizeof(Stmt *) * (NumCaptures + 1);
1259 if (NumCaptures > 0) {
1260 // Realign for the following Capture array.
Benjamin Kramerc3f89252016-10-20 14:27:22 +00001261 Size = llvm::alignTo(Size, alignof(Capture));
Tareq A. Siraj24110cc2013-04-16 18:53:08 +00001262 Size += sizeof(Capture) * NumCaptures;
1263 }
1264
1265 void *Mem = Context.Allocate(Size);
1266 return new (Mem) CapturedStmt(EmptyShell(), NumCaptures);
1267}
1268
1269Stmt::child_range CapturedStmt::children() {
Simon Pilgrim2c518802017-03-30 14:13:19 +00001270 // Children are captured field initializers.
Tareq A. Siraj6dfa25a2013-04-16 19:37:38 +00001271 return child_range(getStoredStmts(), getStoredStmts() + NumCaptures);
Tareq A. Siraj24110cc2013-04-16 18:53:08 +00001272}
1273
Bruno Ricci06186502019-04-12 15:36:02 +00001274Stmt::const_child_range CapturedStmt::children() const {
1275 return const_child_range(getStoredStmts(), getStoredStmts() + NumCaptures);
1276}
1277
Chandler Carruth21c90602015-12-30 03:24:14 +00001278CapturedDecl *CapturedStmt::getCapturedDecl() {
1279 return CapDeclAndKind.getPointer();
1280}
Eugene Zelenko1eab6c12017-11-14 23:35:42 +00001281
Chandler Carruth21c90602015-12-30 03:24:14 +00001282const CapturedDecl *CapturedStmt::getCapturedDecl() const {
1283 return CapDeclAndKind.getPointer();
1284}
1285
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001286/// Set the outlined function declaration.
Chandler Carruth21c90602015-12-30 03:24:14 +00001287void CapturedStmt::setCapturedDecl(CapturedDecl *D) {
1288 assert(D && "null CapturedDecl");
1289 CapDeclAndKind.setPointer(D);
1290}
1291
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001292/// Retrieve the captured region kind.
Chandler Carruth21c90602015-12-30 03:24:14 +00001293CapturedRegionKind CapturedStmt::getCapturedRegionKind() const {
1294 return CapDeclAndKind.getInt();
1295}
1296
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001297/// Set the captured region kind.
Chandler Carruth21c90602015-12-30 03:24:14 +00001298void CapturedStmt::setCapturedRegionKind(CapturedRegionKind Kind) {
1299 CapDeclAndKind.setInt(Kind);
1300}
1301
Tareq A. Siraj24110cc2013-04-16 18:53:08 +00001302bool CapturedStmt::capturesVariable(const VarDecl *Var) const {
Aaron Ballmanc656303a2014-03-14 18:08:33 +00001303 for (const auto &I : captures()) {
Alexey Bataev2c845412017-05-15 16:26:15 +00001304 if (!I.capturesVariable() && !I.capturesVariableByCopy())
Tareq A. Siraj24110cc2013-04-16 18:53:08 +00001305 continue;
Alexey Bataeve85de8f2017-09-20 20:11:31 +00001306 if (I.getCapturedVar()->getCanonicalDecl() == Var->getCanonicalDecl())
Tareq A. Siraj24110cc2013-04-16 18:53:08 +00001307 return true;
1308 }
1309
1310 return false;
1311}