clang: lib/AST/Stmt.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

35#include "llvm/ADT/SmallVector.h"

36#include "llvm/ADT/StringExtras.h"

37#include "llvm/ADT/StringRef.h"

38#include "llvm/Support/Compiler.h"

39#include "llvm/Support/ErrorHandling.h"

40#include "llvm/Support/MathExtras.h"

41#include "llvm/Support/raw_ostream.h"

42#include

43#include

44#include

45#include

46#include

47#include

48

49using namespace clang;

50

51#define STMT(CLASS, PARENT)

52#define STMT_RANGE(BASE, FIRST, LAST)

53#define LAST_STMT_RANGE(BASE, FIRST, LAST) \

54 static_assert(llvm::isUInt(Stmt::StmtClass::LAST##Class), \

55 "The number of 'StmtClass'es is strictly bound " \

56 "by a bitfield of width NumStmtBits");

57#define ABSTRACT_STMT(STMT)

58#include "clang/AST/StmtNodes.inc"

59

65

70

71

73#define ABSTRACT_STMT(STMT)

74#define STMT(CLASS, PARENT) \

75 StmtClassInfo[(unsigned)Stmt::CLASS##Class].Name = #CLASS; \

76 StmtClassInfo[(unsigned)Stmt::CLASS##Class].Size = sizeof(CLASS);

77#include "clang/AST/StmtNodes.inc"

78

80}

81

83 unsigned alignment) {

84 return ::operator new(bytes, C, alignment);

85}

86

89}

90

91

92

93

94#define STMT(CLASS, PARENT) \

95 static_assert(!std::is_polymorphic::value, \

96 #CLASS " should not be polymorphic!");

97#include "clang/AST/StmtNodes.inc"

98

99

100

101

102#define STMT(CLASS, PARENT) \

103 static_assert(std::is_trivially_destructible::value, \

104 #CLASS " should be trivially destructible!");

105

106#define INITLISTEXPR(CLASS, PARENT)

107#include "clang/AST/StmtNodes.inc"

108

110

112

113 unsigned sum = 0;

114 llvm::errs() << "\n*** Stmt/Expr Stats:\n";

115 for (int i = 0; i != Stmt::lastStmtConstant+1; i++) {

118 }

119 llvm::errs() << " " << sum << " stmts/exprs total.\n";

120 sum = 0;

121 for (int i = 0; i != Stmt::lastStmtConstant+1; i++) {

127 << " bytes)\n";

129 }

130

131 llvm::errs() << "Total bytes = " << sum << "\n";

132}

133

136}

137

138bool Stmt::StatisticsEnabled = false;

140 StatisticsEnabled = true;

141}

142

143static std::pair<Stmt::Likelihood, const Attr *>

145 for (const auto *A : Attrs) {

146 if (isa(A))

148

149 if (isa(A))

151 }

152

154}

155

156static std::pair<Stmt::Likelihood, const Attr *> getLikelihood(const Stmt *S) {

157 if (const auto *AS = dyn_cast_or_null(S))

159

161}

162

164 return ::getLikelihood(Attrs).first;

165}

166

168 return ::getLikelihood(S).first;

169}

170

172 return ::getLikelihood(S).second;

173}

174

179 return LHT;

180

181

182 if (LHT == LHE)

184

186 return LHT;

187

188

190}

191

192std::tuple<bool, const Attr *, const Attr *>

194 std::pair<Likelihood, const Attr *> LHT = ::getLikelihood(Then);

195 std::pair<Likelihood, const Attr *> LHE = ::getLikelihood(Else);

196

197 if (LHT.first != LH_None && LHT.first == LHE.first)

198 return std::make_tuple(true, LHT.second, LHE.second);

199

200 return std::make_tuple(false, nullptr, nullptr);

201}

202

203

204

206 Stmt *S = this;

207 if (IgnoreCaptured)

208 if (auto CapS = dyn_cast_or_null(S))

209 S = CapS->getCapturedStmt();

210 while (true) {

211 if (auto AS = dyn_cast_or_null(S))

212 S = AS->getSubStmt();

213 else if (auto CS = dyn_cast_or_null(S)) {

214 if (CS->size() != 1)

215 break;

216 S = CS->body_back();

217 } else

218 break;

219 }

220 return S;

221}

222

223

224

225

226

228 const Stmt *S = this;

229 while (true) {

230 if (const auto *LS = dyn_cast(S))

231 S = LS->getSubStmt();

232 else if (const auto *SC = dyn_cast(S))

233 S = SC->getSubStmt();

234 else if (const auto *AS = dyn_cast(S))

235 S = AS->getSubStmt();

236 else

237 return S;

238 }

239}

240

241namespace {

242

243 struct good {};

244 struct bad {};

245

246

247

248

249 static good is_good(good) { return good(); }

250

252 template good implements_children(children_t T::*) {

253 return good();

254 }

255 LLVM_ATTRIBUTE_UNUSED

256 static bad implements_children(children_t Stmt::*) {

257 return bad();

258 }

259

261 template good implements_getBeginLoc(getBeginLoc_t T::*) {

262 return good();

263 }

264 LLVM_ATTRIBUTE_UNUSED

265 static bad implements_getBeginLoc(getBeginLoc_t Stmt::*) { return bad(); }

266

268 template good implements_getEndLoc(getLocEnd_t T::*) {

269 return good();

270 }

271 LLVM_ATTRIBUTE_UNUSED

272 static bad implements_getEndLoc(getLocEnd_t Stmt::*) { return bad(); }

273

274#define ASSERT_IMPLEMENTS_children(type) \

275 (void) is_good(implements_children(&type::children))

276#define ASSERT_IMPLEMENTS_getBeginLoc(type) \

277 (void)is_good(implements_getBeginLoc(&type::getBeginLoc))

278#define ASSERT_IMPLEMENTS_getEndLoc(type) \

279 (void)is_good(implements_getEndLoc(&type::getEndLoc))

280

281}

282

283

284

285LLVM_ATTRIBUTE_UNUSED

287#define ABSTRACT_STMT(type)

288#define STMT(type, base) \

289 ASSERT_IMPLEMENTS_children(type); \

290 ASSERT_IMPLEMENTS_getBeginLoc(type); \

