blob: bdfaf410131cc4d64d6ed60b823f4b043190dbae [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"
Mark de Wever08196e02020-09-09 19:12:32 +020016#include "clang/AST/Attr.h"
Eugene Zelenko1eab6c12017-11-14 23:35:42 +000017#include "clang/AST/Decl.h"
18#include "clang/AST/DeclGroup.h"
Eugene Zelenko7855e772018-04-03 00:11:50 +000019#include "clang/AST/Expr.h"
Chris Lattner29375652006-12-04 18:06:35 +000020#include "clang/AST/ExprCXX.h"
Mark de Wever08196e02020-09-09 19:12:32 +020021#include "clang/AST/ExprConcepts.h"
Steve Naroff021ca182008-05-29 21:12:08 +000022#include "clang/AST/ExprObjC.h"
Alexey Bataev1a3320e2015-08-25 14:24:04 +000023#include "clang/AST/ExprOpenMP.h"
Chris Lattnerf0b64d72009-04-26 01:32:48 +000024#include "clang/AST/StmtCXX.h"
25#include "clang/AST/StmtObjC.h"
Alexey Bataev5ec3eb12013-07-19 03:13:43 +000026#include "clang/AST/StmtOpenMP.h"
Sebastian Redl54c04d42008-12-22 19:15:10 +000027#include "clang/AST/Type.h"
Jordan Rosea7d03842013-02-08 22:30:41 +000028#include "clang/Basic/CharInfo.h"
Eugene Zelenko1eab6c12017-11-14 23:35:42 +000029#include "clang/Basic/LLVM.h"
30#include "clang/Basic/SourceLocation.h"
Chris Lattner1a8f3942010-04-23 16:29:58 +000031#include "clang/Basic/TargetInfo.h"
Benjamin Kramer444a1302012-12-01 17:12:56 +000032#include "clang/Lex/Token.h"
Eugene Zelenko1eab6c12017-11-14 23:35:42 +000033#include "llvm/ADT/SmallVector.h"
Chad Rosier14836ba2012-08-24 17:05:45 +000034#include "llvm/ADT/StringExtras.h"
Eugene Zelenko1eab6c12017-11-14 23:35:42 +000035#include "llvm/ADT/StringRef.h"
36#include "llvm/Support/Casting.h"
37#include "llvm/Support/Compiler.h"
38#include "llvm/Support/ErrorHandling.h"
39#include "llvm/Support/MathExtras.h"
Chandler Carruthbfb154a2011-07-04 06:13:27 +000040#include "llvm/Support/raw_ostream.h"
Eugene Zelenko1eab6c12017-11-14 23:35:42 +000041#include <algorithm>
42#include <cassert>
43#include <cstring>
44#include <string>
Bruno Riccic397a262019-08-27 11:35:49 +000045#include <type_traits>
Mark de Wever08196e02020-09-09 19:12:32 +020046#include <utility>
Eugene Zelenko1eab6c12017-11-14 23:35:42 +000047
Chris Lattnerf42cce72006-10-25 04:09:21 +000048using namespace clang;
49
Steve Narofff84d11f2007-05-23 21:48:04 +000050static struct StmtClassNameTable {
Chris Lattner4d15a0d2007-08-25 01:42:24 +000051 const char *Name;
52 unsigned Counter;
53 unsigned Size;
Alexis Hunt656bb312010-05-05 15:24:00 +000054} StmtClassInfo[Stmt::lastStmtConstant+1];
Chris Lattner4d15a0d2007-08-25 01:42:24 +000055
56static StmtClassNameTable &getStmtInfoTableEntry(Stmt::StmtClass E) {
57 static bool Initialized = false;
58 if (Initialized)
59 return StmtClassInfo[E];
60
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +000061 // Initialize the table on the first use.
Chris Lattner4d15a0d2007-08-25 01:42:24 +000062 Initialized = true;
Alexis Huntabb2ac82010-05-18 06:22:21 +000063#define ABSTRACT_STMT(STMT)
Douglas Gregorbe35ce92008-11-14 12:46:07 +000064#define STMT(CLASS, PARENT) \
65 StmtClassInfo[(unsigned)Stmt::CLASS##Class].Name = #CLASS; \
66 StmtClassInfo[(unsigned)Stmt::CLASS##Class].Size = sizeof(CLASS);
Alexis Hunt656bb312010-05-05 15:24:00 +000067#include "clang/AST/StmtNodes.inc"
Nico Weberde565e32008-08-05 23:15:29 +000068
Chris Lattner4d15a0d2007-08-25 01:42:24 +000069 return StmtClassInfo[E];
70}
71
Craig Topper37932912013-08-18 10:09:15 +000072void *Stmt::operator new(size_t bytes, const ASTContext& C,
Craig Topper5a050012013-08-18 17:45:38 +000073 unsigned alignment) {
Benjamin Kramerea70eb32012-12-01 15:09:41 +000074 return ::operator new(bytes, C, alignment);
75}
76
Steve Narofff1e53692007-03-23 22:27:02 +000077const char *Stmt::getStmtClassName() const {
John McCall925b16622010-10-26 08:39:16 +000078 return getStmtInfoTableEntry((StmtClass) StmtBits.sClass).Name;
Steve Narofff1e53692007-03-23 22:27:02 +000079}
Steve Narofff84d11f2007-05-23 21:48:04 +000080
Bruno Ricci65034b82018-12-04 16:04:19 +000081// Check that no statement / expression class is polymorphic. LLVM style RTTI
82// should be used instead. If absolutely needed an exception can still be added
83// here by defining the appropriate macro (but please don't do this).
84#define STMT(CLASS, PARENT) \
85 static_assert(!std::is_polymorphic<CLASS>::value, \
86 #CLASS " should not be polymorphic!");
87#include "clang/AST/StmtNodes.inc"
88
Bruno Riccic397a262019-08-27 11:35:49 +000089// Check that no statement / expression class has a non-trival destructor.
90// Statements and expressions are allocated with the BumpPtrAllocator from
91// ASTContext and therefore their destructor is not executed.
92#define STMT(CLASS, PARENT) \
93 static_assert(std::is_trivially_destructible<CLASS>::value, \
94 #CLASS " should be trivially destructible!");
95// FIXME: InitListExpr is not trivially destructible due to its ASTVector.
96#define INITLISTEXPR(CLASS, PARENT)
97#include "clang/AST/StmtNodes.inc"
98
Steve Narofff84d11f2007-05-23 21:48:04 +000099void Stmt::PrintStats() {
Chris Lattner4d15a0d2007-08-25 01:42:24 +0000100 // Ensure the table is primed.
101 getStmtInfoTableEntry(Stmt::NullStmtClass);
Nico Weberde565e32008-08-05 23:15:29 +0000102
Steve Narofff84d11f2007-05-23 21:48:04 +0000103 unsigned sum = 0;
Chandler Carruthbfb154a2011-07-04 06:13:27 +0000104 llvm::errs() << "\n*** Stmt/Expr Stats:\n";
Alexis Hunt656bb312010-05-05 15:24:00 +0000105 for (int i = 0; i != Stmt::lastStmtConstant+1; i++) {
Craig Topper36250ad2014-05-12 05:36:57 +0000106 if (StmtClassInfo[i].Name == nullptr) continue;
Chris Lattner4d15a0d2007-08-25 01:42:24 +0000107 sum += StmtClassInfo[i].Counter;
Steve Narofff84d11f2007-05-23 21:48:04 +0000108 }
Chandler Carruthbfb154a2011-07-04 06:13:27 +0000109 llvm::errs() << " " << sum << " stmts/exprs total.\n";
Steve Narofff84d11f2007-05-23 21:48:04 +0000110 sum = 0;
Alexis Hunt656bb312010-05-05 15:24:00 +0000111 for (int i = 0; i != Stmt::lastStmtConstant+1; i++) {
Craig Topper36250ad2014-05-12 05:36:57 +0000112 if (StmtClassInfo[i].Name == nullptr) continue;
Douglas Gregora30d0462009-05-26 14:40:08 +0000113 if (StmtClassInfo[i].Counter == 0) continue;
Chandler Carruthbfb154a2011-07-04 06:13:27 +0000114 llvm::errs() << " " << StmtClassInfo[i].Counter << " "
115 << StmtClassInfo[i].Name << ", " << StmtClassInfo[i].Size
116 << " each (" << StmtClassInfo[i].Counter*StmtClassInfo[i].Size
117 << " bytes)\n";
Chris Lattner4d15a0d2007-08-25 01:42:24 +0000118 sum += StmtClassInfo[i].Counter*StmtClassInfo[i].Size;
Steve Narofff84d11f2007-05-23 21:48:04 +0000119 }
Chandler Carruthbfb154a2011-07-04 06:13:27 +0000120
121 llvm::errs() << "Total bytes = " << sum << "\n";
Steve Narofff84d11f2007-05-23 21:48:04 +0000122}
123
124void Stmt::addStmtClass(StmtClass s) {
Chris Lattner4d15a0d2007-08-25 01:42:24 +0000125 ++getStmtInfoTableEntry(s).Counter;
Steve Narofff84d11f2007-05-23 21:48:04 +0000126}
127
Daniel Dunbar62905572012-03-05 21:42:49 +0000128bool Stmt::StatisticsEnabled = false;
129void Stmt::EnableStatistics() {
130 StatisticsEnabled = true;
Steve Narofff84d11f2007-05-23 21:48:04 +0000131}
132
Mark de Wever08196e02020-09-09 19:12:32 +0200133static std::pair<Stmt::Likelihood, const Attr *> getLikelihood(const Stmt *S) {
134 if (const auto *AS = dyn_cast_or_null<AttributedStmt>(S))
135 for (const auto *A : AS->getAttrs()) {
136 if (isa<LikelyAttr>(A))
137 return std::make_pair(Stmt::LH_Likely, A);
138
139 if (isa<UnlikelyAttr>(A))
140 return std::make_pair(Stmt::LH_Unlikely, A);
141 }
142
143 return std::make_pair(Stmt::LH_None, nullptr);
144}
145
146Stmt::Likelihood Stmt::getLikelihood(const Stmt *S) {
147 return ::getLikelihood(S).first;
148}
149
150Stmt::Likelihood Stmt::getLikelihood(const Stmt *Then, const Stmt *Else) {
151 Likelihood LHT = ::getLikelihood(Then).first;
152 Likelihood LHE = ::getLikelihood(Else).first;
153 if (LHE == LH_None)
154 return LHT;
155
156 // If the same attribute is used on both branches there's a conflict.
157 if (LHT == LHE)
158 return LH_None;
159
160 if (LHT != LH_None)
161 return LHT;
162
163 // Invert the value of Else to get the value for Then.
164 return LHE == LH_Likely ? LH_Unlikely : LH_Likely;
165}
166
167std::tuple<bool, const Attr *, const Attr *>
168Stmt::determineLikelihoodConflict(const Stmt *Then, const Stmt *Else) {
169 std::pair<Likelihood, const Attr *> LHT = ::getLikelihood(Then);
170 std::pair<Likelihood, const Attr *> LHE = ::getLikelihood(Else);
171 // If the same attribute is used on both branches there's a conflict.
172 if (LHT.first != LH_None && LHT.first == LHE.first)
173 return std::make_tuple(true, LHT.second, LHE.second);
174
175 return std::make_tuple(false, nullptr, nullptr);
176}
177
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000178/// Skip no-op (attributed, compound) container stmts and skip captured
Alexander Musmana5f070a2014-10-01 06:03:56 +0000179/// stmt at the top, if \a IgnoreCaptured is true.
180Stmt *Stmt::IgnoreContainers(bool IgnoreCaptured) {
181 Stmt *S = this;
182 if (IgnoreCaptured)
183 if (auto CapS = dyn_cast_or_null<CapturedStmt>(S))
184 S = CapS->getCapturedStmt();
185 while (true) {
186 if (auto AS = dyn_cast_or_null<AttributedStmt>(S))
187 S = AS->getSubStmt();
188 else if (auto CS = dyn_cast_or_null<CompoundStmt>(S)) {
189 if (CS->size() != 1)
190 break;
191 S = CS->body_back();
192 } else
193 break;
194 }
195 return S;
196}
197
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000198/// Strip off all label-like statements.
Chandler Carrutha626d642011-09-10 00:02:34 +0000199///
Richard Smithc202b282012-04-14 00:33:13 +0000200/// This will strip off label statements, case statements, attributed
201/// statements and default statements recursively.
Chandler Carrutha626d642011-09-10 00:02:34 +0000202const Stmt *Stmt::stripLabelLikeStatements() const {
203 const Stmt *S = this;
204 while (true) {
Eugene Zelenko7855e772018-04-03 00:11:50 +0000205 if (const auto *LS = dyn_cast<LabelStmt>(S))
Chandler Carrutha626d642011-09-10 00:02:34 +0000206 S = LS->getSubStmt();
Eugene Zelenko7855e772018-04-03 00:11:50 +0000207 else if (const auto *SC = dyn_cast<SwitchCase>(S))
Chandler Carrutha626d642011-09-10 00:02:34 +0000208 S = SC->getSubStmt();
Eugene Zelenko7855e772018-04-03 00:11:50 +0000209 else if (const auto *AS = dyn_cast<AttributedStmt>(S))
Richard Smithc202b282012-04-14 00:33:13 +0000210 S = AS->getSubStmt();
Chandler Carrutha626d642011-09-10 00:02:34 +0000211 else
212 return S;
213 }
214}
215
John McCallbd066782011-02-09 08:16:59 +0000216namespace {
Eugene Zelenko1eab6c12017-11-14 23:35:42 +0000217
John McCallbd066782011-02-09 08:16:59 +0000218 struct good {};
219 struct bad {};
John McCallf75152f2011-02-09 08:31:17 +0000220
221 // These silly little functions have to be static inline to suppress
222 // unused warnings, and they have to be defined to suppress other
223 // warnings.
Eugene Zelenko7855e772018-04-03 00:11:50 +0000224 static good is_good(good) { return good(); }
John McCallbd066782011-02-09 08:16:59 +0000225
226 typedef Stmt::child_range children_t();
Nick Lewyckybae992f2011-02-09 08:42:57 +0000227 template <class T> good implements_children(children_t T::*) {
228 return good();
229 }
Eli Friedmandc41d792013-09-10 22:57:15 +0000230 LLVM_ATTRIBUTE_UNUSED
Eugene Zelenko7855e772018-04-03 00:11:50 +0000231 static bad implements_children(children_t Stmt::*) {
Nick Lewyckybae992f2011-02-09 08:42:57 +0000232 return bad();
233 }
John McCallbd066782011-02-09 08:16:59 +0000234
Stephen Kellyf2ceec42018-08-09 21:08:08 +0000235 typedef SourceLocation getBeginLoc_t() const;
236 template <class T> good implements_getBeginLoc(getBeginLoc_t T::*) {
Nick Lewyckybae992f2011-02-09 08:42:57 +0000237 return good();
238 }
Eli Friedmandc41d792013-09-10 22:57:15 +0000239 LLVM_ATTRIBUTE_UNUSED
Stephen Kellyf2ceec42018-08-09 21:08:08 +0000240 static bad implements_getBeginLoc(getBeginLoc_t Stmt::*) { return bad(); }
Erik Verbruggen11a2ecc2012-12-25 14:51:39 +0000241
242 typedef SourceLocation getLocEnd_t() const;
Stephen Kelly1c301dc2018-08-09 21:09:38 +0000243 template <class T> good implements_getEndLoc(getLocEnd_t T::*) {
Erik Verbruggen11a2ecc2012-12-25 14:51:39 +0000244 return good();
245 }
Eli Friedmandc41d792013-09-10 22:57:15 +0000246 LLVM_ATTRIBUTE_UNUSED
Stephen Kelly1c301dc2018-08-09 21:09:38 +0000247 static bad implements_getEndLoc(getLocEnd_t Stmt::*) { return bad(); }
John McCallbd066782011-02-09 08:16:59 +0000248
249#define ASSERT_IMPLEMENTS_children(type) \
Eli Friedmandc41d792013-09-10 22:57:15 +0000250 (void) is_good(implements_children(&type::children))
Stephen Kellyf2ceec42018-08-09 21:08:08 +0000251#define ASSERT_IMPLEMENTS_getBeginLoc(type) \
252 (void)is_good(implements_getBeginLoc(&type::getBeginLoc))
Stephen Kelly1c301dc2018-08-09 21:09:38 +0000253#define ASSERT_IMPLEMENTS_getEndLoc(type) \
254 (void)is_good(implements_getEndLoc(&type::getEndLoc))
Eugene Zelenko1eab6c12017-11-14 23:35:42 +0000255
256} // namespace
John McCallbd066782011-02-09 08:16:59 +0000257
258/// Check whether the various Stmt classes implement their member
259/// functions.
Eli Friedmandc41d792013-09-10 22:57:15 +0000260LLVM_ATTRIBUTE_UNUSED
John McCallbd066782011-02-09 08:16:59 +0000261static inline void check_implementations() {
262#define ABSTRACT_STMT(type)
Stephen Kellyf2ceec42018-08-09 21:08:08 +0000263#define STMT(type, base) \
264 ASSERT_IMPLEMENTS_children(type); \
265 ASSERT_IMPLEMENTS_getBeginLoc(type); \
Stephen Kelly1c301dc2018-08-09 21:09:38 +0000266 ASSERT_IMPLEMENTS_getEndLoc(type);
John McCallbd066782011-02-09 08:16:59 +0000267#include "clang/AST/StmtNodes.inc"
268}
269
270Stmt::child_range Stmt::children() {
271 switch (getStmtClass()) {
272 case Stmt::NoStmtClass: llvm_unreachable("statement without class");
273#define ABSTRACT_STMT(type)
274#define STMT(type, base) \
275 case Stmt::type##Class: \
276 return static_cast<type*>(this)->children();
277#include "clang/AST/StmtNodes.inc"
278 }
279 llvm_unreachable("unknown statement kind!");
John McCallbd066782011-02-09 08:16:59 +0000280}
281
Erik Verbruggen11a2ecc2012-12-25 14:51:39 +0000282// Amusing macro metaprogramming hack: check whether a class provides
283// a more specific implementation of getSourceRange.
284//
285// See also Expr.cpp:getExprLoc().
286namespace {
Eugene Zelenko1eab6c12017-11-14 23:35:42 +0000287
Erik Verbruggen11a2ecc2012-12-25 14:51:39 +0000288 /// This implementation is used when a class provides a custom
289 /// implementation of getSourceRange.
290 template <class S, class T>
291 SourceRange getSourceRangeImpl(const Stmt *stmt,
292 SourceRange (T::*v)() const) {
293 return static_cast<const S*>(stmt)->getSourceRange();
294 }
295
296 /// This implementation is used when a class doesn't provide a custom
297 /// implementation of getSourceRange. Overload resolution should pick it over
298 /// the implementation above because it's more specialized according to
299 /// function template partial ordering.
300 template <class S>
301 SourceRange getSourceRangeImpl(const Stmt *stmt,
302 SourceRange (Stmt::*v)() const) {
Stephen Kellyf2ceec42018-08-09 21:08:08 +0000303 return SourceRange(static_cast<const S *>(stmt)->getBeginLoc(),
Stephen Kelly1c301dc2018-08-09 21:09:38 +0000304 static_cast<const S *>(stmt)->getEndLoc());
Erik Verbruggen11a2ecc2012-12-25 14:51:39 +0000305 }
Eugene Zelenko1eab6c12017-11-14 23:35:42 +0000306
307} // namespace
Erik Verbruggen11a2ecc2012-12-25 14:51:39 +0000308
John McCallbd066782011-02-09 08:16:59 +0000309SourceRange Stmt::getSourceRange() const {
310 switch (getStmtClass()) {
311 case Stmt::NoStmtClass: llvm_unreachable("statement without class");
312#define ABSTRACT_STMT(type)
313#define STMT(type, base) \
314 case Stmt::type##Class: \
Erik Verbruggen11a2ecc2012-12-25 14:51:39 +0000315 return getSourceRangeImpl<type>(this, &type::getSourceRange);
John McCallbd066782011-02-09 08:16:59 +0000316#include "clang/AST/StmtNodes.inc"
317 }
318 llvm_unreachable("unknown statement kind!");
John McCallbd066782011-02-09 08:16:59 +0000319}
320
Stephen Kelly724e9e52018-08-09 20:05:03 +0000321SourceLocation Stmt::getBeginLoc() const {
Daniel Dunbarb0ab5e92012-03-09 15:39:19 +0000322 switch (getStmtClass()) {
323 case Stmt::NoStmtClass: llvm_unreachable("statement without class");
324#define ABSTRACT_STMT(type)
Stephen Kellyf2ceec42018-08-09 21:08:08 +0000325#define STMT(type, base) \
326 case Stmt::type##Class: \
327 return static_cast<const type *>(this)->getBeginLoc();
Daniel Dunbarb0ab5e92012-03-09 15:39:19 +0000328#include "clang/AST/StmtNodes.inc"
329 }
330 llvm_unreachable("unknown statement kind");
331}
332
Stephen Kelly02a67ba2018-08-09 20:05:47 +0000333SourceLocation Stmt::getEndLoc() const {
Daniel Dunbarb0ab5e92012-03-09 15:39:19 +0000334 switch (getStmtClass()) {
335 case Stmt::NoStmtClass: llvm_unreachable("statement without class");
336#define ABSTRACT_STMT(type)
Stephen Kelly1c301dc2018-08-09 21:09:38 +0000337#define STMT(type, base) \
338 case Stmt::type##Class: \
339 return static_cast<const type *>(this)->getEndLoc();
Daniel Dunbarb0ab5e92012-03-09 15:39:19 +0000340#include "clang/AST/StmtNodes.inc"
341 }
342 llvm_unreachable("unknown statement kind");
343}
344
George Karpenkov5eb4cc62018-09-15 02:01:47 +0000345int64_t Stmt::getID(const ASTContext &Context) const {
Artem Dergachev057647d2018-12-03 22:19:05 +0000346 return Context.getAllocator().identifyKnownAlignedObject<Stmt>(this);
George Karpenkov5eb4cc62018-09-15 02:01:47 +0000347}
348
Benjamin Kramer07420902017-12-24 16:24:20 +0000349CompoundStmt::CompoundStmt(ArrayRef<Stmt *> Stmts, SourceLocation LB,
350 SourceLocation RB)
Bruno Ricci41d11c02018-10-27 18:43:27 +0000351 : Stmt(CompoundStmtClass), RBraceLoc(RB) {
Nico Webera2a0eb92012-12-29 20:03:39 +0000352 CompoundStmtBits.NumStmts = Stmts.size();
Benjamin Kramer07420902017-12-24 16:24:20 +0000353 setStmts(Stmts);
Bruno Ricci41d11c02018-10-27 18:43:27 +0000354 CompoundStmtBits.LBraceLoc = LB;
Benjamin Kramere2a929d2012-07-04 17:03:41 +0000355}
356
Benjamin Kramer07420902017-12-24 16:24:20 +0000357void CompoundStmt::setStmts(ArrayRef<Stmt *> Stmts) {
Craig Topper9ee84ad2015-12-04 05:01:44 +0000358 assert(CompoundStmtBits.NumStmts == Stmts.size() &&
359 "NumStmts doesn't fit in bits of CompoundStmtBits.NumStmts!");
Douglas Gregora9af1d12009-04-17 00:04:06 +0000360
Benjamin Kramer07420902017-12-24 16:24:20 +0000361 std::copy(Stmts.begin(), Stmts.end(), body_begin());
362}
363
364CompoundStmt *CompoundStmt::Create(const ASTContext &C, ArrayRef<Stmt *> Stmts,
365 SourceLocation LB, SourceLocation RB) {
366 void *Mem =
367 C.Allocate(totalSizeToAlloc<Stmt *>(Stmts.size()), alignof(CompoundStmt));
368 return new (Mem) CompoundStmt(Stmts, LB, RB);
369}
370
371CompoundStmt *CompoundStmt::CreateEmpty(const ASTContext &C,
372 unsigned NumStmts) {
373 void *Mem =
374 C.Allocate(totalSizeToAlloc<Stmt *>(NumStmts), alignof(CompoundStmt));
375 CompoundStmt *New = new (Mem) CompoundStmt(EmptyShell());
376 New->CompoundStmtBits.NumStmts = NumStmts;
377 return New;
Douglas Gregora9af1d12009-04-17 00:04:06 +0000378}
Steve Narofff84d11f2007-05-23 21:48:04 +0000379
Richard Smitha6e8d5e2019-02-15 00:27:53 +0000380const Expr *ValueStmt::getExprStmt() const {
381 const Stmt *S = this;
382 do {
383 if (const auto *E = dyn_cast<Expr>(S))
384 return E;
385
386 if (const auto *LS = dyn_cast<LabelStmt>(S))
387 S = LS->getSubStmt();
388 else if (const auto *AS = dyn_cast<AttributedStmt>(S))
389 S = AS->getSubStmt();
390 else
391 llvm_unreachable("unknown kind of ValueStmt");
392 } while (isa<ValueStmt>(S));
393
394 return nullptr;
395}
396
Chris Lattnereefa10e2007-05-28 06:56:27 +0000397const char *LabelStmt::getName() const {
Chris Lattnerc8e630e2011-02-17 07:39:24 +0000398 return getDecl()->getIdentifier()->getNameStart();
Chris Lattnereefa10e2007-05-28 06:56:27 +0000399}
400
Craig Toppere6960e22013-08-22 05:28:54 +0000401AttributedStmt *AttributedStmt::Create(const ASTContext &C, SourceLocation Loc,
Alexander Kornienko20f6fc62012-07-09 10:04:07 +0000402 ArrayRef<const Attr*> Attrs,
403 Stmt *SubStmt) {
Aaron Ballmanf3d9b092014-05-13 14:55:01 +0000404 assert(!Attrs.empty() && "Attrs should not be empty");
Benjamin Kramer917fdbe2017-12-24 16:24:11 +0000405 void *Mem = C.Allocate(totalSizeToAlloc<const Attr *>(Attrs.size()),
Benjamin Kramerc3f89252016-10-20 14:27:22 +0000406 alignof(AttributedStmt));
Alexander Kornienko20f6fc62012-07-09 10:04:07 +0000407 return new (Mem) AttributedStmt(Loc, Attrs, SubStmt);
408}
409
Craig Toppere6960e22013-08-22 05:28:54 +0000410AttributedStmt *AttributedStmt::CreateEmpty(const ASTContext &C,
411 unsigned NumAttrs) {
Alexander Kornienko20f6fc62012-07-09 10:04:07 +0000412 assert(NumAttrs > 0 && "NumAttrs should be greater than zero");
Benjamin Kramer917fdbe2017-12-24 16:24:11 +0000413 void *Mem = C.Allocate(totalSizeToAlloc<const Attr *>(NumAttrs),
Benjamin Kramerc3f89252016-10-20 14:27:22 +0000414 alignof(AttributedStmt));
Alexander Kornienko20f6fc62012-07-09 10:04:07 +0000415 return new (Mem) AttributedStmt(EmptyShell(), NumAttrs);
416}
417
Craig Topperc571c812013-08-22 06:02:26 +0000418std::string AsmStmt::generateAsmString(const ASTContext &C) const {
Eugene Zelenko7855e772018-04-03 00:11:50 +0000419 if (const auto *gccAsmStmt = dyn_cast<GCCAsmStmt>(this))
Chad Rosierf70b7e22012-08-28 18:21:14 +0000420 return gccAsmStmt->generateAsmString(C);
Eugene Zelenko7855e772018-04-03 00:11:50 +0000421 if (const auto *msAsmStmt = dyn_cast<MSAsmStmt>(this))
Chad Rosierf70b7e22012-08-28 18:21:14 +0000422 return msAsmStmt->generateAsmString(C);
Chad Rosierbbbe9ab2012-08-28 17:43:23 +0000423 llvm_unreachable("unknown asm statement kind!");
424}
425
426StringRef AsmStmt::getOutputConstraint(unsigned i) const {
Eugene Zelenko7855e772018-04-03 00:11:50 +0000427 if (const auto *gccAsmStmt = dyn_cast<GCCAsmStmt>(this))
Chad Rosierf70b7e22012-08-28 18:21:14 +0000428 return gccAsmStmt->getOutputConstraint(i);
Eugene Zelenko7855e772018-04-03 00:11:50 +0000429 if (const auto *msAsmStmt = dyn_cast<MSAsmStmt>(this))
Chad Rosierf70b7e22012-08-28 18:21:14 +0000430 return msAsmStmt->getOutputConstraint(i);
Chad Rosierbbbe9ab2012-08-28 17:43:23 +0000431 llvm_unreachable("unknown asm statement kind!");
432}
433
434const Expr *AsmStmt::getOutputExpr(unsigned i) const {
Eugene Zelenko7855e772018-04-03 00:11:50 +0000435 if (const auto *gccAsmStmt = dyn_cast<GCCAsmStmt>(this))
Chad Rosierf70b7e22012-08-28 18:21:14 +0000436 return gccAsmStmt->getOutputExpr(i);
Eugene Zelenko7855e772018-04-03 00:11:50 +0000437 if (const auto *msAsmStmt = dyn_cast<MSAsmStmt>(this))
Chad Rosierf70b7e22012-08-28 18:21:14 +0000438 return msAsmStmt->getOutputExpr(i);
Chad Rosierbbbe9ab2012-08-28 17:43:23 +0000439 llvm_unreachable("unknown asm statement kind!");
440}
441
442StringRef AsmStmt::getInputConstraint(unsigned i) const {
Eugene Zelenko7855e772018-04-03 00:11:50 +0000443 if (const auto *gccAsmStmt = dyn_cast<GCCAsmStmt>(this))
Chad Rosierf70b7e22012-08-28 18:21:14 +0000444 return gccAsmStmt->getInputConstraint(i);
Eugene Zelenko7855e772018-04-03 00:11:50 +0000445 if (const auto *msAsmStmt = dyn_cast<MSAsmStmt>(this))
Chad Rosierf70b7e22012-08-28 18:21:14 +0000446 return msAsmStmt->getInputConstraint(i);
Chad Rosierbbbe9ab2012-08-28 17:43:23 +0000447 llvm_unreachable("unknown asm statement kind!");
448}
449
450const Expr *AsmStmt::getInputExpr(unsigned i) const {
Eugene Zelenko7855e772018-04-03 00:11:50 +0000451 if (const auto *gccAsmStmt = dyn_cast<GCCAsmStmt>(this))
Chad Rosierf70b7e22012-08-28 18:21:14 +0000452 return gccAsmStmt->getInputExpr(i);
Eugene Zelenko7855e772018-04-03 00:11:50 +0000453 if (const auto *msAsmStmt = dyn_cast<MSAsmStmt>(this))
Chad Rosierf70b7e22012-08-28 18:21:14 +0000454 return msAsmStmt->getInputExpr(i);
Chad Rosierbbbe9ab2012-08-28 17:43:23 +0000455 llvm_unreachable("unknown asm statement kind!");
456}
457
458StringRef AsmStmt::getClobber(unsigned i) const {
Eugene Zelenko7855e772018-04-03 00:11:50 +0000459 if (const auto *gccAsmStmt = dyn_cast<GCCAsmStmt>(this))
Chad Rosierf70b7e22012-08-28 18:21:14 +0000460 return gccAsmStmt->getClobber(i);
Eugene Zelenko7855e772018-04-03 00:11:50 +0000461 if (const auto *msAsmStmt = dyn_cast<MSAsmStmt>(this))
Chad Rosierf70b7e22012-08-28 18:21:14 +0000462 return msAsmStmt->getClobber(i);
Chad Rosierbbbe9ab2012-08-28 17:43:23 +0000463 llvm_unreachable("unknown asm statement kind!");
464}
465
Chad Rosiera1b5c8c2012-08-28 00:24:05 +0000466/// getNumPlusOperands - Return the number of output operands that have a "+"
467/// constraint.
468unsigned AsmStmt::getNumPlusOperands() const {
469 unsigned Res = 0;
470 for (unsigned i = 0, e = getNumOutputs(); i != e; ++i)
471 if (isOutputPlusConstraint(i))
472 ++Res;
473 return Res;
474}
475
Akira Hatanaka987f1862014-08-22 06:05:21 +0000476char GCCAsmStmt::AsmStringPiece::getModifier() const {
477 assert(isOperand() && "Only Operands can have modifiers.");
478 return isLetter(Str[0]) ? Str[0] : '\0';
479}
480
Chad Rosier6100ae12012-08-27 23:47:56 +0000481StringRef GCCAsmStmt::getClobber(unsigned i) const {
482 return getClobberStringLiteral(i)->getString();
483}
484
Chad Rosierde70e0e2012-08-25 00:11:56 +0000485Expr *GCCAsmStmt::getOutputExpr(unsigned i) {
Ted Kremenek5778acf2008-10-27 18:40:21 +0000486 return cast<Expr>(Exprs[i]);
487}
Chris Lattner72bbf172009-03-10 04:59:06 +0000488
489/// getOutputConstraint - Return the constraint string for the specified
490/// output operand. All output constraints are known to be non-empty (either
491/// '=' or '+').
Chad Rosierde70e0e2012-08-25 00:11:56 +0000492StringRef GCCAsmStmt::getOutputConstraint(unsigned i) const {
Anders Carlsson66de0812010-01-30 20:38:10 +0000493 return getOutputConstraintLiteral(i)->getString();
Ted Kremenek5778acf2008-10-27 18:40:21 +0000494}
Chris Lattner72bbf172009-03-10 04:59:06 +0000495
Chad Rosierde70e0e2012-08-25 00:11:56 +0000496Expr *GCCAsmStmt::getInputExpr(unsigned i) {
Ted Kremenek5778acf2008-10-27 18:40:21 +0000497 return cast<Expr>(Exprs[i + NumOutputs]);
498}
Eugene Zelenko1eab6c12017-11-14 23:35:42 +0000499
Chad Rosierde70e0e2012-08-25 00:11:56 +0000500void GCCAsmStmt::setInputExpr(unsigned i, Expr *E) {
Chris Lattner93ede022011-02-21 22:09:29 +0000501 Exprs[i + NumOutputs] = E;
502}
503
Jennifer Yub8fee672019-06-03 15:57:25 +0000504AddrLabelExpr *GCCAsmStmt::getLabelExpr(unsigned i) const {
Bill Wendling50cac242020-02-24 18:32:50 -0800505 return cast<AddrLabelExpr>(Exprs[i + NumOutputs + NumInputs]);
Jennifer Yub8fee672019-06-03 15:57:25 +0000506}
507
508StringRef GCCAsmStmt::getLabelName(unsigned i) const {
509 return getLabelExpr(i)->getLabel()->getName();
510}
511
Chris Lattner72bbf172009-03-10 04:59:06 +0000512/// getInputConstraint - Return the specified input constraint. Unlike output
513/// constraints, these can be empty.
Chad Rosierde70e0e2012-08-25 00:11:56 +0000514StringRef GCCAsmStmt::getInputConstraint(unsigned i) const {
Anders Carlsson66de0812010-01-30 20:38:10 +0000515 return getInputConstraintLiteral(i)->getString();
Ted Kremenek5778acf2008-10-27 18:40:21 +0000516}
517
Craig Topperc571c812013-08-22 06:02:26 +0000518void GCCAsmStmt::setOutputsAndInputsAndClobbers(const ASTContext &C,
519 IdentifierInfo **Names,
520 StringLiteral **Constraints,
521 Stmt **Exprs,
522 unsigned NumOutputs,
523 unsigned NumInputs,
Jennifer Yub8fee672019-06-03 15:57:25 +0000524 unsigned NumLabels,
Craig Topperc571c812013-08-22 06:02:26 +0000525 StringLiteral **Clobbers,
526 unsigned NumClobbers) {
Douglas Gregorf994f062009-04-17 20:57:14 +0000527 this->NumOutputs = NumOutputs;
528 this->NumInputs = NumInputs;
Anders Carlsson98323d22010-01-30 23:19:41 +0000529 this->NumClobbers = NumClobbers;
Jennifer Yub8fee672019-06-03 15:57:25 +0000530 this->NumLabels = NumLabels;
531 assert(!(NumOutputs && NumLabels) && "asm goto cannot have outputs");
Anders Carlsson98323d22010-01-30 23:19:41 +0000532
Jennifer Yub8fee672019-06-03 15:57:25 +0000533 unsigned NumExprs = NumOutputs + NumInputs + NumLabels;
Chad Rosier42032fa2012-08-07 23:12:23 +0000534
Anders Carlsson98323d22010-01-30 23:19:41 +0000535 C.Deallocate(this->Names);
536 this->Names = new (C) IdentifierInfo*[NumExprs];
537 std::copy(Names, Names + NumExprs, this->Names);
Chad Rosier42032fa2012-08-07 23:12:23 +0000538
Anders Carlsson98323d22010-01-30 23:19:41 +0000539 C.Deallocate(this->Exprs);
540 this->Exprs = new (C) Stmt*[NumExprs];
541 std::copy(Exprs, Exprs + NumExprs, this->Exprs);
Chad Rosier42032fa2012-08-07 23:12:23 +0000542
Benjamin Kramer851f57e2019-05-30 07:21:08 +0000543 unsigned NumConstraints = NumOutputs + NumInputs;
Anders Carlsson98323d22010-01-30 23:19:41 +0000544 C.Deallocate(this->Constraints);
Benjamin Kramer851f57e2019-05-30 07:21:08 +0000545 this->Constraints = new (C) StringLiteral*[NumConstraints];
546 std::copy(Constraints, Constraints + NumConstraints, this->Constraints);
Chad Rosier42032fa2012-08-07 23:12:23 +0000547
Anders Carlsson98323d22010-01-30 23:19:41 +0000548 C.Deallocate(this->Clobbers);
549 this->Clobbers = new (C) StringLiteral*[NumClobbers];
550 std::copy(Clobbers, Clobbers + NumClobbers, this->Clobbers);
Douglas Gregorf994f062009-04-17 20:57:14 +0000551}
552
Chris Lattnerd7d5fdf2009-03-10 06:33:24 +0000553/// getNamedOperand - Given a symbolic operand reference like %[foo],
554/// translate this into a numeric value needed to reference the same operand.
555/// This returns -1 if the operand name is invalid.
Chad Rosierde70e0e2012-08-25 00:11:56 +0000556int GCCAsmStmt::getNamedOperand(StringRef SymbolicName) const {
Chris Lattnerd7d5fdf2009-03-10 06:33:24 +0000557 unsigned NumPlusOperands = 0;
Mike Stump11289f42009-09-09 15:08:12 +0000558
Chris Lattnerd7d5fdf2009-03-10 06:33:24 +0000559 // Check if this is an output operand.
560 for (unsigned i = 0, e = getNumOutputs(); i != e; ++i) {
561 if (getOutputName(i) == SymbolicName)
562 return i;
Chris Lattnerd7d5fdf2009-03-10 06:33:24 +0000563 }
Mike Stump11289f42009-09-09 15:08:12 +0000564
Chris Lattnerd7d5fdf2009-03-10 06:33:24 +0000565 for (unsigned i = 0, e = getNumInputs(); i != e; ++i)
566 if (getInputName(i) == SymbolicName)
567 return getNumOutputs() + NumPlusOperands + i;
568
Jennifer Yub8fee672019-06-03 15:57:25 +0000569 for (unsigned i = 0, e = getNumLabels(); i != e; ++i)
570 if (getLabelName(i) == SymbolicName)
Bill Wendling50cac242020-02-24 18:32:50 -0800571 return i + getNumOutputs() + getNumInputs();
Jennifer Yub8fee672019-06-03 15:57:25 +0000572
Chris Lattnerd7d5fdf2009-03-10 06:33:24 +0000573 // Not found.
574 return -1;
575}
576
Chris Lattner35b58362009-03-10 23:21:44 +0000577/// AnalyzeAsmString - Analyze the asm string of the current asm, decomposing
578/// it into pieces. If the asm string is erroneous, emit errors and return
579/// true, otherwise return false.
Chad Rosierde70e0e2012-08-25 00:11:56 +0000580unsigned GCCAsmStmt::AnalyzeAsmString(SmallVectorImpl<AsmStringPiece>&Pieces,
Craig Topperc571c812013-08-22 06:02:26 +0000581 const ASTContext &C, unsigned &DiagOffs) const {
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000582 StringRef Str = getAsmString()->getString();
Benjamin Kramer35b077e2010-08-17 12:54:38 +0000583 const char *StrStart = Str.begin();
584 const char *StrEnd = Str.end();
Chris Lattnera41b8472009-03-10 23:51:40 +0000585 const char *CurPtr = StrStart;
Mike Stump11289f42009-09-09 15:08:12 +0000586
Chris Lattner35b58362009-03-10 23:21:44 +0000587 // "Simple" inline asms have no constraints or operands, just convert the asm
588 // string to escape $'s.
589 if (isSimple()) {
590 std::string Result;
Chris Lattnera41b8472009-03-10 23:51:40 +0000591 for (; CurPtr != StrEnd; ++CurPtr) {
592 switch (*CurPtr) {
Chris Lattner35b58362009-03-10 23:21:44 +0000593 case '$':
594 Result += "$$";
595 break;
596 default:
Chris Lattnera41b8472009-03-10 23:51:40 +0000597 Result += *CurPtr;
Chris Lattner35b58362009-03-10 23:21:44 +0000598 break;
599 }
600 }
601 Pieces.push_back(AsmStringPiece(Result));
Chris Lattnera41b8472009-03-10 23:51:40 +0000602 return 0;
Chris Lattner35b58362009-03-10 23:21:44 +0000603 }
604
605 // CurStringPiece - The current string that we are building up as we scan the
606 // asm string.
607 std::string CurStringPiece;
Mike Stump11289f42009-09-09 15:08:12 +0000608
Douglas Gregore8bbc122011-09-02 00:18:52 +0000609 bool HasVariants = !C.getTargetInfo().hasNoAsmVariants();
Chad Rosier42032fa2012-08-07 23:12:23 +0000610
Richard Smithd18ab802016-05-16 22:52:23 +0000611 unsigned LastAsmStringToken = 0;
612 unsigned LastAsmStringOffset = 0;
613
Eugene Zelenko1eab6c12017-11-14 23:35:42 +0000614 while (true) {
Chris Lattner35b58362009-03-10 23:21:44 +0000615 // Done with the string?
Chris Lattnera41b8472009-03-10 23:51:40 +0000616 if (CurPtr == StrEnd) {
Chris Lattner35b58362009-03-10 23:21:44 +0000617 if (!CurStringPiece.empty())
618 Pieces.push_back(AsmStringPiece(CurStringPiece));
Chris Lattnera41b8472009-03-10 23:51:40 +0000619 return 0;
Chris Lattner35b58362009-03-10 23:21:44 +0000620 }
Mike Stump11289f42009-09-09 15:08:12 +0000621
Chris Lattnera41b8472009-03-10 23:51:40 +0000622 char CurChar = *CurPtr++;
Chris Lattnerda081a82010-04-05 18:44:00 +0000623 switch (CurChar) {
624 case '$': CurStringPiece += "$$"; continue;
Chris Lattner1a8f3942010-04-23 16:29:58 +0000625 case '{': CurStringPiece += (HasVariants ? "$(" : "{"); continue;
626 case '|': CurStringPiece += (HasVariants ? "$|" : "|"); continue;
627 case '}': CurStringPiece += (HasVariants ? "$)" : "}"); continue;
Chris Lattnerda081a82010-04-05 18:44:00 +0000628 case '%':
629 break;
630 default:
Chris Lattner35b58362009-03-10 23:21:44 +0000631 CurStringPiece += CurChar;
632 continue;
633 }
Chad Rosier42032fa2012-08-07 23:12:23 +0000634
Chris Lattner35b58362009-03-10 23:21:44 +0000635 // Escaped "%" character in asm string.
Chris Lattner3fa25c62009-03-11 00:06:36 +0000636 if (CurPtr == StrEnd) {
637 // % at end of string is invalid (no escape).
638 DiagOffs = CurPtr-StrStart-1;
639 return diag::err_asm_invalid_escape;
640 }
Michael Zuckerman2460bad2016-10-31 15:27:54 +0000641 // Handle escaped char and continue looping over the asm string.
Chris Lattnera41b8472009-03-10 23:51:40 +0000642 char EscapedChar = *CurPtr++;
Michael Zuckerman2460bad2016-10-31 15:27:54 +0000643 switch (EscapedChar) {
644 default:
645 break;
646 case '%': // %% -> %
647 case '{': // %{ -> {
648 case '}': // %} -> }
649 CurStringPiece += EscapedChar;
Chris Lattner35b58362009-03-10 23:21:44 +0000650 continue;
Michael Zuckerman2460bad2016-10-31 15:27:54 +0000651 case '=': // %= -> Generate a unique ID.
Chris Lattner35b58362009-03-10 23:21:44 +0000652 CurStringPiece += "${:uid}";
653 continue;
654 }
Mike Stump11289f42009-09-09 15:08:12 +0000655
Chris Lattner35b58362009-03-10 23:21:44 +0000656 // Otherwise, we have an operand. If we have accumulated a string so far,
657 // add it to the Pieces list.
658 if (!CurStringPiece.empty()) {
659 Pieces.push_back(AsmStringPiece(CurStringPiece));
660 CurStringPiece.clear();
661 }
Mike Stump11289f42009-09-09 15:08:12 +0000662
Akira Hatanaka987f1862014-08-22 06:05:21 +0000663 // Handle operands that have asmSymbolicName (e.g., %x[foo]) and those that
664 // don't (e.g., %x4). 'x' following the '%' is the constraint modifier.
665
666 const char *Begin = CurPtr - 1; // Points to the character following '%'.
667 const char *Percent = Begin - 1; // Points to '%'.
668
Jordan Rosea7d03842013-02-08 22:30:41 +0000669 if (isLetter(EscapedChar)) {
Benjamin Kramere87c38b2011-07-05 11:13:37 +0000670 if (CurPtr == StrEnd) { // Premature end.
671 DiagOffs = CurPtr-StrStart-1;
672 return diag::err_asm_invalid_escape;
673 }
Chris Lattnera41b8472009-03-10 23:51:40 +0000674 EscapedChar = *CurPtr++;
Chris Lattner35b58362009-03-10 23:21:44 +0000675 }
Mike Stump11289f42009-09-09 15:08:12 +0000676
Akira Hatanaka987f1862014-08-22 06:05:21 +0000677 const TargetInfo &TI = C.getTargetInfo();
678 const SourceManager &SM = C.getSourceManager();
679 const LangOptions &LO = C.getLangOpts();
680
681 // Handle operands that don't have asmSymbolicName (e.g., %x4).
Jordan Rosea7d03842013-02-08 22:30:41 +0000682 if (isDigit(EscapedChar)) {
Chris Lattner35b58362009-03-10 23:21:44 +0000683 // %n - Assembler operand n
Chris Lattner99d892b2009-03-11 22:52:17 +0000684 unsigned N = 0;
Mike Stump11289f42009-09-09 15:08:12 +0000685
Chris Lattner99d892b2009-03-11 22:52:17 +0000686 --CurPtr;
Jordan Rosea7d03842013-02-08 22:30:41 +0000687 while (CurPtr != StrEnd && isDigit(*CurPtr))
Chris Lattner84f3afa2009-03-11 23:09:16 +0000688 N = N*10 + ((*CurPtr++)-'0');
Mike Stump11289f42009-09-09 15:08:12 +0000689
Jennifer Yub8fee672019-06-03 15:57:25 +0000690 unsigned NumOperands = getNumOutputs() + getNumPlusOperands() +
691 getNumInputs() + getNumLabels();
Chris Lattner14311922009-03-11 00:23:13 +0000692 if (N >= NumOperands) {
693 DiagOffs = CurPtr-StrStart-1;
694 return diag::err_asm_invalid_operand_number;
695 }
696
Akira Hatanaka987f1862014-08-22 06:05:21 +0000697 // Str contains "x4" (Operand without the leading %).
698 std::string Str(Begin, CurPtr - Begin);
699
700 // (BeginLoc, EndLoc) represents the range of the operand we are currently
701 // processing. Unlike Str, the range includes the leading '%'.
Richard Smithd18ab802016-05-16 22:52:23 +0000702 SourceLocation BeginLoc = getAsmString()->getLocationOfByte(
703 Percent - StrStart, SM, LO, TI, &LastAsmStringToken,
704 &LastAsmStringOffset);
705 SourceLocation EndLoc = getAsmString()->getLocationOfByte(
706 CurPtr - StrStart, SM, LO, TI, &LastAsmStringToken,
707 &LastAsmStringOffset);
Akira Hatanaka987f1862014-08-22 06:05:21 +0000708
Benjamin Kramer3204b152015-05-29 19:42:19 +0000709 Pieces.emplace_back(N, std::move(Str), BeginLoc, EndLoc);
Chris Lattner35b58362009-03-10 23:21:44 +0000710 continue;
711 }
Mike Stump11289f42009-09-09 15:08:12 +0000712
Akira Hatanaka987f1862014-08-22 06:05:21 +0000713 // Handle operands that have asmSymbolicName (e.g., %x[foo]).
Chris Lattner35b58362009-03-10 23:21:44 +0000714 if (EscapedChar == '[') {
Chris Lattner3fa25c62009-03-11 00:06:36 +0000715 DiagOffs = CurPtr-StrStart-1;
Mike Stump11289f42009-09-09 15:08:12 +0000716
Chris Lattner3fa25c62009-03-11 00:06:36 +0000717 // Find the ']'.
Chris Lattnera41b8472009-03-10 23:51:40 +0000718 const char *NameEnd = (const char*)memchr(CurPtr, ']', StrEnd-CurPtr);
Craig Topper36250ad2014-05-12 05:36:57 +0000719 if (NameEnd == nullptr)
Chris Lattner3fa25c62009-03-11 00:06:36 +0000720 return diag::err_asm_unterminated_symbolic_operand_name;
721 if (NameEnd == CurPtr)
722 return diag::err_asm_empty_symbolic_operand_name;
Mike Stump11289f42009-09-09 15:08:12 +0000723
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000724 StringRef SymbolicName(CurPtr, NameEnd - CurPtr);
Mike Stump11289f42009-09-09 15:08:12 +0000725
Chris Lattner35b58362009-03-10 23:21:44 +0000726 int N = getNamedOperand(SymbolicName);
Chris Lattner3fa25c62009-03-11 00:06:36 +0000727 if (N == -1) {
728 // Verify that an operand with that name exists.
729 DiagOffs = CurPtr-StrStart;
730 return diag::err_asm_unknown_symbolic_operand_name;
731 }
Akira Hatanaka987f1862014-08-22 06:05:21 +0000732
733 // Str contains "x[foo]" (Operand without the leading %).
734 std::string Str(Begin, NameEnd + 1 - Begin);
735
736 // (BeginLoc, EndLoc) represents the range of the operand we are currently
737 // processing. Unlike Str, the range includes the leading '%'.
Richard Smithd18ab802016-05-16 22:52:23 +0000738 SourceLocation BeginLoc = getAsmString()->getLocationOfByte(
739 Percent - StrStart, SM, LO, TI, &LastAsmStringToken,
740 &LastAsmStringOffset);
741 SourceLocation EndLoc = getAsmString()->getLocationOfByte(
742 NameEnd + 1 - StrStart, SM, LO, TI, &LastAsmStringToken,
743 &LastAsmStringOffset);
Akira Hatanaka987f1862014-08-22 06:05:21 +0000744
Benjamin Kramer3204b152015-05-29 19:42:19 +0000745 Pieces.emplace_back(N, std::move(Str), BeginLoc, EndLoc);
Mike Stump11289f42009-09-09 15:08:12 +0000746
Chris Lattner3fa25c62009-03-11 00:06:36 +0000747 CurPtr = NameEnd+1;
Chris Lattner35b58362009-03-10 23:21:44 +0000748 continue;
749 }
Mike Stump11289f42009-09-09 15:08:12 +0000750
Chris Lattner0cdaa2e2009-03-10 23:57:07 +0000751 DiagOffs = CurPtr-StrStart-1;
Chris Lattnera41b8472009-03-10 23:51:40 +0000752 return diag::err_asm_invalid_escape;
Chris Lattner35b58362009-03-10 23:21:44 +0000753 }
754}
Chad Rosier3b0c2602012-08-27 20:23:31 +0000755
756/// Assemble final IR asm string (GCC-style).
Craig Topperc571c812013-08-22 06:02:26 +0000757std::string GCCAsmStmt::generateAsmString(const ASTContext &C) const {
Chad Rosier14836ba2012-08-24 17:05:45 +0000758 // Analyze the asm string to decompose it into its pieces. We know that Sema
759 // has already done this, so it is guaranteed to be successful.
Chad Rosierde70e0e2012-08-25 00:11:56 +0000760 SmallVector<GCCAsmStmt::AsmStringPiece, 4> Pieces;
Chad Rosier14836ba2012-08-24 17:05:45 +0000761 unsigned DiagOffs;
762 AnalyzeAsmString(Pieces, C, DiagOffs);
763
764 std::string AsmString;
Eugene Zelenko7855e772018-04-03 00:11:50 +0000765 for (const auto &Piece : Pieces) {
766 if (Piece.isString())
767 AsmString += Piece.getString();
768 else if (Piece.getModifier() == '\0')
769 AsmString += '$' + llvm::utostr(Piece.getOperandNo());
Chad Rosier14836ba2012-08-24 17:05:45 +0000770 else
Eugene Zelenko7855e772018-04-03 00:11:50 +0000771 AsmString += "${" + llvm::utostr(Piece.getOperandNo()) + ':' +
772 Piece.getModifier() + '}';
Chad Rosier14836ba2012-08-24 17:05:45 +0000773 }
774 return AsmString;
775}
Chris Lattner35b58362009-03-10 23:21:44 +0000776
Chad Rosier3b0c2602012-08-27 20:23:31 +0000777/// Assemble final IR asm string (MS-style).
Craig Topperc571c812013-08-22 06:02:26 +0000778std::string MSAsmStmt::generateAsmString(const ASTContext &C) const {
Chad Rosier3b0c2602012-08-27 20:23:31 +0000779 // FIXME: This needs to be translated into the IR string representation.
Benjamin Krameradcd0262020-01-28 20:23:46 +0100780 return std::string(AsmStr);
Chad Rosier3b0c2602012-08-27 20:23:31 +0000781}
782
Chad Rosierfe31e622012-08-24 00:07:09 +0000783Expr *MSAsmStmt::getOutputExpr(unsigned i) {
784 return cast<Expr>(Exprs[i]);
785}
786
787Expr *MSAsmStmt::getInputExpr(unsigned i) {
788 return cast<Expr>(Exprs[i + NumOutputs]);
789}
Eugene Zelenko1eab6c12017-11-14 23:35:42 +0000790
Chad Rosierfe31e622012-08-24 00:07:09 +0000791void MSAsmStmt::setInputExpr(unsigned i, Expr *E) {
792 Exprs[i + NumOutputs] = E;
793}
794
Chris Lattner86f5e132008-01-30 05:01:46 +0000795//===----------------------------------------------------------------------===//
796// Constructors
797//===----------------------------------------------------------------------===//
798
Craig Toppere6960e22013-08-22 05:28:54 +0000799GCCAsmStmt::GCCAsmStmt(const ASTContext &C, SourceLocation asmloc,
800 bool issimple, bool isvolatile, unsigned numoutputs,
801 unsigned numinputs, IdentifierInfo **names,
802 StringLiteral **constraints, Expr **exprs,
803 StringLiteral *asmstr, unsigned numclobbers,
Jennifer Yub8fee672019-06-03 15:57:25 +0000804 StringLiteral **clobbers, unsigned numlabels,
805 SourceLocation rparenloc)
Eugene Zelenko1eab6c12017-11-14 23:35:42 +0000806 : AsmStmt(GCCAsmStmtClass, asmloc, issimple, isvolatile, numoutputs,
Jennifer Yub8fee672019-06-03 15:57:25 +0000807 numinputs, numclobbers),
808 RParenLoc(rparenloc), AsmStr(asmstr), NumLabels(numlabels) {
809 unsigned NumExprs = NumOutputs + NumInputs + NumLabels;
Chad Rosier42032fa2012-08-07 23:12:23 +0000810
Anders Carlsson98323d22010-01-30 23:19:41 +0000811 Names = new (C) IdentifierInfo*[NumExprs];
812 std::copy(names, names + NumExprs, Names);
813
814 Exprs = new (C) Stmt*[NumExprs];
815 std::copy(exprs, exprs + NumExprs, Exprs);
816
Benjamin Kramer851f57e2019-05-30 07:21:08 +0000817 unsigned NumConstraints = NumOutputs + NumInputs;
818 Constraints = new (C) StringLiteral*[NumConstraints];
819 std::copy(constraints, constraints + NumConstraints, Constraints);
Anders Carlsson98323d22010-01-30 23:19:41 +0000820
821 Clobbers = new (C) StringLiteral*[NumClobbers];
822 std::copy(clobbers, clobbers + NumClobbers, Clobbers);
Anders Carlsson94ea8aa2007-11-22 01:36:19 +0000823}
824
Craig Toppere6960e22013-08-22 05:28:54 +0000825MSAsmStmt::MSAsmStmt(const ASTContext &C, SourceLocation asmloc,
Chad Rosier7dbef3e2012-08-16 00:06:53 +0000826 SourceLocation lbraceloc, bool issimple, bool isvolatile,
Chad Rosierf8037a12012-10-16 21:55:39 +0000827 ArrayRef<Token> asmtoks, unsigned numoutputs,
John McCallf413f5e2013-05-03 00:10:13 +0000828 unsigned numinputs,
Chad Rosierf8037a12012-10-16 21:55:39 +0000829 ArrayRef<StringRef> constraints, ArrayRef<Expr*> exprs,
830 StringRef asmstr, ArrayRef<StringRef> clobbers,
831 SourceLocation endloc)
Eugene Zelenko1eab6c12017-11-14 23:35:42 +0000832 : AsmStmt(MSAsmStmtClass, asmloc, issimple, isvolatile, numoutputs,
833 numinputs, clobbers.size()), LBraceLoc(lbraceloc),
834 EndLoc(endloc), NumAsmToks(asmtoks.size()) {
John McCallf413f5e2013-05-03 00:10:13 +0000835 initialize(C, asmstr, asmtoks, constraints, exprs, clobbers);
836}
Chad Rosier7dbef3e2012-08-16 00:06:53 +0000837
Craig Toppere6960e22013-08-22 05:28:54 +0000838static StringRef copyIntoContext(const ASTContext &C, StringRef str) {
Benjamin Kramer2ab0d882015-08-04 12:34:23 +0000839 return str.copy(C);
John McCallf413f5e2013-05-03 00:10:13 +0000840}
841
Craig Toppere6960e22013-08-22 05:28:54 +0000842void MSAsmStmt::initialize(const ASTContext &C, StringRef asmstr,
John McCallf413f5e2013-05-03 00:10:13 +0000843 ArrayRef<Token> asmtoks,
844 ArrayRef<StringRef> constraints,
845 ArrayRef<Expr*> exprs,
846 ArrayRef<StringRef> clobbers) {
847 assert(NumAsmToks == asmtoks.size());
848 assert(NumClobbers == clobbers.size());
849
Craig Toppercaf138e2015-12-05 07:41:42 +0000850 assert(exprs.size() == NumOutputs + NumInputs);
851 assert(exprs.size() == constraints.size());
John McCallf413f5e2013-05-03 00:10:13 +0000852
853 AsmStr = copyIntoContext(C, asmstr);
Chad Rosier99fc3812012-08-07 00:29:06 +0000854
Craig Toppercaf138e2015-12-05 07:41:42 +0000855 Exprs = new (C) Stmt*[exprs.size()];
856 std::copy(exprs.begin(), exprs.end(), Exprs);
Chad Rosierfe31e622012-08-24 00:07:09 +0000857
Craig Toppercaf138e2015-12-05 07:41:42 +0000858 AsmToks = new (C) Token[asmtoks.size()];
859 std::copy(asmtoks.begin(), asmtoks.end(), AsmToks);
Chad Rosier3ed0bd92012-08-08 19:48:07 +0000860
Craig Toppercaf138e2015-12-05 07:41:42 +0000861 Constraints = new (C) StringRef[exprs.size()];
862 std::transform(constraints.begin(), constraints.end(), Constraints,
863 [&](StringRef Constraint) {
864 return copyIntoContext(C, Constraint);
865 });
Chad Rosier3dd7bf22012-08-28 20:28:20 +0000866
Chad Rosierbaf53f92012-08-10 21:36:25 +0000867 Clobbers = new (C) StringRef[NumClobbers];
Craig Toppercaf138e2015-12-05 07:41:42 +0000868 // FIXME: Avoid the allocation/copy if at all possible.
869 std::transform(clobbers.begin(), clobbers.end(), Clobbers,
870 [&](StringRef Clobber) {
871 return copyIntoContext(C, Clobber);
872 });
Chad Rosier32503022012-06-11 20:47:18 +0000873}
874
Bruno Riccib1cc94b2018-10-27 21:12:20 +0000875IfStmt::IfStmt(const ASTContext &Ctx, SourceLocation IL, bool IsConstexpr,
Zequan Wu94c6cea2020-08-10 16:29:33 -0700876 Stmt *Init, VarDecl *Var, Expr *Cond, SourceLocation LPL,
877 SourceLocation RPL, Stmt *Then, SourceLocation EL, Stmt *Else)
878 : Stmt(IfStmtClass), LParenLoc(LPL), RParenLoc(RPL) {
Bruno Riccib1cc94b2018-10-27 21:12:20 +0000879 bool HasElse = Else != nullptr;
880 bool HasVar = Var != nullptr;
881 bool HasInit = Init != nullptr;
882 IfStmtBits.HasElse = HasElse;
883 IfStmtBits.HasVar = HasVar;
884 IfStmtBits.HasInit = HasInit;
885
Richard Smithb130fe72016-06-23 19:16:49 +0000886 setConstexpr(IsConstexpr);
Bruno Riccib1cc94b2018-10-27 21:12:20 +0000887
888 setCond(Cond);
889 setThen(Then);
890 if (HasElse)
891 setElse(Else);
892 if (HasVar)
893 setConditionVariable(Ctx, Var);
894 if (HasInit)
895 setInit(Init);
896
897 setIfLoc(IL);
898 if (HasElse)
899 setElseLoc(EL);
Douglas Gregor27b98ea2010-06-21 23:44:13 +0000900}
901
Bruno Riccib1cc94b2018-10-27 21:12:20 +0000902IfStmt::IfStmt(EmptyShell Empty, bool HasElse, bool HasVar, bool HasInit)
903 : Stmt(IfStmtClass, Empty) {
904 IfStmtBits.HasElse = HasElse;
905 IfStmtBits.HasVar = HasVar;
906 IfStmtBits.HasInit = HasInit;
907}
Chad Rosier42032fa2012-08-07 23:12:23 +0000908
Bruno Riccib1cc94b2018-10-27 21:12:20 +0000909IfStmt *IfStmt::Create(const ASTContext &Ctx, SourceLocation IL,
910 bool IsConstexpr, Stmt *Init, VarDecl *Var, Expr *Cond,
Zequan Wu94c6cea2020-08-10 16:29:33 -0700911 SourceLocation LPL, SourceLocation RPL, Stmt *Then,
912 SourceLocation EL, Stmt *Else) {
Bruno Riccib1cc94b2018-10-27 21:12:20 +0000913 bool HasElse = Else != nullptr;
914 bool HasVar = Var != nullptr;
915 bool HasInit = Init != nullptr;
916 void *Mem = Ctx.Allocate(
917 totalSizeToAlloc<Stmt *, SourceLocation>(
918 NumMandatoryStmtPtr + HasElse + HasVar + HasInit, HasElse),
919 alignof(IfStmt));
920 return new (Mem)
Zequan Wu94c6cea2020-08-10 16:29:33 -0700921 IfStmt(Ctx, IL, IsConstexpr, Init, Var, Cond, LPL, RPL, Then, EL, Else);
Bruno Riccib1cc94b2018-10-27 21:12:20 +0000922}
923
924IfStmt *IfStmt::CreateEmpty(const ASTContext &Ctx, bool HasElse, bool HasVar,
925 bool HasInit) {
926 void *Mem = Ctx.Allocate(
927 totalSizeToAlloc<Stmt *, SourceLocation>(
928 NumMandatoryStmtPtr + HasElse + HasVar + HasInit, HasElse),
929 alignof(IfStmt));
930 return new (Mem) IfStmt(EmptyShell(), HasElse, HasVar, HasInit);
931}
932
933VarDecl *IfStmt::getConditionVariable() {
934 auto *DS = getConditionVariableDeclStmt();
935 if (!DS)
936 return nullptr;
Douglas Gregor27b98ea2010-06-21 23:44:13 +0000937 return cast<VarDecl>(DS->getSingleDecl());
938}
939
Bruno Riccib1cc94b2018-10-27 21:12:20 +0000940void IfStmt::setConditionVariable(const ASTContext &Ctx, VarDecl *V) {
941 assert(hasVarStorage() &&
942 "This if statement has no storage for a condition variable!");
943
Douglas Gregor27b98ea2010-06-21 23:44:13 +0000944 if (!V) {
Bruno Riccib1cc94b2018-10-27 21:12:20 +0000945 getTrailingObjects<Stmt *>()[varOffset()] = nullptr;
Douglas Gregor27b98ea2010-06-21 23:44:13 +0000946 return;
947 }
Chad Rosier42032fa2012-08-07 23:12:23 +0000948
Daniel Dunbar62ee6412012-03-09 18:35:03 +0000949 SourceRange VarRange = V->getSourceRange();
Bruno Riccib1cc94b2018-10-27 21:12:20 +0000950 getTrailingObjects<Stmt *>()[varOffset()] = new (Ctx)
951 DeclStmt(DeclGroupRef(V), VarRange.getBegin(), VarRange.getEnd());
Douglas Gregor27b98ea2010-06-21 23:44:13 +0000952}
953
Erik Pilkington5cd57172016-08-16 17:44:11 +0000954bool IfStmt::isObjCAvailabilityCheck() const {
Bruno Riccib1cc94b2018-10-27 21:12:20 +0000955 return isa<ObjCAvailabilityCheckExpr>(getCond());
Erik Pilkington5cd57172016-08-16 17:44:11 +0000956}
957
Richard Smithfbf60b72019-12-13 14:10:13 -0800958Optional<const Stmt*> IfStmt::getNondiscardedCase(const ASTContext &Ctx) const {
959 if (!isConstexpr() || getCond()->isValueDependent())
960 return None;
961 return !getCond()->EvaluateKnownConstInt(Ctx) ? getElse() : getThen();
962}
963
Craig Toppere6960e22013-08-22 05:28:54 +0000964ForStmt::ForStmt(const ASTContext &C, Stmt *Init, Expr *Cond, VarDecl *condVar,
Chad Rosier42032fa2012-08-07 23:12:23 +0000965 Expr *Inc, Stmt *Body, SourceLocation FL, SourceLocation LP,
Douglas Gregor27b98ea2010-06-21 23:44:13 +0000966 SourceLocation RP)
Bruno Ricci41d11c02018-10-27 18:43:27 +0000967 : Stmt(ForStmtClass), LParenLoc(LP), RParenLoc(RP)
Douglas Gregor27b98ea2010-06-21 23:44:13 +0000968{
969 SubExprs[INIT] = Init;
970 setConditionVariable(C, condVar);
Pavel Labath515f4db2013-09-03 14:41:16 +0000971 SubExprs[COND] = Cond;
972 SubExprs[INC] = Inc;
Douglas Gregor27b98ea2010-06-21 23:44:13 +0000973 SubExprs[BODY] = Body;
Bruno Ricci41d11c02018-10-27 18:43:27 +0000974 ForStmtBits.ForLoc = FL;
Douglas Gregor27b98ea2010-06-21 23:44:13 +0000975}
976
977VarDecl *ForStmt::getConditionVariable() const {
978 if (!SubExprs[CONDVAR])
Craig Topper36250ad2014-05-12 05:36:57 +0000979 return nullptr;
Chad Rosier42032fa2012-08-07 23:12:23 +0000980
Eugene Zelenko7855e772018-04-03 00:11:50 +0000981 auto *DS = cast<DeclStmt>(SubExprs[CONDVAR]);
Douglas Gregor27b98ea2010-06-21 23:44:13 +0000982 return cast<VarDecl>(DS->getSingleDecl());
983}
984
Craig Toppere6960e22013-08-22 05:28:54 +0000985void ForStmt::setConditionVariable(const ASTContext &C, VarDecl *V) {
Douglas Gregor27b98ea2010-06-21 23:44:13 +0000986 if (!V) {
Craig Topper36250ad2014-05-12 05:36:57 +0000987 SubExprs[CONDVAR] = nullptr;
Douglas Gregor27b98ea2010-06-21 23:44:13 +0000988 return;
989 }
Chad Rosier42032fa2012-08-07 23:12:23 +0000990
Daniel Dunbar62ee6412012-03-09 18:35:03 +0000991 SourceRange VarRange = V->getSourceRange();
992 SubExprs[CONDVAR] = new (C) DeclStmt(DeclGroupRef(V), VarRange.getBegin(),
993 VarRange.getEnd());
Douglas Gregor27b98ea2010-06-21 23:44:13 +0000994}
995
Bruno Riccie2806f82018-10-29 16:12:37 +0000996SwitchStmt::SwitchStmt(const ASTContext &Ctx, Stmt *Init, VarDecl *Var,
Zequan Wu94c6cea2020-08-10 16:29:33 -0700997 Expr *Cond, SourceLocation LParenLoc,
998 SourceLocation RParenLoc)
999 : Stmt(SwitchStmtClass), FirstCase(nullptr), LParenLoc(LParenLoc),
1000 RParenLoc(RParenLoc) {
Bruno Riccie2806f82018-10-29 16:12:37 +00001001 bool HasInit = Init != nullptr;
1002 bool HasVar = Var != nullptr;
1003 SwitchStmtBits.HasInit = HasInit;
1004 SwitchStmtBits.HasVar = HasVar;
1005 SwitchStmtBits.AllEnumCasesCovered = false;
1006
1007 setCond(Cond);
1008 setBody(nullptr);
1009 if (HasInit)
1010 setInit(Init);
1011 if (HasVar)
1012 setConditionVariable(Ctx, Var);
1013
1014 setSwitchLoc(SourceLocation{});
Douglas Gregor27b98ea2010-06-21 23:44:13 +00001015}
1016
Bruno Riccie2806f82018-10-29 16:12:37 +00001017SwitchStmt::SwitchStmt(EmptyShell Empty, bool HasInit, bool HasVar)
1018 : Stmt(SwitchStmtClass, Empty) {
1019 SwitchStmtBits.HasInit = HasInit;
1020 SwitchStmtBits.HasVar = HasVar;
1021 SwitchStmtBits.AllEnumCasesCovered = false;
1022}
Chad Rosier42032fa2012-08-07 23:12:23 +00001023
Bruno Riccie2806f82018-10-29 16:12:37 +00001024SwitchStmt *SwitchStmt::Create(const ASTContext &Ctx, Stmt *Init, VarDecl *Var,
Zequan Wu94c6cea2020-08-10 16:29:33 -07001025 Expr *Cond, SourceLocation LParenLoc,
1026 SourceLocation RParenLoc) {
Bruno Riccie2806f82018-10-29 16:12:37 +00001027 bool HasInit = Init != nullptr;
1028 bool HasVar = Var != nullptr;
1029 void *Mem = Ctx.Allocate(
1030 totalSizeToAlloc<Stmt *>(NumMandatoryStmtPtr + HasInit + HasVar),
1031 alignof(SwitchStmt));
Zequan Wu94c6cea2020-08-10 16:29:33 -07001032 return new (Mem) SwitchStmt(Ctx, Init, Var, Cond, LParenLoc, RParenLoc);
Bruno Riccie2806f82018-10-29 16:12:37 +00001033}
1034
1035SwitchStmt *SwitchStmt::CreateEmpty(const ASTContext &Ctx, bool HasInit,
1036 bool HasVar) {
1037 void *Mem = Ctx.Allocate(
1038 totalSizeToAlloc<Stmt *>(NumMandatoryStmtPtr + HasInit + HasVar),
1039 alignof(SwitchStmt));
1040 return new (Mem) SwitchStmt(EmptyShell(), HasInit, HasVar);
1041}
1042
1043VarDecl *SwitchStmt::getConditionVariable() {
1044 auto *DS = getConditionVariableDeclStmt();
1045 if (!DS)
1046 return nullptr;
Douglas Gregor27b98ea2010-06-21 23:44:13 +00001047 return cast<VarDecl>(DS->getSingleDecl());
1048}
1049
Bruno Riccie2806f82018-10-29 16:12:37 +00001050void SwitchStmt::setConditionVariable(const ASTContext &Ctx, VarDecl *V) {
1051 assert(hasVarStorage() &&
1052 "This switch statement has no storage for a condition variable!");
1053
Douglas Gregor27b98ea2010-06-21 23:44:13 +00001054 if (!V) {
Bruno Riccie2806f82018-10-29 16:12:37 +00001055 getTrailingObjects<Stmt *>()[varOffset()] = nullptr;
Douglas Gregor27b98ea2010-06-21 23:44:13 +00001056 return;
1057 }
Chad Rosier42032fa2012-08-07 23:12:23 +00001058
Daniel Dunbar62ee6412012-03-09 18:35:03 +00001059 SourceRange VarRange = V->getSourceRange();
Bruno Riccie2806f82018-10-29 16:12:37 +00001060 getTrailingObjects<Stmt *>()[varOffset()] = new (Ctx)
1061 DeclStmt(DeclGroupRef(V), VarRange.getBegin(), VarRange.getEnd());
Douglas Gregor27b98ea2010-06-21 23:44:13 +00001062}
1063
Bruno Riccibacf7512018-10-30 13:42:41 +00001064WhileStmt::WhileStmt(const ASTContext &Ctx, VarDecl *Var, Expr *Cond,
Vy Nguyen17ea41e2020-07-09 23:19:06 -04001065 Stmt *Body, SourceLocation WL, SourceLocation LParenLoc,
1066 SourceLocation RParenLoc)
Bruno Riccibacf7512018-10-30 13:42:41 +00001067 : Stmt(WhileStmtClass) {
1068 bool HasVar = Var != nullptr;
1069 WhileStmtBits.HasVar = HasVar;
1070
1071 setCond(Cond);
1072 setBody(Body);
1073 if (HasVar)
1074 setConditionVariable(Ctx, Var);
1075
1076 setWhileLoc(WL);
Vy Nguyen17ea41e2020-07-09 23:19:06 -04001077 setLParenLoc(LParenLoc);
1078 setRParenLoc(RParenLoc);
Douglas Gregor27b98ea2010-06-21 23:44:13 +00001079}
1080
Bruno Riccibacf7512018-10-30 13:42:41 +00001081WhileStmt::WhileStmt(EmptyShell Empty, bool HasVar)
1082 : Stmt(WhileStmtClass, Empty) {
1083 WhileStmtBits.HasVar = HasVar;
1084}
Chad Rosier42032fa2012-08-07 23:12:23 +00001085
Bruno Riccibacf7512018-10-30 13:42:41 +00001086WhileStmt *WhileStmt::Create(const ASTContext &Ctx, VarDecl *Var, Expr *Cond,
Vy Nguyen17ea41e2020-07-09 23:19:06 -04001087 Stmt *Body, SourceLocation WL,
1088 SourceLocation LParenLoc,
1089 SourceLocation RParenLoc) {
Bruno Riccibacf7512018-10-30 13:42:41 +00001090 bool HasVar = Var != nullptr;
1091 void *Mem =
1092 Ctx.Allocate(totalSizeToAlloc<Stmt *>(NumMandatoryStmtPtr + HasVar),
1093 alignof(WhileStmt));
Vy Nguyen17ea41e2020-07-09 23:19:06 -04001094 return new (Mem) WhileStmt(Ctx, Var, Cond, Body, WL, LParenLoc, RParenLoc);
Bruno Riccibacf7512018-10-30 13:42:41 +00001095}
1096
1097WhileStmt *WhileStmt::CreateEmpty(const ASTContext &Ctx, bool HasVar) {
1098 void *Mem =
1099 Ctx.Allocate(totalSizeToAlloc<Stmt *>(NumMandatoryStmtPtr + HasVar),
1100 alignof(WhileStmt));
1101 return new (Mem) WhileStmt(EmptyShell(), HasVar);
1102}
1103
1104VarDecl *WhileStmt::getConditionVariable() {
1105 auto *DS = getConditionVariableDeclStmt();
1106 if (!DS)
1107 return nullptr;
Douglas Gregor27b98ea2010-06-21 23:44:13 +00001108 return cast<VarDecl>(DS->getSingleDecl());
1109}
1110
Bruno Riccibacf7512018-10-30 13:42:41 +00001111void WhileStmt::setConditionVariable(const ASTContext &Ctx, VarDecl *V) {
1112 assert(hasVarStorage() &&
1113 "This while statement has no storage for a condition variable!");
1114
Douglas Gregor27b98ea2010-06-21 23:44:13 +00001115 if (!V) {
Bruno Riccibacf7512018-10-30 13:42:41 +00001116 getTrailingObjects<Stmt *>()[varOffset()] = nullptr;
Douglas Gregor27b98ea2010-06-21 23:44:13 +00001117 return;
1118 }
Daniel Dunbar62ee6412012-03-09 18:35:03 +00001119
1120 SourceRange VarRange = V->getSourceRange();
Bruno Riccibacf7512018-10-30 13:42:41 +00001121 getTrailingObjects<Stmt *>()[varOffset()] = new (Ctx)
1122 DeclStmt(DeclGroupRef(V), VarRange.getBegin(), VarRange.getEnd());
Douglas Gregor27b98ea2010-06-21 23:44:13 +00001123}
1124
Ted Kremenek066dd932007-08-24 21:09:09 +00001125// IndirectGotoStmt
Chris Lattnerc8e630e2011-02-17 07:39:24 +00001126LabelDecl *IndirectGotoStmt::getConstantTarget() {
Eugene Zelenko7855e772018-04-03 00:11:50 +00001127 if (auto *E = dyn_cast<AddrLabelExpr>(getTarget()->IgnoreParenImpCasts()))
John McCall9de91602010-10-28 08:53:48 +00001128 return E->getLabel();
Craig Topper36250ad2014-05-12 05:36:57 +00001129 return nullptr;
John McCall9de91602010-10-28 08:53:48 +00001130}
Ted Kremenek066dd932007-08-24 21:09:09 +00001131
Ted Kremenek066dd932007-08-24 21:09:09 +00001132// ReturnStmt
Bruno Ricci023b1d12018-10-30 14:40:49 +00001133ReturnStmt::ReturnStmt(SourceLocation RL, Expr *E, const VarDecl *NRVOCandidate)
1134 : Stmt(ReturnStmtClass), RetExpr(E) {
1135 bool HasNRVOCandidate = NRVOCandidate != nullptr;
1136 ReturnStmtBits.HasNRVOCandidate = HasNRVOCandidate;
1137 if (HasNRVOCandidate)
1138 setNRVOCandidate(NRVOCandidate);
1139 setReturnLoc(RL);
Ted Kremenekc6501db2008-06-17 03:11:08 +00001140}
Bruno Ricci023b1d12018-10-30 14:40:49 +00001141
1142ReturnStmt::ReturnStmt(EmptyShell Empty, bool HasNRVOCandidate)
1143 : Stmt(ReturnStmtClass, Empty) {
1144 ReturnStmtBits.HasNRVOCandidate = HasNRVOCandidate;
1145}
1146
1147ReturnStmt *ReturnStmt::Create(const ASTContext &Ctx, SourceLocation RL,
1148 Expr *E, const VarDecl *NRVOCandidate) {
1149 bool HasNRVOCandidate = NRVOCandidate != nullptr;
1150 void *Mem = Ctx.Allocate(totalSizeToAlloc<const VarDecl *>(HasNRVOCandidate),
1151 alignof(ReturnStmt));
1152 return new (Mem) ReturnStmt(RL, E, NRVOCandidate);
1153}
1154
1155ReturnStmt *ReturnStmt::CreateEmpty(const ASTContext &Ctx,
1156 bool HasNRVOCandidate) {
1157 void *Mem = Ctx.Allocate(totalSizeToAlloc<const VarDecl *>(HasNRVOCandidate),
1158 alignof(ReturnStmt));
1159 return new (Mem) ReturnStmt(EmptyShell(), HasNRVOCandidate);
Ted Kremenek066dd932007-08-24 21:09:09 +00001160}
John Wiegley1c0675e2011-04-28 01:08:34 +00001161
Bruno Ricci5b30571752018-10-28 12:30:53 +00001162// CaseStmt
1163CaseStmt *CaseStmt::Create(const ASTContext &Ctx, Expr *lhs, Expr *rhs,
1164 SourceLocation caseLoc, SourceLocation ellipsisLoc,
1165 SourceLocation colonLoc) {
1166 bool CaseStmtIsGNURange = rhs != nullptr;
1167 void *Mem = Ctx.Allocate(
1168 totalSizeToAlloc<Stmt *, SourceLocation>(
1169 NumMandatoryStmtPtr + CaseStmtIsGNURange, CaseStmtIsGNURange),
1170 alignof(CaseStmt));
1171 return new (Mem) CaseStmt(lhs, rhs, caseLoc, ellipsisLoc, colonLoc);
1172}
1173
1174CaseStmt *CaseStmt::CreateEmpty(const ASTContext &Ctx,
1175 bool CaseStmtIsGNURange) {
1176 void *Mem = Ctx.Allocate(
1177 totalSizeToAlloc<Stmt *, SourceLocation>(
1178 NumMandatoryStmtPtr + CaseStmtIsGNURange, CaseStmtIsGNURange),
1179 alignof(CaseStmt));
1180 return new (Mem) CaseStmt(EmptyShell(), CaseStmtIsGNURange);
1181}
1182
Eugene Zelenko1eab6c12017-11-14 23:35:42 +00001183SEHTryStmt::SEHTryStmt(bool IsCXXTry, SourceLocation TryLoc, Stmt *TryBlock,
Warren Huntf6be4cb2014-07-25 20:52:51 +00001184 Stmt *Handler)
Eugene Zelenko1eab6c12017-11-14 23:35:42 +00001185 : Stmt(SEHTryStmtClass), IsCXXTry(IsCXXTry), TryLoc(TryLoc) {
Warren Huntf6be4cb2014-07-25 20:52:51 +00001186 Children[TRY] = TryBlock;
John Wiegley1c0675e2011-04-28 01:08:34 +00001187 Children[HANDLER] = Handler;
1188}
1189
Warren Huntf6be4cb2014-07-25 20:52:51 +00001190SEHTryStmt* SEHTryStmt::Create(const ASTContext &C, bool IsCXXTry,
Craig Toppere6960e22013-08-22 05:28:54 +00001191 SourceLocation TryLoc, Stmt *TryBlock,
Warren Huntf6be4cb2014-07-25 20:52:51 +00001192 Stmt *Handler) {
1193 return new(C) SEHTryStmt(IsCXXTry,TryLoc,TryBlock,Handler);
John Wiegley1c0675e2011-04-28 01:08:34 +00001194}
1195
1196SEHExceptStmt* SEHTryStmt::getExceptHandler() const {
1197 return dyn_cast<SEHExceptStmt>(getHandler());
1198}
1199
1200SEHFinallyStmt* SEHTryStmt::getFinallyHandler() const {
1201 return dyn_cast<SEHFinallyStmt>(getHandler());
1202}
1203
Eugene Zelenko1eab6c12017-11-14 23:35:42 +00001204SEHExceptStmt::SEHExceptStmt(SourceLocation Loc, Expr *FilterExpr, Stmt *Block)
1205 : Stmt(SEHExceptStmtClass), Loc(Loc) {
Pavel Labath515f4db2013-09-03 14:41:16 +00001206 Children[FILTER_EXPR] = FilterExpr;
John Wiegley1c0675e2011-04-28 01:08:34 +00001207 Children[BLOCK] = Block;
1208}
1209
Craig Toppere6960e22013-08-22 05:28:54 +00001210SEHExceptStmt* SEHExceptStmt::Create(const ASTContext &C, SourceLocation Loc,
1211 Expr *FilterExpr, Stmt *Block) {
John Wiegley1c0675e2011-04-28 01:08:34 +00001212 return new(C) SEHExceptStmt(Loc,FilterExpr,Block);
1213}
1214
Eugene Zelenko1eab6c12017-11-14 23:35:42 +00001215SEHFinallyStmt::SEHFinallyStmt(SourceLocation Loc, Stmt *Block)
1216 : Stmt(SEHFinallyStmtClass), Loc(Loc), Block(Block) {}
John Wiegley1c0675e2011-04-28 01:08:34 +00001217
Craig Toppere6960e22013-08-22 05:28:54 +00001218SEHFinallyStmt* SEHFinallyStmt::Create(const ASTContext &C, SourceLocation Loc,
John Wiegley1c0675e2011-04-28 01:08:34 +00001219 Stmt *Block) {
1220 return new(C)SEHFinallyStmt(Loc,Block);
1221}
Tareq A. Siraj24110cc2013-04-16 18:53:08 +00001222
Samuel Antao4af1b7b2015-12-02 17:44:43 +00001223CapturedStmt::Capture::Capture(SourceLocation Loc, VariableCaptureKind Kind,
1224 VarDecl *Var)
1225 : VarAndKind(Var, Kind), Loc(Loc) {
1226 switch (Kind) {
1227 case VCK_This:
1228 assert(!Var && "'this' capture cannot have a variable!");
1229 break;
1230 case VCK_ByRef:
1231 assert(Var && "capturing by reference must have a variable!");
1232 break;
1233 case VCK_ByCopy:
1234 assert(Var && "capturing by copy must have a variable!");
1235 assert(
1236 (Var->getType()->isScalarType() || (Var->getType()->isReferenceType() &&
1237 Var->getType()
1238 ->castAs<ReferenceType>()
1239 ->getPointeeType()
1240 ->isScalarType())) &&
1241 "captures by copy are expected to have a scalar type!");
1242 break;
1243 case VCK_VLAType:
1244 assert(!Var &&
1245 "Variable-length array type capture cannot have a variable!");
1246 break;
1247 }
1248}
1249
Chandler Carruth21c90602015-12-30 03:24:14 +00001250CapturedStmt::VariableCaptureKind
1251CapturedStmt::Capture::getCaptureKind() const {
1252 return VarAndKind.getInt();
1253}
1254
1255VarDecl *CapturedStmt::Capture::getCapturedVar() const {
1256 assert((capturesVariable() || capturesVariableByCopy()) &&
1257 "No variable available for 'this' or VAT capture");
1258 return VarAndKind.getPointer();
1259}
1260
Tareq A. Siraj24110cc2013-04-16 18:53:08 +00001261CapturedStmt::Capture *CapturedStmt::getStoredCaptures() const {
1262 unsigned Size = sizeof(CapturedStmt) + sizeof(Stmt *) * (NumCaptures + 1);
1263
1264 // Offset of the first Capture object.
Benjamin Kramerc3f89252016-10-20 14:27:22 +00001265 unsigned FirstCaptureOffset = llvm::alignTo(Size, alignof(Capture));
Tareq A. Siraj24110cc2013-04-16 18:53:08 +00001266
1267 return reinterpret_cast<Capture *>(
1268 reinterpret_cast<char *>(const_cast<CapturedStmt *>(this))
1269 + FirstCaptureOffset);
1270}
1271
Wei Pan17fbf6e2013-05-04 03:59:06 +00001272CapturedStmt::CapturedStmt(Stmt *S, CapturedRegionKind Kind,
1273 ArrayRef<Capture> Captures,
Tareq A. Siraj24110cc2013-04-16 18:53:08 +00001274 ArrayRef<Expr *> CaptureInits,
Tareq A. Siraj6dfa25a2013-04-16 19:37:38 +00001275 CapturedDecl *CD,
Tareq A. Siraj24110cc2013-04-16 18:53:08 +00001276 RecordDecl *RD)
1277 : Stmt(CapturedStmtClass), NumCaptures(Captures.size()),
Wei Pan17fbf6e2013-05-04 03:59:06 +00001278 CapDeclAndKind(CD, Kind), TheRecordDecl(RD) {
Tareq A. Siraj24110cc2013-04-16 18:53:08 +00001279 assert( S && "null captured statement");
Tareq A. Siraj6dfa25a2013-04-16 19:37:38 +00001280 assert(CD && "null captured declaration for captured statement");
Tareq A. Siraj24110cc2013-04-16 18:53:08 +00001281 assert(RD && "null record declaration for captured statement");
1282
1283 // Copy initialization expressions.
1284 Stmt **Stored = getStoredStmts();
1285 for (unsigned I = 0, N = NumCaptures; I != N; ++I)
1286 *Stored++ = CaptureInits[I];
1287
1288 // Copy the statement being captured.
1289 *Stored = S;
1290
1291 // Copy all Capture objects.
1292 Capture *Buffer = getStoredCaptures();
1293 std::copy(Captures.begin(), Captures.end(), Buffer);
1294}
1295
1296CapturedStmt::CapturedStmt(EmptyShell Empty, unsigned NumCaptures)
1297 : Stmt(CapturedStmtClass, Empty), NumCaptures(NumCaptures),
Eugene Zelenko1eab6c12017-11-14 23:35:42 +00001298 CapDeclAndKind(nullptr, CR_Default) {
Craig Topper36250ad2014-05-12 05:36:57 +00001299 getStoredStmts()[NumCaptures] = nullptr;
Tareq A. Siraj24110cc2013-04-16 18:53:08 +00001300}
1301
Craig Toppere6960e22013-08-22 05:28:54 +00001302CapturedStmt *CapturedStmt::Create(const ASTContext &Context, Stmt *S,
Wei Pan17fbf6e2013-05-04 03:59:06 +00001303 CapturedRegionKind Kind,
Tareq A. Siraj24110cc2013-04-16 18:53:08 +00001304 ArrayRef<Capture> Captures,
1305 ArrayRef<Expr *> CaptureInits,
Tareq A. Siraj6dfa25a2013-04-16 19:37:38 +00001306 CapturedDecl *CD,
Tareq A. Siraj24110cc2013-04-16 18:53:08 +00001307 RecordDecl *RD) {
1308 // The layout is
1309 //
1310 // -----------------------------------------------------------
1311 // | CapturedStmt, Init, ..., Init, S, Capture, ..., Capture |
1312 // ----------------^-------------------^----------------------
1313 // getStoredStmts() getStoredCaptures()
1314 //
1315 // where S is the statement being captured.
1316 //
1317 assert(CaptureInits.size() == Captures.size() && "wrong number of arguments");
1318
1319 unsigned Size = sizeof(CapturedStmt) + sizeof(Stmt *) * (Captures.size() + 1);
1320 if (!Captures.empty()) {
1321 // Realign for the following Capture array.
Benjamin Kramerc3f89252016-10-20 14:27:22 +00001322 Size = llvm::alignTo(Size, alignof(Capture));
Tareq A. Siraj24110cc2013-04-16 18:53:08 +00001323 Size += sizeof(Capture) * Captures.size();
1324 }
1325
1326 void *Mem = Context.Allocate(Size);
Wei Pan17fbf6e2013-05-04 03:59:06 +00001327 return new (Mem) CapturedStmt(S, Kind, Captures, CaptureInits, CD, RD);
Tareq A. Siraj24110cc2013-04-16 18:53:08 +00001328}
1329
Craig Toppere6960e22013-08-22 05:28:54 +00001330CapturedStmt *CapturedStmt::CreateDeserialized(const ASTContext &Context,
Tareq A. Siraj24110cc2013-04-16 18:53:08 +00001331 unsigned NumCaptures) {
1332 unsigned Size = sizeof(CapturedStmt) + sizeof(Stmt *) * (NumCaptures + 1);
1333 if (NumCaptures > 0) {
1334 // Realign for the following Capture array.
Benjamin Kramerc3f89252016-10-20 14:27:22 +00001335 Size = llvm::alignTo(Size, alignof(Capture));
Tareq A. Siraj24110cc2013-04-16 18:53:08 +00001336 Size += sizeof(Capture) * NumCaptures;
1337 }
1338
1339 void *Mem = Context.Allocate(Size);
1340 return new (Mem) CapturedStmt(EmptyShell(), NumCaptures);
1341}
1342
1343Stmt::child_range CapturedStmt::children() {
Simon Pilgrim2c518802017-03-30 14:13:19 +00001344 // Children are captured field initializers.
Tareq A. Siraj6dfa25a2013-04-16 19:37:38 +00001345 return child_range(getStoredStmts(), getStoredStmts() + NumCaptures);
Tareq A. Siraj24110cc2013-04-16 18:53:08 +00001346}
1347
Bruno Ricci06186502019-04-12 15:36:02 +00001348Stmt::const_child_range CapturedStmt::children() const {
1349 return const_child_range(getStoredStmts(), getStoredStmts() + NumCaptures);
1350}
1351
Chandler Carruth21c90602015-12-30 03:24:14 +00001352CapturedDecl *CapturedStmt::getCapturedDecl() {
1353 return CapDeclAndKind.getPointer();
1354}
Eugene Zelenko1eab6c12017-11-14 23:35:42 +00001355
Chandler Carruth21c90602015-12-30 03:24:14 +00001356const CapturedDecl *CapturedStmt::getCapturedDecl() const {
1357 return CapDeclAndKind.getPointer();
1358}
1359
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001360/// Set the outlined function declaration.
Chandler Carruth21c90602015-12-30 03:24:14 +00001361void CapturedStmt::setCapturedDecl(CapturedDecl *D) {
1362 assert(D && "null CapturedDecl");
1363 CapDeclAndKind.setPointer(D);
1364}
1365
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001366/// Retrieve the captured region kind.
Chandler Carruth21c90602015-12-30 03:24:14 +00001367CapturedRegionKind CapturedStmt::getCapturedRegionKind() const {
1368 return CapDeclAndKind.getInt();
1369}
1370
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001371/// Set the captured region kind.
Chandler Carruth21c90602015-12-30 03:24:14 +00001372void CapturedStmt::setCapturedRegionKind(CapturedRegionKind Kind) {
1373 CapDeclAndKind.setInt(Kind);
1374}
1375
Tareq A. Siraj24110cc2013-04-16 18:53:08 +00001376bool CapturedStmt::capturesVariable(const VarDecl *Var) const {
Aaron Ballmanc656303a2014-03-14 18:08:33 +00001377 for (const auto &I : captures()) {
Alexey Bataev2c845412017-05-15 16:26:15 +00001378 if (!I.capturesVariable() && !I.capturesVariableByCopy())
Tareq A. Siraj24110cc2013-04-16 18:53:08 +00001379 continue;
Alexey Bataeve85de8f2017-09-20 20:11:31 +00001380 if (I.getCapturedVar()->getCanonicalDecl() == Var->getCanonicalDecl())
Tareq A. Siraj24110cc2013-04-16 18:53:08 +00001381 return true;
1382 }
1383
1384 return false;
1385}