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

1

2

3

4

5

6

7

8

9

10

11

12

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

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

36#include "llvm/ADT/StringRef.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"

41#include

42#include

43#include

44#include

45#include

46#include

47

48using namespace clang;

49

50#define STMT(CLASS, PARENT)

51#define STMT_RANGE(BASE, FIRST, LAST)

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

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

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

55 "by a bitfield of width NumStmtBits");

56#define ABSTRACT_STMT(STMT)

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

58

64

69

70

72#define ABSTRACT_STMT(STMT)

73#define STMT(CLASS, PARENT) \

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

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

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

77

79}

80

82 unsigned alignment) {

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

84}

85

88}

89

90

91

92

93#define STMT(CLASS, PARENT) \

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

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

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

97

98

99

100

101#define STMT(CLASS, PARENT) \

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

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

104

105#define INITLISTEXPR(CLASS, PARENT)

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

107

109

111

112 unsigned sum = 0;

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

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

117 }

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

119 sum = 0;

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

126 << " bytes)\n";

128 }

129

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

131}

132

135}

136

137bool Stmt::StatisticsEnabled = false;

139 StatisticsEnabled = true;

140}

141

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

144 for (const auto *A : Attrs) {

145 if (isa(A))

147

148 if (isa(A))

150 }

151

153}

154

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

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

158

160}

161

163 return ::getLikelihood(Attrs).first;

164}

165

167 return ::getLikelihood(S).first;

168}

169

171 return ::getLikelihood(S).second;

172}

173

178 return LHT;

179

180

181 if (LHT == LHE)

183

185 return LHT;

186

187

189}

190

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

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

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

195

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

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

198

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

200}

201

202

203

205 Stmt *S = this;

206 if (IgnoreCaptured)

207 if (auto CapS = dyn_cast_or_null(S))

208 S = CapS->getCapturedStmt();

209 while (true) {

210 if (auto AS = dyn_cast_or_null(S))

211 S = AS->getSubStmt();

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

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

214 break;

215 S = CS->body_back();

216 } else

217 break;

218 }

219 return S;

220}

221

222

223

224

225

227 const Stmt *S = this;

228 while (true) {

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

230 S = LS->getSubStmt();

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

232 S = SC->getSubStmt();

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

234 S = AS->getSubStmt();

235 else

236 return S;

237 }

238}

239

240namespace {

241

242 struct good {};

243 struct bad {};

244

245

246

247

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

249

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

252 return good();

253 }

254 LLVM_ATTRIBUTE_UNUSED

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

256 return bad();

257 }

258

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

261 return good();

262 }

263 LLVM_ATTRIBUTE_UNUSED

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

265

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

268 return good();

269 }

270 LLVM_ATTRIBUTE_UNUSED

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

272

273#define ASSERT_IMPLEMENTS_children(type) \

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

275#define ASSERT_IMPLEMENTS_getBeginLoc(type) \

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

277#define ASSERT_IMPLEMENTS_getEndLoc(type) \

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

279

280}

281

282

283

284LLVM_ATTRIBUTE_UNUSED

286#define ABSTRACT_STMT(type)

287#define STMT(type, base) \

288 ASSERT_IMPLEMENTS_children(type); \

289 ASSERT_IMPLEMENTS_getBeginLoc(type); \

290 ASSERT_IMPLEMENTS_getEndLoc(type);

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

292}

293

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

297#define ABSTRACT_STMT(type)

298#define STMT(type, base) \

299 case Stmt::type##Class: \

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

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

302 }

303 llvm_unreachable("unknown statement kind!");

304}

305

306

307

308

309

310namespace {

311

312

313

314 template <class S, class T>

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

318 }

319

320

321

322

323

324 template

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

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

329 }

330

331}

332

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

336#define ABSTRACT_STMT(type)

337#define STMT(type, base) \

338 case Stmt::type##Class: \

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

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

341 }

342 llvm_unreachable("unknown statement kind!");

343}

344

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

348#define ABSTRACT_STMT(type)

349#define STMT(type, base) \

350 case Stmt::type##Class: \

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

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

353 }

354 llvm_unreachable("unknown statement kind");

355}

356

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

360#define ABSTRACT_STMT(type)

361#define STMT(type, base) \

362 case Stmt::type##Class: \

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

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

365 }

366 llvm_unreachable("unknown statement kind");

367}

368

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

371}

372

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

378 setStmts(Stmts);

379 if (hasStoredFPFeatures())

380 setStoredFPFeatures(FPFeatures);

381}

382

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

386

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

388}

389