291 ASSERT_IMPLEMENTS_getEndLoc(type);

292#include "clang/AST/StmtNodes.inc"

293}

294

297 case Stmt::NoStmtClass: llvm_unreachable("statement without class");

298#define ABSTRACT_STMT(type)

299#define STMT(type, base) \

300 case Stmt::type##Class: \

301 return static_cast<type*>(this)->children();

302#include "clang/AST/StmtNodes.inc"

303 }

304 llvm_unreachable("unknown statement kind!");

305}

306

307

308

309

310

311namespace {

312

313

314

315 template <class S, class T>

318 return static_cast<const S*>(stmt)->getSourceRange();

319 }

320

321

322

323

324

325 template

328 return SourceRange(static_cast<const S *>(stmt)->getBeginLoc(),

329 static_cast<const S *>(stmt)->getEndLoc());

330 }

331

332}

333

336 case Stmt::NoStmtClass: llvm_unreachable("statement without class");

337#define ABSTRACT_STMT(type)

338#define STMT(type, base) \

339 case Stmt::type##Class: \

340 return getSourceRangeImpl(this, &type::getSourceRange);

341#include "clang/AST/StmtNodes.inc"

342 }

343 llvm_unreachable("unknown statement kind!");

344}

345

348 case Stmt::NoStmtClass: llvm_unreachable("statement without class");

349#define ABSTRACT_STMT(type)

350#define STMT(type, base) \

351 case Stmt::type##Class: \

352 return static_cast<const type *>(this)->getBeginLoc();

353#include "clang/AST/StmtNodes.inc"

354 }

355 llvm_unreachable("unknown statement kind");

356}

357

360 case Stmt::NoStmtClass: llvm_unreachable("statement without class");

361#define ABSTRACT_STMT(type)

362#define STMT(type, base) \

363 case Stmt::type##Class: \

364 return static_cast<const type *>(this)->getEndLoc();

365#include "clang/AST/StmtNodes.inc"

366 }

367 llvm_unreachable("unknown statement kind");

368}

369

371 return Context.getAllocator().identifyKnownAlignedObject<Stmt>(this);

372}

373

376 : Stmt(CompoundStmtClass), LBraceLoc(LB), RBraceLoc(RB) {

379 setStmts(Stmts);

380 if (hasStoredFPFeatures())

381 setStoredFPFeatures(FPFeatures);

382}

383

386 "NumStmts doesn't fit in bits of CompoundStmtBits.NumStmts!");

387

388 std::copy(Stmts.begin(), Stmts.end(), body_begin());

389}

390

394 void *Mem =

395 C.Allocate(totalSizeToAlloc<Stmt *, FPOptionsOverride>(

398 return new (Mem) CompoundStmt(Stmts, FPFeatures, LB, RB);

399}

400

402 bool HasFPFeatures) {

403 void *Mem = C.Allocate(

404 totalSizeToAlloc<Stmt *, FPOptionsOverride>(NumStmts, HasFPFeatures),

409 return New;

410}

411

413 const Stmt *S = this;

414 do {

415 if (const auto *E = dyn_cast(S))

416 return E;

417

418 if (const auto *LS = dyn_cast(S))

419 S = LS->getSubStmt();

420 else if (const auto *AS = dyn_cast(S))

421 S = AS->getSubStmt();

422 else

423 llvm_unreachable("unknown kind of ValueStmt");

424 } while (isa(S));

425

426 return nullptr;

427}

428

431}

432

435 Stmt *SubStmt) {

436 assert(!Attrs.empty() && "Attrs should not be empty");

437 void *Mem = C.Allocate(totalSizeToAlloc<const Attr *>(Attrs.size()),

440}

441

443 unsigned NumAttrs) {

444 assert(NumAttrs > 0 && "NumAttrs should be greater than zero");

445 void *Mem = C.Allocate(totalSizeToAlloc<const Attr *>(NumAttrs),

448}

449

451 if (const auto *gccAsmStmt = dyn_cast(this))

452 return gccAsmStmt->generateAsmString(C);

453 if (const auto *msAsmStmt = dyn_cast(this))

454 return msAsmStmt->generateAsmString(C);

455 llvm_unreachable("unknown asm statement kind!");

456}

457

459 if (const auto *gccAsmStmt = dyn_cast(this))

460 return gccAsmStmt->getOutputConstraint(i);

461 if (const auto *msAsmStmt = dyn_cast(this))

462 return msAsmStmt->getOutputConstraint(i);

463 llvm_unreachable("unknown asm statement kind!");

464}

465

467 if (const auto *gccAsmStmt = dyn_cast(this))

468 return gccAsmStmt->getOutputExpr(i);

469 if (const auto *msAsmStmt = dyn_cast(this))

470 return msAsmStmt->getOutputExpr(i);

471 llvm_unreachable("unknown asm statement kind!");

472}

473

475 if (const auto *gccAsmStmt = dyn_cast(this))

476 return gccAsmStmt->getInputConstraint(i);

477 if (const auto *msAsmStmt = dyn_cast(this))

478 return msAsmStmt->getInputConstraint(i);

479 llvm_unreachable("unknown asm statement kind!");

480}

481

483 if (const auto *gccAsmStmt = dyn_cast(this))

484 return gccAsmStmt->getInputExpr(i);

485 if (const auto *msAsmStmt = dyn_cast(this))

486 return msAsmStmt->getInputExpr(i);

487 llvm_unreachable("unknown asm statement kind!");

488}

489

491 if (const auto *gccAsmStmt = dyn_cast(this))

492 return gccAsmStmt->getClobber(i);

493 if (const auto *msAsmStmt = dyn_cast(this))

494 return msAsmStmt->getClobber(i);

495 llvm_unreachable("unknown asm statement kind!");

496}

497

498

499

501 unsigned Res = 0;

502 for (unsigned i = 0, e = getNumOutputs(); i != e; ++i)

504 ++Res;

505 return Res;

506}

507

509 assert(isOperand() && "Only Operands can have modifiers.");

510 return isLetter(Str[0]) ? Str[0] : '\0';

511}

512

515}

516

518 return cast(Exprs[i]);

519}

520

521

522

523

526}

527

530}

531

534}

535

538}

539

542}

543

544

545

548}

549

