clang: lib/Sema/JumpDiagnostics.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

23#include "llvm/ADT/BitVector.h"

24using namespace clang;

25

26namespace {

27

28

29

30

31

32

33

34

35

36

37

38class JumpScopeChecker {

40

41

42

43 const bool Permissive;

44

45

46

47

48

49

50 struct GotoScope {

51

52

53 unsigned ParentScope;

54

55

56 unsigned InDiag;

57

58

59

60

61 unsigned OutDiag;

62

63

65

66 GotoScope(unsigned parentScope, unsigned InDiag, unsigned OutDiag,

68 : ParentScope(parentScope), InDiag(InDiag), OutDiag(OutDiag), Loc(L) {}

69 };

70

72 llvm::DenseMap<Stmt*, unsigned> LabelAndGotoScopes;

74

78

79public:

80 JumpScopeChecker(Stmt *Body, Sema &S);

81private:

82 void BuildScopeInformation(Decl *D, unsigned &ParentScope);

84 unsigned &ParentScope);

85 void BuildScopeInformation(CompoundLiteralExpr *CLE, unsigned &ParentScope);

86 void BuildScopeInformation(Stmt *S, unsigned &origParentScope);

87

88 void VerifyJumps();

89 void VerifyIndirectJumps();

90 void VerifyMustTailStmts();

92 void DiagnoseIndirectOrAsmJump(Stmt *IG, unsigned IGScope, LabelDecl *Target,

93 unsigned TargetScope);

95 unsigned JumpDiag, unsigned JumpDiagWarning,

96 unsigned JumpDiagCXX98Compat);

97 void CheckGotoStmt(GotoStmt *GS);

99

100 unsigned GetDeepestCommonScope(unsigned A, unsigned B);

101};

102}

103

104#define CHECK_PERMISSIVE(x) (assert(Permissive || !(x)), (Permissive && (x)))

105

106JumpScopeChecker::JumpScopeChecker(Stmt *Body, Sema &s)

107 : S(s), Permissive(s.hasAnyUnrecoverableErrorsInThisFunction()) {

108

110

111

112

113 unsigned BodyParentScope = 0;

114 BuildScopeInformation(Body, BodyParentScope);

115

116

117 VerifyJumps();

118 VerifyIndirectJumps();

119 VerifyMustTailStmts();

120}

121

122

123

124unsigned JumpScopeChecker::GetDeepestCommonScope(unsigned A, unsigned B) {

125 while (A != B) {

126

127

128 if (A < B) {

129 assert(Scopes[B].ParentScope < B);

130 B = Scopes[B].ParentScope;

131 } else {

132 assert(Scopes[A].ParentScope < A);

133 A = Scopes[A].ParentScope;

134 }

135 }

136 return A;

137}

138

139typedef std::pair<unsigned,unsigned> ScopePair;

140

141

142

144 if (const VarDecl *VD = dyn_cast(D)) {

145 unsigned InDiag = 0;

146 unsigned OutDiag = 0;

147

148 if (VD->getType()->isVariablyModifiedType())

149 InDiag = diag::note_protected_by_vla;

150

151 if (VD->hasAttr())

152 return ScopePair(diag::note_protected_by___block,

153 diag::note_exits___block);

154

155 if (VD->hasAttr())

156 return ScopePair(diag::note_protected_by_cleanup,

157 diag::note_exits_cleanup);

158

159 if (VD->hasLocalStorage()) {

160 switch (VD->getType().isDestructedType()) {

162 return ScopePair(diag::note_protected_by_objc_strong_init,

163 diag::note_exits_objc_strong);

164

166 return ScopePair(diag::note_protected_by_objc_weak_init,

167 diag::note_exits_objc_weak);

168

170 return ScopePair(diag::note_protected_by_non_trivial_c_struct_init,

171 diag::note_exits_dtor);

172

174 OutDiag = diag::note_exits_dtor;

175 break;

176

178 break;

179 }

180 }

181

183 VD->hasLocalStorage() && Init &&

184 Init->containsErrors()) {

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199 InDiag = diag::note_protected_by_variable_init;

200

201

202

203

208 if (OutDiag)

209 InDiag = diag::note_protected_by_variable_nontriv_destructor;

211 InDiag = diag::note_protected_by_variable_non_pod;

212 else

213 InDiag = 0;

214 }