393 void *Mem =

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

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

398}

399

401 bool HasFPFeatures) {

402 void *Mem = C.Allocate(

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

408 return New;

409}

410

412 const Stmt *S = this;

413 do {

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

415 return E;

416

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

418 S = LS->getSubStmt();

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

420 S = AS->getSubStmt();

421 else

422 llvm_unreachable("unknown kind of ValueStmt");

423 } while (isa(S));

424

425 return nullptr;

426}

427

430}

431

434 Stmt *SubStmt) {

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

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

439}

440

442 unsigned NumAttrs) {

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

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

447}

448

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

451 return gccAsmStmt->generateAsmString(C);

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

453 return msAsmStmt->generateAsmString(C);

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

455}

456

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

459 return gccAsmStmt->getOutputConstraint(i);

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

461 return msAsmStmt->getOutputConstraint(i);

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

463}

464

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

467 return gccAsmStmt->getOutputExpr(i);

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

469 return msAsmStmt->getOutputExpr(i);

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

471}

472

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

475 return gccAsmStmt->getInputConstraint(i);

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

477 return msAsmStmt->getInputConstraint(i);

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

479}

480

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

483 return gccAsmStmt->getInputExpr(i);

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

485 return msAsmStmt->getInputExpr(i);

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

487}

488

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

491 return gccAsmStmt->getClobber(i);

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

493 return msAsmStmt->getClobber(i);

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

495}

496

497

498

500 unsigned Res = 0;

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

503 ++Res;

504 return Res;

505}

506

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

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

510}

511

514}

515

517 return cast(Exprs[i]);

518}

519

520

521

522

525}

526

529}

530

533}

534

537}

538

541}

542

543

544

547}

548

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

555 unsigned NumLabels,

561 this->NumLabels = NumLabels;

562

564

565 C.Deallocate(this->Names);

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

568

569 C.Deallocate(this->Exprs);

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

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

572

574 C.Deallocate(this->Constraints);

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

577

578 C.Deallocate(this->Clobbers);

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

581}

582

583

584

585

587

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

591 return i;

592

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

597

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

601

602

603 return -1;

604}

605

606

607

608

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

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

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

614 const char *CurPtr = StrStart;

615

616

617

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

621 switch (*CurPtr) {

622 case '$':

624 break;

625 default:

627 break;

628 }

629 }

631 return 0;

632 }

633

634

635

636 std::string CurStringPiece;

637

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

639

640 unsigned LastAsmStringToken = 0;

641 unsigned LastAsmStringOffset = 0;

642

643 while (true) {

644

645 if (CurPtr == StrEnd) {

646 if (!CurStringPiece.empty())

648 return 0;

649 }

650

651 char CurChar = *CurPtr++;

652 switch (CurChar) {

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

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

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

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

657 case '%':

658 break;

659 default:

660 CurStringPiece += CurChar;

661 continue;

662 }

663

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

665

666

667 if (CurPtr == StrEnd) {

668

669 DiagOffs = CurPtr-StrStart-1;

670 return diag::err_asm_invalid_escape;

671 }

672

673 char EscapedChar = *CurPtr++;

674 switch (EscapedChar) {

675 default:

676

678 CurStringPiece += *MaybeReplaceStr;

679 continue;

680 }

681 break;

682 case '%':

683 case '{':

684 case '}':

685 CurStringPiece += EscapedChar;

686 continue;

687 case '=':

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

689 continue;

690 }

691

692

693

694 if (!CurStringPiece.empty()) {

696 CurStringPiece.clear();

697 }

698

699

700

701

702 const char *Begin = CurPtr - 1;

703 const char *Percent = Begin - 1;

704

706 if (CurPtr == StrEnd) {

707 DiagOffs = CurPtr-StrStart-1;

708 return diag::err_asm_invalid_escape;

709 }

710 EscapedChar = *CurPtr++;

711 }

712

715

716

717 if (isDigit(EscapedChar)) {

718

719 unsigned N = 0;

720

721 --CurPtr;

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

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

724

727 if (N >= NumOperands) {

728 DiagOffs = CurPtr-StrStart-1;

729 return diag::err_asm_invalid_operand_number;

730 }

731

732

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

734

735

736

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

739 &LastAsmStringOffset);

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

742 &LastAsmStringOffset);

743

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

745 continue;

746 }

747

748