550void GCCAsmStmt::setOutputsAndInputsAndClobbers(const ASTContext &C,

556 unsigned NumLabels,

562 this->NumLabels = NumLabels;

563

565

566 C.Deallocate(this->Names);

568 std::copy(Names, Names + NumExprs, this->Names);

569

570 C.Deallocate(this->Exprs);

571 this->Exprs = new (C) Stmt*[NumExprs];

572 std::copy(Exprs, Exprs + NumExprs, this->Exprs);

573

575 C.Deallocate(this->Constraints);

577 std::copy(Constraints, Constraints + NumConstraints, this->Constraints);

578

579 C.Deallocate(this->Clobbers);

581 std::copy(Clobbers, Clobbers + NumClobbers, this->Clobbers);

582}

583

584

585

586

588

590 for (unsigned i = 0; i != NumOutputs; ++i)

592 return i;

593

595 for (unsigned i = 0; i != NumInputs; ++i)

598

599 for (unsigned i = 0, e = getNumLabels(); i != e; ++i)

602

603

604 return -1;

605}

606

607

608

609

611 const ASTContext &C, unsigned &DiagOffs) const {

613 const char *StrStart = Str.begin();

614 const char *StrEnd = Str.end();

615 const char *CurPtr = StrStart;

616

617

618

621 for (; CurPtr != StrEnd; ++CurPtr) {

622 switch (*CurPtr) {

623 case '$':

625 break;

626 default:

628 break;

629 }

630 }

632 return 0;

633 }

634

635

636

637 std::string CurStringPiece;

638

639 bool HasVariants = C.getTargetInfo().hasNoAsmVariants();

640

641 unsigned LastAsmStringToken = 0;

642 unsigned LastAsmStringOffset = 0;

643

644 while (true) {

645

646 if (CurPtr == StrEnd) {

647 if (!CurStringPiece.empty())

649 return 0;

650 }

651

652 char CurChar = *CurPtr++;

653 switch (CurChar) {

654 case '$': CurStringPiece += "$$"; continue;

655 case '{': CurStringPiece += (HasVariants ? "$(" : "{"); continue;

656 case '|': CurStringPiece += (HasVariants ? "$|" : "|"); continue;

657 case '}': CurStringPiece += (HasVariants ? "$)" : "}"); continue;

658 case '%':

659 break;

660 default:

661 CurStringPiece += CurChar;

662 continue;

663 }

664

665 const TargetInfo &TI = C.getTargetInfo();

666

667

668 if (CurPtr == StrEnd) {

669

670 DiagOffs = CurPtr-StrStart-1;

671 return diag::err_asm_invalid_escape;

672 }

673

674 char EscapedChar = *CurPtr++;

675 switch (EscapedChar) {

676 default:

677

679 CurStringPiece += *MaybeReplaceStr;

680 continue;

681 }

682 break;

683 case '%':

684 case '{':

685 case '}':

686 CurStringPiece += EscapedChar;

687 continue;

688 case '=':

689 CurStringPiece += "${:uid}";

690 continue;

691 }

692

693

694

695 if (!CurStringPiece.empty()) {

697 CurStringPiece.clear();

698 }

699

700

701

702

703 const char *Begin = CurPtr - 1;

704 const char *Percent = Begin - 1;

705

707 if (CurPtr == StrEnd) {

708 DiagOffs = CurPtr-StrStart-1;

709 return diag::err_asm_invalid_escape;

710 }

711 EscapedChar = *CurPtr++;

712 }

713

716

717

718 if (isDigit(EscapedChar)) {

719

720 unsigned N = 0;

721

722 --CurPtr;

723 while (CurPtr != StrEnd && isDigit(*CurPtr))

724 N = N*10 + ((*CurPtr++)-'0');

725

728 if (N >= NumOperands) {

729 DiagOffs = CurPtr-StrStart-1;

730 return diag::err_asm_invalid_operand_number;

731 }

732

733

734 std::string Str(Begin, CurPtr - Begin);

735

736

737

739 Percent - StrStart, SM, LO, TI, &LastAsmStringToken,

740 &LastAsmStringOffset);

742 CurPtr - StrStart, SM, LO, TI, &LastAsmStringToken,

743 &LastAsmStringOffset);

744

745 Pieces.emplace_back(N, std::move(Str), BeginLoc, EndLoc);

746 continue;

747 }

748

749

750 if (EscapedChar == '[') {

751 DiagOffs = CurPtr-StrStart-1;

752

753

754 const char *NameEnd = (const char*)memchr(CurPtr, ']', StrEnd-CurPtr);

755 if (NameEnd == nullptr)

756 return diag::err_asm_unterminated_symbolic_operand_name;

757 if (NameEnd == CurPtr)

758 return diag::err_asm_empty_symbolic_operand_name;

759

760 StringRef SymbolicName(CurPtr, NameEnd - CurPtr);

761

763 if (N == -1) {

764

765 DiagOffs = CurPtr-StrStart;

766 return diag::err_asm_unknown_symbolic_operand_name;

767 }

768

769

770 std::string Str(Begin, NameEnd + 1 - Begin);

771

772

773

775 Percent - StrStart, SM, LO, TI, &LastAsmStringToken,

776 &LastAsmStringOffset);

778 NameEnd + 1 - StrStart, SM, LO, TI, &LastAsmStringToken,

779 &LastAsmStringOffset);

780

781 Pieces.emplace_back(N, std::move(Str), BeginLoc, EndLoc);

782

783 CurPtr = NameEnd+1;

784 continue;

785 }

786

787 DiagOffs = CurPtr-StrStart-1;

788 return diag::err_asm_invalid_escape;

789 }

790}

791

792

794

795

797 unsigned DiagOffs;

799

800 std::string AsmString;

801 for (const auto &Piece : Pieces) {

802 if (Piece.isString())

803 AsmString += Piece.getString();

804 else if (Piece.getModifier() == '\0')

805 AsmString += '$' + llvm::utostr(Piece.getOperandNo());

806 else

807 AsmString += "${" + llvm::utostr(Piece.getOperandNo()) + ':' +

808 Piece.getModifier() + '}';

809 }

810 return AsmString;

811}

812

813

815

817 AsmStr.split(Pieces, "\n\t");