215 }

216 }

217

218 return ScopePair(InDiag, OutDiag);

219 }

220

221 if (const TypedefNameDecl *TD = dyn_cast(D)) {

222 if (TD->getUnderlyingType()->isVariablyModifiedType())

223 return ScopePair(isa(TD)

224 ? diag::note_protected_by_vla_typedef

225 : diag::note_protected_by_vla_type_alias,

226 0);

227 }

228

230}

231

232

233void JumpScopeChecker::BuildScopeInformation(Decl *D, unsigned &ParentScope) {

234

236 if (Diags.first || Diags.second) {

237 Scopes.push_back(GotoScope(ParentScope, Diags.first, Diags.second,

239 ParentScope = Scopes.size()-1;

240 }

241

242

243

244 if (VarDecl *VD = dyn_cast(D))

245 if (Expr *Init = VD->getInit())

246 BuildScopeInformation(Init, ParentScope);

247}

248

249

250void JumpScopeChecker::BuildScopeInformation(VarDecl *D,

252 unsigned &ParentScope) {

253

254

255 if (D->hasAttr())

256 return;

260 std::pair<unsigned,unsigned> Diags;

261 switch (destructKind) {

263 Diags = ScopePair(diag::note_enters_block_captures_cxx_obj,

264 diag::note_exits_block_captures_cxx_obj);

265 break;

267 Diags = ScopePair(diag::note_enters_block_captures_strong,

268 diag::note_exits_block_captures_strong);

269 break;

271 Diags = ScopePair(diag::note_enters_block_captures_weak,

272 diag::note_exits_block_captures_weak);

273 break;

275 Diags = ScopePair(diag::note_enters_block_captures_non_trivial_c_struct,

276 diag::note_exits_block_captures_non_trivial_c_struct);

277 break;

279 llvm_unreachable("non-lifetime captured variable");

280 }

284 Scopes.push_back(GotoScope(ParentScope,

285 Diags.first, Diags.second, Loc));

286 ParentScope = Scopes.size()-1;

287 }

288}

289

290

291

293 unsigned &ParentScope) {

294 unsigned InDiag = diag::note_enters_compound_literal_scope;

295 unsigned OutDiag = diag::note_exits_compound_literal_scope;

296 Scopes.push_back(GotoScope(ParentScope, InDiag, OutDiag, CLE->getExprLoc()));

297 ParentScope = Scopes.size() - 1;

298}

299

300

301

302

303

