1 //===- Stmt.cpp - Statement AST Node Implementation -----------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file implements the Stmt class and statement subclasses.
11 //===----------------------------------------------------------------------===//
13 #include "clang/AST/Stmt.h"
14 #include "clang/AST/ASTContext.h"
15 #include "clang/AST/ASTDiagnostic.h"
16 #include "clang/AST/Attr.h"
17 #include "clang/AST/Decl.h"
18 #include "clang/AST/DeclGroup.h"
19 #include "clang/AST/Expr.h"
20 #include "clang/AST/ExprCXX.h"
21 #include "clang/AST/ExprConcepts.h"
22 #include "clang/AST/ExprObjC.h"
23 #include "clang/AST/ExprOpenMP.h"
24 #include "clang/AST/StmtCXX.h"
25 #include "clang/AST/StmtObjC.h"
26 #include "clang/AST/StmtOpenMP.h"
27 #include "clang/AST/Type.h"
28 #include "clang/Basic/CharInfo.h"
29 #include "clang/Basic/LLVM.h"
30 #include "clang/Basic/SourceLocation.h"
31 #include "clang/Basic/TargetInfo.h"
32 #include "clang/Lex/Token.h"
33 #include "llvm/ADT/SmallVector.h"
34 #include "llvm/ADT/StringExtras.h"
35 #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"
40 #include "llvm/Support/raw_ostream.h"
46 #include <type_traits>
49 using namespace clang
;
51 static struct StmtClassNameTable
{
55 } StmtClassInfo
[Stmt::lastStmtConstant
+1];
57 static StmtClassNameTable
&getStmtInfoTableEntry(Stmt::StmtClass E
) {
58 static bool Initialized
= false;
60 return StmtClassInfo
[E
];
62 // Initialize the table on the first use.
64 #define ABSTRACT_STMT(STMT)
65 #define STMT(CLASS, PARENT) \
66 StmtClassInfo[(unsigned)Stmt::CLASS##Class].Name = #CLASS; \
67 StmtClassInfo[(unsigned)Stmt::CLASS##Class].Size = sizeof(CLASS);
68 #include "clang/AST/StmtNodes.inc"
70 return StmtClassInfo
[E
];
73 void *Stmt::operator new(size_t bytes
, const ASTContext
& C
,
75 return ::operator new(bytes
, C
, alignment
);
78 const char *Stmt::getStmtClassName() const {
79 return getStmtInfoTableEntry((StmtClass
) StmtBits
.sClass
).Name
;
82 // Check that no statement / expression class is polymorphic. LLVM style RTTI
83 // should be used instead. If absolutely needed an exception can still be added
84 // here by defining the appropriate macro (but please don't do this).
85 #define STMT(CLASS, PARENT) \
86 static_assert(!std::is_polymorphic<CLASS>::value, \
87 #CLASS " should not be polymorphic!");
88 #include "clang/AST/StmtNodes.inc"
90 // Check that no statement / expression class has a non-trival destructor.
91 // Statements and expressions are allocated with the BumpPtrAllocator from
92 // ASTContext and therefore their destructor is not executed.
93 #define STMT(CLASS, PARENT) \
94 static_assert(std::is_trivially_destructible<CLASS>::value, \
95 #CLASS " should be trivially destructible!");
96 // FIXME: InitListExpr is not trivially destructible due to its ASTVector.
97 #define INITLISTEXPR(CLASS, PARENT)
98 #include "clang/AST/StmtNodes.inc"
100 void Stmt::PrintStats() {
101 // Ensure the table is primed.
102 getStmtInfoTableEntry(Stmt::NullStmtClass
);
105 llvm::errs() << "\n*** Stmt/Expr Stats:\n";
106 for (int i
= 0; i
!= Stmt::lastStmtConstant
+1; i
++) {
107 if (StmtClassInfo
[i
].Name
== nullptr) continue;
108 sum
+= StmtClassInfo
[i
].Counter
;
110 llvm::errs() << " " << sum
<< " stmts/exprs total.\n";
112 for (int i
= 0; i
!= Stmt::lastStmtConstant
+1; i
++) {
113 if (StmtClassInfo
[i
].Name
== nullptr) continue;
114 if (StmtClassInfo
[i
].Counter
== 0) continue;
115 llvm::errs() << " " << StmtClassInfo
[i
].Counter
<< " "
116 << StmtClassInfo
[i
].Name
<< ", " << StmtClassInfo
[i
].Size
117 << " each (" << StmtClassInfo
[i
].Counter
*StmtClassInfo
[i
].Size
119 sum
+= StmtClassInfo
[i
].Counter
*StmtClassInfo
[i
].Size
;
122 llvm::errs() << "Total bytes = " << sum
<< "\n";
125 void Stmt::addStmtClass(StmtClass s
) {
126 ++getStmtInfoTableEntry(s
).Counter
;
129 bool Stmt::StatisticsEnabled
= false;
130 void Stmt::EnableStatistics() {
131 StatisticsEnabled
= true;
134 static std::pair
<Stmt::Likelihood
, const Attr
*>
135 getLikelihood(ArrayRef
<const Attr
*> Attrs
) {
136 for (const auto *A
: Attrs
) {
137 if (isa
<LikelyAttr
>(A
))
138 return std::make_pair(Stmt::LH_Likely
, A
);
140 if (isa
<UnlikelyAttr
>(A
))
141 return std::make_pair(Stmt::LH_Unlikely
, A
);
144 return std::make_pair(Stmt::LH_None
, nullptr);
147 static std::pair
<Stmt::Likelihood
, const Attr
*> getLikelihood(const Stmt
*S
) {
148 if (const auto *AS
= dyn_cast_or_null
<AttributedStmt
>(S
))
149 return getLikelihood(AS
->getAttrs());
151 return std::make_pair(Stmt::LH_None
, nullptr);
154 Stmt::Likelihood
Stmt::getLikelihood(ArrayRef
<const Attr
*> Attrs
) {
155 return ::getLikelihood(Attrs
).first
;
158 Stmt::Likelihood
Stmt::getLikelihood(const Stmt
*S
) {
159 return ::getLikelihood(S
).first
;
162 const Attr
*Stmt::getLikelihoodAttr(const Stmt
*S
) {
163 return ::getLikelihood(S
).second
;
166 Stmt::Likelihood
Stmt::getLikelihood(const Stmt
*Then
, const Stmt
*Else
) {
167 Likelihood LHT
= ::getLikelihood(Then
).first
;
168 Likelihood LHE
= ::getLikelihood(Else
).first
;
172 // If the same attribute is used on both branches there's a conflict.
179 // Invert the value of Else to get the value for Then.
180 return LHE
== LH_Likely
? LH_Unlikely
: LH_Likely
;
183 std::tuple
<bool, const Attr
*, const Attr
*>
184 Stmt::determineLikelihoodConflict(const Stmt
*Then
, const Stmt
*Else
) {
185 std::pair
<Likelihood
, const Attr
*> LHT
= ::getLikelihood(Then
);
186 std::pair
<Likelihood
, const Attr
*> LHE
= ::getLikelihood(Else
);
187 // If the same attribute is used on both branches there's a conflict.
188 if (LHT
.first
!= LH_None
&& LHT
.first
== LHE
.first
)
189 return std::make_tuple(true, LHT
.second
, LHE
.second
);
191 return std::make_tuple(false, nullptr, nullptr);
194 /// Skip no-op (attributed, compound) container stmts and skip captured
195 /// stmt at the top, if \a IgnoreCaptured is true.
196 Stmt
*Stmt::IgnoreContainers(bool IgnoreCaptured
) {
199 if (auto CapS
= dyn_cast_or_null
<CapturedStmt
>(S
))
200 S
= CapS
->getCapturedStmt();
202 if (auto AS
= dyn_cast_or_null
<AttributedStmt
>(S
))
203 S
= AS
->getSubStmt();
204 else if (auto CS
= dyn_cast_or_null
<CompoundStmt
>(S
)) {
214 /// Strip off all label-like statements.
216 /// This will strip off label statements, case statements, attributed
217 /// statements and default statements recursively.
218 const Stmt
*Stmt::stripLabelLikeStatements() const {
219 const Stmt
*S
= this;
221 if (const auto *LS
= dyn_cast
<LabelStmt
>(S
))
222 S
= LS
->getSubStmt();
223 else if (const auto *SC
= dyn_cast
<SwitchCase
>(S
))
224 S
= SC
->getSubStmt();
225 else if (const auto *AS
= dyn_cast
<AttributedStmt
>(S
))
226 S
= AS
->getSubStmt();
237 // These silly little functions have to be static inline to suppress
238 // unused warnings, and they have to be defined to suppress other
240 static good
is_good(good
) { return good(); }
242 typedef Stmt::child_range
children_t();
243 template <class T
> good
implements_children(children_t
T::*) {
246 LLVM_ATTRIBUTE_UNUSED
247 static bad
implements_children(children_t
Stmt::*) {
251 typedef SourceLocation
getBeginLoc_t() const;
252 template <class T
> good
implements_getBeginLoc(getBeginLoc_t
T::*) {
255 LLVM_ATTRIBUTE_UNUSED
256 static bad
implements_getBeginLoc(getBeginLoc_t
Stmt::*) { return bad(); }
258 typedef SourceLocation
getLocEnd_t() const;
259 template <class T
> good
implements_getEndLoc(getLocEnd_t
T::*) {
262 LLVM_ATTRIBUTE_UNUSED
263 static bad
implements_getEndLoc(getLocEnd_t
Stmt::*) { return bad(); }
265 #define ASSERT_IMPLEMENTS_children(type) \
266 (void) is_good(implements_children(&type::children))
267 #define ASSERT_IMPLEMENTS_getBeginLoc(type) \
268 (void)is_good(implements_getBeginLoc(&type::getBeginLoc))
269 #define ASSERT_IMPLEMENTS_getEndLoc(type) \
270 (void)is_good(implements_getEndLoc(&type::getEndLoc))
274 /// Check whether the various Stmt classes implement their member
276 LLVM_ATTRIBUTE_UNUSED
277 static inline void check_implementations() {
278 #define ABSTRACT_STMT(type)
279 #define STMT(type, base) \
280 ASSERT_IMPLEMENTS_children(type); \
281 ASSERT_IMPLEMENTS_getBeginLoc(type); \
282 ASSERT_IMPLEMENTS_getEndLoc(type);
283 #include "clang/AST/StmtNodes.inc"
286 Stmt::child_range
Stmt::children() {
287 switch (getStmtClass()) {
288 case Stmt::NoStmtClass
: llvm_unreachable("statement without class");
289 #define ABSTRACT_STMT(type)
290 #define STMT(type, base) \
291 case Stmt::type##Class: \
292 return static_cast<type*>(this)->children();
293 #include "clang/AST/StmtNodes.inc"
295 llvm_unreachable("unknown statement kind!");
298 // Amusing macro metaprogramming hack: check whether a class provides
299 // a more specific implementation of getSourceRange.
301 // See also Expr.cpp:getExprLoc().
304 /// This implementation is used when a class provides a custom
305 /// implementation of getSourceRange.
306 template <class S
, class T
>
307 SourceRange
getSourceRangeImpl(const Stmt
*stmt
,
308 SourceRange (T::*v
)() const) {
309 return static_cast<const S
*>(stmt
)->getSourceRange();
312 /// This implementation is used when a class doesn't provide a custom
313 /// implementation of getSourceRange. Overload resolution should pick it over
314 /// the implementation above because it's more specialized according to
315 /// function template partial ordering.
317 SourceRange
getSourceRangeImpl(const Stmt
*stmt
,
318 SourceRange (Stmt::*v
)() const) {
319 return SourceRange(static_cast<const S
*>(stmt
)->getBeginLoc(),
320 static_cast<const S
*>(stmt
)->getEndLoc());
325 SourceRange
Stmt::getSourceRange() const {
326 switch (getStmtClass()) {
327 case Stmt::NoStmtClass
: llvm_unreachable("statement without class");
328 #define ABSTRACT_STMT(type)
329 #define STMT(type, base) \
330 case Stmt::type##Class: \
331 return getSourceRangeImpl<type>(this, &type::getSourceRange);
332 #include "clang/AST/StmtNodes.inc"
334 llvm_unreachable("unknown statement kind!");
337 SourceLocation
Stmt::getBeginLoc() const {
338 switch (getStmtClass()) {
339 case Stmt::NoStmtClass
: llvm_unreachable("statement without class");
340 #define ABSTRACT_STMT(type)
341 #define STMT(type, base) \
342 case Stmt::type##Class: \
343 return static_cast<const type *>(this)->getBeginLoc();
344 #include "clang/AST/StmtNodes.inc"
346 llvm_unreachable("unknown statement kind");
349 SourceLocation
Stmt::getEndLoc() const {
350 switch (getStmtClass()) {
351 case Stmt::NoStmtClass
: llvm_unreachable("statement without class");
352 #define ABSTRACT_STMT(type)
353 #define STMT(type, base) \
354 case Stmt::type##Class: \
355 return static_cast<const type *>(this)->getEndLoc();
356 #include "clang/AST/StmtNodes.inc"
358 llvm_unreachable("unknown statement kind");
361 int64_t Stmt::getID(const ASTContext
&Context
) const {
362 return Context
.getAllocator().identifyKnownAlignedObject
<Stmt
>(this);
365 CompoundStmt::CompoundStmt(ArrayRef
<Stmt
*> Stmts
, FPOptionsOverride FPFeatures
,
366 SourceLocation LB
, SourceLocation RB
)
367 : Stmt(CompoundStmtClass
), LBraceLoc(LB
), RBraceLoc(RB
) {
368 CompoundStmtBits
.NumStmts
= Stmts
.size();
369 CompoundStmtBits
.HasFPFeatures
= FPFeatures
.requiresTrailingStorage();
371 if (hasStoredFPFeatures())
372 setStoredFPFeatures(FPFeatures
);
375 void CompoundStmt::setStmts(ArrayRef
<Stmt
*> Stmts
) {
376 assert(CompoundStmtBits
.NumStmts
== Stmts
.size() &&
377 "NumStmts doesn't fit in bits of CompoundStmtBits.NumStmts!");
379 std::copy(Stmts
.begin(), Stmts
.end(), body_begin());
382 CompoundStmt
*CompoundStmt::Create(const ASTContext
&C
, ArrayRef
<Stmt
*> Stmts
,
383 FPOptionsOverride FPFeatures
,
384 SourceLocation LB
, SourceLocation RB
) {
386 C
.Allocate(totalSizeToAlloc
<Stmt
*, FPOptionsOverride
>(
387 Stmts
.size(), FPFeatures
.requiresTrailingStorage()),
388 alignof(CompoundStmt
));
389 return new (Mem
) CompoundStmt(Stmts
, FPFeatures
, LB
, RB
);
392 CompoundStmt
*CompoundStmt::CreateEmpty(const ASTContext
&C
, unsigned NumStmts
,
393 bool HasFPFeatures
) {
394 void *Mem
= C
.Allocate(
395 totalSizeToAlloc
<Stmt
*, FPOptionsOverride
>(NumStmts
, HasFPFeatures
),
396 alignof(CompoundStmt
));
397 CompoundStmt
*New
= new (Mem
) CompoundStmt(EmptyShell());
398 New
->CompoundStmtBits
.NumStmts
= NumStmts
;
399 New
->CompoundStmtBits
.HasFPFeatures
= HasFPFeatures
;
403 const Expr
*ValueStmt::getExprStmt() const {
404 const Stmt
*S
= this;
406 if (const auto *E
= dyn_cast
<Expr
>(S
))
409 if (const auto *LS
= dyn_cast
<LabelStmt
>(S
))
410 S
= LS
->getSubStmt();
411 else if (const auto *AS
= dyn_cast
<AttributedStmt
>(S
))
412 S
= AS
->getSubStmt();
414 llvm_unreachable("unknown kind of ValueStmt");
415 } while (isa
<ValueStmt
>(S
));
420 const char *LabelStmt::getName() const {
421 return getDecl()->getIdentifier()->getNameStart();
424 AttributedStmt
*AttributedStmt::Create(const ASTContext
&C
, SourceLocation Loc
,
425 ArrayRef
<const Attr
*> Attrs
,
427 assert(!Attrs
.empty() && "Attrs should not be empty");
428 void *Mem
= C
.Allocate(totalSizeToAlloc
<const Attr
*>(Attrs
.size()),
429 alignof(AttributedStmt
));
430 return new (Mem
) AttributedStmt(Loc
, Attrs
, SubStmt
);
433 AttributedStmt
*AttributedStmt::CreateEmpty(const ASTContext
&C
,
435 assert(NumAttrs
> 0 && "NumAttrs should be greater than zero");
436 void *Mem
= C
.Allocate(totalSizeToAlloc
<const Attr
*>(NumAttrs
),
437 alignof(AttributedStmt
));
438 return new (Mem
) AttributedStmt(EmptyShell(), NumAttrs
);
441 std::string
AsmStmt::generateAsmString(const ASTContext
&C
) const {
442 if (const auto *gccAsmStmt
= dyn_cast
<GCCAsmStmt
>(this))
443 return gccAsmStmt
->generateAsmString(C
);
444 if (const auto *msAsmStmt
= dyn_cast
<MSAsmStmt
>(this))
445 return msAsmStmt
->generateAsmString(C
);
446 llvm_unreachable("unknown asm statement kind!");
449 StringRef
AsmStmt::getOutputConstraint(unsigned i
) const {
450 if (const auto *gccAsmStmt
= dyn_cast
<GCCAsmStmt
>(this))
451 return gccAsmStmt
->getOutputConstraint(i
);
452 if (const auto *msAsmStmt
= dyn_cast
<MSAsmStmt
>(this))
453 return msAsmStmt
->getOutputConstraint(i
);
454 llvm_unreachable("unknown asm statement kind!");
457 const Expr
*AsmStmt::getOutputExpr(unsigned i
) const {
458 if (const auto *gccAsmStmt
= dyn_cast
<GCCAsmStmt
>(this))
459 return gccAsmStmt
->getOutputExpr(i
);
460 if (const auto *msAsmStmt
= dyn_cast
<MSAsmStmt
>(this))
461 return msAsmStmt
->getOutputExpr(i
);
462 llvm_unreachable("unknown asm statement kind!");
465 StringRef
AsmStmt::getInputConstraint(unsigned i
) const {
466 if (const auto *gccAsmStmt
= dyn_cast
<GCCAsmStmt
>(this))
467 return gccAsmStmt
->getInputConstraint(i
);
468 if (const auto *msAsmStmt
= dyn_cast
<MSAsmStmt
>(this))
469 return msAsmStmt
->getInputConstraint(i
);
470 llvm_unreachable("unknown asm statement kind!");
473 const Expr
*AsmStmt::getInputExpr(unsigned i
) const {
474 if (const auto *gccAsmStmt
= dyn_cast
<GCCAsmStmt
>(this))
475 return gccAsmStmt
->getInputExpr(i
);
476 if (const auto *msAsmStmt
= dyn_cast
<MSAsmStmt
>(this))
477 return msAsmStmt
->getInputExpr(i
);
478 llvm_unreachable("unknown asm statement kind!");
481 StringRef
AsmStmt::getClobber(unsigned i
) const {
482 if (const auto *gccAsmStmt
= dyn_cast
<GCCAsmStmt
>(this))
483 return gccAsmStmt
->getClobber(i
);
484 if (const auto *msAsmStmt
= dyn_cast
<MSAsmStmt
>(this))
485 return msAsmStmt
->getClobber(i
);
486 llvm_unreachable("unknown asm statement kind!");
489 /// getNumPlusOperands - Return the number of output operands that have a "+"
491 unsigned AsmStmt::getNumPlusOperands() const {
493 for (unsigned i
= 0, e
= getNumOutputs(); i
!= e
; ++i
)
494 if (isOutputPlusConstraint(i
))
499 char GCCAsmStmt::AsmStringPiece::getModifier() const {
500 assert(isOperand() && "Only Operands can have modifiers.");
501 return isLetter(Str
[0]) ? Str
[0] : '\0';
504 StringRef
GCCAsmStmt::getClobber(unsigned i
) const {
505 return getClobberStringLiteral(i
)->getString();
508 Expr
*GCCAsmStmt::getOutputExpr(unsigned i
) {
509 return cast
<Expr
>(Exprs
[i
]);
512 /// getOutputConstraint - Return the constraint string for the specified
513 /// output operand. All output constraints are known to be non-empty (either
515 StringRef
GCCAsmStmt::getOutputConstraint(unsigned i
) const {
516 return getOutputConstraintLiteral(i
)->getString();
519 Expr
*GCCAsmStmt::getInputExpr(unsigned i
) {
520 return cast
<Expr
>(Exprs
[i
+ NumOutputs
]);
523 void GCCAsmStmt::setInputExpr(unsigned i
, Expr
*E
) {
524 Exprs
[i
+ NumOutputs
] = E
;
527 AddrLabelExpr
*GCCAsmStmt::getLabelExpr(unsigned i
) const {
528 return cast
<AddrLabelExpr
>(Exprs
[i
+ NumOutputs
+ NumInputs
]);
531 StringRef
GCCAsmStmt::getLabelName(unsigned i
) const {
532 return getLabelExpr(i
)->getLabel()->getName();
535 /// getInputConstraint - Return the specified input constraint. Unlike output
536 /// constraints, these can be empty.
537 StringRef
GCCAsmStmt::getInputConstraint(unsigned i
) const {
538 return getInputConstraintLiteral(i
)->getString();
541 void GCCAsmStmt::setOutputsAndInputsAndClobbers(const ASTContext
&C
,
542 IdentifierInfo
**Names
,
543 StringLiteral
**Constraints
,
548 StringLiteral
**Clobbers
,
549 unsigned NumClobbers
) {
550 this->NumOutputs
= NumOutputs
;
551 this->NumInputs
= NumInputs
;
552 this->NumClobbers
= NumClobbers
;
553 this->NumLabels
= NumLabels
;
555 unsigned NumExprs
= NumOutputs
+ NumInputs
+ NumLabels
;
557 C
.Deallocate(this->Names
);
558 this->Names
= new (C
) IdentifierInfo
*[NumExprs
];
559 std::copy(Names
, Names
+ NumExprs
, this->Names
);
561 C
.Deallocate(this->Exprs
);
562 this->Exprs
= new (C
) Stmt
*[NumExprs
];
563 std::copy(Exprs
, Exprs
+ NumExprs
, this->Exprs
);
565 unsigned NumConstraints
= NumOutputs
+ NumInputs
;
566 C
.Deallocate(this->Constraints
);
567 this->Constraints
= new (C
) StringLiteral
*[NumConstraints
];
568 std::copy(Constraints
, Constraints
+ NumConstraints
, this->Constraints
);
570 C
.Deallocate(this->Clobbers
);
571 this->Clobbers
= new (C
) StringLiteral
*[NumClobbers
];
572 std::copy(Clobbers
, Clobbers
+ NumClobbers
, this->Clobbers
);
575 /// getNamedOperand - Given a symbolic operand reference like %[foo],
576 /// translate this into a numeric value needed to reference the same operand.
577 /// This returns -1 if the operand name is invalid.
578 int GCCAsmStmt::getNamedOperand(StringRef SymbolicName
) const {
579 // Check if this is an output operand.
580 unsigned NumOutputs
= getNumOutputs();
581 for (unsigned i
= 0; i
!= NumOutputs
; ++i
)
582 if (getOutputName(i
) == SymbolicName
)
585 unsigned NumInputs
= getNumInputs();
586 for (unsigned i
= 0; i
!= NumInputs
; ++i
)
587 if (getInputName(i
) == SymbolicName
)
588 return NumOutputs
+ i
;
590 for (unsigned i
= 0, e
= getNumLabels(); i
!= e
; ++i
)
591 if (getLabelName(i
) == SymbolicName
)
592 return NumOutputs
+ NumInputs
+ getNumPlusOperands() + i
;
598 /// AnalyzeAsmString - Analyze the asm string of the current asm, decomposing
599 /// it into pieces. If the asm string is erroneous, emit errors and return
600 /// true, otherwise return false.
601 unsigned GCCAsmStmt::AnalyzeAsmString(SmallVectorImpl
<AsmStringPiece
>&Pieces
,
602 const ASTContext
&C
, unsigned &DiagOffs
) const {
603 StringRef Str
= getAsmString()->getString();
604 const char *StrStart
= Str
.begin();
605 const char *StrEnd
= Str
.end();
606 const char *CurPtr
= StrStart
;
608 // "Simple" inline asms have no constraints or operands, just convert the asm
609 // string to escape $'s.
612 for (; CurPtr
!= StrEnd
; ++CurPtr
) {
622 Pieces
.push_back(AsmStringPiece(Result
));
626 // CurStringPiece - The current string that we are building up as we scan the
628 std::string CurStringPiece
;
630 bool HasVariants
= !C
.getTargetInfo().hasNoAsmVariants();
632 unsigned LastAsmStringToken
= 0;
633 unsigned LastAsmStringOffset
= 0;
636 // Done with the string?
637 if (CurPtr
== StrEnd
) {
638 if (!CurStringPiece
.empty())
639 Pieces
.push_back(AsmStringPiece(CurStringPiece
));
643 char CurChar
= *CurPtr
++;
645 case '$': CurStringPiece
+= "$$"; continue;
646 case '{': CurStringPiece
+= (HasVariants
? "$(" : "{"); continue;
647 case '|': CurStringPiece
+= (HasVariants
? "$|" : "|"); continue;
648 case '}': CurStringPiece
+= (HasVariants
? "$)" : "}"); continue;
652 CurStringPiece
+= CurChar
;
656 const TargetInfo
&TI
= C
.getTargetInfo();
658 // Escaped "%" character in asm string.
659 if (CurPtr
== StrEnd
) {
660 // % at end of string is invalid (no escape).
661 DiagOffs
= CurPtr
-StrStart
-1;
662 return diag::err_asm_invalid_escape
;
664 // Handle escaped char and continue looping over the asm string.
665 char EscapedChar
= *CurPtr
++;
666 switch (EscapedChar
) {
668 // Handle target-specific escaped characters.
669 if (auto MaybeReplaceStr
= TI
.handleAsmEscapedChar(EscapedChar
)) {
670 CurStringPiece
+= *MaybeReplaceStr
;
677 CurStringPiece
+= EscapedChar
;
679 case '=': // %= -> Generate a unique ID.
680 CurStringPiece
+= "${:uid}";
684 // Otherwise, we have an operand. If we have accumulated a string so far,
685 // add it to the Pieces list.
686 if (!CurStringPiece
.empty()) {
687 Pieces
.push_back(AsmStringPiece(CurStringPiece
));
688 CurStringPiece
.clear();
691 // Handle operands that have asmSymbolicName (e.g., %x[foo]) and those that
692 // don't (e.g., %x4). 'x' following the '%' is the constraint modifier.
694 const char *Begin
= CurPtr
- 1; // Points to the character following '%'.
695 const char *Percent
= Begin
- 1; // Points to '%'.
697 if (isLetter(EscapedChar
)) {
698 if (CurPtr
== StrEnd
) { // Premature end.
699 DiagOffs
= CurPtr
-StrStart
-1;
700 return diag::err_asm_invalid_escape
;
702 EscapedChar
= *CurPtr
++;
705 const SourceManager
&SM
= C
.getSourceManager();
706 const LangOptions
&LO
= C
.getLangOpts();
708 // Handle operands that don't have asmSymbolicName (e.g., %x4).
709 if (isDigit(EscapedChar
)) {
710 // %n - Assembler operand n
714 while (CurPtr
!= StrEnd
&& isDigit(*CurPtr
))
715 N
= N
*10 + ((*CurPtr
++)-'0');
717 unsigned NumOperands
= getNumOutputs() + getNumPlusOperands() +
718 getNumInputs() + getNumLabels();
719 if (N
>= NumOperands
) {
720 DiagOffs
= CurPtr
-StrStart
-1;
721 return diag::err_asm_invalid_operand_number
;
724 // Str contains "x4" (Operand without the leading %).
725 std::string
Str(Begin
, CurPtr
- Begin
);
727 // (BeginLoc, EndLoc) represents the range of the operand we are currently
728 // processing. Unlike Str, the range includes the leading '%'.
729 SourceLocation BeginLoc
= getAsmString()->getLocationOfByte(
730 Percent
- StrStart
, SM
, LO
, TI
, &LastAsmStringToken
,
731 &LastAsmStringOffset
);
732 SourceLocation EndLoc
= getAsmString()->getLocationOfByte(
733 CurPtr
- StrStart
, SM
, LO
, TI
, &LastAsmStringToken
,
734 &LastAsmStringOffset
);
736 Pieces
.emplace_back(N
, std::move(Str
), BeginLoc
, EndLoc
);
740 // Handle operands that have asmSymbolicName (e.g., %x[foo]).
741 if (EscapedChar
== '[') {
742 DiagOffs
= CurPtr
-StrStart
-1;
745 const char *NameEnd
= (const char*)memchr(CurPtr
, ']', StrEnd
-CurPtr
);
746 if (NameEnd
== nullptr)
747 return diag::err_asm_unterminated_symbolic_operand_name
;
748 if (NameEnd
== CurPtr
)
749 return diag::err_asm_empty_symbolic_operand_name
;
751 StringRef
SymbolicName(CurPtr
, NameEnd
- CurPtr
);
753 int N
= getNamedOperand(SymbolicName
);
755 // Verify that an operand with that name exists.
756 DiagOffs
= CurPtr
-StrStart
;
757 return diag::err_asm_unknown_symbolic_operand_name
;
760 // Str contains "x[foo]" (Operand without the leading %).
761 std::string
Str(Begin
, NameEnd
+ 1 - Begin
);
763 // (BeginLoc, EndLoc) represents the range of the operand we are currently
764 // processing. Unlike Str, the range includes the leading '%'.
765 SourceLocation BeginLoc
= getAsmString()->getLocationOfByte(
766 Percent
- StrStart
, SM
, LO
, TI
, &LastAsmStringToken
,
767 &LastAsmStringOffset
);
768 SourceLocation EndLoc
= getAsmString()->getLocationOfByte(
769 NameEnd
+ 1 - StrStart
, SM
, LO
, TI
, &LastAsmStringToken
,
770 &LastAsmStringOffset
);
772 Pieces
.emplace_back(N
, std::move(Str
), BeginLoc
, EndLoc
);
778 DiagOffs
= CurPtr
-StrStart
-1;
779 return diag::err_asm_invalid_escape
;
783 /// Assemble final IR asm string (GCC-style).
784 std::string
GCCAsmStmt::generateAsmString(const ASTContext
&C
) const {
785 // Analyze the asm string to decompose it into its pieces. We know that Sema
786 // has already done this, so it is guaranteed to be successful.
787 SmallVector
<GCCAsmStmt::AsmStringPiece
, 4> Pieces
;
789 AnalyzeAsmString(Pieces
, C
, DiagOffs
);
791 std::string AsmString
;
792 for (const auto &Piece
: Pieces
) {
793 if (Piece
.isString())
794 AsmString
+= Piece
.getString();
795 else if (Piece
.getModifier() == '\0')
796 AsmString
+= '$' + llvm::utostr(Piece
.getOperandNo());
798 AsmString
+= "${" + llvm::utostr(Piece
.getOperandNo()) + ':' +
799 Piece
.getModifier() + '}';
804 /// Assemble final IR asm string (MS-style).
805 std::string
MSAsmStmt::generateAsmString(const ASTContext
&C
) const {
806 // FIXME: This needs to be translated into the IR string representation.
807 SmallVector
<StringRef
, 8> Pieces
;
808 AsmStr
.split(Pieces
, "\n\t");
809 std::string MSAsmString
;
810 for (size_t I
= 0, E
= Pieces
.size(); I
< E
; ++I
) {
811 StringRef Instruction
= Pieces
[I
];
812 // For vex/vex2/vex3/evex masm style prefix, convert it to att style
813 // since we don't support masm style prefix in backend.
814 if (Instruction
.startswith("vex "))
815 MSAsmString
+= '{' + Instruction
.substr(0, 3).str() + '}' +
816 Instruction
.substr(3).str();
817 else if (Instruction
.startswith("vex2 ") ||
818 Instruction
.startswith("vex3 ") || Instruction
.startswith("evex "))
819 MSAsmString
+= '{' + Instruction
.substr(0, 4).str() + '}' +
820 Instruction
.substr(4).str();
822 MSAsmString
+= Instruction
.str();
823 // If this is not the last instruction, adding back the '\n\t'.
825 MSAsmString
+= "\n\t";
830 Expr
*MSAsmStmt::getOutputExpr(unsigned i
) {
831 return cast
<Expr
>(Exprs
[i
]);
834 Expr
*MSAsmStmt::getInputExpr(unsigned i
) {
835 return cast
<Expr
>(Exprs
[i
+ NumOutputs
]);
838 void MSAsmStmt::setInputExpr(unsigned i
, Expr
*E
) {
839 Exprs
[i
+ NumOutputs
] = E
;
842 //===----------------------------------------------------------------------===//
844 //===----------------------------------------------------------------------===//
846 GCCAsmStmt::GCCAsmStmt(const ASTContext
&C
, SourceLocation asmloc
,
847 bool issimple
, bool isvolatile
, unsigned numoutputs
,
848 unsigned numinputs
, IdentifierInfo
**names
,
849 StringLiteral
**constraints
, Expr
**exprs
,
850 StringLiteral
*asmstr
, unsigned numclobbers
,
851 StringLiteral
**clobbers
, unsigned numlabels
,
852 SourceLocation rparenloc
)
853 : AsmStmt(GCCAsmStmtClass
, asmloc
, issimple
, isvolatile
, numoutputs
,
854 numinputs
, numclobbers
),
855 RParenLoc(rparenloc
), AsmStr(asmstr
), NumLabels(numlabels
) {
856 unsigned NumExprs
= NumOutputs
+ NumInputs
+ NumLabels
;
858 Names
= new (C
) IdentifierInfo
*[NumExprs
];
859 std::copy(names
, names
+ NumExprs
, Names
);
861 Exprs
= new (C
) Stmt
*[NumExprs
];
862 std::copy(exprs
, exprs
+ NumExprs
, Exprs
);
864 unsigned NumConstraints
= NumOutputs
+ NumInputs
;
865 Constraints
= new (C
) StringLiteral
*[NumConstraints
];
866 std::copy(constraints
, constraints
+ NumConstraints
, Constraints
);
868 Clobbers
= new (C
) StringLiteral
*[NumClobbers
];
869 std::copy(clobbers
, clobbers
+ NumClobbers
, Clobbers
);
872 MSAsmStmt::MSAsmStmt(const ASTContext
&C
, SourceLocation asmloc
,
873 SourceLocation lbraceloc
, bool issimple
, bool isvolatile
,
874 ArrayRef
<Token
> asmtoks
, unsigned numoutputs
,
876 ArrayRef
<StringRef
> constraints
, ArrayRef
<Expr
*> exprs
,
877 StringRef asmstr
, ArrayRef
<StringRef
> clobbers
,
878 SourceLocation endloc
)
879 : AsmStmt(MSAsmStmtClass
, asmloc
, issimple
, isvolatile
, numoutputs
,
880 numinputs
, clobbers
.size()), LBraceLoc(lbraceloc
),
881 EndLoc(endloc
), NumAsmToks(asmtoks
.size()) {
882 initialize(C
, asmstr
, asmtoks
, constraints
, exprs
, clobbers
);
885 static StringRef
copyIntoContext(const ASTContext
&C
, StringRef str
) {
889 void MSAsmStmt::initialize(const ASTContext
&C
, StringRef asmstr
,
890 ArrayRef
<Token
> asmtoks
,
891 ArrayRef
<StringRef
> constraints
,
892 ArrayRef
<Expr
*> exprs
,
893 ArrayRef
<StringRef
> clobbers
) {
894 assert(NumAsmToks
== asmtoks
.size());
895 assert(NumClobbers
== clobbers
.size());
897 assert(exprs
.size() == NumOutputs
+ NumInputs
);
898 assert(exprs
.size() == constraints
.size());
900 AsmStr
= copyIntoContext(C
, asmstr
);
902 Exprs
= new (C
) Stmt
*[exprs
.size()];
903 std::copy(exprs
.begin(), exprs
.end(), Exprs
);
905 AsmToks
= new (C
) Token
[asmtoks
.size()];
906 std::copy(asmtoks
.begin(), asmtoks
.end(), AsmToks
);
908 Constraints
= new (C
) StringRef
[exprs
.size()];
909 std::transform(constraints
.begin(), constraints
.end(), Constraints
,
910 [&](StringRef Constraint
) {
911 return copyIntoContext(C
, Constraint
);
914 Clobbers
= new (C
) StringRef
[NumClobbers
];
915 // FIXME: Avoid the allocation/copy if at all possible.
916 std::transform(clobbers
.begin(), clobbers
.end(), Clobbers
,
917 [&](StringRef Clobber
) {
918 return copyIntoContext(C
, Clobber
);
922 IfStmt::IfStmt(const ASTContext
&Ctx
, SourceLocation IL
, IfStatementKind Kind
,
923 Stmt
*Init
, VarDecl
*Var
, Expr
*Cond
, SourceLocation LPL
,
924 SourceLocation RPL
, Stmt
*Then
, SourceLocation EL
, Stmt
*Else
)
925 : Stmt(IfStmtClass
), LParenLoc(LPL
), RParenLoc(RPL
) {
926 bool HasElse
= Else
!= nullptr;
927 bool HasVar
= Var
!= nullptr;
928 bool HasInit
= Init
!= nullptr;
929 IfStmtBits
.HasElse
= HasElse
;
930 IfStmtBits
.HasVar
= HasVar
;
931 IfStmtBits
.HasInit
= HasInit
;
933 setStatementKind(Kind
);
940 setConditionVariable(Ctx
, Var
);
949 IfStmt::IfStmt(EmptyShell Empty
, bool HasElse
, bool HasVar
, bool HasInit
)
950 : Stmt(IfStmtClass
, Empty
) {
951 IfStmtBits
.HasElse
= HasElse
;
952 IfStmtBits
.HasVar
= HasVar
;
953 IfStmtBits
.HasInit
= HasInit
;
956 IfStmt
*IfStmt::Create(const ASTContext
&Ctx
, SourceLocation IL
,
957 IfStatementKind Kind
, Stmt
*Init
, VarDecl
*Var
,
958 Expr
*Cond
, SourceLocation LPL
, SourceLocation RPL
,
959 Stmt
*Then
, SourceLocation EL
, Stmt
*Else
) {
960 bool HasElse
= Else
!= nullptr;
961 bool HasVar
= Var
!= nullptr;
962 bool HasInit
= Init
!= nullptr;
963 void *Mem
= Ctx
.Allocate(
964 totalSizeToAlloc
<Stmt
*, SourceLocation
>(
965 NumMandatoryStmtPtr
+ HasElse
+ HasVar
+ HasInit
, HasElse
),
968 IfStmt(Ctx
, IL
, Kind
, Init
, Var
, Cond
, LPL
, RPL
, Then
, EL
, Else
);
971 IfStmt
*IfStmt::CreateEmpty(const ASTContext
&Ctx
, bool HasElse
, bool HasVar
,
973 void *Mem
= Ctx
.Allocate(
974 totalSizeToAlloc
<Stmt
*, SourceLocation
>(
975 NumMandatoryStmtPtr
+ HasElse
+ HasVar
+ HasInit
, HasElse
),
977 return new (Mem
) IfStmt(EmptyShell(), HasElse
, HasVar
, HasInit
);
980 VarDecl
*IfStmt::getConditionVariable() {
981 auto *DS
= getConditionVariableDeclStmt();
984 return cast
<VarDecl
>(DS
->getSingleDecl());
987 void IfStmt::setConditionVariable(const ASTContext
&Ctx
, VarDecl
*V
) {
988 assert(hasVarStorage() &&
989 "This if statement has no storage for a condition variable!");
992 getTrailingObjects
<Stmt
*>()[varOffset()] = nullptr;
996 SourceRange VarRange
= V
->getSourceRange();
997 getTrailingObjects
<Stmt
*>()[varOffset()] = new (Ctx
)
998 DeclStmt(DeclGroupRef(V
), VarRange
.getBegin(), VarRange
.getEnd());
1001 bool IfStmt::isObjCAvailabilityCheck() const {
1002 return isa
<ObjCAvailabilityCheckExpr
>(getCond());
1005 std::optional
<Stmt
*> IfStmt::getNondiscardedCase(const ASTContext
&Ctx
) {
1006 if (!isConstexpr() || getCond()->isValueDependent())
1007 return std::nullopt
;
1008 return !getCond()->EvaluateKnownConstInt(Ctx
) ? getElse() : getThen();
1011 std::optional
<const Stmt
*>
1012 IfStmt::getNondiscardedCase(const ASTContext
&Ctx
) const {
1013 if (std::optional
<Stmt
*> Result
=
1014 const_cast<IfStmt
*>(this)->getNondiscardedCase(Ctx
))
1016 return std::nullopt
;
1019 ForStmt::ForStmt(const ASTContext
&C
, Stmt
*Init
, Expr
*Cond
, VarDecl
*condVar
,
1020 Expr
*Inc
, Stmt
*Body
, SourceLocation FL
, SourceLocation LP
,
1022 : Stmt(ForStmtClass
), LParenLoc(LP
), RParenLoc(RP
)
1024 SubExprs
[INIT
] = Init
;
1025 setConditionVariable(C
, condVar
);
1026 SubExprs
[COND
] = Cond
;
1027 SubExprs
[INC
] = Inc
;
1028 SubExprs
[BODY
] = Body
;
1029 ForStmtBits
.ForLoc
= FL
;
1032 VarDecl
*ForStmt::getConditionVariable() const {
1033 if (!SubExprs
[CONDVAR
])
1036 auto *DS
= cast
<DeclStmt
>(SubExprs
[CONDVAR
]);
1037 return cast
<VarDecl
>(DS
->getSingleDecl());
1040 void ForStmt::setConditionVariable(const ASTContext
&C
, VarDecl
*V
) {
1042 SubExprs
[CONDVAR
] = nullptr;
1046 SourceRange VarRange
= V
->getSourceRange();
1047 SubExprs
[CONDVAR
] = new (C
) DeclStmt(DeclGroupRef(V
), VarRange
.getBegin(),
1051 SwitchStmt::SwitchStmt(const ASTContext
&Ctx
, Stmt
*Init
, VarDecl
*Var
,
1052 Expr
*Cond
, SourceLocation LParenLoc
,
1053 SourceLocation RParenLoc
)
1054 : Stmt(SwitchStmtClass
), FirstCase(nullptr), LParenLoc(LParenLoc
),
1055 RParenLoc(RParenLoc
) {
1056 bool HasInit
= Init
!= nullptr;
1057 bool HasVar
= Var
!= nullptr;
1058 SwitchStmtBits
.HasInit
= HasInit
;
1059 SwitchStmtBits
.HasVar
= HasVar
;
1060 SwitchStmtBits
.AllEnumCasesCovered
= false;
1067 setConditionVariable(Ctx
, Var
);
1069 setSwitchLoc(SourceLocation
{});
1072 SwitchStmt::SwitchStmt(EmptyShell Empty
, bool HasInit
, bool HasVar
)
1073 : Stmt(SwitchStmtClass
, Empty
) {
1074 SwitchStmtBits
.HasInit
= HasInit
;
1075 SwitchStmtBits
.HasVar
= HasVar
;
1076 SwitchStmtBits
.AllEnumCasesCovered
= false;
1079 SwitchStmt
*SwitchStmt::Create(const ASTContext
&Ctx
, Stmt
*Init
, VarDecl
*Var
,
1080 Expr
*Cond
, SourceLocation LParenLoc
,
1081 SourceLocation RParenLoc
) {
1082 bool HasInit
= Init
!= nullptr;
1083 bool HasVar
= Var
!= nullptr;
1084 void *Mem
= Ctx
.Allocate(
1085 totalSizeToAlloc
<Stmt
*>(NumMandatoryStmtPtr
+ HasInit
+ HasVar
),
1086 alignof(SwitchStmt
));
1087 return new (Mem
) SwitchStmt(Ctx
, Init
, Var
, Cond
, LParenLoc
, RParenLoc
);
1090 SwitchStmt
*SwitchStmt::CreateEmpty(const ASTContext
&Ctx
, bool HasInit
,
1092 void *Mem
= Ctx
.Allocate(
1093 totalSizeToAlloc
<Stmt
*>(NumMandatoryStmtPtr
+ HasInit
+ HasVar
),
1094 alignof(SwitchStmt
));
1095 return new (Mem
) SwitchStmt(EmptyShell(), HasInit
, HasVar
);
1098 VarDecl
*SwitchStmt::getConditionVariable() {
1099 auto *DS
= getConditionVariableDeclStmt();
1102 return cast
<VarDecl
>(DS
->getSingleDecl());
1105 void SwitchStmt::setConditionVariable(const ASTContext
&Ctx
, VarDecl
*V
) {
1106 assert(hasVarStorage() &&
1107 "This switch statement has no storage for a condition variable!");
1110 getTrailingObjects
<Stmt
*>()[varOffset()] = nullptr;
1114 SourceRange VarRange
= V
->getSourceRange();
1115 getTrailingObjects
<Stmt
*>()[varOffset()] = new (Ctx
)
1116 DeclStmt(DeclGroupRef(V
), VarRange
.getBegin(), VarRange
.getEnd());
1119 WhileStmt::WhileStmt(const ASTContext
&Ctx
, VarDecl
*Var
, Expr
*Cond
,
1120 Stmt
*Body
, SourceLocation WL
, SourceLocation LParenLoc
,
1121 SourceLocation RParenLoc
)
1122 : Stmt(WhileStmtClass
) {
1123 bool HasVar
= Var
!= nullptr;
1124 WhileStmtBits
.HasVar
= HasVar
;
1129 setConditionVariable(Ctx
, Var
);
1132 setLParenLoc(LParenLoc
);
1133 setRParenLoc(RParenLoc
);
1136 WhileStmt::WhileStmt(EmptyShell Empty
, bool HasVar
)
1137 : Stmt(WhileStmtClass
, Empty
) {
1138 WhileStmtBits
.HasVar
= HasVar
;
1141 WhileStmt
*WhileStmt::Create(const ASTContext
&Ctx
, VarDecl
*Var
, Expr
*Cond
,
1142 Stmt
*Body
, SourceLocation WL
,
1143 SourceLocation LParenLoc
,
1144 SourceLocation RParenLoc
) {
1145 bool HasVar
= Var
!= nullptr;
1147 Ctx
.Allocate(totalSizeToAlloc
<Stmt
*>(NumMandatoryStmtPtr
+ HasVar
),
1148 alignof(WhileStmt
));
1149 return new (Mem
) WhileStmt(Ctx
, Var
, Cond
, Body
, WL
, LParenLoc
, RParenLoc
);
1152 WhileStmt
*WhileStmt::CreateEmpty(const ASTContext
&Ctx
, bool HasVar
) {
1154 Ctx
.Allocate(totalSizeToAlloc
<Stmt
*>(NumMandatoryStmtPtr
+ HasVar
),
1155 alignof(WhileStmt
));
1156 return new (Mem
) WhileStmt(EmptyShell(), HasVar
);
1159 VarDecl
*WhileStmt::getConditionVariable() {
1160 auto *DS
= getConditionVariableDeclStmt();
1163 return cast
<VarDecl
>(DS
->getSingleDecl());
1166 void WhileStmt::setConditionVariable(const ASTContext
&Ctx
, VarDecl
*V
) {
1167 assert(hasVarStorage() &&
1168 "This while statement has no storage for a condition variable!");
1171 getTrailingObjects
<Stmt
*>()[varOffset()] = nullptr;
1175 SourceRange VarRange
= V
->getSourceRange();
1176 getTrailingObjects
<Stmt
*>()[varOffset()] = new (Ctx
)
1177 DeclStmt(DeclGroupRef(V
), VarRange
.getBegin(), VarRange
.getEnd());
1181 LabelDecl
*IndirectGotoStmt::getConstantTarget() {
1182 if (auto *E
= dyn_cast
<AddrLabelExpr
>(getTarget()->IgnoreParenImpCasts()))
1183 return E
->getLabel();
1188 ReturnStmt::ReturnStmt(SourceLocation RL
, Expr
*E
, const VarDecl
*NRVOCandidate
)
1189 : Stmt(ReturnStmtClass
), RetExpr(E
) {
1190 bool HasNRVOCandidate
= NRVOCandidate
!= nullptr;
1191 ReturnStmtBits
.HasNRVOCandidate
= HasNRVOCandidate
;
1192 if (HasNRVOCandidate
)
1193 setNRVOCandidate(NRVOCandidate
);
1197 ReturnStmt::ReturnStmt(EmptyShell Empty
, bool HasNRVOCandidate
)
1198 : Stmt(ReturnStmtClass
, Empty
) {
1199 ReturnStmtBits
.HasNRVOCandidate
= HasNRVOCandidate
;
1202 ReturnStmt
*ReturnStmt::Create(const ASTContext
&Ctx
, SourceLocation RL
,
1203 Expr
*E
, const VarDecl
*NRVOCandidate
) {
1204 bool HasNRVOCandidate
= NRVOCandidate
!= nullptr;
1205 void *Mem
= Ctx
.Allocate(totalSizeToAlloc
<const VarDecl
*>(HasNRVOCandidate
),
1206 alignof(ReturnStmt
));
1207 return new (Mem
) ReturnStmt(RL
, E
, NRVOCandidate
);
1210 ReturnStmt
*ReturnStmt::CreateEmpty(const ASTContext
&Ctx
,
1211 bool HasNRVOCandidate
) {
1212 void *Mem
= Ctx
.Allocate(totalSizeToAlloc
<const VarDecl
*>(HasNRVOCandidate
),
1213 alignof(ReturnStmt
));
1214 return new (Mem
) ReturnStmt(EmptyShell(), HasNRVOCandidate
);
1218 CaseStmt
*CaseStmt::Create(const ASTContext
&Ctx
, Expr
*lhs
, Expr
*rhs
,
1219 SourceLocation caseLoc
, SourceLocation ellipsisLoc
,
1220 SourceLocation colonLoc
) {
1221 bool CaseStmtIsGNURange
= rhs
!= nullptr;
1222 void *Mem
= Ctx
.Allocate(
1223 totalSizeToAlloc
<Stmt
*, SourceLocation
>(
1224 NumMandatoryStmtPtr
+ CaseStmtIsGNURange
, CaseStmtIsGNURange
),
1226 return new (Mem
) CaseStmt(lhs
, rhs
, caseLoc
, ellipsisLoc
, colonLoc
);
1229 CaseStmt
*CaseStmt::CreateEmpty(const ASTContext
&Ctx
,
1230 bool CaseStmtIsGNURange
) {
1231 void *Mem
= Ctx
.Allocate(
1232 totalSizeToAlloc
<Stmt
*, SourceLocation
>(
1233 NumMandatoryStmtPtr
+ CaseStmtIsGNURange
, CaseStmtIsGNURange
),
1235 return new (Mem
) CaseStmt(EmptyShell(), CaseStmtIsGNURange
);
1238 SEHTryStmt::SEHTryStmt(bool IsCXXTry
, SourceLocation TryLoc
, Stmt
*TryBlock
,
1240 : Stmt(SEHTryStmtClass
), IsCXXTry(IsCXXTry
), TryLoc(TryLoc
) {
1241 Children
[TRY
] = TryBlock
;
1242 Children
[HANDLER
] = Handler
;
1245 SEHTryStmt
* SEHTryStmt::Create(const ASTContext
&C
, bool IsCXXTry
,
1246 SourceLocation TryLoc
, Stmt
*TryBlock
,
1248 return new(C
) SEHTryStmt(IsCXXTry
,TryLoc
,TryBlock
,Handler
);
1251 SEHExceptStmt
* SEHTryStmt::getExceptHandler() const {
1252 return dyn_cast
<SEHExceptStmt
>(getHandler());
1255 SEHFinallyStmt
* SEHTryStmt::getFinallyHandler() const {
1256 return dyn_cast
<SEHFinallyStmt
>(getHandler());
1259 SEHExceptStmt::SEHExceptStmt(SourceLocation Loc
, Expr
*FilterExpr
, Stmt
*Block
)
1260 : Stmt(SEHExceptStmtClass
), Loc(Loc
) {
1261 Children
[FILTER_EXPR
] = FilterExpr
;
1262 Children
[BLOCK
] = Block
;
1265 SEHExceptStmt
* SEHExceptStmt::Create(const ASTContext
&C
, SourceLocation Loc
,
1266 Expr
*FilterExpr
, Stmt
*Block
) {
1267 return new(C
) SEHExceptStmt(Loc
,FilterExpr
,Block
);
1270 SEHFinallyStmt::SEHFinallyStmt(SourceLocation Loc
, Stmt
*Block
)
1271 : Stmt(SEHFinallyStmtClass
), Loc(Loc
), Block(Block
) {}
1273 SEHFinallyStmt
* SEHFinallyStmt::Create(const ASTContext
&C
, SourceLocation Loc
,
1275 return new(C
)SEHFinallyStmt(Loc
,Block
);
1278 CapturedStmt::Capture::Capture(SourceLocation Loc
, VariableCaptureKind Kind
,
1280 : VarAndKind(Var
, Kind
), Loc(Loc
) {
1283 assert(!Var
&& "'this' capture cannot have a variable!");
1286 assert(Var
&& "capturing by reference must have a variable!");
1289 assert(Var
&& "capturing by copy must have a variable!");
1293 "Variable-length array type capture cannot have a variable!");
1298 CapturedStmt::VariableCaptureKind
1299 CapturedStmt::Capture::getCaptureKind() const {
1300 return VarAndKind
.getInt();
1303 VarDecl
*CapturedStmt::Capture::getCapturedVar() const {
1304 assert((capturesVariable() || capturesVariableByCopy()) &&
1305 "No variable available for 'this' or VAT capture");
1306 return VarAndKind
.getPointer();
1309 CapturedStmt::Capture
*CapturedStmt::getStoredCaptures() const {
1310 unsigned Size
= sizeof(CapturedStmt
) + sizeof(Stmt
*) * (NumCaptures
+ 1);
1312 // Offset of the first Capture object.
1313 unsigned FirstCaptureOffset
= llvm::alignTo(Size
, alignof(Capture
));
1315 return reinterpret_cast<Capture
*>(
1316 reinterpret_cast<char *>(const_cast<CapturedStmt
*>(this))
1317 + FirstCaptureOffset
);
1320 CapturedStmt::CapturedStmt(Stmt
*S
, CapturedRegionKind Kind
,
1321 ArrayRef
<Capture
> Captures
,
1322 ArrayRef
<Expr
*> CaptureInits
,
1325 : Stmt(CapturedStmtClass
), NumCaptures(Captures
.size()),
1326 CapDeclAndKind(CD
, Kind
), TheRecordDecl(RD
) {
1327 assert( S
&& "null captured statement");
1328 assert(CD
&& "null captured declaration for captured statement");
1329 assert(RD
&& "null record declaration for captured statement");
1331 // Copy initialization expressions.
1332 Stmt
**Stored
= getStoredStmts();
1333 for (unsigned I
= 0, N
= NumCaptures
; I
!= N
; ++I
)
1334 *Stored
++ = CaptureInits
[I
];
1336 // Copy the statement being captured.
1339 // Copy all Capture objects.
1340 Capture
*Buffer
= getStoredCaptures();
1341 std::copy(Captures
.begin(), Captures
.end(), Buffer
);
1344 CapturedStmt::CapturedStmt(EmptyShell Empty
, unsigned NumCaptures
)
1345 : Stmt(CapturedStmtClass
, Empty
), NumCaptures(NumCaptures
),
1346 CapDeclAndKind(nullptr, CR_Default
) {
1347 getStoredStmts()[NumCaptures
] = nullptr;
1349 // Construct default capture objects.
1350 Capture
*Buffer
= getStoredCaptures();
1351 for (unsigned I
= 0, N
= NumCaptures
; I
!= N
; ++I
)
1352 new (Buffer
++) Capture();
1355 CapturedStmt
*CapturedStmt::Create(const ASTContext
&Context
, Stmt
*S
,
1356 CapturedRegionKind Kind
,
1357 ArrayRef
<Capture
> Captures
,
1358 ArrayRef
<Expr
*> CaptureInits
,
1363 // -----------------------------------------------------------
1364 // | CapturedStmt, Init, ..., Init, S, Capture, ..., Capture |
1365 // ----------------^-------------------^----------------------
1366 // getStoredStmts() getStoredCaptures()
1368 // where S is the statement being captured.
1370 assert(CaptureInits
.size() == Captures
.size() && "wrong number of arguments");
1372 unsigned Size
= sizeof(CapturedStmt
) + sizeof(Stmt
*) * (Captures
.size() + 1);
1373 if (!Captures
.empty()) {
1374 // Realign for the following Capture array.
1375 Size
= llvm::alignTo(Size
, alignof(Capture
));
1376 Size
+= sizeof(Capture
) * Captures
.size();
1379 void *Mem
= Context
.Allocate(Size
);
1380 return new (Mem
) CapturedStmt(S
, Kind
, Captures
, CaptureInits
, CD
, RD
);
1383 CapturedStmt
*CapturedStmt::CreateDeserialized(const ASTContext
&Context
,
1384 unsigned NumCaptures
) {
1385 unsigned Size
= sizeof(CapturedStmt
) + sizeof(Stmt
*) * (NumCaptures
+ 1);
1386 if (NumCaptures
> 0) {
1387 // Realign for the following Capture array.
1388 Size
= llvm::alignTo(Size
, alignof(Capture
));
1389 Size
+= sizeof(Capture
) * NumCaptures
;
1392 void *Mem
= Context
.Allocate(Size
);
1393 return new (Mem
) CapturedStmt(EmptyShell(), NumCaptures
);
1396 Stmt::child_range
CapturedStmt::children() {
1397 // Children are captured field initializers.
1398 return child_range(getStoredStmts(), getStoredStmts() + NumCaptures
);
1401 Stmt::const_child_range
CapturedStmt::children() const {
1402 return const_child_range(getStoredStmts(), getStoredStmts() + NumCaptures
);
1405 CapturedDecl
*CapturedStmt::getCapturedDecl() {
1406 return CapDeclAndKind
.getPointer();
1409 const CapturedDecl
*CapturedStmt::getCapturedDecl() const {
1410 return CapDeclAndKind
.getPointer();
1413 /// Set the outlined function declaration.
1414 void CapturedStmt::setCapturedDecl(CapturedDecl
*D
) {
1415 assert(D
&& "null CapturedDecl");
1416 CapDeclAndKind
.setPointer(D
);
1419 /// Retrieve the captured region kind.
1420 CapturedRegionKind
CapturedStmt::getCapturedRegionKind() const {
1421 return CapDeclAndKind
.getInt();
1424 /// Set the captured region kind.
1425 void CapturedStmt::setCapturedRegionKind(CapturedRegionKind Kind
) {
1426 CapDeclAndKind
.setInt(Kind
);
1429 bool CapturedStmt::capturesVariable(const VarDecl
*Var
) const {
1430 for (const auto &I
: captures()) {
1431 if (!I
.capturesVariable() && !I
.capturesVariableByCopy())
1433 if (I
.getCapturedVar()->getCanonicalDecl() == Var
->getCanonicalDecl())