818 std::string MSAsmString;

819 for (size_t I = 0, E = Pieces.size(); I < E; ++I) {

820 StringRef Instruction = Pieces[I];

821

822

823 if (Instruction.starts_with("vex "))

824 MSAsmString += '{' + Instruction.substr(0, 3).str() + '}' +

825 Instruction.substr(3).str();

826 else if (Instruction.starts_with("vex2 ") ||

827 Instruction.starts_with("vex3 ") ||

828 Instruction.starts_with("evex "))

829 MSAsmString += '{' + Instruction.substr(0, 4).str() + '}' +

830 Instruction.substr(4).str();

831 else

832 MSAsmString += Instruction.str();

833

834 if (I < E - 1)

835 MSAsmString += "\n\t";

836 }

837 return MSAsmString;

838}

839

841 return cast(Exprs[i]);

842}

843

846}

847

850}

851

852

853

854

855

857 bool issimple, bool isvolatile, unsigned numoutputs,

863 : AsmStmt(GCCAsmStmtClass, asmloc, issimple, isvolatile, numoutputs,

864 numinputs, numclobbers),

865 RParenLoc(rparenloc), AsmStr(asmstr), NumLabels(numlabels) {

867

869 std::copy(names, names + NumExprs, Names);

870

872 std::copy(exprs, exprs + NumExprs, Exprs);

873

876 std::copy(constraints, constraints + NumConstraints, Constraints);

877

879 std::copy(clobbers, clobbers + NumClobbers, Clobbers);

880}

881

883 SourceLocation lbraceloc, bool issimple, bool isvolatile,

885 unsigned numinputs,

889 : AsmStmt(MSAsmStmtClass, asmloc, issimple, isvolatile, numoutputs,

890 numinputs, clobbers.size()), LBraceLoc(lbraceloc),

891 EndLoc(endloc), NumAsmToks(asmtoks.size()) {

892 initialize(C, asmstr, asmtoks, constraints, exprs, clobbers);

893}

894

896 return str.copy(C);

897}

898

899void MSAsmStmt::initialize(const ASTContext &C, StringRef asmstr,

904 assert(NumAsmToks == asmtoks.size());

906

908 assert(exprs.size() == constraints.size());

909

911

913 std::copy(exprs.begin(), exprs.end(), Exprs);

914

915 AsmToks = new (C) Token[asmtoks.size()];

916 std::copy(asmtoks.begin(), asmtoks.end(), AsmToks);

917

918 Constraints = new (C) StringRef[exprs.size()];

919 std::transform(constraints.begin(), constraints.end(), Constraints,

920 [&](StringRef Constraint) {

921 return copyIntoContext(C, Constraint);

922 });

923

925

926 std::transform(clobbers.begin(), clobbers.end(), Clobbers,

927 [&](StringRef Clobber) {

928 return copyIntoContext(C, Clobber);

929 });

930}

931

935 : Stmt(IfStmtClass), LParenLoc(LPL), RParenLoc(RPL) {

936 bool HasElse = Else != nullptr;

937 bool HasVar = Var != nullptr;

938 bool HasInit = Init != nullptr;

939 IfStmtBits.HasElse = HasElse;

940 IfStmtBits.HasVar = HasVar;

941 IfStmtBits.HasInit = HasInit;

942

943 setStatementKind(Kind);

944

945 setCond(Cond);

946 setThen(Then);

947 if (HasElse)

948 setElse(Else);

949 if (HasVar)

950 setConditionVariable(Ctx, Var);

951 if (HasInit)

952 setInit(Init);

953

954 setIfLoc(IL);

955 if (HasElse)

956 setElseLoc(EL);

957}

958

959IfStmt::IfStmt(EmptyShell Empty, bool HasElse, bool HasVar, bool HasInit)

961 IfStmtBits.HasElse = HasElse;

962 IfStmtBits.HasVar = HasVar;

963 IfStmtBits.HasInit = HasInit;

964}

965

970 bool HasElse = Else != nullptr;

971 bool HasVar = Var != nullptr;

972 bool HasInit = Init != nullptr;

974 totalSizeToAlloc<Stmt *, SourceLocation>(

975 NumMandatoryStmtPtr + HasElse + HasVar + HasInit, HasElse),

977 return new (Mem)

978 IfStmt(Ctx, IL, Kind, Init, Var, Cond, LPL, RPL, Then, EL, Else);

979}

980

982 bool HasInit) {

984 totalSizeToAlloc<Stmt *, SourceLocation>(

985 NumMandatoryStmtPtr + HasElse + HasVar + HasInit, HasElse),

987 return new (Mem) IfStmt(EmptyShell(), HasElse, HasVar, HasInit);

988}

989

992 if (!DS)

993 return nullptr;

994 return cast(DS->getSingleDecl());

995}

996

999 "This if statement has no storage for a condition variable!");

1000

1001 if (V) {

1002 getTrailingObjects<Stmt *>()[varOffset()] = nullptr;

1003 return;

1004 }

1005

1007 getTrailingObjects<Stmt *>()[varOffset()] = new (Ctx)

1009}

1010

1012 return isa(getCond());

1013}

1014

1017 return std::nullopt;

1019}

1020

1021std::optional<const Stmt *>

1023 if (std::optional<Stmt *> Result =

1026 return std::nullopt;

1027}

1028

1032 : Stmt(ForStmtClass), LParenLoc(LP), RParenLoc(RP)

1033{

1034 SubExprs[INIT] = Init;

1036 SubExprs[COND] = Cond;

1037 SubExprs[INC] = Inc;

1038 SubExprs[BODY] = Body;

1040}

1041

1043 if (!SubExprs[CONDVAR])

1044 return nullptr;

1045

1046 auto *DS = cast(SubExprs[CONDVAR]);

1047 return cast(DS->getSingleDecl());

1048}

1049

1051 if (V) {

1052 SubExprs[CONDVAR] = nullptr;

1053 return;

1054 }

1055

1059}

1060

1064 : Stmt(SwitchStmtClass), FirstCase(nullptr), LParenLoc(LParenLoc),

1065 RParenLoc(RParenLoc) {

1066 bool HasInit = Init != nullptr;

1067 bool HasVar = Var != nullptr;

1071

1074 if (HasInit)

1076 if (HasVar)

1078

1080}