304void JumpScopeChecker::BuildScopeInformation(Stmt *S,

305 unsigned &origParentScope) {

306

307

308

309 unsigned independentParentScope = origParentScope;

310 unsigned &ParentScope = ((isa(S) && !isa(S))

311 ? origParentScope : independentParentScope);

312

313 unsigned StmtsToSkip = 0u;

314

315

316 switch (S->getStmtClass()) {

317 case Stmt::AddrLabelExprClass:

318 IndirectJumpTargets.push_back(cast(S)->getLabel());

319 break;

320

321 case Stmt::ObjCForCollectionStmtClass: {

322 auto *CS = cast(S);

323 unsigned Diag = diag::note_protected_by_objc_fast_enumeration;

324 unsigned NewParentScope = Scopes.size();

325 Scopes.push_back(GotoScope(ParentScope, Diag, 0, S->getBeginLoc()));

326 BuildScopeInformation(CS->getBody(), NewParentScope);

327 return;

328 }

329

330 case Stmt::IndirectGotoStmtClass:

331

332

333

334

335

336 if (cast(S)->getConstantTarget())

337 goto RecordJumpScope;

338

339 LabelAndGotoScopes[S] = ParentScope;

340 IndirectJumps.push_back(S);

341 break;

342

343 case Stmt::SwitchStmtClass:

344

345

346 if (Stmt *Init = cast(S)->getInit()) {

347 BuildScopeInformation(Init, ParentScope);

348 ++StmtsToSkip;

349 }

350 if (VarDecl *Var = cast(S)->getConditionVariable()) {

351 BuildScopeInformation(Var, ParentScope);

352 ++StmtsToSkip;

353 }

354 goto RecordJumpScope;

355

356 case Stmt::GCCAsmStmtClass:

357 if (!cast(S)->isAsmGoto())

358 break;

359 [[fallthrough]];

360

361 case Stmt::GotoStmtClass:

362 RecordJumpScope:

363

364

365 LabelAndGotoScopes[S] = ParentScope;

366 Jumps.push_back(S);

367 break;

368

369 case Stmt::IfStmtClass: {

370 IfStmt *IS = cast(S);

373 break;

374

375 unsigned Diag = diag::note_protected_by_if_available;

377 Diag = diag::note_protected_by_constexpr_if;

379 Diag = diag::note_protected_by_consteval_if;

380

382 BuildScopeInformation(Var, ParentScope);

383

384

385 unsigned NewParentScope = Scopes.size();

386 Scopes.push_back(GotoScope(ParentScope, Diag, 0, IS->getBeginLoc()));

387

389 BuildScopeInformation(IS->getCond(), NewParentScope);

390

391

392 NewParentScope = Scopes.size();

393 Scopes.push_back(GotoScope(ParentScope, Diag, 0, IS->getBeginLoc()));

394 BuildScopeInformation(IS->getThen(), NewParentScope);

396 NewParentScope = Scopes.size();

397 Scopes.push_back(GotoScope(ParentScope, Diag, 0, IS->getBeginLoc()));

398 BuildScopeInformation(Else, NewParentScope);

399 }

400 return;

401 }

402

403 case Stmt::CXXTryStmtClass: {

404 CXXTryStmt *TS = cast(S);

405 {

406 unsigned NewParentScope = Scopes.size();

407 Scopes.push_back(GotoScope(ParentScope,

408 diag::note_protected_by_cxx_try,

409 diag::note_exits_cxx_try,

412 BuildScopeInformation(TryBlock, NewParentScope);

413 }

414

415

416 for (unsigned I = 0, E = TS->getNumHandlers(); I != E; ++I) {

418 unsigned NewParentScope = Scopes.size();

419 Scopes.push_back(GotoScope(ParentScope,

420 diag::note_protected_by_cxx_catch,

421 diag::note_exits_cxx_catch,

423 BuildScopeInformation(CS->getHandlerBlock(), NewParentScope);

424 }

425 return;

426 }

427

428 case Stmt::SEHTryStmtClass: {

429 SEHTryStmt *TS = cast(S);

430 {

431 unsigned NewParentScope = Scopes.size();

432 Scopes.push_back(GotoScope(ParentScope,

433 diag::note_protected_by_seh_try,

434 diag::note_exits_seh_try,

437 BuildScopeInformation(TryBlock, NewParentScope);

438 }

439

440

442 unsigned NewParentScope = Scopes.size();

443 Scopes.push_back(GotoScope(ParentScope,

444 diag::note_protected_by_seh_except,

445 diag::note_exits_seh_except,

446 Except->getSourceRange().getBegin()));

447 BuildScopeInformation(Except->getBlock(), NewParentScope);

449 unsigned NewParentScope = Scopes.size();

450 Scopes.push_back(GotoScope(ParentScope,

451 diag::note_protected_by_seh_finally,

452 diag::note_exits_seh_finally,

453 Finally->getSourceRange().getBegin()));

454 BuildScopeInformation(Finally->getBlock(), NewParentScope);

455 }

456

457 return;

458 }

459

460 case Stmt::DeclStmtClass: {

461

462

463 DeclStmt *DS = cast(S);

464

465

466 for (auto *I : DS->decls())

467 BuildScopeInformation(I, origParentScope);

468 return;

469 }

470

471 case Stmt::StmtExprClass: {

472

473

474

475

476

477 StmtExpr *SE = cast(S);

478 unsigned NewParentScope = Scopes.size();

479 Scopes.push_back(GotoScope(ParentScope,

480 diag::note_enters_statement_expression,

482 BuildScopeInformation(SE->getSubStmt(), NewParentScope);

483 return;

484 }

485

486 case Stmt::ObjCAtTryStmtClass: {

487

488

490

491 {

492 unsigned NewParentScope = Scopes.size();

493 Scopes.push_back(GotoScope(ParentScope,

494 diag::note_protected_by_objc_try,

495 diag::note_exits_objc_try,

498 BuildScopeInformation(TryPart, NewParentScope);

499 }

500

501

503 unsigned NewParentScope = Scopes.size();

504 Scopes.push_back(GotoScope(ParentScope,

505 diag::note_protected_by_objc_catch,

506 diag::note_exits_objc_catch,

507 AC->getAtCatchLoc()));

508

509 BuildScopeInformation(AC->getCatchBody(), NewParentScope);

510 }

511

512

514 unsigned NewParentScope = Scopes.size();

515 Scopes.push_back(GotoScope(ParentScope,

516 diag::note_protected_by_objc_finally,

517 diag::note_exits_objc_finally,

518 AF->getAtFinallyLoc()));

519 BuildScopeInformation(AF, NewParentScope);

520 }

521

522 return;

523 }

524

525 case Stmt::ObjCAtSynchronizedStmtClass: {

526

527

529

530

531 BuildScopeInformation(AS->getSynchExpr(), ParentScope);

532

533

534

535 unsigned NewParentScope = Scopes.size();

536 Scopes.push_back(GotoScope(ParentScope,

537 diag::note_protected_by_objc_synchronized,

538 diag::note_exits_objc_synchronized,

540 BuildScopeInformation(AS->getSynchBody(), NewParentScope);

541 return;

542 }

543

544 case Stmt::ObjCAutoreleasePoolStmtClass: {

545

547

548

549 unsigned NewParentScope = Scopes.size();

550 Scopes.push_back(GotoScope(ParentScope,

551 diag::note_protected_by_objc_autoreleasepool,

552 diag::note_exits_objc_autoreleasepool,

554 BuildScopeInformation(AS->getSubStmt(), NewParentScope);

555 return;

556 }

557

558 case Stmt::ExprWithCleanupsClass: {

559

560

561

563 for (unsigned i = 0, e = EWC->getNumObjects(); i != e; ++i) {

565 for (const auto &CI : BDecl->captures()) {

566 VarDecl *variable = CI.getVariable();

567 BuildScopeInformation(variable, BDecl, origParentScope);

568 }

570 BuildScopeInformation(CLE, origParentScope);

571 else

572 llvm_unreachable("unexpected cleanup object type");

573 }

574 break;

575 }

576

577 case Stmt::MaterializeTemporaryExprClass: {

578

579

582 const Expr *ExtendedObject =

585 Scopes.push_back(GotoScope(ParentScope, 0,

586 diag::note_exits_temporary_dtor,

588 origParentScope = Scopes.size()-1;

589 }

590 }

591 break;

592 }

593

594 case Stmt::CaseStmtClass:

595 case Stmt::DefaultStmtClass:

596 case Stmt::LabelStmtClass:

597 LabelAndGotoScopes[S] = ParentScope;

598 break;

599

600 case Stmt::AttributedStmtClass: {

602 if (GetMustTailAttr(AS)) {

603 LabelAndGotoScopes[AS] = ParentScope;

604 MustTailStmts.push_back(AS);

605 }

606 break;

607 }

608

609 case Stmt::OpenACCComputeConstructClass: {

610 unsigned NewParentScope = Scopes.size();

612 Scopes.push_back(GotoScope(

613 ParentScope, diag::note_acc_branch_into_compute_construct,

614 diag::note_acc_branch_out_of_compute_construct, CC->getBeginLoc()));

616 return;

617 }

618

619 case Stmt::OpenACCCombinedConstructClass: {

620 unsigned NewParentScope = Scopes.size();

622 Scopes.push_back(GotoScope(

623 ParentScope, diag::note_acc_branch_into_compute_construct,

624 diag::note_acc_branch_out_of_compute_construct, CC->getBeginLoc()));

625 BuildScopeInformation(CC->getLoop(), NewParentScope);

626 return;

627 }

628

629 default:

630 if (auto *ED = dyn_cast(S)) {

631 if (!ED->isStandaloneDirective()) {

632 unsigned NewParentScope = Scopes.size();

633 Scopes.emplace_back(ParentScope,

634 diag::note_omp_protected_structured_block,

635 diag::note_omp_exits_structured_block,

636 ED->getStructuredBlock()->getBeginLoc());

637 BuildScopeInformation(ED->getStructuredBlock(), NewParentScope);

638 return;

639 }

640 }

641 break;

642 }

643

644 for (Stmt *SubStmt : S->children()) {

645 if (!SubStmt)

646 continue;

647 if (StmtsToSkip) {

648 --StmtsToSkip;

649 continue;

650 }

651

652

653

654

655 while (true) {

657 if (SwitchCase *SC = dyn_cast(SubStmt))

658 Next = SC->getSubStmt();

659 else if (LabelStmt *LS = dyn_cast(SubStmt))

660 Next = LS->getSubStmt();

661 else

662 break;

663

664 LabelAndGotoScopes[SubStmt] = ParentScope;

665 SubStmt = Next;

666 }

667

668

669 BuildScopeInformation(SubStmt, ParentScope);

670 }

671}

672

673

674

675void JumpScopeChecker::VerifyJumps() {

676 while (!Jumps.empty()) {

677 Stmt *Jump = Jumps.pop_back_val();

678

679

680 if (GotoStmt *GS = dyn_cast(Jump)) {

681

682 if (GS->getLabel()->getStmt()) {

683 CheckJump(GS, GS->getLabel()->getStmt(), GS->getGotoLoc(),

684 diag::err_goto_into_protected_scope,

685 diag::ext_goto_into_protected_scope,

686 diag::warn_cxx98_compat_goto_into_protected_scope);

687 }

688 CheckGotoStmt(GS);

689 continue;

690 }

691

692

693

694

695

696

697 if (auto *G = dyn_cast(Jump)) {

700 unsigned JumpScope = LabelAndGotoScopes[G];

701 unsigned TargetScope = LabelAndGotoScopes[LD->getStmt()];

702 if (JumpScope != TargetScope)

703 DiagnoseIndirectOrAsmJump(G, JumpScope, LD, TargetScope);

704 }

705 continue;

706 }

707

708

709 if (IndirectGotoStmt *IGS = dyn_cast(Jump)) {

711 CheckJump(IGS, Target->getStmt(), IGS->getGotoLoc(),

712 diag::err_goto_into_protected_scope,

713 diag::ext_goto_into_protected_scope,

714 diag::warn_cxx98_compat_goto_into_protected_scope);

715 continue;

716 }

717

718 SwitchStmt *SS = cast(Jump);

722 continue;

724 if (CaseStmt *CS = dyn_cast(SC))

726 else if (DefaultStmt *DS = dyn_cast(SC))

728 else

729 Loc = SC->getBeginLoc();

730 CheckJump(SS, SC, Loc, diag::err_switch_into_protected_scope, 0,

731 diag::warn_cxx98_compat_switch_into_protected_scope);

732 }

733 }

734}

735

736

737

738

739

740

741

742

743

744

745

746

747

748

749

750

751

752

753void JumpScopeChecker::VerifyIndirectJumps() {

754 if (IndirectJumps.empty())

755 return;

756

757

758 if (IndirectJumpTargets.empty()) {

759 S.Diag(IndirectJumps[0]->getBeginLoc(),

760 diag::err_indirect_goto_without_addrlabel);

761 return;

762 }

763

764

765

766 using JumpScope = std::pair<unsigned, Stmt *>;

768 {

769 llvm::DenseMap<unsigned, Stmt*> JumpScopesMap;

770 for (Stmt *IG : IndirectJumps) {

772 continue;

773 unsigned IGScope = LabelAndGotoScopes[IG];

774 JumpScopesMap.try_emplace(IGScope, IG);

775 }

776 JumpScopes.reserve(JumpScopesMap.size());

777 for (auto &Pair : JumpScopesMap)

778 JumpScopes.emplace_back(Pair);

779 }

780

781

782

783

784 llvm::DenseMap<unsigned, LabelDecl*> TargetScopes;

785 for (LabelDecl *TheLabel : IndirectJumpTargets) {

786 if (CHECK_PERMISSIVE(!LabelAndGotoScopes.count(TheLabel->getStmt())))

787 continue;

788 unsigned LabelScope = LabelAndGotoScopes[TheLabel->getStmt()];

789 if (!TargetScopes.contains(LabelScope))

790 TargetScopes[LabelScope] = TheLabel;

791 }

792

793

794

795

796

797

798

799

800

801 llvm::BitVector Reachable(Scopes.size(), false);

802 for (auto [TargetScope, TargetLabel] : TargetScopes) {

803 Reachable.reset();

804

805

806

807

808 unsigned Min = TargetScope;

809 while (true) {

810 Reachable.set(Min);

811

812

813 if (Min == 0) break;

814

815

816 if (Scopes[Min].InDiag) break;

817

818 Min = Scopes[Min].ParentScope;

819 }

820

821

822

823 for (auto [JumpScope, JumpStmt] : JumpScopes) {

824 unsigned Scope = JumpScope;

825

826

827

828

829

830 bool IsReachable = false;

831 while (true) {

832 if (Reachable.test(Scope)) {

833

834

835 for (unsigned S = JumpScope; S != Scope; S = Scopes[S].ParentScope)

836 Reachable.set(S);

837 IsReachable = true;

838 break;

839 }

840

841

842

844

845

846 if (Scopes[Scope].OutDiag) break;

847

849 }

850

851

852 if (IsReachable) continue;

853

854 DiagnoseIndirectOrAsmJump(JumpStmt, JumpScope, TargetLabel, TargetScope);

855 }

856 }

857}

858

859

860

862 return (JumpDiag == diag::err_goto_into_protected_scope &&

863 (InDiagNote == diag::note_protected_by_variable_init ||

864 InDiagNote == diag::note_protected_by_variable_nontriv_destructor));

865}

866

867

868

871 InDiagNote == diag::note_protected_by_variable_non_pod;

872}

873

874

877 if (Diagnosed)

878 return;

879 bool IsAsmGoto = isa(Jump);

880 S.Diag(Jump->getBeginLoc(), diag::err_indirect_goto_in_protected_scope)

881 << IsAsmGoto;

882 S.Diag(Target->getStmt()->getIdentLoc(), diag::note_indirect_goto_target)

883 << IsAsmGoto;

884 Diagnosed = true;

885}

886

887

888void JumpScopeChecker::NoteJumpIntoScopes(ArrayRef ToScopes) {

890 return;

891 for (unsigned I = 0, E = ToScopes.size(); I != E; ++I)

892 if (Scopes[ToScopes[I]].InDiag)

893 S.Diag(Scopes[ToScopes[I]].Loc, Scopes[ToScopes[I]].InDiag);

894}

895

896

897void JumpScopeChecker::DiagnoseIndirectOrAsmJump(Stmt *Jump, unsigned JumpScope,

899 unsigned TargetScope) {

901 return;

902

903 unsigned Common = GetDeepestCommonScope(JumpScope, TargetScope);

904 bool Diagnosed = false;

905

906

907 for (unsigned I = JumpScope; I != Common; I = Scopes[I].ParentScope)

908 if (Scopes[I].OutDiag) {

910 S.Diag(Scopes[I].Loc, Scopes[I].OutDiag);

911 }

912

914

915

916 for (unsigned I = TargetScope; I != Common; I = Scopes[I].ParentScope)

918 ToScopesCXX98Compat.push_back(I);

919 else if (Scopes[I].InDiag) {

921 S.Diag(Scopes[I].Loc, Scopes[I].InDiag);

922 }

923

924

925 if (!Diagnosed && !ToScopesCXX98Compat.empty()) {

926 bool IsAsmGoto = isa(Jump);

928 diag::warn_cxx98_compat_indirect_goto_in_protected_scope)

929 << IsAsmGoto;

930 S.Diag(Target->getStmt()->getIdentLoc(), diag::note_indirect_goto_target)

931 << IsAsmGoto;

932 NoteJumpIntoScopes(ToScopesCXX98Compat);

933 }

934}

935

936

937

939 unsigned JumpDiagError, unsigned JumpDiagWarning,

940 unsigned JumpDiagCXX98Compat) {

942 return;

944 return;

945

946 unsigned FromScope = LabelAndGotoScopes[From];

947 unsigned ToScope = LabelAndGotoScopes[To];

948

949

950 if (FromScope == ToScope) return;

951

952

953 if (isa(From) || isa(From)) {

954

955

956 for (unsigned I = FromScope; I > ToScope; I = Scopes[I].ParentScope) {

957 if (Scopes[I].InDiag == diag::note_protected_by_seh_finally) {

958 S.Diag(From->getBeginLoc(), diag::warn_jump_out_of_seh_finally);

959 break;

960 } else if (Scopes[I].InDiag ==

961 diag::note_omp_protected_structured_block) {

962 S.Diag(From->getBeginLoc(), diag::err_goto_into_protected_scope);

963 S.Diag(To->getBeginLoc(), diag::note_omp_exits_structured_block);

964 break;

965 } else if (Scopes[I].InDiag ==

966 diag::note_acc_branch_into_compute_construct) {

967 S.Diag(From->getBeginLoc(), diag::err_goto_into_protected_scope);

968 S.Diag(Scopes[I].Loc, diag::note_acc_branch_out_of_compute_construct);

969 return;

970 }

971 }

972 }

973

974 unsigned CommonScope = GetDeepestCommonScope(FromScope, ToScope);

975

976

977 if (CommonScope == ToScope) return;

978

979

983 for (unsigned I = ToScope; I != CommonScope; I = Scopes[I].ParentScope) {

984 if (S.getLangOpts().MSVCCompat && JumpDiagWarning != 0 &&

986 ToScopesWarning.push_back(I);

988 ToScopesCXX98Compat.push_back(I);

989 else if (Scopes[I].InDiag)

990 ToScopesError.push_back(I);

991 }

992

993

994 if (!ToScopesWarning.empty()) {

995 S.Diag(DiagLoc, JumpDiagWarning);

996 NoteJumpIntoScopes(ToScopesWarning);

997 assert(isa(To));

999 Label->setSideEntry(true);

1000 }

1001

1002

1003 if (!ToScopesError.empty()) {

1004 S.Diag(DiagLoc, JumpDiagError);

1005 NoteJumpIntoScopes(ToScopesError);

1006 }

1007

1008

1009 if (ToScopesError.empty() && !ToScopesCXX98Compat.empty()) {

1010 S.Diag(DiagLoc, JumpDiagCXX98Compat);

1011 NoteJumpIntoScopes(ToScopesCXX98Compat);

1012 }

1013}

1014

1015void JumpScopeChecker::CheckGotoStmt(GotoStmt *GS) {

1017 S.Diag(GS->getGotoLoc(), diag::err_goto_ms_asm_label)

1021 }

1022}

1023

1024void JumpScopeChecker::VerifyMustTailStmts() {

1026 for (unsigned I = LabelAndGotoScopes[AS]; I; I = Scopes[I].ParentScope) {

1027 if (Scopes[I].OutDiag) {

1029 S.Diag(Scopes[I].Loc, Scopes[I].OutDiag);

1030 }

1031 }

1032 }

1033}

1034

1037 const auto *Iter =

1038 llvm::find_if(Attrs, [](const Attr *A) { return isa(A); });

1039 return Iter != Attrs.end() ? *Iter : nullptr;

1040}

1041

1043 (void)JumpScopeChecker(Body, *this);

1044}

Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....

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