749 if (EscapedChar == '[') {

750 DiagOffs = CurPtr-StrStart-1;

751

752

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

754 if (NameEnd == nullptr)

755 return diag::err_asm_unterminated_symbolic_operand_name;

756 if (NameEnd == CurPtr)

757 return diag::err_asm_empty_symbolic_operand_name;

758

759 StringRef SymbolicName(CurPtr, NameEnd - CurPtr);

760

762 if (N == -1) {

763

764 DiagOffs = CurPtr-StrStart;

765 return diag::err_asm_unknown_symbolic_operand_name;

766 }

767

768

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

770

771

772

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

775 &LastAsmStringOffset);

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

778 &LastAsmStringOffset);

779

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

781

782 CurPtr = NameEnd+1;

783 continue;

784 }

785

786 DiagOffs = CurPtr-StrStart-1;

787 return diag::err_asm_invalid_escape;

788 }

789}

790

791

793

794

796 unsigned DiagOffs;

798

799 std::string AsmString;

800 for (const auto &Piece : Pieces) {

801 if (Piece.isString())

802 AsmString += Piece.getString();

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

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

805 else

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

807 Piece.getModifier() + '}';

808 }

809 return AsmString;

810}

811

812

814

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

817 std::string MSAsmString;

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

819 StringRef Instruction = Pieces[I];

820

821

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

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

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

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

826 Instruction.starts_with("vex3 ") ||

827 Instruction.starts_with("evex "))

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

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

830 else

831 MSAsmString += Instruction.str();

832

833 if (I < E - 1)

834 MSAsmString += "\n\t";

835 }

836 return MSAsmString;

837}

838

840 return cast(Exprs[i]);

841}

842

845}

846

849}

850

851

852

853

854

856 bool issimple, bool isvolatile, unsigned numoutputs,

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

863 numinputs, numclobbers),

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

866

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

869

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

872

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

876

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

879}

880

882 SourceLocation lbraceloc, bool issimple, bool isvolatile,

884 unsigned numinputs,

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

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

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

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

892}

893

895 return str.copy(C);

896}

897

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

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

905

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

908

910

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

913

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

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

916

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

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

919 [&](StringRef Constraint) {

920 return copyIntoContext(C, Constraint);

921 });

922

924

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

926 [&](StringRef Clobber) {

927 return copyIntoContext(C, Clobber);

928 });

929}

930

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

935 bool HasElse = Else != nullptr;

936 bool HasVar = Var != nullptr;

937 bool HasInit = Init != nullptr;

938 IfStmtBits.HasElse = HasElse;

939 IfStmtBits.HasVar = HasVar;

940 IfStmtBits.HasInit = HasInit;

941

942 setStatementKind(Kind);

943

944 setCond(Cond);

945 setThen(Then);

946 if (HasElse)

947 setElse(Else);

948 if (HasVar)

949 setConditionVariable(Ctx, Var);

950 if (HasInit)

951 setInit(Init);

952

953 setIfLoc(IL);

954 if (HasElse)

955 setElseLoc(EL);

956}

957

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

960 IfStmtBits.HasElse = HasElse;

961 IfStmtBits.HasVar = HasVar;

962 IfStmtBits.HasInit = HasInit;

963}

964

969 bool HasElse = Else != nullptr;

970 bool HasVar = Var != nullptr;

971 bool HasInit = Init != nullptr;

973 totalSizeToAlloc<Stmt *, SourceLocation>(

974 NumMandatoryStmtPtr + HasElse + HasVar + HasInit, HasElse),

976 return new (Mem)

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

978}

979

981 bool HasInit) {

983 totalSizeToAlloc<Stmt *, SourceLocation>(

984 NumMandatoryStmtPtr + HasElse + HasVar + HasInit, HasElse),

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

987}

988

991 if (!DS)

992 return nullptr;

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

994}

995

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

999

1000 if (V) {

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

1002 return;

1003 }

1004

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

1008}

1009

1011 return isa(getCond());

1012}

1013

1016 return std::nullopt;

1018}

1019

1020std::optional<const Stmt *>

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

1025 return std::nullopt;

1026}

1027

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

1032{

1033 SubExprs[INIT] = Init;

1035 SubExprs[COND] = Cond;

1036 SubExprs[INC] = Inc;

1037 SubExprs[BODY] = Body;

1039}

1040

1042 if (!SubExprs[CONDVAR])

1043 return nullptr;

1044

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

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

1047}

1048

1050 if (V) {

1051 SubExprs[CONDVAR] = nullptr;

1052 return;

1053 }

1054

1058}

1059

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

1064 RParenLoc(RParenLoc) {

1065 bool HasInit = Init != nullptr;

1066 bool HasVar = Var != nullptr;

1070

1073 if (HasInit)

1075 if (HasVar)

1077

1079}