1081

1082SwitchStmt::SwitchStmt(EmptyShell Empty, bool HasInit, bool HasVar)

1083 : Stmt(SwitchStmtClass, Empty) {

1087}

1088

1092 bool HasInit = Init != nullptr;

1093 bool HasVar = Var != nullptr;

1095 totalSizeToAlloc<Stmt *>(NumMandatoryStmtPtr + HasInit + HasVar),

1097 return new (Mem) SwitchStmt(Ctx, Init, Var, Cond, LParenLoc, RParenLoc);

1098}

1099

1101 bool HasVar) {

1103 totalSizeToAlloc<Stmt *>(NumMandatoryStmtPtr + HasInit + HasVar),

1106}

1107

1110 if (!DS)

1111 return nullptr;

1112 return cast(DS->getSingleDecl());

1113}

1114

1117 "This switch statement has no storage for a condition variable!");

1118

1119 if (V) {

1120 getTrailingObjects<Stmt *>()[varOffset()] = nullptr;

1121 return;

1122 }

1123

1125 getTrailingObjects<Stmt *>()[varOffset()] = new (Ctx)

1127}

1128

1132 : Stmt(WhileStmtClass) {

1133 bool HasVar = Var != nullptr;

1135

1138 if (HasVar)

1140

1141 setWhileLoc(WL);

1144}

1145

1146WhileStmt::WhileStmt(EmptyShell Empty, bool HasVar)

1149}

1150

1155 bool HasVar = Var != nullptr;

1156 void *Mem =

1157 Ctx.Allocate(totalSizeToAlloc<Stmt *>(NumMandatoryStmtPtr + HasVar),

1159 return new (Mem) WhileStmt(Ctx, Var, Cond, Body, WL, LParenLoc, RParenLoc);

1160}

1161

1163 void *Mem =

1164 Ctx.Allocate(totalSizeToAlloc<Stmt *>(NumMandatoryStmtPtr + HasVar),

1167}

1168

1171 if (!DS)

1172 return nullptr;

1173 return cast(DS->getSingleDecl());

1174}

1175

1178 "This while statement has no storage for a condition variable!");

1179

1180 if (V) {

1181 getTrailingObjects<Stmt *>()[varOffset()] = nullptr;

1182 return;

1183 }

1184

1186 getTrailingObjects<Stmt *>()[varOffset()] = new (Ctx)

1188}

1189

1190

1192 if (auto *E = dyn_cast(getTarget()->IgnoreParenImpCasts()))

1193 return E->getLabel();

1194 return nullptr;

1195}

1196

1197

1199 : Stmt(ReturnStmtClass), RetExpr(E) {

1200 bool HasNRVOCandidate = NRVOCandidate != nullptr;

1202 if (HasNRVOCandidate)

1203 setNRVOCandidate(NRVOCandidate);

1204 setReturnLoc(RL);

1205}

1206

1207ReturnStmt::ReturnStmt(EmptyShell Empty, bool HasNRVOCandidate)

1208 : Stmt(ReturnStmtClass, Empty) {

1210}

1211

1214 bool HasNRVOCandidate = NRVOCandidate != nullptr;

1215 void *Mem = Ctx.Allocate(totalSizeToAlloc<const VarDecl *>(HasNRVOCandidate),

1217 return new (Mem) ReturnStmt(RL, E, NRVOCandidate);

1218}

1219

1221 bool HasNRVOCandidate) {

1222 void *Mem = Ctx.Allocate(totalSizeToAlloc<const VarDecl *>(HasNRVOCandidate),

1225}

1226

1227

1231 bool CaseStmtIsGNURange = rhs != nullptr;

1233 totalSizeToAlloc<Stmt *, SourceLocation>(

1234 NumMandatoryStmtPtr + CaseStmtIsGNURange, CaseStmtIsGNURange),

1236 return new (Mem) CaseStmt(lhs, rhs, caseLoc, ellipsisLoc, colonLoc);

1237}

1238

1240 bool CaseStmtIsGNURange) {

1242 totalSizeToAlloc<Stmt *, SourceLocation>(

1243 NumMandatoryStmtPtr + CaseStmtIsGNURange, CaseStmtIsGNURange),

1246}

1247

1248SEHTryStmt::SEHTryStmt(bool IsCXXTry, SourceLocation TryLoc, Stmt *TryBlock,

1249 Stmt *Handler)

1250 : Stmt(SEHTryStmtClass), IsCXXTry(IsCXXTry), TryLoc(TryLoc) {

1251 Children[TRY] = TryBlock;

1252 Children[HANDLER] = Handler;

1253}

1254

1257 Stmt *Handler) {

1258 return new(C) SEHTryStmt(IsCXXTry,TryLoc,TryBlock,Handler);

1259}

1260

1262 return dyn_cast(getHandler());

1263}

1264

1266 return dyn_cast(getHandler());

1267}

1268

1270 : Stmt(SEHExceptStmtClass), Loc(Loc) {

1271 Children[FILTER_EXPR] = FilterExpr;

1273}

1274

1278}

1279

1282

1286}

1287

1290 : VarAndKind(Var, Kind), Loc(Loc) {

1291 switch (Kind) {

1293 assert(!Var && "'this' capture cannot have a variable!");

1294 break;

1296 assert(Var && "capturing by reference must have a variable!");

1297 break;

1299 assert(Var && "capturing by copy must have a variable!");

1300 break;

1302 assert(!Var &&

1303 "Variable-length array type capture cannot have a variable!");

1304 break;

1305 }

1306}

1307

1310 return VarAndKind.getInt();

1311}

1312

1315 "No variable available for 'this' or VAT capture");

1316 return VarAndKind.getPointer();

1317}

1318

1320 unsigned Size = sizeof(CapturedStmt) + sizeof(Stmt *) * (NumCaptures + 1);

1321

1322

1323 unsigned FirstCaptureOffset = llvm::alignTo(Size, alignof(Capture));

1324

1325 return reinterpret_cast<Capture *>(

1326 reinterpret_cast<char *>(const_cast<CapturedStmt *>(this))

1327 + FirstCaptureOffset);

1328}

1329

1335 : Stmt(CapturedStmtClass), NumCaptures(Captures.size()),