std::pair< unsigned, unsigned > ScopePair

static ScopePair GetDiagForGotoScopeDecl(Sema &S, const Decl *D)

GetDiagForGotoScopeDecl - If this decl induces a new goto scope, return a diagnostic that should be e...

static bool IsCXX98CompatWarning(Sema &S, unsigned InDiagNote)

Return true if a particular note should be downgraded to a compatibility warning in C++11 mode.

static bool IsMicrosoftJumpWarning(unsigned JumpDiag, unsigned InDiagNote)

Return true if a particular error+note combination must be downgraded to a warning in Microsoft mode.

#define CHECK_PERMISSIVE(x)

static void DiagnoseIndirectOrAsmJumpStmt(Sema &S, Stmt *Jump, LabelDecl *Target, bool &Diagnosed)

Produce primary diagnostic for an indirect jump statement.

static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)

Produce a diagnostic highlighting some portion of a literal.

llvm::MachO::Target Target

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.

__device__ __2f16 float __ockl_bool s

const LangOptions & getLangOpts() const

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

Attr - This represents one attribute.

Represents an attribute applied to a statement.

ArrayRef< const Attr * > getAttrs() const

SourceLocation getBeginLoc() const

Represents a block literal declaration, which is like an unnamed FunctionDecl.

ArrayRef< Capture > captures() const