1080

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

1082 : Stmt(SwitchStmtClass, Empty) {

1086}

1087

1091 bool HasInit = Init != nullptr;

1092 bool HasVar = Var != nullptr;

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

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

1097}

1098

1100 bool HasVar) {

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

1105}

1106

1109 if (!DS)

1110 return nullptr;

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

1112}

1113

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

1117

1118 if (V) {

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

1120 return;

1121 }

1122

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

1126}

1127

1131 : Stmt(WhileStmtClass) {

1132 bool HasVar = Var != nullptr;

1134

1137 if (HasVar)

1139

1140 setWhileLoc(WL);

1143}

1144

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

1148}

1149

1154 bool HasVar = Var != nullptr;

1155 void *Mem =

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

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

1159}

1160

1162 void *Mem =

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

1166}

1167

1170 if (!DS)

1171 return nullptr;

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

1173}

1174

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

1178

1179 if (V) {

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

1181 return;

1182 }

1183

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

1187}

1188

1189

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

1192 return E->getLabel();

1193 return nullptr;

1194}

1195

1196

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

1199 bool HasNRVOCandidate = NRVOCandidate != nullptr;

1201 if (HasNRVOCandidate)

1202 setNRVOCandidate(NRVOCandidate);

1203 setReturnLoc(RL);

1204}

1205

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

1207 : Stmt(ReturnStmtClass, Empty) {

1209}

1210

1213 bool HasNRVOCandidate = NRVOCandidate != nullptr;

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

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

1217}

1218

1220 bool HasNRVOCandidate) {

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

1224}

1225

1226

1230 bool CaseStmtIsGNURange = rhs != nullptr;

1232 totalSizeToAlloc<Stmt *, SourceLocation>(

1233 NumMandatoryStmtPtr + CaseStmtIsGNURange, CaseStmtIsGNURange),

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

1236}

1237

1239 bool CaseStmtIsGNURange) {

1241 totalSizeToAlloc<Stmt *, SourceLocation>(

1242 NumMandatoryStmtPtr + CaseStmtIsGNURange, CaseStmtIsGNURange),

1245}

1246

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

1248 Stmt *Handler)

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

1250 Children[TRY] = TryBlock;

1251 Children[HANDLER] = Handler;

1252}

1253

1256 Stmt *Handler) {

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

1258}

1259

1261 return dyn_cast(getHandler());

1262}

1263

1265 return dyn_cast(getHandler());

1266}

1267

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

1270 Children[FILTER_EXPR] = FilterExpr;

1272}

1273

1277}

1278

1281

1285}

1286

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

1290 switch (Kind) {

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

1293 break;

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

1296 break;

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

1299 break;

1301 assert(!Var &&

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

1303 break;

1304 }

1305}

1306

1309 return VarAndKind.getInt();

1310}

1311

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

1315 return VarAndKind.getPointer();

1316}

1317

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

1320

1321

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

1323

1324 return reinterpret_cast<Capture *>(

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

1326 + FirstCaptureOffset);

1327}

1328

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

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

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

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

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

1339

1340

1341 Stmt **Stored = getStoredStmts();

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

1343 *Stored++ = CaptureInits[I];

1344

1345

1346 *Stored = S;

1347

1348

1349 Capture *Buffer = getStoredCaptures();

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

1351}

1352

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

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

1355 CapDeclAndKind(nullptr, CR_Default) {

1356 getStoredStmts()[NumCaptures] = nullptr;

1357

1358

1359 Capture *Buffer = getStoredCaptures();

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

1361 new (Buffer++) Capture();

1362}

1363

1370

1371

1372

1373

1374

1375

1376

1377

1378

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

1380

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

1382 if (!Captures.empty()) {

1383

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

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

1386 }

1387

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

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

1390}

1391

1393 unsigned NumCaptures) {

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

1395 if (NumCaptures > 0) {

1396

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

1398 Size += sizeof(Capture) * NumCaptures;

1399 }

1400

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

1403}

1404

1406

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

1408}

1409

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

1412}

1413

1415 return CapDeclAndKind.getPointer();

1416}

1417

1419 return CapDeclAndKind.getPointer();

1420}

1421

1422

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

1425 CapDeclAndKind.setPointer(D);

1426}

1427

1428

1430 return CapDeclAndKind.getInt();

1431}

1432

1433

1435 CapDeclAndKind.setInt(Kind);

1436}

1437

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

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

1441 continue;

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

1443 return true;

1444 }

1445

1446 return false;

1447}

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.

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....