1336 CapDeclAndKind(CD, Kind), TheRecordDecl(RD) {

1337 assert( S && "null captured statement");

1338 assert(CD && "null captured declaration for captured statement");

1339 assert(RD && "null record declaration for captured statement");

1340

1341

1342 Stmt **Stored = getStoredStmts();

1343 for (unsigned I = 0, N = NumCaptures; I != N; ++I)

1344 *Stored++ = CaptureInits[I];

1345

1346

1347 *Stored = S;

1348

1349

1350 Capture *Buffer = getStoredCaptures();

1351 std::copy(Captures.begin(), Captures.end(), Buffer);

1352}

1353

1354CapturedStmt::CapturedStmt(EmptyShell Empty, unsigned NumCaptures)

1355 : Stmt(CapturedStmtClass, Empty), NumCaptures(NumCaptures),

1356 CapDeclAndKind(nullptr, CR_Default) {

1357 getStoredStmts()[NumCaptures] = nullptr;

1358

1359

1360 Capture *Buffer = getStoredCaptures();

1361 for (unsigned I = 0, N = NumCaptures; I != N; ++I)

1362 new (Buffer++) Capture();

1363}

1364

1371

1372

1373

1374

1375

1376

1377

1378

1379

1380 assert(CaptureInits.size() == Captures.size() && "wrong number of arguments");

1381

1382 unsigned Size = sizeof(CapturedStmt) + sizeof(Stmt *) * (Captures.size() + 1);

1383 if (!Captures.empty()) {

1384

1385 Size = llvm::alignTo(Size, alignof(Capture));

1386 Size += sizeof(Capture) * Captures.size();

1387 }

1388

1389 void *Mem = Context.Allocate(Size);

1390 return new (Mem) CapturedStmt(S, Kind, Captures, CaptureInits, CD, RD);

1391}

1392

1394 unsigned NumCaptures) {

1395 unsigned Size = sizeof(CapturedStmt) + sizeof(Stmt *) * (NumCaptures + 1);

1396 if (NumCaptures > 0) {

1397

1398 Size = llvm::alignTo(Size, alignof(Capture));

1399 Size += sizeof(Capture) * NumCaptures;

1400 }

1401

1402 void *Mem = Context.Allocate(Size);

1404}

1405

1407

1408 return child_range(getStoredStmts(), getStoredStmts() + NumCaptures);

1409}

1410

1412 return const_child_range(getStoredStmts(), getStoredStmts() + NumCaptures);

1413}

1414

1416 return CapDeclAndKind.getPointer();

1417}

1418

1420 return CapDeclAndKind.getPointer();

1421}

1422

1423

1425 assert(D && "null CapturedDecl");

1426 CapDeclAndKind.setPointer(D);

1427}

1428

1429

1431 return CapDeclAndKind.getInt();

1432}

1433

1434

1436 CapDeclAndKind.setInt(Kind);

1437}

1438

1440 for (const auto &I : captures()) {

1441 if (!I.capturesVariable() && !I.capturesVariableByCopy())

1442 continue;

1443 if (I.getCapturedVar()->getCanonicalDecl() == Var->getCanonicalDecl())

1444 return true;

1445 }

1446

1447 return false;

1448}

Defines the clang::ASTContext interface.

static StringRef bytes(const std::vector< T, Allocator > &v)

Defines the clang::Expr interface and subclasses for C++ expressions.

Defines Expressions and AST nodes for C++2a concepts.

Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.

Defines the clang::SourceLocation class and associated facilities.

Defines the Objective-C statement AST node classes.

This file defines OpenACC AST classes for statement-level contructs.

This file defines OpenMP AST classes for executable directives and clauses.

This file defines SYCL AST classes used to represent calls to SYCL kernels.

static StmtClassNameTable & getStmtInfoTableEntry(Stmt::StmtClass E)

static LLVM_ATTRIBUTE_UNUSED void check_implementations()

Check whether the various Stmt classes implement their member functions.

static StringRef copyIntoContext(const ASTContext &C, StringRef str)

static std::pair< Stmt::Likelihood, const Attr * > getLikelihood(ArrayRef< const Attr * > Attrs)

static struct StmtClassNameTable StmtClassInfo[Stmt::lastStmtConstant+1]

#define BLOCK(DERIVED, BASE)

C Language Family Type Representation.

__device__ __2f16 float __ockl_bool s

Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...

llvm::BumpPtrAllocator & getAllocator() const

void * Allocate(size_t Size, unsigned Align=8) const

AddrLabelExpr - The GNU address of label extension, representing &&label.

LabelDecl * getLabel() const

AsmStmt is the base class for GCCAsmStmt and MSAsmStmt.

unsigned getNumPlusOperands() const

getNumPlusOperands - Return the number of output operands that have a "+" constraint.

StringRef getOutputConstraint(unsigned i) const

getOutputConstraint - Return the constraint string for the specified output operand.

const Expr * getInputExpr(unsigned i) const

bool isOutputPlusConstraint(unsigned i) const

