1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | #include "clang/AST/Stmt.h" |
14 | #include "clang/AST/ASTContext.h" |
15 | #include "clang/AST/ASTDiagnostic.h" |
16 | #include "clang/AST/Decl.h" |
17 | #include "clang/AST/DeclGroup.h" |
18 | #include "clang/AST/Expr.h" |
19 | #include "clang/AST/ExprCXX.h" |
20 | #include "clang/AST/ExprObjC.h" |
21 | #include "clang/AST/ExprOpenMP.h" |
22 | #include "clang/AST/StmtCXX.h" |
23 | #include "clang/AST/StmtObjC.h" |
24 | #include "clang/AST/StmtOpenMP.h" |
25 | #include "clang/AST/Type.h" |
26 | #include "clang/Basic/CharInfo.h" |
27 | #include "clang/Basic/LLVM.h" |
28 | #include "clang/Basic/SourceLocation.h" |
29 | #include "clang/Basic/TargetInfo.h" |
30 | #include "clang/Lex/Token.h" |
31 | #include "llvm/ADT/SmallVector.h" |
32 | #include "llvm/ADT/StringExtras.h" |
33 | #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" |
38 | #include "llvm/Support/raw_ostream.h" |
39 | #include <algorithm> |
40 | #include <cassert> |
41 | #include <cstring> |
42 | #include <string> |
43 | #include <utility> |
44 | |
45 | using namespace clang; |
46 | |
47 | static struct StmtClassNameTable { |
48 | const char *Name; |
49 | unsigned Counter; |
50 | unsigned Size; |
51 | } StmtClassInfo[Stmt::lastStmtConstant+1]; |
52 | |
53 | static StmtClassNameTable &getStmtInfoTableEntry(Stmt::StmtClass E) { |
54 | static bool Initialized = false; |
55 | if (Initialized) |
56 | return StmtClassInfo[E]; |
57 | |
58 | |
59 | Initialized = true; |
60 | #define ABSTRACT_STMT(STMT) |
61 | #define STMT(CLASS, PARENT) \ |
62 | StmtClassInfo[(unsigned)Stmt::CLASS##Class].Name = #CLASS; \ |
63 | StmtClassInfo[(unsigned)Stmt::CLASS##Class].Size = sizeof(CLASS); |
64 | #include "clang/AST/StmtNodes.inc" |
65 | |
66 | return StmtClassInfo[E]; |
67 | } |
68 | |
69 | void *Stmt::operator new(size_t bytes, const ASTContext& C, |
70 | unsigned alignment) { |
71 | return ::operator new(bytes, C, alignment); |
72 | } |
73 | |
74 | const char *Stmt::getStmtClassName() const { |
75 | return getStmtInfoTableEntry((StmtClass) StmtBits.sClass).Name; |
76 | } |
77 | |
78 | |
79 | |
80 | |
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 | |
86 | void Stmt::PrintStats() { |
87 | |
88 | getStmtInfoTableEntry(Stmt::NullStmtClass); |
89 | |
90 | unsigned sum = 0; |
91 | llvm::errs() << "\n*** Stmt/Expr Stats:\n"; |
92 | for (int i = 0; i != Stmt::lastStmtConstant+1; i++) { |
93 | if (StmtClassInfo[i].Name == nullptr) continue; |
94 | sum += StmtClassInfo[i].Counter; |
95 | } |
96 | llvm::errs() << " " << sum << " stmts/exprs total.\n"; |
97 | sum = 0; |
98 | for (int i = 0; i != Stmt::lastStmtConstant+1; i++) { |
99 | if (StmtClassInfo[i].Name == nullptr) continue; |
100 | if (StmtClassInfo[i].Counter == 0) continue; |
101 | llvm::errs() << " " << StmtClassInfo[i].Counter << " " |
102 | << StmtClassInfo[i].Name << ", " << StmtClassInfo[i].Size |
103 | << " each (" << StmtClassInfo[i].Counter*StmtClassInfo[i].Size |
104 | << " bytes)\n"; |
105 | sum += StmtClassInfo[i].Counter*StmtClassInfo[i].Size; |
106 | } |
107 | |
108 | llvm::errs() << "Total bytes = " << sum << "\n"; |
109 | } |
110 | |
111 | void Stmt::addStmtClass(StmtClass s) { |
112 | ++getStmtInfoTableEntry(s).Counter; |
113 | } |
114 | |
115 | bool Stmt::StatisticsEnabled = false; |
116 | void Stmt::EnableStatistics() { |
117 | StatisticsEnabled = true; |
118 | } |
119 | |
120 | |
121 | |
122 | Stmt *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 | |
140 | |
141 | |
142 | |
143 | |
144 | const Stmt *Stmt::stripLabelLikeStatements() const { |
145 | const Stmt *S = this; |
146 | while (true) { |
147 | if (const auto *LS = dyn_cast<LabelStmt>(S)) |
148 | S = LS->getSubStmt(); |
149 | else if (const auto *SC = dyn_cast<SwitchCase>(S)) |
150 | S = SC->getSubStmt(); |
151 | else if (const auto *AS = dyn_cast<AttributedStmt>(S)) |
152 | S = AS->getSubStmt(); |
153 | else |
154 | return S; |
155 | } |
156 | } |
157 | |
158 | namespace { |
159 | |
160 | struct good {}; |
161 | struct bad {}; |
162 | |
163 | |
164 | |
165 | |
166 | static good is_good(good) { return good(); } |
167 | |
168 | typedef Stmt::child_range children_t(); |
169 | template <class T> good implements_children(children_t T::*) { |
170 | return good(); |
171 | } |
172 | LLVM_ATTRIBUTE_UNUSED |
173 | static bad implements_children(children_t Stmt::*) { |
174 | return bad(); |
175 | } |
176 | |
177 | typedef SourceLocation getBeginLoc_t() const; |
178 | template <class T> good implements_getBeginLoc(getBeginLoc_t T::*) { |
179 | return good(); |
180 | } |
181 | LLVM_ATTRIBUTE_UNUSED |
182 | static bad implements_getBeginLoc(getBeginLoc_t Stmt::*) { return bad(); } |
183 | |
184 | typedef SourceLocation getLocEnd_t() const; |
185 | template <class T> good implements_getEndLoc(getLocEnd_t T::*) { |
186 | return good(); |
187 | } |
188 | LLVM_ATTRIBUTE_UNUSED |
189 | static bad implements_getEndLoc(getLocEnd_t Stmt::*) { return bad(); } |
190 | |
191 | #define ASSERT_IMPLEMENTS_children(type) \ |
192 | (void) is_good(implements_children(&type::children)) |
193 | #define ASSERT_IMPLEMENTS_getBeginLoc(type) \ |
194 | (void)is_good(implements_getBeginLoc(&type::getBeginLoc)) |
195 | #define ASSERT_IMPLEMENTS_getEndLoc(type) \ |
196 | (void)is_good(implements_getEndLoc(&type::getEndLoc)) |
197 | |
198 | } |
199 | |
200 | |
201 | |
202 | LLVM_ATTRIBUTE_UNUSED |
203 | static inline void check_implementations() { |
204 | #define ABSTRACT_STMT(type) |
205 | #define STMT(type, base) \ |
206 | ASSERT_IMPLEMENTS_children(type); \ |
207 | ASSERT_IMPLEMENTS_getBeginLoc(type); \ |
208 | ASSERT_IMPLEMENTS_getEndLoc(type); |
209 | #include "clang/AST/StmtNodes.inc" |
210 | } |
211 | |
212 | Stmt::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!"); |
222 | } |
223 | |
224 | |
225 | |
226 | |
227 | |
228 | namespace { |
229 | |
230 | |
231 | |
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 | |
239 | |
240 | |
241 | |
242 | template <class S> |
243 | SourceRange getSourceRangeImpl(const Stmt *stmt, |
244 | SourceRange (Stmt::*v)() const) { |
245 | return SourceRange(static_cast<const S *>(stmt)->getBeginLoc(), |
246 | static_cast<const S *>(stmt)->getEndLoc()); |
247 | } |
248 | |
249 | } |
250 | |
251 | SourceRange 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: \ |
257 | return getSourceRangeImpl<type>(this, &type::getSourceRange); |
258 | #include "clang/AST/StmtNodes.inc" |
259 | } |
260 | llvm_unreachable("unknown statement kind!"); |
261 | } |
262 | |
263 | SourceLocation Stmt::getBeginLoc() const { |
264 | |
265 | switch (getStmtClass()) { |
266 | case Stmt::NoStmtClass: llvm_unreachable("statement without class"); |
267 | #define ABSTRACT_STMT(type) |
268 | #define STMT(type, base) \ |
269 | case Stmt::type##Class: \ |
270 | return static_cast<const type *>(this)->getBeginLoc(); |
271 | #include "clang/AST/StmtNodes.inc" |
272 | } |
273 | llvm_unreachable("unknown statement kind"); |
274 | } |
275 | |
276 | SourceLocation Stmt::getEndLoc() const { |
277 | switch (getStmtClass()) { |
278 | case Stmt::NoStmtClass: llvm_unreachable("statement without class"); |
279 | #define ABSTRACT_STMT(type) |
280 | #define STMT(type, base) \ |
281 | case Stmt::type##Class: \ |
282 | return static_cast<const type *>(this)->getEndLoc(); |
283 | #include "clang/AST/StmtNodes.inc" |
284 | } |
285 | llvm_unreachable("unknown statement kind"); |
286 | } |
287 | |
288 | int64_t Stmt::getID(const ASTContext &Context) const { |
289 | return Context.getAllocator().identifyKnownAlignedObject<Stmt>(this); |
290 | } |
291 | |
292 | CompoundStmt::CompoundStmt(ArrayRef<Stmt *> Stmts, SourceLocation LB, |
293 | SourceLocation RB) |
294 | : Stmt(CompoundStmtClass), RBraceLoc(RB) { |
295 | CompoundStmtBits.NumStmts = Stmts.size(); |
296 | setStmts(Stmts); |
297 | CompoundStmtBits.LBraceLoc = LB; |
298 | } |
299 | |
300 | void CompoundStmt::setStmts(ArrayRef<Stmt *> Stmts) { |
301 | (0) . __assert_fail ("CompoundStmtBits.NumStmts == Stmts.size() && \"NumStmts doesn't fit in bits of CompoundStmtBits.NumStmts!\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/Stmt.cpp", 302, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(CompoundStmtBits.NumStmts == Stmts.size() && |
302 | (0) . __assert_fail ("CompoundStmtBits.NumStmts == Stmts.size() && \"NumStmts doesn't fit in bits of CompoundStmtBits.NumStmts!\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/Stmt.cpp", 302, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> "NumStmts doesn't fit in bits of CompoundStmtBits.NumStmts!"); |
303 | |
304 | std::copy(Stmts.begin(), Stmts.end(), body_begin()); |
305 | } |
306 | |
307 | CompoundStmt *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 | |
314 | CompoundStmt *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; |
321 | } |
322 | |
323 | const 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 | |
340 | const char *LabelStmt::getName() const { |
341 | return getDecl()->getIdentifier()->getNameStart(); |
342 | } |
343 | |
344 | AttributedStmt *AttributedStmt::Create(const ASTContext &C, SourceLocation Loc, |
345 | ArrayRef<const Attr*> Attrs, |
346 | Stmt *SubStmt) { |
347 | (0) . __assert_fail ("!Attrs.empty() && \"Attrs should not be empty\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/Stmt.cpp", 347, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(!Attrs.empty() && "Attrs should not be empty"); |
348 | void *Mem = C.Allocate(totalSizeToAlloc<const Attr *>(Attrs.size()), |
349 | alignof(AttributedStmt)); |
350 | return new (Mem) AttributedStmt(Loc, Attrs, SubStmt); |
351 | } |
352 | |
353 | AttributedStmt *AttributedStmt::CreateEmpty(const ASTContext &C, |
354 | unsigned NumAttrs) { |
355 | (0) . __assert_fail ("NumAttrs > 0 && \"NumAttrs should be greater than zero\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/Stmt.cpp", 355, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(NumAttrs > 0 && "NumAttrs should be greater than zero"); |
356 | void *Mem = C.Allocate(totalSizeToAlloc<const Attr *>(NumAttrs), |
357 | alignof(AttributedStmt)); |
358 | return new (Mem) AttributedStmt(EmptyShell(), NumAttrs); |
359 | } |
360 | |
361 | std::string AsmStmt::generateAsmString(const ASTContext &C) const { |
362 | if (const auto *gccAsmStmt = dyn_cast<GCCAsmStmt>(this)) |
363 | return gccAsmStmt->generateAsmString(C); |
364 | if (const auto *msAsmStmt = dyn_cast<MSAsmStmt>(this)) |
365 | return msAsmStmt->generateAsmString(C); |
366 | llvm_unreachable("unknown asm statement kind!"); |
367 | } |
368 | |
369 | StringRef AsmStmt::getOutputConstraint(unsigned i) const { |
370 | if (const auto *gccAsmStmt = dyn_cast<GCCAsmStmt>(this)) |
371 | return gccAsmStmt->getOutputConstraint(i); |
372 | if (const auto *msAsmStmt = dyn_cast<MSAsmStmt>(this)) |
373 | return msAsmStmt->getOutputConstraint(i); |
374 | llvm_unreachable("unknown asm statement kind!"); |
375 | } |
376 | |
377 | const Expr *AsmStmt::getOutputExpr(unsigned i) const { |
378 | if (const auto *gccAsmStmt = dyn_cast<GCCAsmStmt>(this)) |
379 | return gccAsmStmt->getOutputExpr(i); |
380 | if (const auto *msAsmStmt = dyn_cast<MSAsmStmt>(this)) |
381 | return msAsmStmt->getOutputExpr(i); |
382 | llvm_unreachable("unknown asm statement kind!"); |
383 | } |
384 | |
385 | StringRef AsmStmt::getInputConstraint(unsigned i) const { |
386 | if (const auto *gccAsmStmt = dyn_cast<GCCAsmStmt>(this)) |
387 | return gccAsmStmt->getInputConstraint(i); |
388 | if (const auto *msAsmStmt = dyn_cast<MSAsmStmt>(this)) |
389 | return msAsmStmt->getInputConstraint(i); |
390 | llvm_unreachable("unknown asm statement kind!"); |
391 | } |
392 | |
393 | const Expr *AsmStmt::getInputExpr(unsigned i) const { |
394 | if (const auto *gccAsmStmt = dyn_cast<GCCAsmStmt>(this)) |
395 | return gccAsmStmt->getInputExpr(i); |
396 | if (const auto *msAsmStmt = dyn_cast<MSAsmStmt>(this)) |
397 | return msAsmStmt->getInputExpr(i); |
398 | llvm_unreachable("unknown asm statement kind!"); |
399 | } |
400 | |
401 | StringRef AsmStmt::getClobber(unsigned i) const { |
402 | if (const auto *gccAsmStmt = dyn_cast<GCCAsmStmt>(this)) |
403 | return gccAsmStmt->getClobber(i); |
404 | if (const auto *msAsmStmt = dyn_cast<MSAsmStmt>(this)) |
405 | return msAsmStmt->getClobber(i); |
406 | llvm_unreachable("unknown asm statement kind!"); |
407 | } |
408 | |
409 | |
410 | |
411 | unsigned 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 | |
419 | char GCCAsmStmt::AsmStringPiece::getModifier() const { |
420 | (0) . __assert_fail ("isOperand() && \"Only Operands can have modifiers.\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/Stmt.cpp", 420, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(isOperand() && "Only Operands can have modifiers."); |
421 | return isLetter(Str[0]) ? Str[0] : '\0'; |
422 | } |
423 | |
424 | StringRef GCCAsmStmt::getClobber(unsigned i) const { |
425 | return getClobberStringLiteral(i)->getString(); |
426 | } |
427 | |
428 | Expr *GCCAsmStmt::getOutputExpr(unsigned i) { |
429 | return cast<Expr>(Exprs[i]); |
430 | } |
431 | |
432 | |
433 | |
434 | |
435 | StringRef GCCAsmStmt::getOutputConstraint(unsigned i) const { |
436 | return getOutputConstraintLiteral(i)->getString(); |
437 | } |
438 | |
439 | Expr *GCCAsmStmt::getInputExpr(unsigned i) { |
440 | return cast<Expr>(Exprs[i + NumOutputs]); |
441 | } |
442 | |
443 | void GCCAsmStmt::setInputExpr(unsigned i, Expr *E) { |
444 | Exprs[i + NumOutputs] = E; |
445 | } |
446 | |
447 | |
448 | |
449 | StringRef GCCAsmStmt::getInputConstraint(unsigned i) const { |
450 | return getInputConstraintLiteral(i)->getString(); |
451 | } |
452 | |
453 | void GCCAsmStmt::setOutputsAndInputsAndClobbers(const ASTContext &C, |
454 | IdentifierInfo **Names, |
455 | StringLiteral **Constraints, |
456 | Stmt **Exprs, |
457 | unsigned NumOutputs, |
458 | unsigned NumInputs, |
459 | StringLiteral **Clobbers, |
460 | unsigned NumClobbers) { |
461 | this->NumOutputs = NumOutputs; |
462 | this->NumInputs = NumInputs; |
463 | this->NumClobbers = NumClobbers; |
464 | |
465 | unsigned NumExprs = NumOutputs + NumInputs; |
466 | |
467 | C.Deallocate(this->Names); |
468 | this->Names = new (C) IdentifierInfo*[NumExprs]; |
469 | std::copy(Names, Names + NumExprs, this->Names); |
470 | |
471 | C.Deallocate(this->Exprs); |
472 | this->Exprs = new (C) Stmt*[NumExprs]; |
473 | std::copy(Exprs, Exprs + NumExprs, this->Exprs); |
474 | |
475 | C.Deallocate(this->Constraints); |
476 | this->Constraints = new (C) StringLiteral*[NumExprs]; |
477 | std::copy(Constraints, Constraints + NumExprs, this->Constraints); |
478 | |
479 | C.Deallocate(this->Clobbers); |
480 | this->Clobbers = new (C) StringLiteral*[NumClobbers]; |
481 | std::copy(Clobbers, Clobbers + NumClobbers, this->Clobbers); |
482 | } |
483 | |
484 | |
485 | |
486 | |
487 | int GCCAsmStmt::getNamedOperand(StringRef SymbolicName) const { |
488 | unsigned NumPlusOperands = 0; |
489 | |
490 | |
491 | for (unsigned i = 0, e = getNumOutputs(); i != e; ++i) { |
492 | if (getOutputName(i) == SymbolicName) |
493 | return i; |
494 | } |
495 | |
496 | for (unsigned i = 0, e = getNumInputs(); i != e; ++i) |
497 | if (getInputName(i) == SymbolicName) |
498 | return getNumOutputs() + NumPlusOperands + i; |
499 | |
500 | |
501 | return -1; |
502 | } |
503 | |
504 | |
505 | |
506 | |
507 | unsigned GCCAsmStmt::AnalyzeAsmString(SmallVectorImpl<AsmStringPiece>&Pieces, |
508 | const ASTContext &C, unsigned &DiagOffs) const { |
509 | StringRef Str = getAsmString()->getString(); |
510 | const char *StrStart = Str.begin(); |
511 | const char *StrEnd = Str.end(); |
512 | const char *CurPtr = StrStart; |
513 | |
514 | |
515 | |
516 | if (isSimple()) { |
517 | std::string Result; |
518 | for (; CurPtr != StrEnd; ++CurPtr) { |
519 | switch (*CurPtr) { |
520 | case '$': |
521 | Result += "$$"; |
522 | break; |
523 | default: |
524 | Result += *CurPtr; |
525 | break; |
526 | } |
527 | } |
528 | Pieces.push_back(AsmStringPiece(Result)); |
529 | return 0; |
530 | } |
531 | |
532 | |
533 | |
534 | std::string CurStringPiece; |
535 | |
536 | bool HasVariants = !C.getTargetInfo().hasNoAsmVariants(); |
537 | |
538 | unsigned LastAsmStringToken = 0; |
539 | unsigned LastAsmStringOffset = 0; |
540 | |
541 | while (true) { |
542 | |
543 | if (CurPtr == StrEnd) { |
544 | if (!CurStringPiece.empty()) |
545 | Pieces.push_back(AsmStringPiece(CurStringPiece)); |
546 | return 0; |
547 | } |
548 | |
549 | char CurChar = *CurPtr++; |
550 | switch (CurChar) { |
551 | case '$': CurStringPiece += "$$"; continue; |
552 | case '{': CurStringPiece += (HasVariants ? "$(" : "{"); continue; |
553 | case '|': CurStringPiece += (HasVariants ? "$|" : "|"); continue; |
554 | case '}': CurStringPiece += (HasVariants ? "$)" : "}"); continue; |
555 | case '%': |
556 | break; |
557 | default: |
558 | CurStringPiece += CurChar; |
559 | continue; |
560 | } |
561 | |
562 | |
563 | if (CurPtr == StrEnd) { |
564 | |
565 | DiagOffs = CurPtr-StrStart-1; |
566 | return diag::err_asm_invalid_escape; |
567 | } |
568 | |
569 | char EscapedChar = *CurPtr++; |
570 | switch (EscapedChar) { |
571 | default: |
572 | break; |
573 | case '%': |
574 | case '{': |
575 | case '}': |
576 | CurStringPiece += EscapedChar; |
577 | continue; |
578 | case '=': |
579 | CurStringPiece += "${:uid}"; |
580 | continue; |
581 | } |
582 | |
583 | |
584 | |
585 | if (!CurStringPiece.empty()) { |
586 | Pieces.push_back(AsmStringPiece(CurStringPiece)); |
587 | CurStringPiece.clear(); |
588 | } |
589 | |
590 | |
591 | |
592 | |
593 | const char *Begin = CurPtr - 1; |
594 | const char *Percent = Begin - 1; |
595 | |
596 | if (isLetter(EscapedChar)) { |
597 | if (CurPtr == StrEnd) { |
598 | DiagOffs = CurPtr-StrStart-1; |
599 | return diag::err_asm_invalid_escape; |
600 | } |
601 | EscapedChar = *CurPtr++; |
602 | } |
603 | |
604 | const TargetInfo &TI = C.getTargetInfo(); |
605 | const SourceManager &SM = C.getSourceManager(); |
606 | const LangOptions &LO = C.getLangOpts(); |
607 | |
608 | |
609 | if (isDigit(EscapedChar)) { |
610 | |
611 | unsigned N = 0; |
612 | |
613 | --CurPtr; |
614 | while (CurPtr != StrEnd && isDigit(*CurPtr)) |
615 | N = N*10 + ((*CurPtr++)-'0'); |
616 | |
617 | unsigned NumOperands = |
618 | getNumOutputs() + getNumPlusOperands() + getNumInputs(); |
619 | if (N >= NumOperands) { |
620 | DiagOffs = CurPtr-StrStart-1; |
621 | return diag::err_asm_invalid_operand_number; |
622 | } |
623 | |
624 | |
625 | std::string Str(Begin, CurPtr - Begin); |
626 | |
627 | |
628 | |
629 | SourceLocation BeginLoc = getAsmString()->getLocationOfByte( |
630 | Percent - StrStart, SM, LO, TI, &LastAsmStringToken, |
631 | &LastAsmStringOffset); |
632 | SourceLocation EndLoc = getAsmString()->getLocationOfByte( |
633 | CurPtr - StrStart, SM, LO, TI, &LastAsmStringToken, |
634 | &LastAsmStringOffset); |
635 | |
636 | Pieces.emplace_back(N, std::move(Str), BeginLoc, EndLoc); |
637 | continue; |
638 | } |
639 | |
640 | |
641 | if (EscapedChar == '[') { |
642 | DiagOffs = CurPtr-StrStart-1; |
643 | |
644 | |
645 | const char *NameEnd = (const char*)memchr(CurPtr, ']', StrEnd-CurPtr); |
646 | if (NameEnd == nullptr) |
647 | return diag::err_asm_unterminated_symbolic_operand_name; |
648 | if (NameEnd == CurPtr) |
649 | return diag::err_asm_empty_symbolic_operand_name; |
650 | |
651 | StringRef SymbolicName(CurPtr, NameEnd - CurPtr); |
652 | |
653 | int N = getNamedOperand(SymbolicName); |
654 | if (N == -1) { |
655 | |
656 | DiagOffs = CurPtr-StrStart; |
657 | return diag::err_asm_unknown_symbolic_operand_name; |
658 | } |
659 | |
660 | |
661 | std::string Str(Begin, NameEnd + 1 - Begin); |
662 | |
663 | |
664 | |
665 | SourceLocation BeginLoc = getAsmString()->getLocationOfByte( |
666 | Percent - StrStart, SM, LO, TI, &LastAsmStringToken, |
667 | &LastAsmStringOffset); |
668 | SourceLocation EndLoc = getAsmString()->getLocationOfByte( |
669 | NameEnd + 1 - StrStart, SM, LO, TI, &LastAsmStringToken, |
670 | &LastAsmStringOffset); |
671 | |
672 | Pieces.emplace_back(N, std::move(Str), BeginLoc, EndLoc); |
673 | |
674 | CurPtr = NameEnd+1; |
675 | continue; |
676 | } |
677 | |
678 | DiagOffs = CurPtr-StrStart-1; |
679 | return diag::err_asm_invalid_escape; |
680 | } |
681 | } |
682 | |
683 | |
684 | std::string GCCAsmStmt::generateAsmString(const ASTContext &C) const { |
685 | |
686 | |
687 | SmallVector<GCCAsmStmt::AsmStringPiece, 4> Pieces; |
688 | unsigned DiagOffs; |
689 | AnalyzeAsmString(Pieces, C, DiagOffs); |
690 | |
691 | std::string AsmString; |
692 | for (const auto &Piece : Pieces) { |
693 | if (Piece.isString()) |
694 | AsmString += Piece.getString(); |
695 | else if (Piece.getModifier() == '\0') |
696 | AsmString += '$' + llvm::utostr(Piece.getOperandNo()); |
697 | else |
698 | AsmString += "${" + llvm::utostr(Piece.getOperandNo()) + ':' + |
699 | Piece.getModifier() + '}'; |
700 | } |
701 | return AsmString; |
702 | } |
703 | |
704 | |
705 | std::string MSAsmStmt::generateAsmString(const ASTContext &C) const { |
706 | |
707 | return AsmStr; |
708 | } |
709 | |
710 | Expr *MSAsmStmt::getOutputExpr(unsigned i) { |
711 | return cast<Expr>(Exprs[i]); |
712 | } |
713 | |
714 | Expr *MSAsmStmt::getInputExpr(unsigned i) { |
715 | return cast<Expr>(Exprs[i + NumOutputs]); |
716 | } |
717 | |
718 | void MSAsmStmt::setInputExpr(unsigned i, Expr *E) { |
719 | Exprs[i + NumOutputs] = E; |
720 | } |
721 | |
722 | |
723 | |
724 | |
725 | |
726 | GCCAsmStmt::GCCAsmStmt(const ASTContext &C, SourceLocation asmloc, |
727 | bool issimple, bool isvolatile, unsigned numoutputs, |
728 | unsigned numinputs, IdentifierInfo **names, |
729 | StringLiteral **constraints, Expr **exprs, |
730 | StringLiteral *asmstr, unsigned numclobbers, |
731 | StringLiteral **clobbers, SourceLocation rparenloc) |
732 | : AsmStmt(GCCAsmStmtClass, asmloc, issimple, isvolatile, numoutputs, |
733 | numinputs, numclobbers), RParenLoc(rparenloc), AsmStr(asmstr) { |
734 | unsigned NumExprs = NumOutputs + NumInputs; |
735 | |
736 | Names = new (C) IdentifierInfo*[NumExprs]; |
737 | std::copy(names, names + NumExprs, Names); |
738 | |
739 | Exprs = new (C) Stmt*[NumExprs]; |
740 | std::copy(exprs, exprs + NumExprs, Exprs); |
741 | |
742 | Constraints = new (C) StringLiteral*[NumExprs]; |
743 | std::copy(constraints, constraints + NumExprs, Constraints); |
744 | |
745 | Clobbers = new (C) StringLiteral*[NumClobbers]; |
746 | std::copy(clobbers, clobbers + NumClobbers, Clobbers); |
747 | } |
748 | |
749 | MSAsmStmt::MSAsmStmt(const ASTContext &C, SourceLocation asmloc, |
750 | SourceLocation lbraceloc, bool issimple, bool isvolatile, |
751 | ArrayRef<Token> asmtoks, unsigned numoutputs, |
752 | unsigned numinputs, |
753 | ArrayRef<StringRef> constraints, ArrayRef<Expr*> exprs, |
754 | StringRef asmstr, ArrayRef<StringRef> clobbers, |
755 | SourceLocation endloc) |
756 | : AsmStmt(MSAsmStmtClass, asmloc, issimple, isvolatile, numoutputs, |
757 | numinputs, clobbers.size()), LBraceLoc(lbraceloc), |
758 | EndLoc(endloc), NumAsmToks(asmtoks.size()) { |
759 | initialize(C, asmstr, asmtoks, constraints, exprs, clobbers); |
760 | } |
761 | |
762 | static StringRef copyIntoContext(const ASTContext &C, StringRef str) { |
763 | return str.copy(C); |
764 | } |
765 | |
766 | void MSAsmStmt::initialize(const ASTContext &C, StringRef asmstr, |
767 | ArrayRef<Token> asmtoks, |
768 | ArrayRef<StringRef> constraints, |
769 | ArrayRef<Expr*> exprs, |
770 | ArrayRef<StringRef> clobbers) { |
771 | assert(NumAsmToks == asmtoks.size()); |
772 | assert(NumClobbers == clobbers.size()); |
773 | |
774 | assert(exprs.size() == NumOutputs + NumInputs); |
775 | assert(exprs.size() == constraints.size()); |
776 | |
777 | AsmStr = copyIntoContext(C, asmstr); |
778 | |
779 | Exprs = new (C) Stmt*[exprs.size()]; |
780 | std::copy(exprs.begin(), exprs.end(), Exprs); |
781 | |
782 | AsmToks = new (C) Token[asmtoks.size()]; |
783 | std::copy(asmtoks.begin(), asmtoks.end(), AsmToks); |
784 | |
785 | Constraints = new (C) StringRef[exprs.size()]; |
786 | std::transform(constraints.begin(), constraints.end(), Constraints, |
787 | [&](StringRef Constraint) { |
788 | return copyIntoContext(C, Constraint); |
789 | }); |
790 | |
791 | Clobbers = new (C) StringRef[NumClobbers]; |
792 | |
793 | std::transform(clobbers.begin(), clobbers.end(), Clobbers, |
794 | [&](StringRef Clobber) { |
795 | return copyIntoContext(C, Clobber); |
796 | }); |
797 | } |
798 | |
799 | IfStmt::IfStmt(const ASTContext &Ctx, SourceLocation IL, bool IsConstexpr, |
800 | Stmt *Init, VarDecl *Var, Expr *Cond, Stmt *Then, |
801 | SourceLocation EL, Stmt *Else) |
802 | : Stmt(IfStmtClass) { |
803 | bool HasElse = Else != nullptr; |
804 | bool HasVar = Var != nullptr; |
805 | bool HasInit = Init != nullptr; |
806 | IfStmtBits.HasElse = HasElse; |
807 | IfStmtBits.HasVar = HasVar; |
808 | IfStmtBits.HasInit = HasInit; |
809 | |
810 | setConstexpr(IsConstexpr); |
811 | |
812 | setCond(Cond); |
813 | setThen(Then); |
814 | if (HasElse) |
815 | setElse(Else); |
816 | if (HasVar) |
817 | setConditionVariable(Ctx, Var); |
818 | if (HasInit) |
819 | setInit(Init); |
820 | |
821 | setIfLoc(IL); |
822 | if (HasElse) |
823 | setElseLoc(EL); |
824 | } |
825 | |
826 | IfStmt::IfStmt(EmptyShell Empty, bool HasElse, bool HasVar, bool HasInit) |
827 | : Stmt(IfStmtClass, Empty) { |
828 | IfStmtBits.HasElse = HasElse; |
829 | IfStmtBits.HasVar = HasVar; |
830 | IfStmtBits.HasInit = HasInit; |
831 | } |
832 | |
833 | IfStmt *IfStmt::Create(const ASTContext &Ctx, SourceLocation IL, |
834 | bool IsConstexpr, Stmt *Init, VarDecl *Var, Expr *Cond, |
835 | Stmt *Then, SourceLocation EL, Stmt *Else) { |
836 | bool HasElse = Else != nullptr; |
837 | bool HasVar = Var != nullptr; |
838 | bool HasInit = Init != nullptr; |
839 | void *Mem = Ctx.Allocate( |
840 | totalSizeToAlloc<Stmt *, SourceLocation>( |
841 | NumMandatoryStmtPtr + HasElse + HasVar + HasInit, HasElse), |
842 | alignof(IfStmt)); |
843 | return new (Mem) |
844 | IfStmt(Ctx, IL, IsConstexpr, Init, Var, Cond, Then, EL, Else); |
845 | } |
846 | |
847 | IfStmt *IfStmt::CreateEmpty(const ASTContext &Ctx, bool HasElse, bool HasVar, |
848 | bool HasInit) { |
849 | void *Mem = Ctx.Allocate( |
850 | totalSizeToAlloc<Stmt *, SourceLocation>( |
851 | NumMandatoryStmtPtr + HasElse + HasVar + HasInit, HasElse), |
852 | alignof(IfStmt)); |
853 | return new (Mem) IfStmt(EmptyShell(), HasElse, HasVar, HasInit); |
854 | } |
855 | |
856 | VarDecl *IfStmt::getConditionVariable() { |
857 | auto *DS = getConditionVariableDeclStmt(); |
858 | if (!DS) |
859 | return nullptr; |
860 | return cast<VarDecl>(DS->getSingleDecl()); |
861 | } |
862 | |
863 | void IfStmt::setConditionVariable(const ASTContext &Ctx, VarDecl *V) { |
864 | (0) . __assert_fail ("hasVarStorage() && \"This if statement has no storage for a condition variable!\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/Stmt.cpp", 865, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(hasVarStorage() && |
865 | (0) . __assert_fail ("hasVarStorage() && \"This if statement has no storage for a condition variable!\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/Stmt.cpp", 865, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> "This if statement has no storage for a condition variable!"); |
866 | |
867 | if (!V) { |
868 | getTrailingObjects<Stmt *>()[varOffset()] = nullptr; |
869 | return; |
870 | } |
871 | |
872 | SourceRange VarRange = V->getSourceRange(); |
873 | getTrailingObjects<Stmt *>()[varOffset()] = new (Ctx) |
874 | DeclStmt(DeclGroupRef(V), VarRange.getBegin(), VarRange.getEnd()); |
875 | } |
876 | |
877 | bool IfStmt::isObjCAvailabilityCheck() const { |
878 | return isa<ObjCAvailabilityCheckExpr>(getCond()); |
879 | } |
880 | |
881 | ForStmt::ForStmt(const ASTContext &C, Stmt *Init, Expr *Cond, VarDecl *condVar, |
882 | Expr *Inc, Stmt *Body, SourceLocation FL, SourceLocation LP, |
883 | SourceLocation RP) |
884 | : Stmt(ForStmtClass), LParenLoc(LP), RParenLoc(RP) |
885 | { |
886 | SubExprs[INIT] = Init; |
887 | setConditionVariable(C, condVar); |
888 | SubExprs[COND] = Cond; |
889 | SubExprs[INC] = Inc; |
890 | SubExprs[BODY] = Body; |
891 | ForStmtBits.ForLoc = FL; |
892 | } |
893 | |
894 | VarDecl *ForStmt::getConditionVariable() const { |
895 | if (!SubExprs[CONDVAR]) |
896 | return nullptr; |
897 | |
898 | auto *DS = cast<DeclStmt>(SubExprs[CONDVAR]); |
899 | return cast<VarDecl>(DS->getSingleDecl()); |
900 | } |
901 | |
902 | void ForStmt::setConditionVariable(const ASTContext &C, VarDecl *V) { |
903 | if (!V) { |
904 | SubExprs[CONDVAR] = nullptr; |
905 | return; |
906 | } |
907 | |
908 | SourceRange VarRange = V->getSourceRange(); |
909 | SubExprs[CONDVAR] = new (C) DeclStmt(DeclGroupRef(V), VarRange.getBegin(), |
910 | VarRange.getEnd()); |
911 | } |
912 | |
913 | SwitchStmt::SwitchStmt(const ASTContext &Ctx, Stmt *Init, VarDecl *Var, |
914 | Expr *Cond) |
915 | : Stmt(SwitchStmtClass), FirstCase(nullptr) { |
916 | bool HasInit = Init != nullptr; |
917 | bool HasVar = Var != nullptr; |
918 | SwitchStmtBits.HasInit = HasInit; |
919 | SwitchStmtBits.HasVar = HasVar; |
920 | SwitchStmtBits.AllEnumCasesCovered = false; |
921 | |
922 | setCond(Cond); |
923 | setBody(nullptr); |
924 | if (HasInit) |
925 | setInit(Init); |
926 | if (HasVar) |
927 | setConditionVariable(Ctx, Var); |
928 | |
929 | setSwitchLoc(SourceLocation{}); |
930 | } |
931 | |
932 | SwitchStmt::SwitchStmt(EmptyShell Empty, bool HasInit, bool HasVar) |
933 | : Stmt(SwitchStmtClass, Empty) { |
934 | SwitchStmtBits.HasInit = HasInit; |
935 | SwitchStmtBits.HasVar = HasVar; |
936 | SwitchStmtBits.AllEnumCasesCovered = false; |
937 | } |
938 | |
939 | SwitchStmt *SwitchStmt::Create(const ASTContext &Ctx, Stmt *Init, VarDecl *Var, |
940 | Expr *Cond) { |
941 | bool HasInit = Init != nullptr; |
942 | bool HasVar = Var != nullptr; |
943 | void *Mem = Ctx.Allocate( |
944 | totalSizeToAlloc<Stmt *>(NumMandatoryStmtPtr + HasInit + HasVar), |
945 | alignof(SwitchStmt)); |
946 | return new (Mem) SwitchStmt(Ctx, Init, Var, Cond); |
947 | } |
948 | |
949 | SwitchStmt *SwitchStmt::CreateEmpty(const ASTContext &Ctx, bool HasInit, |
950 | bool HasVar) { |
951 | void *Mem = Ctx.Allocate( |
952 | totalSizeToAlloc<Stmt *>(NumMandatoryStmtPtr + HasInit + HasVar), |
953 | alignof(SwitchStmt)); |
954 | return new (Mem) SwitchStmt(EmptyShell(), HasInit, HasVar); |
955 | } |
956 | |
957 | VarDecl *SwitchStmt::getConditionVariable() { |
958 | auto *DS = getConditionVariableDeclStmt(); |
959 | if (!DS) |
960 | return nullptr; |
961 | return cast<VarDecl>(DS->getSingleDecl()); |
962 | } |
963 | |
964 | void SwitchStmt::setConditionVariable(const ASTContext &Ctx, VarDecl *V) { |
965 | (0) . __assert_fail ("hasVarStorage() && \"This switch statement has no storage for a condition variable!\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/Stmt.cpp", 966, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(hasVarStorage() && |
966 | (0) . __assert_fail ("hasVarStorage() && \"This switch statement has no storage for a condition variable!\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/Stmt.cpp", 966, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> "This switch statement has no storage for a condition variable!"); |
967 | |
968 | if (!V) { |
969 | getTrailingObjects<Stmt *>()[varOffset()] = nullptr; |
970 | return; |
971 | } |
972 | |
973 | SourceRange VarRange = V->getSourceRange(); |
974 | getTrailingObjects<Stmt *>()[varOffset()] = new (Ctx) |
975 | DeclStmt(DeclGroupRef(V), VarRange.getBegin(), VarRange.getEnd()); |
976 | } |
977 | |
978 | WhileStmt::WhileStmt(const ASTContext &Ctx, VarDecl *Var, Expr *Cond, |
979 | Stmt *Body, SourceLocation WL) |
980 | : Stmt(WhileStmtClass) { |
981 | bool HasVar = Var != nullptr; |
982 | WhileStmtBits.HasVar = HasVar; |
983 | |
984 | setCond(Cond); |
985 | setBody(Body); |
986 | if (HasVar) |
987 | setConditionVariable(Ctx, Var); |
988 | |
989 | setWhileLoc(WL); |
990 | } |
991 | |
992 | WhileStmt::WhileStmt(EmptyShell Empty, bool HasVar) |
993 | : Stmt(WhileStmtClass, Empty) { |
994 | WhileStmtBits.HasVar = HasVar; |
995 | } |
996 | |
997 | WhileStmt *WhileStmt::Create(const ASTContext &Ctx, VarDecl *Var, Expr *Cond, |
998 | Stmt *Body, SourceLocation WL) { |
999 | bool HasVar = Var != nullptr; |
1000 | void *Mem = |
1001 | Ctx.Allocate(totalSizeToAlloc<Stmt *>(NumMandatoryStmtPtr + HasVar), |
1002 | alignof(WhileStmt)); |
1003 | return new (Mem) WhileStmt(Ctx, Var, Cond, Body, WL); |
1004 | } |
1005 | |
1006 | WhileStmt *WhileStmt::CreateEmpty(const ASTContext &Ctx, bool HasVar) { |
1007 | void *Mem = |
1008 | Ctx.Allocate(totalSizeToAlloc<Stmt *>(NumMandatoryStmtPtr + HasVar), |
1009 | alignof(WhileStmt)); |
1010 | return new (Mem) WhileStmt(EmptyShell(), HasVar); |
1011 | } |
1012 | |
1013 | VarDecl *WhileStmt::getConditionVariable() { |
1014 | auto *DS = getConditionVariableDeclStmt(); |
1015 | if (!DS) |
1016 | return nullptr; |
1017 | return cast<VarDecl>(DS->getSingleDecl()); |
1018 | } |
1019 | |
1020 | void WhileStmt::setConditionVariable(const ASTContext &Ctx, VarDecl *V) { |
1021 | (0) . __assert_fail ("hasVarStorage() && \"This while statement has no storage for a condition variable!\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/Stmt.cpp", 1022, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(hasVarStorage() && |
1022 | (0) . __assert_fail ("hasVarStorage() && \"This while statement has no storage for a condition variable!\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/Stmt.cpp", 1022, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> "This while statement has no storage for a condition variable!"); |
1023 | |
1024 | if (!V) { |
1025 | getTrailingObjects<Stmt *>()[varOffset()] = nullptr; |
1026 | return; |
1027 | } |
1028 | |
1029 | SourceRange VarRange = V->getSourceRange(); |
1030 | getTrailingObjects<Stmt *>()[varOffset()] = new (Ctx) |
1031 | DeclStmt(DeclGroupRef(V), VarRange.getBegin(), VarRange.getEnd()); |
1032 | } |
1033 | |
1034 | |
1035 | LabelDecl *IndirectGotoStmt::getConstantTarget() { |
1036 | if (auto *E = dyn_cast<AddrLabelExpr>(getTarget()->IgnoreParenImpCasts())) |
1037 | return E->getLabel(); |
1038 | return nullptr; |
1039 | } |
1040 | |
1041 | |
1042 | ReturnStmt::ReturnStmt(SourceLocation RL, Expr *E, const VarDecl *NRVOCandidate) |
1043 | : Stmt(ReturnStmtClass), RetExpr(E) { |
1044 | bool HasNRVOCandidate = NRVOCandidate != nullptr; |
1045 | ReturnStmtBits.HasNRVOCandidate = HasNRVOCandidate; |
1046 | if (HasNRVOCandidate) |
1047 | setNRVOCandidate(NRVOCandidate); |
1048 | setReturnLoc(RL); |
1049 | } |
1050 | |
1051 | ReturnStmt::ReturnStmt(EmptyShell Empty, bool HasNRVOCandidate) |
1052 | : Stmt(ReturnStmtClass, Empty) { |
1053 | ReturnStmtBits.HasNRVOCandidate = HasNRVOCandidate; |
1054 | } |
1055 | |
1056 | ReturnStmt *ReturnStmt::Create(const ASTContext &Ctx, SourceLocation RL, |
1057 | Expr *E, const VarDecl *NRVOCandidate) { |
1058 | bool HasNRVOCandidate = NRVOCandidate != nullptr; |
1059 | void *Mem = Ctx.Allocate(totalSizeToAlloc<const VarDecl *>(HasNRVOCandidate), |
1060 | alignof(ReturnStmt)); |
1061 | return new (Mem) ReturnStmt(RL, E, NRVOCandidate); |
1062 | } |
1063 | |
1064 | ReturnStmt *ReturnStmt::CreateEmpty(const ASTContext &Ctx, |
1065 | bool HasNRVOCandidate) { |
1066 | void *Mem = Ctx.Allocate(totalSizeToAlloc<const VarDecl *>(HasNRVOCandidate), |
1067 | alignof(ReturnStmt)); |
1068 | return new (Mem) ReturnStmt(EmptyShell(), HasNRVOCandidate); |
1069 | } |
1070 | |
1071 | |
1072 | CaseStmt *CaseStmt::Create(const ASTContext &Ctx, Expr *lhs, Expr *rhs, |
1073 | SourceLocation caseLoc, SourceLocation ellipsisLoc, |
1074 | SourceLocation colonLoc) { |
1075 | bool CaseStmtIsGNURange = rhs != nullptr; |
1076 | void *Mem = Ctx.Allocate( |
1077 | totalSizeToAlloc<Stmt *, SourceLocation>( |
1078 | NumMandatoryStmtPtr + CaseStmtIsGNURange, CaseStmtIsGNURange), |
1079 | alignof(CaseStmt)); |
1080 | return new (Mem) CaseStmt(lhs, rhs, caseLoc, ellipsisLoc, colonLoc); |
1081 | } |
1082 | |
1083 | CaseStmt *CaseStmt::CreateEmpty(const ASTContext &Ctx, |
1084 | bool CaseStmtIsGNURange) { |
1085 | void *Mem = Ctx.Allocate( |
1086 | totalSizeToAlloc<Stmt *, SourceLocation>( |
1087 | NumMandatoryStmtPtr + CaseStmtIsGNURange, CaseStmtIsGNURange), |
1088 | alignof(CaseStmt)); |
1089 | return new (Mem) CaseStmt(EmptyShell(), CaseStmtIsGNURange); |
1090 | } |
1091 | |
1092 | SEHTryStmt::SEHTryStmt(bool IsCXXTry, SourceLocation TryLoc, Stmt *TryBlock, |
1093 | Stmt *Handler) |
1094 | : Stmt(SEHTryStmtClass), IsCXXTry(IsCXXTry), TryLoc(TryLoc) { |
1095 | Children[TRY] = TryBlock; |
1096 | Children[HANDLER] = Handler; |
1097 | } |
1098 | |
1099 | SEHTryStmt* SEHTryStmt::Create(const ASTContext &C, bool IsCXXTry, |
1100 | SourceLocation TryLoc, Stmt *TryBlock, |
1101 | Stmt *Handler) { |
1102 | return new(C) SEHTryStmt(IsCXXTry,TryLoc,TryBlock,Handler); |
1103 | } |
1104 | |
1105 | SEHExceptStmt* SEHTryStmt::getExceptHandler() const { |
1106 | return dyn_cast<SEHExceptStmt>(getHandler()); |
1107 | } |
1108 | |
1109 | SEHFinallyStmt* SEHTryStmt::getFinallyHandler() const { |
1110 | return dyn_cast<SEHFinallyStmt>(getHandler()); |
1111 | } |
1112 | |
1113 | SEHExceptStmt::SEHExceptStmt(SourceLocation Loc, Expr *FilterExpr, Stmt *Block) |
1114 | : Stmt(SEHExceptStmtClass), Loc(Loc) { |
1115 | Children[FILTER_EXPR] = FilterExpr; |
1116 | Children[BLOCK] = Block; |
1117 | } |
1118 | |
1119 | SEHExceptStmt* SEHExceptStmt::Create(const ASTContext &C, SourceLocation Loc, |
1120 | Expr *FilterExpr, Stmt *Block) { |
1121 | return new(C) SEHExceptStmt(Loc,FilterExpr,Block); |
1122 | } |
1123 | |
1124 | SEHFinallyStmt::SEHFinallyStmt(SourceLocation Loc, Stmt *Block) |
1125 | : Stmt(SEHFinallyStmtClass), Loc(Loc), Block(Block) {} |
1126 | |
1127 | SEHFinallyStmt* SEHFinallyStmt::Create(const ASTContext &C, SourceLocation Loc, |
1128 | Stmt *Block) { |
1129 | return new(C)SEHFinallyStmt(Loc,Block); |
1130 | } |
1131 | |
1132 | CapturedStmt::Capture::Capture(SourceLocation Loc, VariableCaptureKind Kind, |
1133 | VarDecl *Var) |
1134 | : VarAndKind(Var, Kind), Loc(Loc) { |
1135 | switch (Kind) { |
1136 | case VCK_This: |
1137 | (0) . __assert_fail ("!Var && \"'this' capture cannot have a variable!\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/Stmt.cpp", 1137, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(!Var && "'this' capture cannot have a variable!"); |
1138 | break; |
1139 | case VCK_ByRef: |
1140 | (0) . __assert_fail ("Var && \"capturing by reference must have a variable!\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/Stmt.cpp", 1140, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(Var && "capturing by reference must have a variable!"); |
1141 | break; |
1142 | case VCK_ByCopy: |
1143 | (0) . __assert_fail ("Var && \"capturing by copy must have a variable!\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/Stmt.cpp", 1143, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(Var && "capturing by copy must have a variable!"); |
1144 | (0) . __assert_fail ("(Var->getType()->isScalarType() || (Var->getType()->isReferenceType() && Var->getType() ->castAs() ->getPointeeType() ->isScalarType())) && \"captures by copy are expected to have a scalar type!\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/Stmt.cpp", 1150, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert( |
1145 | (0) . __assert_fail ("(Var->getType()->isScalarType() || (Var->getType()->isReferenceType() && Var->getType() ->castAs() ->getPointeeType() ->isScalarType())) && \"captures by copy are expected to have a scalar type!\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/Stmt.cpp", 1150, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> (Var->getType()->isScalarType() || (Var->getType()->isReferenceType() && |
1146 | (0) . __assert_fail ("(Var->getType()->isScalarType() || (Var->getType()->isReferenceType() && Var->getType() ->castAs() ->getPointeeType() ->isScalarType())) && \"captures by copy are expected to have a scalar type!\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/Stmt.cpp", 1150, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> Var->getType() |
1147 | (0) . __assert_fail ("(Var->getType()->isScalarType() || (Var->getType()->isReferenceType() && Var->getType() ->castAs() ->getPointeeType() ->isScalarType())) && \"captures by copy are expected to have a scalar type!\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/Stmt.cpp", 1150, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> ->castAs<ReferenceType>() |
1148 | (0) . __assert_fail ("(Var->getType()->isScalarType() || (Var->getType()->isReferenceType() && Var->getType() ->castAs() ->getPointeeType() ->isScalarType())) && \"captures by copy are expected to have a scalar type!\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/Stmt.cpp", 1150, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> ->getPointeeType() |
1149 | (0) . __assert_fail ("(Var->getType()->isScalarType() || (Var->getType()->isReferenceType() && Var->getType() ->castAs() ->getPointeeType() ->isScalarType())) && \"captures by copy are expected to have a scalar type!\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/Stmt.cpp", 1150, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> ->isScalarType())) && |
1150 | (0) . __assert_fail ("(Var->getType()->isScalarType() || (Var->getType()->isReferenceType() && Var->getType() ->castAs() ->getPointeeType() ->isScalarType())) && \"captures by copy are expected to have a scalar type!\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/Stmt.cpp", 1150, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> "captures by copy are expected to have a scalar type!"); |
1151 | break; |
1152 | case VCK_VLAType: |
1153 | (0) . __assert_fail ("!Var && \"Variable-length array type capture cannot have a variable!\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/Stmt.cpp", 1154, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(!Var && |
1154 | (0) . __assert_fail ("!Var && \"Variable-length array type capture cannot have a variable!\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/Stmt.cpp", 1154, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> "Variable-length array type capture cannot have a variable!"); |
1155 | break; |
1156 | } |
1157 | } |
1158 | |
1159 | CapturedStmt::VariableCaptureKind |
1160 | CapturedStmt::Capture::getCaptureKind() const { |
1161 | return VarAndKind.getInt(); |
1162 | } |
1163 | |
1164 | VarDecl *CapturedStmt::Capture::getCapturedVar() const { |
1165 | (0) . __assert_fail ("(capturesVariable() || capturesVariableByCopy()) && \"No variable available for 'this' or VAT capture\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/Stmt.cpp", 1166, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert((capturesVariable() || capturesVariableByCopy()) && |
1166 | (0) . __assert_fail ("(capturesVariable() || capturesVariableByCopy()) && \"No variable available for 'this' or VAT capture\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/Stmt.cpp", 1166, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> "No variable available for 'this' or VAT capture"); |
1167 | return VarAndKind.getPointer(); |
1168 | } |
1169 | |
1170 | CapturedStmt::Capture *CapturedStmt::getStoredCaptures() const { |
1171 | unsigned Size = sizeof(CapturedStmt) + sizeof(Stmt *) * (NumCaptures + 1); |
1172 | |
1173 | |
1174 | unsigned FirstCaptureOffset = llvm::alignTo(Size, alignof(Capture)); |
1175 | |
1176 | return reinterpret_cast<Capture *>( |
1177 | reinterpret_cast<char *>(const_cast<CapturedStmt *>(this)) |
1178 | + FirstCaptureOffset); |
1179 | } |
1180 | |
1181 | CapturedStmt::CapturedStmt(Stmt *S, CapturedRegionKind Kind, |
1182 | ArrayRef<Capture> Captures, |
1183 | ArrayRef<Expr *> CaptureInits, |
1184 | CapturedDecl *CD, |
1185 | RecordDecl *RD) |
1186 | : Stmt(CapturedStmtClass), NumCaptures(Captures.size()), |
1187 | CapDeclAndKind(CD, Kind), TheRecordDecl(RD) { |
1188 | (0) . __assert_fail ("S && \"null captured statement\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/Stmt.cpp", 1188, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert( S && "null captured statement"); |
1189 | (0) . __assert_fail ("CD && \"null captured declaration for captured statement\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/Stmt.cpp", 1189, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(CD && "null captured declaration for captured statement"); |
1190 | (0) . __assert_fail ("RD && \"null record declaration for captured statement\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/Stmt.cpp", 1190, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(RD && "null record declaration for captured statement"); |
1191 | |
1192 | |
1193 | Stmt **Stored = getStoredStmts(); |
1194 | for (unsigned I = 0, N = NumCaptures; I != N; ++I) |
1195 | *Stored++ = CaptureInits[I]; |
1196 | |
1197 | |
1198 | *Stored = S; |
1199 | |
1200 | |
1201 | Capture *Buffer = getStoredCaptures(); |
1202 | std::copy(Captures.begin(), Captures.end(), Buffer); |
1203 | } |
1204 | |
1205 | CapturedStmt::CapturedStmt(EmptyShell Empty, unsigned NumCaptures) |
1206 | : Stmt(CapturedStmtClass, Empty), NumCaptures(NumCaptures), |
1207 | CapDeclAndKind(nullptr, CR_Default) { |
1208 | getStoredStmts()[NumCaptures] = nullptr; |
1209 | } |
1210 | |
1211 | CapturedStmt *CapturedStmt::Create(const ASTContext &Context, Stmt *S, |
1212 | CapturedRegionKind Kind, |
1213 | ArrayRef<Capture> Captures, |
1214 | ArrayRef<Expr *> CaptureInits, |
1215 | CapturedDecl *CD, |
1216 | RecordDecl *RD) { |
1217 | |
1218 | |
1219 | |
1220 | |
1221 | |
1222 | |
1223 | |
1224 | |
1225 | |
1226 | (0) . __assert_fail ("CaptureInits.size() == Captures.size() && \"wrong number of arguments\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/Stmt.cpp", 1226, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(CaptureInits.size() == Captures.size() && "wrong number of arguments"); |
1227 | |
1228 | unsigned Size = sizeof(CapturedStmt) + sizeof(Stmt *) * (Captures.size() + 1); |
1229 | if (!Captures.empty()) { |
1230 | |
1231 | Size = llvm::alignTo(Size, alignof(Capture)); |
1232 | Size += sizeof(Capture) * Captures.size(); |
1233 | } |
1234 | |
1235 | void *Mem = Context.Allocate(Size); |
1236 | return new (Mem) CapturedStmt(S, Kind, Captures, CaptureInits, CD, RD); |
1237 | } |
1238 | |
1239 | CapturedStmt *CapturedStmt::CreateDeserialized(const ASTContext &Context, |
1240 | unsigned NumCaptures) { |
1241 | unsigned Size = sizeof(CapturedStmt) + sizeof(Stmt *) * (NumCaptures + 1); |
1242 | if (NumCaptures > 0) { |
1243 | |
1244 | Size = llvm::alignTo(Size, alignof(Capture)); |
1245 | Size += sizeof(Capture) * NumCaptures; |
1246 | } |
1247 | |
1248 | void *Mem = Context.Allocate(Size); |
1249 | return new (Mem) CapturedStmt(EmptyShell(), NumCaptures); |
1250 | } |
1251 | |
1252 | Stmt::child_range CapturedStmt::children() { |
1253 | |
1254 | return child_range(getStoredStmts(), getStoredStmts() + NumCaptures); |
1255 | } |
1256 | |
1257 | CapturedDecl *CapturedStmt::getCapturedDecl() { |
1258 | return CapDeclAndKind.getPointer(); |
1259 | } |
1260 | |
1261 | const CapturedDecl *CapturedStmt::getCapturedDecl() const { |
1262 | return CapDeclAndKind.getPointer(); |
1263 | } |
1264 | |
1265 | |
1266 | void CapturedStmt::setCapturedDecl(CapturedDecl *D) { |
1267 | (0) . __assert_fail ("D && \"null CapturedDecl\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/Stmt.cpp", 1267, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(D && "null CapturedDecl"); |
1268 | CapDeclAndKind.setPointer(D); |
1269 | } |
1270 | |
1271 | |
1272 | CapturedRegionKind CapturedStmt::getCapturedRegionKind() const { |
1273 | return CapDeclAndKind.getInt(); |
1274 | } |
1275 | |
1276 | |
1277 | void CapturedStmt::setCapturedRegionKind(CapturedRegionKind Kind) { |
1278 | CapDeclAndKind.setInt(Kind); |
1279 | } |
1280 | |
1281 | bool CapturedStmt::capturesVariable(const VarDecl *Var) const { |
1282 | for (const auto &I : captures()) { |
1283 | if (!I.capturesVariable() && !I.capturesVariableByCopy()) |
1284 | continue; |
1285 | if (I.getCapturedVar()->getCanonicalDecl() == Var->getCanonicalDecl()) |
1286 | return true; |
1287 | } |
1288 | |
1289 | return false; |
1290 | } |
1291 | |