CXXCatchStmt - This represents a C++ catch block.

Stmt * getHandlerBlock() const

SourceLocation getBeginLoc() const LLVM_READONLY

Represents a call to a C++ constructor.

Represents a C++ constructor within a class.

bool isDefaultConstructor() const

Whether this constructor is a default constructor (C++ [class.ctor]p5), which can be used to default-...

const CXXRecordDecl * getParent() const

Return the parent of this method declaration, which is the class in which this method is defined.

bool isPOD() const

Whether this class is a POD-type (C++ [class]p4)

CXXTryStmt - A C++ try block, including all handlers.

CXXCatchStmt * getHandler(unsigned i)

unsigned getNumHandlers() const

CompoundStmt * getTryBlock()

CaseStmt - Represent a case statement.

CompoundLiteralExpr - [C99 6.5.2.5].

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

SourceLocation getBeginLoc() const LLVM_READONLY

Decl - This represents one declaration (or definition), e.g.

SourceLocation getLocation() const

Represents an expression – generally a full-expression – that introduces cleanups to be run at the en...

CleanupObject getObject(unsigned i) const

unsigned getNumObjects() const

This represents one expression.

const Expr * skipRValueSubobjectAdjustments(SmallVectorImpl< const Expr * > &CommaLHS, SmallVectorImpl< SubobjectAdjustment > &Adjustments) const