isOutputPlusConstraint - Return true if the specified output constraint is a "+" constraint (which is...

const Expr * getOutputExpr(unsigned i) const

StringRef getInputConstraint(unsigned i) const

getInputConstraint - Return the specified input constraint.

unsigned getNumOutputs() const

std::string generateAsmString(const ASTContext &C) const

Assemble final IR asm string.

unsigned getNumInputs() const

StringRef getClobber(unsigned i) const

Attr - This represents one attribute.

Represents an attribute applied to a statement.

static AttributedStmt * CreateEmpty(const ASTContext &C, unsigned NumAttrs)

static AttributedStmt * Create(const ASTContext &C, SourceLocation Loc, ArrayRef< const Attr * > Attrs, Stmt *SubStmt)

Represents the body of a CapturedStmt, and serves as its DeclContext.

Describes the capture of either a variable, or 'this', or variable-length array type.

VariableCaptureKind getCaptureKind() const

Determine the kind of capture.

VarDecl * getCapturedVar() const

Retrieve the declaration of the variable being captured.

This captures a statement into a function.

static CapturedStmt * CreateDeserialized(const ASTContext &Context, unsigned NumCaptures)

void setCapturedRegionKind(CapturedRegionKind Kind)

Set the captured region kind.

CapturedDecl * getCapturedDecl()

Retrieve the outlined function declaration.

bool capturesVariable(const VarDecl *Var) const

True if this variable has been captured.

void setCapturedDecl(CapturedDecl *D)

Set the outlined function declaration.

static CapturedStmt * Create(const ASTContext &Context, Stmt *S, CapturedRegionKind Kind, ArrayRef< Capture > Captures, ArrayRef< Expr * > CaptureInits, CapturedDecl *CD, RecordDecl *RD)

CapturedRegionKind getCapturedRegionKind() const

Retrieve the captured region kind.

VariableCaptureKind

The different capture forms: by 'this', by reference, capture for variable-length array type etc.

CaseStmt - Represent a case statement.

static CaseStmt * Create(const ASTContext &Ctx, Expr *lhs, Expr *rhs, SourceLocation caseLoc, SourceLocation ellipsisLoc, SourceLocation colonLoc)

Build a case statement.

static CaseStmt * CreateEmpty(const ASTContext &Ctx, bool CaseStmtIsGNURange)

Build an empty case statement.

CompoundStmt - This represents a group of statements like { stmt stmt }.

static CompoundStmt * CreateEmpty(const ASTContext &C, unsigned NumStmts, bool HasFPFeatures)

body_iterator body_begin()

static CompoundStmt * Create(const ASTContext &C, ArrayRef< Stmt * > Stmts, FPOptionsOverride FPFeatures, SourceLocation LB, SourceLocation RB)

DeclStmt - Adaptor class for mixing declarations with statements and expressions.

This represents one expression.

llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx, SmallVectorImpl< PartialDiagnosticAt > *Diag=nullptr) const

EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded integer.

Represents difference between two FPOptions values.

bool requiresTrailingStorage() const

ForStmt(const ASTContext &C, Stmt *Init, Expr *Cond, VarDecl *condVar, Expr *Inc, Stmt *Body, SourceLocation FL, SourceLocation LP, SourceLocation RP)

VarDecl * getConditionVariable() const

Retrieve the variable declared in this "for" statement, if any.

void setConditionVariable(const ASTContext &C, VarDecl *V)