Walk outwards from an expression we want to bind a reference to and find the expression whose lifetim...

SourceLocation getExprLoc() const LLVM_READONLY

getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...

bool isTrivial() const

Whether this function is "trivial" in some specialized C++ senses.

GotoStmt - This represents a direct goto.

SourceLocation getGotoLoc() const

LabelDecl * getLabel() const

IfStmt - This represents an if/then/else.

bool isObjCAvailabilityCheck() const

SourceLocation getBeginLoc() const

VarDecl * getConditionVariable()

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

IndirectGotoStmt - This represents an indirect goto.

Represents the declaration of a label.

LabelStmt * getStmt() const

bool isMSAsmLabel() const

LabelStmt - Represents a label, which has a substatement.

Represents a prvalue temporary that is written into memory so that a reference can bind to it.

StorageDuration getStorageDuration() const

Retrieve the storage duration for the materialized temporary.

Expr * getSubExpr() const

Retrieve the temporary-generating subexpression whose value will be materialized into a glvalue.

IdentifierInfo * getIdentifier() const

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

Represents Objective-C's @catch statement.

Represents Objective-C's @finally statement.

Represents Objective-C's @synchronized statement.

const Expr * getSynchExpr() const

const CompoundStmt * getSynchBody() const

SourceLocation getAtSynchronizedLoc() const