AsmStringPiece - this is part of a decomposed asm string specification (for use with the AnalyzeAsmSt...

char getModifier() const

getModifier - Get the modifier for this operand, if present.

unsigned getNumLabels() const

const StringLiteral * getInputConstraintLiteral(unsigned i) const

std::string generateAsmString(const ASTContext &C) const

Assemble final IR asm string.

StringRef getClobber(unsigned i) const

StringRef getLabelName(unsigned i) const

unsigned AnalyzeAsmString(SmallVectorImpl< AsmStringPiece > &Pieces, const ASTContext &C, unsigned &DiagOffs) const

AnalyzeAsmString - Analyze the asm string of the current asm, decomposing it into pieces.

const StringLiteral * getOutputConstraintLiteral(unsigned i) const

StringRef getOutputConstraint(unsigned i) const

getOutputConstraint - Return the constraint string for the specified output operand.

void setInputExpr(unsigned i, Expr *E)

const StringLiteral * getAsmString() const

StringLiteral * getClobberStringLiteral(unsigned i)

StringRef getInputName(unsigned i) const

GCCAsmStmt(const ASTContext &C, SourceLocation asmloc, bool issimple, bool isvolatile, unsigned numoutputs, unsigned numinputs, IdentifierInfo **names, StringLiteral **constraints, Expr **exprs, StringLiteral *asmstr, unsigned numclobbers, StringLiteral **clobbers, unsigned numlabels, SourceLocation rparenloc)

StringRef getOutputName(unsigned i) const

Expr * getOutputExpr(unsigned i)

int getNamedOperand(StringRef SymbolicName) const

getNamedOperand - Given a symbolic operand reference like %[foo], translate this into a numeric value...

Expr * getInputExpr(unsigned i)

AddrLabelExpr * getLabelExpr(unsigned i) const

StringRef getInputConstraint(unsigned i) const

getInputConstraint - Return the specified input constraint.

One of these records is kept for each identifier that is lexed.

const char * getNameStart() const

Return the beginning of the actual null-terminated string for this identifier.

IfStmt - This represents an if/then/else.

static IfStmt * Create(const ASTContext &Ctx, SourceLocation IL, IfStatementKind Kind, Stmt *Init, VarDecl *Var, Expr *Cond, SourceLocation LPL, SourceLocation RPL, Stmt *Then, SourceLocation EL=SourceLocation(), Stmt *Else=nullptr)

Create an IfStmt.

void setConditionVariable(const ASTContext &Ctx, VarDecl *V)

Set the condition variable for this if statement.

bool hasVarStorage() const

True if this IfStmt has storage for a variable declaration.

static IfStmt * CreateEmpty(const ASTContext &Ctx, bool HasElse, bool HasVar, bool HasInit)

Create an empty IfStmt optionally with storage for an else statement, condition variable and init exp...

std::optional< const Stmt * > getNondiscardedCase(const ASTContext &Ctx) const

If this is an 'if constexpr', determine which substatement will be taken.

bool isObjCAvailabilityCheck() const

DeclStmt * getConditionVariableDeclStmt()

If this IfStmt has a condition variable, return the faux DeclStmt associated with the creation of tha...

VarDecl * getConditionVariable()

Retrieve the variable declared in this "if" statement, if any.

LabelDecl * getConstantTarget()

getConstantTarget - Returns the fixed target of this indirect goto, if one exists.

Represents the declaration of a label.

LabelDecl * getDecl() const

const char * getName() const

Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...

Expr * getOutputExpr(unsigned i)

void setInputExpr(unsigned i, Expr *E)

MSAsmStmt(const ASTContext &C, SourceLocation asmloc, SourceLocation lbraceloc, bool issimple, bool isvolatile, ArrayRef< Token > asmtoks, unsigned numoutputs, unsigned numinputs, ArrayRef< StringRef > constraints, ArrayRef< Expr * > exprs, StringRef asmstr, ArrayRef< StringRef > clobbers, SourceLocation endloc)

std::string generateAsmString(const ASTContext &C) const

Assemble final IR asm string.

Expr * getInputExpr(unsigned i)

IdentifierInfo * getIdentifier() const

Get the identifier that names this declaration, if there is one.

StringRef getName() const

Get the name of identifier for this declaration as a StringRef.

Represents a struct/union/class.

ReturnStmt - This represents a return, optionally of an expression: return; return 4;.

static ReturnStmt * Create(const ASTContext &Ctx, SourceLocation RL, Expr *E, const VarDecl *NRVOCandidate)

Create a return statement.

static ReturnStmt * CreateEmpty(const ASTContext &Ctx, bool HasNRVOCandidate)

Create an empty return statement, optionally with storage for an NRVO candidate.

static SEHExceptStmt * Create(const ASTContext &C, SourceLocation ExceptLoc, Expr *FilterExpr, Stmt *Block)

static SEHFinallyStmt * Create(const ASTContext &C, SourceLocation FinallyLoc, Stmt *Block)

SEHFinallyStmt * getFinallyHandler() const

static SEHTryStmt * Create(const ASTContext &C, bool isCXXTry, SourceLocation TryLoc, Stmt *TryBlock, Stmt *Handler)

SEHExceptStmt * getExceptHandler() const

Returns 0 if not defined.

Stmt * getHandler() const

Encodes a location in the source.

This class handles loading and caching of source files into memory.

A trivial tuple used to represent a source range.

SourceLocation getEnd() const

SourceLocation getBegin() const

Stmt - This represents one statement.

SourceLocation getEndLoc() const LLVM_READONLY

WhileStmtBitfields WhileStmtBits

static void EnableStatistics()

SwitchStmtBitfields SwitchStmtBits

const Stmt * stripLabelLikeStatements() const

Strip off all label-like statements.

StmtClass getStmtClass() const

SourceRange getSourceRange() const LLVM_READONLY

SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...

static std::tuple< bool, const Attr *, const Attr * > determineLikelihoodConflict(const Stmt *Then, const Stmt *Else)

llvm::iterator_range< child_iterator > child_range

CompoundStmtBitfields CompoundStmtBits

Likelihood

The likelihood of a branch being taken.

@ LH_Unlikely

Branch has the [[unlikely]] attribute.

@ LH_None

No attribute set or branches of the IfStmt have the same attribute.

@ LH_Likely

Branch has the [[likely]] attribute.

static void addStmtClass(const StmtClass s)

ForStmtBitfields ForStmtBits

const char * getStmtClassName() const

static const Attr * getLikelihoodAttr(const Stmt *S)

Stmt * IgnoreContainers(bool IgnoreCaptured=false)

Skip no-op (attributed, compound) container stmts and skip captured stmt at the top,...

int64_t getID(const ASTContext &Context) const

ReturnStmtBitfields ReturnStmtBits

SourceLocation getBeginLoc() const LLVM_READONLY

llvm::iterator_range< const_child_iterator > const_child_range

static Likelihood getLikelihood(ArrayRef< const Attr * > Attrs)

StringLiteral - This represents a string literal expression, e.g.

SourceLocation getLocationOfByte(unsigned ByteNo, const SourceManager &SM, const LangOptions &Features, const TargetInfo &Target, unsigned *StartToken=nullptr, unsigned *StartTokenByteOffset=nullptr) const

getLocationOfByte - Return a source location that points to the specified byte of this string literal...

StringRef getString() const

SwitchStmt - This represents a 'switch' stmt.

void setRParenLoc(SourceLocation Loc)

void setConditionVariable(const ASTContext &Ctx, VarDecl *VD)

Set the condition variable in this switch statement.

static SwitchStmt * Create(const ASTContext &Ctx, Stmt *Init, VarDecl *Var, Expr *Cond, SourceLocation LParenLoc, SourceLocation RParenLoc)

Create a switch statement.

void setLParenLoc(SourceLocation Loc)

static SwitchStmt * CreateEmpty(const ASTContext &Ctx, bool HasInit, bool HasVar)

Create an empty switch statement optionally with storage for an init expression and a condition varia...

bool hasVarStorage() const

True if this SwitchStmt has storage for a condition variable.

VarDecl * getConditionVariable()

Retrieve the variable declared in this "switch" statement, if any.

DeclStmt * getConditionVariableDeclStmt()

If this SwitchStmt has a condition variable, return the faux DeclStmt associated with the creation of...

Exposes information about the current target.

virtual std::optional< std::string > handleAsmEscapedChar(char C) const

Replace some escaped characters with another string based on target-specific rules.

Token - This structure provides full information about a lexed token.

const Expr * getExprStmt() const

Represents a variable declaration or definition.

VarDecl * getCanonicalDecl() override

Retrieves the "canonical" declaration of the given declaration.

WhileStmt - This represents a 'while' stmt.

DeclStmt * getConditionVariableDeclStmt()

If this WhileStmt has a condition variable, return the faux DeclStmt associated with the creation of ...

VarDecl * getConditionVariable()

Retrieve the variable declared in this "while" statement, if any.

void setConditionVariable(const ASTContext &Ctx, VarDecl *V)

Set the condition variable of this while statement.

bool hasVarStorage() const

True if this WhileStmt has storage for a condition variable.

static WhileStmt * Create(const ASTContext &Ctx, VarDecl *Var, Expr *Cond, Stmt *Body, SourceLocation WL, SourceLocation LParenLoc, SourceLocation RParenLoc)

Create a while statement.

static WhileStmt * CreateEmpty(const ASTContext &Ctx, bool HasVar)

Create an empty while statement optionally with storage for a condition variable.

Defines the clang::TargetInfo interface.

const internal::VariadicAllOfMatcher< Stmt > stmt

Matches statements.

The JSON file list parser is used to communicate input to InstallAPI.

IfStatementKind

In an if statement, this denotes whether the statement is a constexpr or consteval if statement.

CapturedRegionKind

The different kinds of captured statement.

LLVM_READONLY bool isLetter(unsigned char c)

Return true if this character is an ASCII letter: [a-zA-Z].

@ Result

The result type of a method or function.

LLVM_READONLY bool isDigit(unsigned char c)

Return true if this character is an ASCII digit: [0-9].

const FunctionProtoType * T

A placeholder type used to construct an empty shell of a type, that will be filled in later (e....