Represents Objective-C's @try ... @catch ... @finally statement.

const ObjCAtFinallyStmt * getFinallyStmt() const

Retrieve the @finally statement, if any.

const Stmt * getTryBody() const

Retrieve the @try body.

SourceLocation getAtTryLoc() const

Retrieve the location of the @ in the @try.

catch_range catch_stmts()

Represents Objective-C's @autoreleasepool Statement.

SourceLocation getAtLoc() const

const Stmt * getSubStmt() const

This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...

Stmt * getStructuredBlock()

SourceLocation getBeginLoc() const

A (possibly-)qualified type.

@ DK_objc_strong_lifetime

DestructionKind isDestructedType() const

Returns a nonzero value if objects of this type require non-trivial work to clean up after.

CompoundStmt * getTryBlock() const

SEHFinallyStmt * getFinallyHandler() const

SEHExceptStmt * getExceptHandler() const

Returns 0 if not defined.

Scope - A scope is a transient data structure that is used while parsing the program.

SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, bool DeferHint=false)

Emit a diagnostic.

Sema - This implements semantic analysis and AST building for C.

const LangOptions & getLangOpts() const

void DiagnoseInvalidJumps(Stmt *Body)

Encodes a location in the source.

SourceLocation getBegin() const

StmtExpr - This is the GNU Statement Expression extension: ({int X=4; X;}).

CompoundStmt * getSubStmt()

SourceLocation getBeginLoc() const LLVM_READONLY

Stmt - This represents one statement.

SourceRange getSourceRange() const LLVM_READONLY

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

SourceLocation getBeginLoc() const LLVM_READONLY

const SwitchCase * getNextSwitchCase() const

SwitchStmt - This represents a 'switch' stmt.

SwitchCase * getSwitchCaseList()

Base class for declarations which introduce a typedef-name.

Represents a variable declaration or definition.

@ CallInit

Call-style initialization (C++98)

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

@ SD_Automatic

Automatic storage duration (most local variables).

const FunctionProtoType * T