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

1

2

3

4

5

6

7

8

9

10

11

12

39#include "llvm/ADT/ArrayRef.h"

40#include "llvm/ADT/DenseMap.h"

41#include "llvm/ADT/STLExtras.h"

42#include "llvm/ADT/STLForwardCompat.h"

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

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

45

46using namespace clang;

47using namespace sema;

48

52

56

57

58

59

60

61

63}

64

65

69}

70

72 bool HasLeadingEmptyMacro) {

73 return new (Context) NullStmt(SemiLoc, HasLeadingEmptyMacro);

74}

75

79

80

82

84}

85

88

89

90

92 return;

93

95 if (decl || decl->isInvalidDecl())

96 return;

97

98

100 if (!var) {

101 Diag(decl->getLocation(), diag::err_non_variable_decl_in_for);

102 decl->setInvalidDecl();

103 return;

104 }

105

106

107

108 var->setInit(nullptr);

109

110

111

112

115

116

117

118

120

121 var->setType(type.withConst());

122 var->setARCPseudoStrong(true);

123 }

124 }

125}

126

127

128

129

130

131

134 bool CanAssign;

135 enum { Equality, Inequality, Relational, ThreeWay } Kind;

136

137 if (const BinaryOperator *Op = dyn_cast(E)) {

138 if (!Op->isComparisonOp())

139 return false;

140

141 if (Op->getOpcode() == BO_EQ)

142 Kind = Equality;

143 else if (Op->getOpcode() == BO_NE)

144 Kind = Inequality;

145 else if (Op->getOpcode() == BO_Cmp)

146 Kind = ThreeWay;

147 else {

148 assert(Op->isRelationalOp());

149 Kind = Relational;

150 }

151 Loc = Op->getOperatorLoc();

152 CanAssign = Op->getLHS()->IgnoreParenImpCasts()->isLValue();

153 } else if (const CXXOperatorCallExpr *Op = dyn_cast(E)) {

154 switch (Op->getOperator()) {

155 case OO_EqualEqual:

156 Kind = Equality;

157 break;

158 case OO_ExclaimEqual:

159 Kind = Inequality;

160 break;

161 case OO_Less:

162 case OO_Greater:

163 case OO_GreaterEqual:

164 case OO_LessEqual:

165 Kind = Relational;

166 break;

167 case OO_Spaceship:

168 Kind = ThreeWay;

169 break;

170 default:

171 return false;

172 }

173

174 Loc = Op->getOperatorLoc();

175 CanAssign = Op->getArg(0)->IgnoreParenImpCasts()->isLValue();

176 } else {

177

178 return false;

179 }

180

181

182

184 return false;

185

186 S.Diag(Loc, diag::warn_unused_comparison)

188

189

190

191 if (CanAssign) {

192 if (Kind == Inequality)

193 S.Diag(Loc, diag::note_inequality_comparison_to_or_assign)

195 else if (Kind == Equality)

196 S.Diag(Loc, diag::note_equality_comparison_to_assign)

198 }

199

200 return true;

201}

202

206 if (!A)

207 return false;

208 StringRef Msg = A->getMessage();

209

210 if (Msg.empty()) {

211 if (OffendingDecl)

212 return S.Diag(Loc, diag::warn_unused_return_type)

213 << IsCtor << A << OffendingDecl << false << R1 << R2;

214 if (IsCtor)

215 return S.Diag(Loc, diag::warn_unused_constructor)

216 << A << false << R1 << R2;

217 return S.Diag(Loc, diag::warn_unused_result) << A << false << R1 << R2;

218 }

219

220 if (OffendingDecl)

221 return S.Diag(Loc, diag::warn_unused_return_type)

222 << IsCtor << A << OffendingDecl << true << Msg << R1 << R2;

223 if (IsCtor)

224 return S.Diag(Loc, diag::warn_unused_constructor)

225 << A << true << Msg << R1 << R2;

226 return S.Diag(Loc, diag::warn_unused_result) << A << true << Msg << R1 << R2;

227}

228

229namespace {

230

231

232

233

234

235void DiagnoseUnused(Sema &S, const Expr *E, std::optional DiagID) {

236 bool NoDiscardOnly = !DiagID.has_value();

237

238

239

241 return;

242

244

245

246

247

248

251

252 const Expr *WarnExpr;

256 return;

257

258 if (!NoDiscardOnly) {

259

260

261

262

264 return;

265

266

267

268

272 return;

273 }

274 }

275

276

277

278

279 if (const FullExpr *Temps = dyn_cast(E))

280 E = Temps->getSubExpr();

282 E = TempExpr->getSubExpr();

283

285 return;

286

287 E = WarnExpr;

288 if (const auto *Cast = dyn_cast(E))

289 if (Cast->getCastKind() == CK_NoOp ||

290 Cast->getCastKind() == CK_ConstructorConversion ||

291 Cast->getCastKind() == CK_IntegralCast)

292 E = Cast->getSubExpr()->IgnoreImpCasts();

293

294 if (const CallExpr *CE = dyn_cast(E)) {

296 return;

297

298 auto [OffendingDecl, A] = CE->getUnusedResultAttr(S.Context);

300 cast_or_null(A), Loc, R1, R2,

301 false))

302 return;

303

304

305

306

307

308 if (const Decl *FD = CE->getCalleeDecl()) {

309 if (ShouldSuppress)

310 return;

311 if (FD->hasAttr()) {

312 S.Diag(Loc, diag::warn_unused_call) << R1 << R2 << "pure";

313 return;

314 }

315 if (FD->hasAttr()) {

316 S.Diag(Loc, diag::warn_unused_call) << R1 << R2 << "const";

317 return;

318 }

319 }

320 } else if (const auto *CE = dyn_cast(E)) {

322 const NamedDecl *OffendingDecl = nullptr;

323 const auto *A = Ctor->getAttr();

324 if (!A) {

325 OffendingDecl = Ctor->getParent();

326 A = OffendingDecl->getAttr();

327 }

329 true))

330 return;

331 }

332 } else if (const auto *ILE = dyn_cast(E)) {

333 if (const TagDecl *TD = ILE->getType()->getAsTagDecl()) {

334

336 R2, false))

337 return;

338 }

339 } else if (ShouldSuppress)

340 return;

341

342 E = WarnExpr;

343 if (const ObjCMessageExpr *ME = dyn_cast(E)) {

344 if (S.getLangOpts().ObjCAutoRefCount && ME->isDelegateInitCall()) {

345 S.Diag(Loc, diag::err_arc_unused_init_message) << R1;

346 return;

347 }

349 if (MD) {

351 Loc, R1, R2,

352 false))

353 return;

354 }

355 } else if (const PseudoObjectExpr *POE = dyn_cast(E)) {

356 const Expr *Source = POE->getSyntacticForm();

357

358 if (S.LangOpts.OpenMP && isa(Source) &&

359 POE->getNumSemanticExprs() == 1 &&

360 isa(POE->getSemanticExpr(0)))

361 return DiagnoseUnused(S, POE->getSemanticExpr(0), DiagID);

362 if (isa(Source))

363 DiagID = diag::warn_unused_container_subscript_expr;

364 else if (isa(Source))

365 DiagID = diag::warn_unused_property_expr;

367 = dyn_cast(E)) {

368 const Expr *E = FC->getSubExpr();

370 E = TE->getSubExpr();

371 if (isa(E))

372 return;

374 if (const CXXRecordDecl *RD = CE->getType()->getAsCXXRecordDecl())

375 if (!RD->getAttr())

376 return;

377 }

378

379 if (NoDiscardOnly)

380 return;

381

382

383 if (const CStyleCastExpr *CE = dyn_cast(E)) {

386

387

390

391 S.Diag(Loc, diag::warn_unused_voidptr)

393 return;

394 }

395 }

396

397

398

401 S.Diag(Loc, diag::warn_unused_volatile) << R1 << R2;

402 return;

403 }

404

405

406

407

408 if (DiagID == diag::warn_unused_comma_left_operand && S.isSFINAEContext())

409 return;

410

412 S.PDiag(*DiagID) << R1 << R2);

413}

414}

415

417 DiagnoseUnused(*this, E, std::nullopt);

418}

419

421 if (const LabelStmt *Label = dyn_cast_if_present(S))

422 S = Label->getSubStmt();

423

424 const Expr *E = dyn_cast_if_present(S);

425 if (E)

426 return;

427

428 DiagnoseUnused(*this, E, DiagID);

429}

430

433}

434

438 assert(FSI);

440 }

441}

442

445}

446

449}

450

453 const unsigned NumElts = Elts.size();

454

455

456

457

458 const unsigned MixedDeclsCodeID = getLangOpts().C99

459 ? diag::warn_mixed_decls_code

460 : diag::ext_mixed_decls_code;

462

463 unsigned i = 0;

464

465 for (; i != NumElts && isa(Elts[i]); ++i)

466 ;

467

468

469 for (; i != NumElts && !isa(Elts[i]); ++i)

470 ;

471

472 if (i != NumElts) {

473 Decl *D = *cast(Elts[i])->decl_begin();

475 }

476 }

477

478

479

480

483 for (unsigned i = 0; i != NumElts - 1; ++i)

485 }

486

487

488

489

490

495

497}

498

501 if (!Val.get())

502 return Val;

503

506

507

508

512

513 Expr *CondExpr =

515 if (!CondExpr)

518

519 auto CheckAndFinish = [&](Expr *E) {

522

524

525

526 llvm::APSInt TempVal;

529 }

530

540 return ER;

541 };

542

544 Val, nullptr, false,

545 CheckAndFinish);

546 if (Converted.get() == Val.get())

547 Converted = CheckAndFinish(Val.get());

548 return Converted;

549}

550

555 assert((LHSVal.isInvalid() || LHSVal.get()) && "missing LHS value");

558 "missing RHS value");

559

561 Diag(CaseLoc, diag::err_case_not_in_switch);

563 }

564

568 }

569

572 Diag(CaseLoc, diag::err_acc_branch_in_out_compute_construct)

573 << 0 << 1;

575 }

576

578 CaseLoc, DotDotDotLoc, ColonLoc);

580 return CS;

581}

582

584 cast(S)->setSubStmt(SubStmt);

585}

586

589 Stmt *SubStmt, Scope *CurScope) {

591 Diag(DefaultLoc, diag::err_default_not_in_switch);

592 return SubStmt;

593 }

594

597 Diag(DefaultLoc, diag::err_acc_branch_in_out_compute_construct)

598 << 0 << 1;

600 }

601

604 return DS;

605}

606

610

611 if (TheDecl->getStmt()) {

612 Diag(IdentLoc, diag::err_redefinition_of_label) << TheDecl->getDeclName();

613 Diag(TheDecl->getLocation(), diag::note_previous_definition);

614 return SubStmt;

615 }

616

620 Diag(IdentLoc, diag::warn_reserved_extern_symbol)

621 << TheDecl << static_cast(Status);

622

623

624

625 if (getCurScope()->isInOpenACCComputeConstructScope())

627

628

629

630

631

632 if (isa(SubStmt)) {

633 Diag(SubStmt->getBeginLoc(), diag::err_acc_update_as_body) << 4;

635 }

636

637

643

644

646 }

647 }

648 return LS;

649}

650

653 Stmt *SubStmt) {

654

655

656 for (const auto *A : Attrs) {

657 if (A->getKind() == attr::MustTail) {

659 return SubStmt;

660 }

662 }

663 }

664

666}

667

669 Stmt *SubStmt) {

672 if (!SemanticAttrs.empty())

674

675

676

677 return SubStmt;

678}

679

681 ReturnStmt *R = cast(St);

683

685

686 return true;

687

688 if (!checkMustTailAttr(St, MTA))

689 return false;

690

691

692

693

694 auto IgnoreImplicitAsWritten = [](Expr *E) -> Expr * {

697 };

698

699

700

702 return true;

703}

704

705bool Sema::checkMustTailAttr(const Stmt *St, const Attr &MTA) {

707 "musttail cannot be checked from a dependent context");

708

709

710 auto IgnoreParenImplicitAsWritten = [](const Expr *E) -> const Expr * {

714 };

715

716 const Expr *E = cast(St)->getRetValue();

717 const auto *CE = dyn_cast_or_null(IgnoreParenImplicitAsWritten(E));

718

719 if (!CE) {

720 Diag(St->getBeginLoc(), diag::err_musttail_needs_call) << &MTA;

721 return false;

722 }

723

724 if (const auto *EWC = dyn_cast(E)) {

725 if (EWC->cleanupsHaveSideEffects()) {

726 Diag(St->getBeginLoc(), diag::err_musttail_needs_trivial_args) << &MTA;

727 return false;

728 }

729 }

730

731

732

733 struct FuncType {

734 enum {

735 ft_non_member,

736 ft_static_member,

737 ft_non_static_member,

738 ft_pointer_to_member,

739 } MemberType = ft_non_member;

740

744 } CallerType, CalleeType;

745

746 auto GetMethodType = [this, St, MTA](const CXXMethodDecl *CMD, FuncType &Type,

747 bool IsCallee) -> bool {

748 if (isa<CXXConstructorDecl, CXXDestructorDecl>(CMD)) {

749 Diag(St->getBeginLoc(), diag::err_musttail_structors_forbidden)

750 << IsCallee << isa(CMD);

751 if (IsCallee)

752 Diag(CMD->getBeginLoc(), diag::note_musttail_structors_forbidden)

753 << isa(CMD);

754 Diag(MTA.getLocation(), diag::note_tail_call_required) << &MTA;

755 return false;

756 }

757 if (CMD->isStatic())

758 Type.MemberType = FuncType::ft_static_member;

759 else {

760 Type.This = CMD->getFunctionObjectParameterType();

761 Type.MemberType = FuncType::ft_non_static_member;

762 }

764 return true;

765 };

766

767 const auto *CallerDecl = dyn_cast(CurContext);

768

769

770 if (!CallerDecl) {

774 else if (isa(CurContext))

776 else

778 Diag(St->getBeginLoc(), diag::err_musttail_forbidden_from_this_context)

780 return false;

781 } else if (const auto *CMD = dyn_cast(CurContext)) {

782

783 if (!GetMethodType(CMD, CallerType, false))

784 return false;

785 } else {

786

787 CallerType.Func = CallerDecl->getType()->getAs<FunctionProtoType>();

788 }

789

791 const auto *CalleeBinOp = dyn_cast(CalleeExpr);

793 ? CE->getCalleeDecl()->getBeginLoc()

795

796

798 dyn_cast_or_null(CE->getCalleeDecl())) {

799

800 if (!GetMethodType(CMD, CalleeType, true))

801 return false;

802 } else if (CalleeBinOp && CalleeBinOp->isPtrMemOp()) {

803

804 const auto *MPT =

806 CalleeType.This = QualType(MPT->getClass(), 0);

807 CalleeType.Func = MPT->getPointeeType()->castAs<FunctionProtoType>();

808 CalleeType.MemberType = FuncType::ft_pointer_to_member;

809 } else if (isa(CalleeExpr)) {

810 Diag(St->getBeginLoc(), diag::err_musttail_structors_forbidden)

811 << 1 << 1;

812 Diag(MTA.getLocation(), diag::note_tail_call_required) << &MTA;

813 return false;

814 } else {

815

816 CalleeType.Func =

818 }

819

820

821 if (!CalleeType.Func || !CallerType.Func) {

822 Diag(St->getBeginLoc(), diag::err_musttail_needs_prototype) << &MTA;

823 if (!CalleeType.Func && CE->getDirectCallee()) {

824 Diag(CE->getDirectCallee()->getBeginLoc(),

825 diag::note_musttail_fix_non_prototype);

826 }

827 if (!CallerType.Func)

828 Diag(CallerDecl->getBeginLoc(), diag::note_musttail_fix_non_prototype);

829 return false;

830 }

831

832

833

834

835

836

837

838

839 if (CallerType.Func->getCallConv() != CalleeType.Func->getCallConv()) {

840 if (const auto *ND = dyn_cast_or_null(CE->getCalleeDecl()))

841 Diag(St->getBeginLoc(), diag::err_musttail_callconv_mismatch)

842 << true << ND->getDeclName();

843 else

844 Diag(St->getBeginLoc(), diag::err_musttail_callconv_mismatch) << false;

845 Diag(CalleeLoc, diag::note_musttail_callconv_mismatch)

848 Diag(MTA.getLocation(), diag::note_tail_call_required) << &MTA;

849 return false;

850 }

851

852 if (CalleeType.Func->isVariadic() || CallerType.Func->isVariadic()) {

853 Diag(St->getBeginLoc(), diag::err_musttail_no_variadic) << &MTA;

854 return false;

855 }

856

857 const auto *CalleeDecl = CE->getCalleeDecl();

858 if (CalleeDecl && CalleeDecl->hasAttr()) {

859 Diag(St->getBeginLoc(), diag::err_musttail_no_return) << &MTA;

860 return false;

861 }

862

863

864 if (CallerType.This.isNull() != CalleeType.This.isNull()) {

865 if (const auto *ND = dyn_cast_or_null(CE->getCalleeDecl())) {

866 Diag(St->getBeginLoc(), diag::err_musttail_member_mismatch)

867 << CallerType.MemberType << CalleeType.MemberType << true

868 << ND->getDeclName();

869 Diag(CalleeLoc, diag::note_musttail_callee_defined_here)

870 << ND->getDeclName();

871 } else

872 Diag(St->getBeginLoc(), diag::err_musttail_member_mismatch)

873 << CallerType.MemberType << CalleeType.MemberType << false;

874 Diag(MTA.getLocation(), diag::note_tail_call_required) << &MTA;

875 return false;

876 }

877

878 auto CheckTypesMatch = [this](FuncType CallerType, FuncType CalleeType,

880 enum {

885 };

886

888 unsigned Select) -> bool {

891 return false;

892 }

893 return true;

894 };

895

896 if (!CallerType.This.isNull() &&

898 return false;

899

900 if (!DoTypesMatch(CallerType.Func->getReturnType(),

902 return false;

903

904 if (CallerType.Func->getNumParams() != CalleeType.Func->getNumParams()) {

906 << CalleeType.Func->getNumParams();

907 return false;

908 }

909

912 size_t N = CallerType.Func->getNumParams();

913 for (size_t I = 0; I < N; I++) {

914 if (!DoTypesMatch(CalleeParams[I], CallerParams[I],

916 PD << static_cast(I) + 1;

917 return false;

918 }

919 }

920

921 return true;

922 };

923

925 if (!CheckTypesMatch(CallerType, CalleeType, PD)) {

926 if (const auto *ND = dyn_cast_or_null(CE->getCalleeDecl()))

928 << true << ND->getDeclName();

929 else

930 Diag(St->getBeginLoc(), diag::err_musttail_mismatch) << false;

931 Diag(CalleeLoc, PD);

932 Diag(MTA.getLocation(), diag::note_tail_call_required) << &MTA;

933 return false;

934 }

935

936

937

938

939 for (auto ArgExpr : CE->arguments()) {

941 Context, ArgExpr->getType(), false);

943 }

944

945 return true;

946}

947

948namespace {

951 Sema &SemaRef;

952public:

953 CommaVisitor(Sema &SemaRef) : Inherited(SemaRef.Context), SemaRef(SemaRef) {}

955 if (E->getOpcode() == BO_Comma)

958 }

959};

960}

961

967 Stmt *elseStmt) {

970

971 bool ConstevalOrNegatedConsteval =

974

975 Expr *CondExpr = Cond.get().second;

976 assert((CondExpr || ConstevalOrNegatedConsteval) &&

977 "If statement: missing condition");

978

981 CommaVisitor(*this).Visit(CondExpr);

982

983 if (!ConstevalOrNegatedConsteval && !elseStmt)

985

986 if (ConstevalOrNegatedConsteval ||

988 auto DiagnoseLikelihood = [&](const Stmt *S) {

991 diag::warn_attribute_has_no_effect_on_compile_time_if)

992 << A << ConstevalOrNegatedConsteval << A->getRange();

994 diag::note_attribute_has_no_effect_on_compile_time_if_here)

995 << ConstevalOrNegatedConsteval

996 << SourceRange(IfLoc, (ConstevalOrNegatedConsteval

998 : LParenLoc)

1000 }

1001 };

1002 DiagnoseLikelihood(thenStmt);

1003 DiagnoseLikelihood(elseStmt);

1004 } else {

1005 std::tuple<bool, const Attr *, const Attr *> LHC =

1007 if (std::get<0>(LHC)) {

1008 const Attr *ThenAttr = std::get<1>(LHC);

1009 const Attr *ElseAttr = std::get<2>(LHC);

1011 diag::warn_attributes_likelihood_ifstmt_conflict)

1012 << ThenAttr << ThenAttr->getRange();

1014 << ElseAttr << ElseAttr->getRange();

1015 }

1016 }

1017

1018 if (ConstevalOrNegatedConsteval) {

1022 const auto *FD =

1024 if (FD && FD->isImmediateFunction())

1025 Immediate = true;

1026 }

1028 Diags.Report(IfLoc, diag::warn_consteval_if_always_true) << Immediate;

1029 }

1030

1031

1032

1033

1034

1035 if (isa(thenStmt)) {

1036 Diag(thenStmt->getBeginLoc(), diag::err_acc_update_as_body) << 0;

1038 }

1039

1040 return BuildIfStmt(IfLoc, StatementKind, LParenLoc, InitStmt, Cond, RParenLoc,

1041 thenStmt, ElseLoc, elseStmt);

1042}

1043

1049 Stmt *elseStmt) {

1052

1054 isa(Cond.get().second))

1056

1058 Cond.get().first, Cond.get().second, LParenLoc,

1059 RParenLoc, thenStmt, ElseLoc, elseStmt);

1060}

1061

1062namespace {

1063 struct CaseCompareFunctor {

1064 bool operator()(const std::pair<llvm::APSInt, CaseStmt*> &LHS,

1065 const llvm::APSInt &RHS) {

1066 return LHS.first < RHS;

1067 }

1068 bool operator()(const std::pair<llvm::APSInt, CaseStmt*> &LHS,

1069 const std::pair<llvm::APSInt, CaseStmt*> &RHS) {

1070 return LHS.first < RHS.first;

1071 }

1072 bool operator()(const llvm::APSInt &LHS,

1073 const std::pair<llvm::APSInt, CaseStmt*> &RHS) {

1074 return LHS < RHS.first;

1075 }

1076 };

1077}

1078

1079

1080

1081static bool CmpCaseVals(const std::pair<llvm::APSInt, CaseStmt*>& lhs,

1082 const std::pair<llvm::APSInt, CaseStmt*>& rhs) {

1083 if (lhs.first < rhs.first)

1084 return true;

1085

1086 if (lhs.first == rhs.first &&

1087 lhs.second->getCaseLoc() < rhs.second->getCaseLoc())

1088 return true;

1089 return false;

1090}

1091

1092

1093

1094static bool CmpEnumVals(const std::pair<llvm::APSInt, EnumConstantDecl*>& lhs,

1095 const std::pair<llvm::APSInt, EnumConstantDecl*>& rhs)

1096{

1097 return lhs.first < rhs.first;

1098}

1099

1100

1101

1102static bool EqEnumVals(const std::pair<llvm::APSInt, EnumConstantDecl*>& lhs,

1103 const std::pair<llvm::APSInt, EnumConstantDecl*>& rhs)

1104{

1105 return lhs.first == rhs.first;

1106}

1107

1108

1109

1111 if (const auto *FE = dyn_cast(E))

1112 E = FE->getSubExpr();

1113 while (const auto *ImpCast = dyn_cast(E)) {

1114 if (ImpCast->getCastKind() != CK_IntegralCast) break;

1115 E = ImpCast->getSubExpr();

1116 }

1118}

1119

1123

1124 public:

1125 SwitchConvertDiagnoser(Expr *Cond)

1127 Cond(Cond) {}

1128

1131 return S.Diag(Loc, diag::err_typecheck_statement_requires_integer) << T;

1132 }

1133

1136 return S.Diag(Loc, diag::err_switch_incomplete_class_type)

1138 }

1139

1142 return S.Diag(Loc, diag::err_switch_explicit_conversion) << T << ConvTy;

1143 }

1144

1147 return S.Diag(Conv->getLocation(), diag::note_switch_conversion)

1149 }

1150

1153 return S.Diag(Loc, diag::err_switch_multiple_conversions) << T;

1154 }

1155

1158 return S.Diag(Conv->getLocation(), diag::note_switch_conversion)

1160 }

1161

1164 llvm_unreachable("conversion functions are permitted");

1165 }

1166 } SwitchDiagnoser(Cond);

1167

1172

1173

1174

1175 Cond = CondResult.get();

1179

1180

1182}

1183

1188 Expr *CondExpr = Cond.get().second;

1189 assert((Cond.isInvalid() || CondExpr) && "switch with no condition");

1190

1192

1193

1194

1195

1199

1200

1201

1202 Diag(SwitchLoc, diag::warn_bool_switch_condition)

1204 }

1205 }

1206

1208

1210 LParenLoc, RParenLoc);

1213 return SS;

1214}

1215

1216static void AdjustAPSInt(llvm::APSInt &Val, unsigned BitWidth, bool IsSigned) {

1217 Val = Val.extOrTrunc(BitWidth);

1218 Val.setIsSigned(IsSigned);

1219}

1220

1221

1222

1224 unsigned UnpromotedWidth, bool UnpromotedSign) {

1225

1227 return;

1228

1229

1230

1231

1232 if (UnpromotedWidth < Val.getBitWidth()) {

1233 llvm::APSInt ConvVal(Val);

1234 AdjustAPSInt(ConvVal, UnpromotedWidth, UnpromotedSign);

1235 AdjustAPSInt(ConvVal, Val.getBitWidth(), Val.isSigned());

1236

1237

1238

1239 if (ConvVal != Val)

1240 S.Diag(Loc, diag::warn_case_value_overflow) << toString(Val, 10)

1242 }

1243}

1244

1246

1247

1248

1251 const Expr *CaseExpr,

1252 EnumValsTy::iterator &EI,

1253 EnumValsTy::iterator &EIEnd,

1254 const llvm::APSInt &Val) {

1256 return false;

1257

1260 if (const VarDecl *VD = dyn_cast(DRE->getDecl())) {

1261 QualType VarType = VD->getType();

1265 return false;

1266 }

1267 }

1268

1269 if (ED->hasAttr())

1271

1272 while (EI != EIEnd && EI->first < Val)

1273 EI++;

1274

1275 if (EI != EIEnd && EI->first == Val)

1276 return false;

1277

1278 return true;

1279}

1280

1282 const Expr *Case) {

1285

1288 if (!CondEnumType || !CaseEnumType)

1289 return;

1290

1291

1294 return;

1295 if (!CaseEnumType->getDecl()->getIdentifier() &&

1296 !CaseEnumType->getDecl()->getTypedefNameForAnonDecl())

1297 return;

1298

1300 return;

1301

1302 S.Diag(Case->getExprLoc(), diag::warn_comparison_of_mixed_enum_types_switch)

1305}

1306

1309 Stmt *BodyStmt) {

1312 assert(SS == getCurFunction()->SwitchStack.back().getPointer() &&

1313 "switch stack missing push/pop!");

1314

1316

1317 if (!BodyStmt) return StmtError();

1318

1319

1320

1321

1322

1323 if (isa(BodyStmt)) {

1324 Diag(BodyStmt->getBeginLoc(), diag::err_acc_update_as_body) << 3;

1326 }

1327

1328 SS->setBody(BodyStmt, SwitchLoc);

1329

1331 if (!CondExpr) return StmtError();

1332

1334

1335

1336

1337

1338

1339

1340

1341

1342 const Expr *CondExprBeforePromotion = CondExpr;

1343 QualType CondTypeBeforePromotion =

1345

1346

1347

1348 bool HasDependentValue

1350 unsigned CondWidth = HasDependentValue ? 0 : Context.getIntWidth(CondType);

1352

1353

1354

1355

1356

1357 unsigned CondWidthBeforePromotion

1358 = HasDependentValue ? 0 : Context.getIntWidth(CondTypeBeforePromotion);

1359 bool CondIsSignedBeforePromotion

1361

1362

1363

1364

1366 CaseValsTy CaseVals;

1367

1368

1369 typedef std::vector<std::pair<llvm::APSInt, CaseStmt*> > CaseRangesTy;

1370 CaseRangesTy CaseRanges;

1371

1373

1374 bool CaseListIsErroneous = false;

1375

1376

1377

1378

1381

1382 if (DefaultStmt *DS = dyn_cast(SC)) {

1383 if (TheDefaultStmt) {

1384 Diag(DS->getDefaultLoc(), diag::err_multiple_default_labels_defined);

1385 Diag(TheDefaultStmt->getDefaultLoc(), diag::note_duplicate_case_prev);

1386

1387

1388

1389

1390

1391 CaseListIsErroneous = true;

1392 }

1393 TheDefaultStmt = DS;

1394

1395 } else {

1396 CaseStmt *CS = cast(SC);

1397

1399

1401 HasDependentValue = true;

1402 break;

1403 }

1404

1405

1406

1407 const Expr *LoBeforePromotion = Lo;

1410

1411

1412

1414 CondIsSignedBeforePromotion);

1415

1416

1418 LoBeforePromotion);

1419

1420

1421 AdjustAPSInt(LoVal, CondWidth, CondIsSigned);

1422

1423

1426 HasDependentValue = true;

1427 break;

1428 }

1429 CaseRanges.push_back(std::make_pair(LoVal, CS));

1430 } else

1431 CaseVals.push_back(std::make_pair(LoVal, CS));

1432 }

1433 }

1434

1435 if (!HasDependentValue) {

1436

1437

1438 llvm::APSInt ConstantCondValue;

1439 bool HasConstantCond = false;

1440 if (!TheDefaultStmt) {

1444 if (Result.Val.isInt())

1445 ConstantCondValue = Result.Val.getInt();

1446 assert(!HasConstantCond ||

1447 (ConstantCondValue.getBitWidth() == CondWidth &&

1448 ConstantCondValue.isSigned() == CondIsSigned));

1449 Diag(SwitchLoc, diag::warn_switch_default);

1450 }

1451 bool ShouldCheckConstantCond = HasConstantCond;

1452

1453

1454 llvm::stable_sort(CaseVals, CmpCaseVals);

1455

1456 if (!CaseVals.empty()) {

1457 for (unsigned i = 0, e = CaseVals.size(); i != e; ++i) {

1458 if (ShouldCheckConstantCond &&

1459 CaseVals[i].first == ConstantCondValue)

1460 ShouldCheckConstantCond = false;

1461

1462 if (i != 0 && CaseVals[i].first == CaseVals[i-1].first) {

1463

1464

1465 StringRef PrevString, CurrString;

1468 if (DeclRefExpr *DeclRef = dyn_cast(PrevCase)) {

1469 PrevString = DeclRef->getDecl()->getName();

1470 }

1471 if (DeclRefExpr *DeclRef = dyn_cast(CurrCase)) {

1472 CurrString = DeclRef->getDecl()->getName();

1473 }

1475 CaseVals[i-1].first.toString(CaseValStr);

1476

1477 if (PrevString == CurrString)

1478 Diag(CaseVals[i].second->getLHS()->getBeginLoc(),

1479 diag::err_duplicate_case)

1480 << (PrevString.empty() ? CaseValStr.str() : PrevString);

1481 else

1482 Diag(CaseVals[i].second->getLHS()->getBeginLoc(),

1483 diag::err_duplicate_case_differing_expr)

1484 << (PrevString.empty() ? CaseValStr.str() : PrevString)

1485 << (CurrString.empty() ? CaseValStr.str() : CurrString)

1486 << CaseValStr;

1487

1488 Diag(CaseVals[i - 1].second->getLHS()->getBeginLoc(),

1489 diag::note_duplicate_case_prev);

1490

1491

1492 CaseListIsErroneous = true;

1493 }

1494 }

1495 }

1496

1497

1498

1499 if (!CaseRanges.empty()) {

1500

1501

1502 llvm::stable_sort(CaseRanges);

1503

1504

1505 std::vectorllvm::APSInt HiVals;

1506 for (unsigned i = 0, e = CaseRanges.size(); i != e; ++i) {

1507 llvm::APSInt &LoVal = CaseRanges[i].first;

1508 CaseStmt *CR = CaseRanges[i].second;

1510

1511 const Expr *HiBeforePromotion = Hi;

1514

1515

1516

1518 CondWidthBeforePromotion, CondIsSignedBeforePromotion);

1519

1520

1521 AdjustAPSInt(HiVal, CondWidth, CondIsSigned);

1522

1523

1524 if (LoVal > HiVal) {

1527 CaseRanges.erase(CaseRanges.begin()+i);

1528 --i;

1529 --e;

1530 continue;

1531 }

1532

1533 if (ShouldCheckConstantCond &&

1534 LoVal <= ConstantCondValue &&

1535 ConstantCondValue <= HiVal)

1536 ShouldCheckConstantCond = false;

1537

1538 HiVals.push_back(HiVal);

1539 }

1540

1541

1542

1543

1544 for (unsigned i = 0, e = CaseRanges.size(); i != e; ++i) {

1545 llvm::APSInt &CRLo = CaseRanges[i].first;

1546 llvm::APSInt &CRHi = HiVals[i];

1547 CaseStmt *CR = CaseRanges[i].second;

1548

1549

1550

1551 CaseStmt *OverlapStmt = nullptr;

1552 llvm::APSInt OverlapVal(32);

1553

1554

1555

1556 CaseValsTy::iterator I =

1557 llvm::lower_bound(CaseVals, CRLo, CaseCompareFunctor());

1558 if (I != CaseVals.end() && I->first < CRHi) {

1559 OverlapVal = I->first;

1560 OverlapStmt = I->second;

1561 }

1562

1563

1564 I = std::upper_bound(I, CaseVals.end(), CRHi, CaseCompareFunctor());

1565 if (I != CaseVals.begin() && (I-1)->first >= CRLo) {

1566 OverlapVal = (I-1)->first;

1567 OverlapStmt = (I-1)->second;

1568 }

1569

1570

1571

1572 if (i && CRLo <= HiVals[i-1]) {

1573 OverlapVal = HiVals[i-1];

1574 OverlapStmt = CaseRanges[i-1].second;

1575 }

1576

1577 if (OverlapStmt) {

1578

1580 << toString(OverlapVal, 10);

1582 diag::note_duplicate_case_prev);

1583

1584

1585 CaseListIsErroneous = true;

1586 }

1587 }

1588 }

1589

1590

1591 if (!CaseListIsErroneous && !CaseListIsIncomplete &&

1592 ShouldCheckConstantCond) {

1593

1594

1595 Diag(CondExpr->getExprLoc(), diag::warn_missing_case_for_condition)

1596 << toString(ConstantCondValue, 10)

1598 }

1599

1600

1601

1602

1603

1604

1606

1607

1608 if (!CaseListIsErroneous && !CaseListIsIncomplete && !HasConstantCond &&

1613

1614

1615

1617 llvm::APSInt Val = EDI->getInitVal();

1619 EnumVals.push_back(std::make_pair(Val, EDI));

1620 }

1621 llvm::stable_sort(EnumVals, CmpEnumVals);

1622 auto EI = EnumVals.begin(), EIEnd =

1623 std::unique(EnumVals.begin(), EnumVals.end(), EqEnumVals);

1624

1625

1626 for (CaseValsTy::const_iterator CI = CaseVals.begin();

1627 CI != CaseVals.end(); CI++) {

1628 Expr *CaseExpr = CI->second->getLHS();

1630 CI->first))

1631 Diag(CaseExpr->getExprLoc(), diag::warn_not_in_enum)

1632 << CondTypeBeforePromotion;

1633 }

1634

1635

1636 EI = EnumVals.begin();

1637 for (CaseRangesTy::const_iterator RI = CaseRanges.begin();

1638 RI != CaseRanges.end(); RI++) {

1639 Expr *CaseExpr = RI->second->getLHS();

1641 RI->first))

1642 Diag(CaseExpr->getExprLoc(), diag::warn_not_in_enum)

1643 << CondTypeBeforePromotion;

1644

1645 llvm::APSInt Hi =

1646 RI->second->getRHS()->EvaluateKnownConstInt(Context);

1648

1649 CaseExpr = RI->second->getRHS();

1651 Hi))

1652 Diag(CaseExpr->getExprLoc(), diag::warn_not_in_enum)

1653 << CondTypeBeforePromotion;

1654 }

1655

1656

1657 auto CI = CaseVals.begin();

1658 auto RI = CaseRanges.begin();

1659 bool hasCasesNotInSwitch = false;

1660

1662

1663 for (EI = EnumVals.begin(); EI != EIEnd; EI++) {

1664

1665 switch (EI->second->getAvailability()) {

1667

1669 continue;

1670

1672

1673

1675 break;

1676 }

1677

1678 if (EI->second->hasAttr())

1679 continue;

1680

1681

1682 while (CI != CaseVals.end() && CI->first < EI->first)

1683 CI++;

1684

1685 if (CI != CaseVals.end() && CI->first == EI->first)

1686 continue;

1687

1688

1689 for (; RI != CaseRanges.end(); RI++) {

1690 llvm::APSInt Hi =

1691 RI->second->getRHS()->EvaluateKnownConstInt(Context);

1693 if (EI->first <= Hi)

1694 break;

1695 }

1696

1697 if (RI == CaseRanges.end() || EI->first < RI->first) {

1698 hasCasesNotInSwitch = true;

1699 UnhandledNames.push_back(EI->second->getDeclName());

1700 }

1701 }

1702

1703 if (TheDefaultStmt && UnhandledNames.empty() && ED->isClosedNonFlag())

1704 Diag(TheDefaultStmt->getDefaultLoc(), diag::warn_unreachable_default);

1705

1706

1707 if (!UnhandledNames.empty()) {

1708 auto DB = Diag(CondExpr->getExprLoc(), TheDefaultStmt

1709 ? diag::warn_def_missing_case

1710 : diag::warn_missing_case)

1712

1713 for (size_t I = 0, E = std::min(UnhandledNames.size(), (size_t)3);

1714 I != E; ++I)

1715 DB << UnhandledNames[I];

1716 }

1717

1718 if (!hasCasesNotInSwitch)

1720 }

1721 }

1722

1723 if (BodyStmt)

1725 diag::warn_empty_switch_body);

1726

1727

1728

1729 if (CaseListIsErroneous)

1731

1732 return SS;

1733}

1734

1735void

1737 Expr *SrcExpr) {

1739 return;

1740

1746

1749

1751 AdjustAPSInt(RhsVal, DstWidth, DstIsSigned);

1752 const EnumDecl *ED = ET->getDecl();

1753

1755 return;

1756

1757 if (ED->hasAttr()) {

1759 Diag(SrcExpr->getExprLoc(), diag::warn_not_in_enum_assignment)

1761 } else {

1765

1766

1767

1769 llvm::APSInt Val = EDI->getInitVal();

1771 EnumVals.push_back(std::make_pair(Val, EDI));

1772 }

1773 if (EnumVals.empty())

1774 return;

1775 llvm::stable_sort(EnumVals, CmpEnumVals);

1776 EnumValsTy::iterator EIend =

1777 std::unique(EnumVals.begin(), EnumVals.end(), EqEnumVals);

1778

1779

1780 EnumValsTy::const_iterator EI = EnumVals.begin();

1781 while (EI != EIend && EI->first < RhsVal)

1782 EI++;

1783 if (EI == EIend || EI->first != RhsVal) {

1784 Diag(SrcExpr->getExprLoc(), diag::warn_not_in_enum_assignment)

1786 }

1787 }

1788 }

1789 }

1790}

1791

1797

1798 auto CondVal = Cond.get();

1799 CheckBreakContinueBinding(CondVal.second);

1800

1801 if (CondVal.second &&

1802 Diags.isIgnored(diag::warn_comma_operator, CondVal.second->getExprLoc()))

1803 CommaVisitor(*this).Visit(CondVal.second);

1804

1805

1806

1807

1808

1809 if (isa(Body)) {

1810 Diag(Body->getBeginLoc(), diag::err_acc_update_as_body) << 1;

1812 }

1813

1814 if (isa(Body))

1816

1818 WhileLoc, LParenLoc, RParenLoc);

1819}

1820

1825 assert(Cond && "ActOnDoStmt(): missing expression");

1826

1827 CheckBreakContinueBinding(Cond);

1831 Cond = CondResult.get();

1832

1833 CondResult = ActOnFinishFullExpr(Cond, DoLoc, false);

1836 Cond = CondResult.get();

1837

1838

1841 CommaVisitor(*this).Visit(Cond);

1842

1843

1844

1845

1846

1847 if (isa(Body)) {

1848 Diag(Body->getBeginLoc(), diag::err_acc_update_as_body) << 2;

1850 }

1851

1852 return new (Context) DoStmt(Body, Cond, DoLoc, WhileLoc, CondRParen);

1853}

1854

1855namespace {

1856

1858

1859

1860

1861

1863 DeclSetVector &Decls;

1865 bool Simple;

1866 public:

1868

1869 DeclExtractor(Sema &S, DeclSetVector &Decls,

1871 Inherited(S.Context),

1872 Decls(Decls),

1873 Ranges(Ranges),

1874 Simple(true) {}

1875

1876 bool isSimple() { return Simple; }

1877

1878

1880 Simple = false;

1881 }

1882

1883

1884

1885 void VisitStmt(Stmt *S) { Simple = false; }

1886

1888 Visit(E->getLHS());

1889 Visit(E->getRHS());

1890 }

1891

1892 void VisitCastExpr(CastExpr *E) {

1893 Visit(E->getSubExpr());

1894 }

1895

1897

1898 if (E->getOpcode() == UO_Deref)

1899 Simple = false;

1900 else

1901 Visit(E->getSubExpr());

1902 }

1903

1905 Visit(E->getCond());

1906 Visit(E->getTrueExpr());

1907 Visit(E->getFalseExpr());

1908 }

1909

1911 Visit(E->getSubExpr());

1912 }

1913

1915 Visit(E->getOpaqueValue()->getSourceExpr());

1916 Visit(E->getFalseExpr());

1917 }

1918

1925

1927 VarDecl *VD = dyn_cast(E->getDecl());

1928 if (!VD) {

1929

1930 Simple = false;

1931 return;

1932 }

1933

1935

1936 Decls.insert(VD);

1937 }

1938

1939 };

1940

1941

1942

1944 DeclSetVector &Decls;

1945 bool FoundDecl;

1946

1947 public:

1949

1950 DeclMatcher(Sema &S, DeclSetVector &Decls, Stmt *Statement) :

1951 Inherited(S.Context), Decls(Decls), FoundDecl(false) {

1952 if (!Statement) return;

1953

1954 Visit(Statement);

1955 }

1956

1957 void VisitReturnStmt(ReturnStmt *S) {

1958 FoundDecl = true;

1959 }

1960

1961 void VisitBreakStmt(BreakStmt *S) {

1962 FoundDecl = true;

1963 }

1964

1965 void VisitGotoStmt(GotoStmt *S) {

1966 FoundDecl = true;

1967 }

1968

1969 void VisitCastExpr(CastExpr *E) {

1970 if (E->getCastKind() == CK_LValueToRValue)

1971 CheckLValueToRValueCast(E->getSubExpr());

1972 else

1973 Visit(E->getSubExpr());

1974 }

1975

1976 void CheckLValueToRValueCast(Expr *E) {

1978

1979 if (isa(E)) {

1980 return;

1981 }

1982

1984 Visit(CO->getCond());

1985 CheckLValueToRValueCast(CO->getTrueExpr());

1986 CheckLValueToRValueCast(CO->getFalseExpr());

1987 return;

1988 }

1989

1991 dyn_cast(E)) {

1992 CheckLValueToRValueCast(BCO->getOpaqueValue()->getSourceExpr());

1993 CheckLValueToRValueCast(BCO->getFalseExpr());

1994 return;

1995 }

1996

1997 Visit(E);

1998 }

1999

2001 if (VarDecl *VD = dyn_cast(E->getDecl()))

2002 if (Decls.count(VD))

2003 FoundDecl = true;

2004 }

2005

2007

2008

2009 for (auto *S : POE->semantics()) {

2010 if (auto *OVE = dyn_cast(S))

2011

2012 Visit(OVE->getSourceExpr());

2013 else

2014 Visit(S);

2015 }

2016 }

2017

2018 bool FoundDeclInUse() { return FoundDecl; }

2019

2020 };

2021

2022 void CheckForLoopConditionalStatement(Sema &S, Expr *Second,

2024

2025 if (!Second) return;

2026

2027 if (S.Diags.isIgnored(diag::warn_variables_not_in_loop_body,

2029 return;

2030

2032 DeclSetVector Decls;

2034 DeclExtractor DE(S, Decls, Ranges);

2035 DE.Visit(Second);

2036

2037

2038 if (!DE.isSimple()) return;

2039

2040

2041 if (Decls.size() == 0) return;

2042

2043

2044 for (auto *VD : Decls)

2046 return;

2047

2048 if (DeclMatcher(S, Decls, Second).FoundDeclInUse() ||

2049 DeclMatcher(S, Decls, Third).FoundDeclInUse() ||

2050 DeclMatcher(S, Decls, Body).FoundDeclInUse())

2051 return;

2052

2053

2054 if (Decls.size() > 4) {

2055 PDiag << 0;

2056 } else {

2057 PDiag << (unsigned)Decls.size();

2058 for (auto *VD : Decls)

2060 }

2061

2062 for (auto Range : Ranges)

2064

2065 S.Diag(Ranges.begin()->getBegin(), PDiag);

2066 }

2067

2068

2069

2070 bool ProcessIterationStmt(Sema &S, Stmt* Statement, bool &Increment,

2072 if (auto Cleanups = dyn_cast(Statement))

2073 if (!Cleanups->cleanupsHaveSideEffects())

2074 Statement = Cleanups->getSubExpr();

2075

2076 if (UnaryOperator *UO = dyn_cast(Statement)) {

2077 switch (UO->getOpcode()) {

2078 default: return false;

2079 case UO_PostInc:

2080 case UO_PreInc:

2081 Increment = true;

2082 break;

2083 case UO_PostDec:

2084 case UO_PreDec:

2085 Increment = false;

2086 break;

2087 }

2088 DRE = dyn_cast(UO->getSubExpr());

2089 return DRE;

2090 }

2091

2096 default: return false;

2097 case OO_PlusPlus:

2098 Increment = true;

2099 break;

2100 case OO_MinusMinus:

2101 Increment = false;

2102 break;

2103 }

2104 DRE = dyn_cast(Call->getArg(0));

2105 return DRE;

2106 }

2107

2108 return false;

2109 }

2110

2111

2112

2116 bool InSwitch = false;

2117

2118 public:

2119 BreakContinueFinder(Sema &S, const Stmt* Body) :

2120 Inherited(S.Context) {

2121 Visit(Body);

2122 }

2123

2125

2127 ContinueLoc = E->getContinueLoc();

2128 }

2129

2130 void VisitBreakStmt(const BreakStmt* E) {

2131 if (!InSwitch)

2132 BreakLoc = E->getBreakLoc();

2133 }

2134

2135 void VisitSwitchStmt(const SwitchStmt* S) {

2136 if (const Stmt *Init = S->getInit())

2137 Visit(Init);

2138 if (const Stmt *CondVar = S->getConditionVariableDeclStmt())

2139 Visit(CondVar);

2140 if (const Stmt *Cond = S->getCond())

2141 Visit(Cond);

2142

2143

2144 InSwitch = true;

2145 if (const Stmt *Body = S->getBody())

2146 Visit(Body);

2147 InSwitch = false;

2148 }

2149

2150 void VisitForStmt(const ForStmt *S) {

2151

2152

2153 if (const Stmt *Init = S->getInit())

2154 Visit(Init);

2155 }

2156

2157 void VisitWhileStmt(const WhileStmt *) {

2158

2159

2160 }

2161

2162 void VisitDoStmt(const DoStmt *) {

2163

2164

2165 }

2166

2168

2169

2170 if (const Stmt *Init = S->getInit())

2171 Visit(Init);

2172 if (const Stmt *Range = S->getRangeStmt())

2174 if (const Stmt *Begin = S->getBeginStmt())

2176 if (const Stmt *End = S->getEndStmt())

2177 Visit(End);

2178 }

2179

2181

2182

2183 if (const Stmt *Element = S->getElement())

2184 Visit(Element);

2185 if (const Stmt *Collection = S->getCollection())

2186 Visit(Collection);

2187 }

2188

2189 bool ContinueFound() { return ContinueLoc.isValid(); }

2190 bool BreakFound() { return BreakLoc.isValid(); }

2191 SourceLocation GetContinueLoc() { return ContinueLoc; }

2193

2194 };

2195

2196

2197

2198

2199

2200

2201 void CheckForRedundantIteration(Sema &S, Expr *Third, Stmt *Body) {

2202

2203 if (!Body || !Third) return;

2204

2205 if (S.Diags.isIgnored(diag::warn_redundant_loop_iteration,

2207 return;

2208

2209

2210 CompoundStmt *CS = dyn_cast(Body);

2211 if (!CS || CS->body_empty()) return;

2213 if (!LastStmt) return;

2214

2215 bool LoopIncrement, LastIncrement;

2217

2218 if (!ProcessIterationStmt(S, Third, LoopIncrement, LoopDRE)) return;

2219 if (!ProcessIterationStmt(S, LastStmt, LastIncrement, LastDRE)) return;

2220

2221

2222

2223 if (LoopIncrement != LastIncrement ||

2225

2226 if (BreakContinueFinder(S, Body).ContinueFound()) return;

2227

2228 S.Diag(LastDRE->getLocation(), diag::warn_redundant_loop_iteration)

2229 << LastDRE->getDecl() << LastIncrement;

2230 S.Diag(LoopDRE->getLocation(), diag::note_loop_iteration_here)

2231 << LoopIncrement;

2232 }

2233

2234}

2235

2236

2237void Sema::CheckBreakContinueBinding(Expr *E) {

2239 return;

2240 BreakContinueFinder BCFinder(*this, E);

2242 if (BCFinder.BreakFound() && BreakParent) {

2244 Diag(BCFinder.GetBreakLoc(), diag::warn_break_binds_to_switch);

2245 } else {

2246 Diag(BCFinder.GetBreakLoc(), diag::warn_loop_ctrl_binds_to_inner)

2247 << "break";

2248 }

2249 } else if (BCFinder.ContinueFound() && CurScope->getContinueParent()) {

2250 Diag(BCFinder.GetContinueLoc(), diag::warn_loop_ctrl_binds_to_inner)

2251 << "continue";

2252 }

2253}

2254

2258 Stmt *Body) {

2261

2263 if (DeclStmt *DS = dyn_cast_or_null(First)) {

2264

2265

2266

2267 const Decl *NonVarSeen = nullptr;

2268 bool VarDeclSeen = false;

2269 for (auto *DI : DS->decls()) {

2270 if (VarDecl *VD = dyn_cast(DI)) {

2271 VarDeclSeen = true;

2273 Diag(DI->getLocation(), diag::err_non_local_variable_decl_in_for);

2274 DI->setInvalidDecl();

2275 }

2276 } else if (!NonVarSeen) {

2277

2278

2279

2280

2281 NonVarSeen = DI;

2282 }

2283 }

2284

2285

2286 if (NonVarSeen && !VarDeclSeen)

2287 Diag(NonVarSeen->getLocation(), diag::err_non_variable_decl_in_for);

2288 }

2289 }

2290

2291 CheckBreakContinueBinding(Second.get().second);

2292 CheckBreakContinueBinding(third.get());

2293

2294 if (!Second.get().first)

2295 CheckForLoopConditionalStatement(*this, Second.get().second, third.get(),

2296 Body);

2297 CheckForRedundantIteration(*this, third.get(), Body);

2298

2299 if (Second.get().second &&

2301 Second.get().second->getExprLoc()))

2302 CommaVisitor(*this).Visit(Second.get().second);

2303

2305 if (isa(Body))

2307

2310 Body, ForLoc, LParenLoc, RParenLoc);

2311}

2312

2314

2315

2318 E = result.get();

2319

2324}

2325

2326

2327

2330 if (Decl->getType()->isUndeducedType()) {

2334 return true;

2335 }

2337 }

2338

2339

2340

2342 if (!isa(Init) && Init->getType()->isVoidType()) {

2343 SemaRef.Diag(Loc, DiagID) << Init->getType();

2344 } else {

2347 Decl->getTypeSourceInfo()->getTypeLoc(), Init, InitType, Info);

2350 SemaRef.Diag(Loc, DiagID) << Init->getType();

2351 }

2352

2353 if (InitType.isNull()) {

2355 return true;

2356 }

2357 Decl->setType(InitType);

2358

2359

2360

2361

2362 if (SemaRef.getLangOpts().ObjCAutoRefCount &&

2365

2369 return false;

2370}

2371

2372namespace {

2373

2374

2375enum BeginEndFunction {

2376 BEF_begin,

2377 BEF_end

2378};

2379

2380

2381

2382

2383

2384void NoteForRangeBeginEndFunction(Sema &SemaRef, Expr *E,

2385 BeginEndFunction BEF) {

2386 CallExpr *CE = dyn_cast(E);

2387 if (!CE)

2388 return;

2390 if (D)

2391 return;

2393

2394 std::string Description;

2395 bool IsTemplate = false;

2398 FunTmpl->getTemplateParameters(), *D->getTemplateSpecializationArgs());

2399 IsTemplate = true;

2400 }

2401

2402 SemaRef.Diag(Loc, diag::note_for_range_begin_end)

2403 << BEF << IsTemplate << Description << E->getType();

2404}

2405

2406

2415 return Decl;

2416}

2417

2418}

2419

2423}

2424

2430

2433

2435

2436 if (InitStmt)

2437 return Diag(InitStmt->getBeginLoc(), diag::err_objc_for_range_init_stmt)

2440 }

2441

2443 assert(DS && "first part of for range not a decl stmt");

2444

2446 Diag(DS->getBeginLoc(), diag::err_type_defined_in_for_range);

2448 }

2449

2450

2451

2457 }

2458

2459

2460

2465 }

2466 }

2467

2468

2469

2470 const auto DepthStr = std::to_string(S->getDepth() / 2);

2472 VarDecl *RangeVar = BuildForRangeVarDecl(*this, RangeLoc,

2474 std::string("__range") + DepthStr);

2476 diag::err_for_range_deduction_failure)) {

2479 }

2480

2481

2488 }

2489

2491 ForLoc, CoawaitLoc, InitStmt, ColonLoc, RangeDecl.get(),

2492 nullptr, nullptr,

2493 nullptr, nullptr, DS, RParenLoc, Kind,

2494 LifetimeExtendTemps);

2498 }

2499

2500 return R;

2501}

2502

2503

2504

2505

2506

2507

2508

2509

2510

2511

2517 ExprResult *EndExpr, BeginEndFunction *BEF) {

2521 ColonLoc);

2522

2523 LookupResult BeginMemberLookup(SemaRef, BeginNameInfo,

2526

2527 auto BuildBegin = [&] {

2528 *BEF = BEF_begin;

2531 BeginMemberLookup, CandidateSet,

2532 BeginRange, BeginExpr);

2533

2536 SemaRef.Diag(BeginRange->getBeginLoc(), diag::note_in_for_range)

2537 << ColonLoc << BEF_begin << BeginRange->getType();

2538 return RangeStatus;

2539 }

2541

2542

2543

2545 BeginExpr->get());

2548 }

2550 diag::err_for_range_iter_deduction_failure)) {

2551 NoteForRangeBeginEndFunction(SemaRef, BeginExpr->get(), *BEF);

2553 }

2555 };

2556

2557 auto BuildEnd = [&] {

2558 *BEF = BEF_end;

2561 EndMemberLookup, CandidateSet,

2562 EndRange, EndExpr);

2565 SemaRef.Diag(EndRange->getBeginLoc(), diag::note_in_for_range)

2566 << ColonLoc << BEF_end << EndRange->getType();

2567 return RangeStatus;

2568 }

2570 diag::err_for_range_iter_deduction_failure)) {

2571 NoteForRangeBeginEndFunction(SemaRef, EndExpr->get(), *BEF);

2573 }

2575 };

2576

2578

2579

2580

2581

2582

2586

2590

2591 if (BeginMemberLookup.empty() != EndMemberLookup.empty()) {

2592

2593

2594

2595

2596 auto BuildNonmember = [&](

2602

2605

2606 switch (BuildFound()) {

2609

2613 SemaRef.PDiag(diag::err_for_range_invalid)

2614 << BeginRange->getType() << BEFFound),

2616 [[fallthrough]];

2617

2621 diag::note_for_range_member_begin_end_ignored)

2622 << BeginRange->getType() << BEFFound;

2623 }

2625 }

2626 llvm_unreachable("unexpected ForRangeStatus");

2627 };

2628 if (BeginMemberLookup.empty())

2629 return BuildNonmember(BEF_end, EndMemberLookup, BuildEnd, BuildBegin);

2630 return BuildNonmember(BEF_begin, BeginMemberLookup, BuildBegin, BuildEnd);

2631 }

2632 } else {

2633

2634

2635

2636

2637 }

2638

2641 return BuildEnd();

2642}

2643

2644

2645

2646

2650 Stmt *InitStmt,

2651 Stmt *LoopVarDecl,

2656

2657

2659 {

2661

2662 AdjustedRange = SemaRef.BuildUnaryOp(S, RangeLoc, UO_Deref, Range);

2665

2667 S, ForLoc, CoawaitLoc, InitStmt, LoopVarDecl, ColonLoc,

2671 }

2672

2673

2674

2675

2676 SemaRef.Diag(RangeLoc, diag::err_for_range_dereference)

2679 S, ForLoc, CoawaitLoc, InitStmt, LoopVarDecl, ColonLoc,

2681}

2682

2689

2690

2691

2692

2693

2694

2695

2696

2697

2699

2700 DeclStmt *RangeDS = cast(RangeDecl);

2703

2704 DeclStmt *LoopVarDS = cast(LoopVarDecl);

2706

2709 ExprResult NotEqExpr = Cond, IncrExpr = Inc;

2710

2712

2714

2715

2716

2718 if (auto *DD = dyn_cast(LoopVar))

2719 for (auto *Binding : DD->bindings())

2722 }

2723 } else if (!BeginDeclStmt.get()) {

2725

2727

2732

2737

2743

2745 diag::err_for_range_incomplete_type))

2747

2748

2752 for (auto *MTE : LifetimeExtendTemps)

2754 }

2755

2756

2757

2758 const auto DepthStr = std::to_string(S->getDepth() / 2);

2759 VarDecl *BeginVar = BuildForRangeVarDecl(*this, ColonLoc, AutoType,

2760 std::string("__begin") + DepthStr);

2761 VarDecl *EndVar = BuildForRangeVarDecl(*this, ColonLoc, AutoType,

2762 std::string("__end") + DepthStr);

2763

2764

2767

2768

2769

2770

2771

2772

2773 BeginExpr = BeginRangeRef;

2778 }

2780 diag::err_for_range_iter_deduction_failure)) {

2781 NoteForRangeBeginEndFunction(*this, BeginExpr.get(), BEF_begin);

2783 }

2784

2785

2787 if (const ConstantArrayType *CAT = dyn_cast(UnqAT))

2791 dyn_cast(UnqAT)) {

2792

2793

2794

2795

2796

2797

2798

2799

2800

2801

2802

2803

2804

2805

2806

2807

2808

2809

2810

2811

2812

2813

2816 true,

2818 VAT->desugar(), RangeLoc))

2823

2826 true,

2829 VAT->getElementType(), RangeLoc))

2832 if (SizeOfEachElementExprR.isInvalid())

2834

2835 BoundExpr =

2837 SizeOfVLAExprR.get(), SizeOfEachElementExprR.get());

2840

2841 } else {

2842

2843

2844 llvm_unreachable("Unexpected array type in for-range");

2845 }

2846

2847

2848 EndExpr = ActOnBinOp(S, ColonLoc, tok::plus, EndRangeRef.get(),

2849 BoundExpr.get());

2853 diag::err_for_range_iter_deduction_failure)) {

2854 NoteForRangeBeginEndFunction(*this, EndExpr.get(), BEF_end);

2856 }

2857 } else {

2860 BeginEndFunction BEFFailure;

2862 *this, BeginRangeRef.get(), EndRangeRef.get(), RangeType, BeginVar,

2863 EndVar, ColonLoc, CoawaitLoc, &CandidateSet, &BeginExpr, &EndExpr,

2864 &BEFFailure);

2865

2867 BEFFailure == BEF_begin) {

2868

2869

2872 QualType ArrayTy = PVD->getOriginalType();

2873 QualType PointerTy = PVD->getType();

2875 Diag(Range->getBeginLoc(), diag::err_range_on_array_parameter)

2876 << RangeLoc << PVD << ArrayTy << PointerTy;

2877 Diag(PVD->getLocation(), diag::note_declared_at);

2879 }

2880 }

2881 }

2882

2883

2884

2886 CoawaitLoc, InitStmt,

2887 LoopVarDecl, ColonLoc,

2888 Range, RangeLoc,

2889 RParenLoc);

2891 return SR;

2892 }

2893

2894

2896 Expr *Range = BEFFailure ? EndRangeRef.get() : BeginRangeRef.get();

2899 PDiag(diag::err_for_range_invalid)

2900 << RangeLoc << Range->getType()

2901 << BEFFailure),

2903 }

2904

2907 }

2908

2910 "invalid range expression in for loop");

2911

2912

2913

2917 ? diag::warn_for_range_begin_end_types_differ

2918 : diag::ext_for_range_begin_end_types_differ)

2919 << BeginType << EndType;

2920 NoteForRangeBeginEndFunction(*this, BeginExpr.get(), BEF_begin);

2921 NoteForRangeBeginEndFunction(*this, EndExpr.get(), BEF_end);

2922 }

2923

2924 BeginDeclStmt =

2926 EndDeclStmt =

2928

2934

2939

2940

2941 NotEqExpr = ActOnBinOp(S, ColonLoc, tok::exclaimequal,

2942 BeginRef.get(), EndRef.get());

2946 NotEqExpr =

2949 Diag(RangeLoc, diag::note_for_range_invalid_iterator)

2950 << RangeLoc << 0 << BeginRangeRef.get()->getType();

2951 NoteForRangeBeginEndFunction(*this, BeginExpr.get(), BEF_begin);

2953 NoteForRangeBeginEndFunction(*this, EndExpr.get(), BEF_end);

2955 }

2956

2957

2962

2963 IncrExpr = ActOnUnaryOp(S, ColonLoc, tok::plusplus, BeginRef.get());

2964 if (!IncrExpr.isInvalid() && CoawaitLoc.isValid())

2965

2966

2967

2969 if (!IncrExpr.isInvalid())

2970 IncrExpr = ActOnFinishFullExpr(IncrExpr.get(), false);

2971 if (IncrExpr.isInvalid()) {

2972 Diag(RangeLoc, diag::note_for_range_invalid_iterator)

2973 << RangeLoc << 2 << BeginRangeRef.get()->getType() ;

2974 NoteForRangeBeginEndFunction(*this, BeginExpr.get(), BEF_begin);

2976 }

2977

2978

2983

2986 Diag(RangeLoc, diag::note_for_range_invalid_iterator)

2987 << RangeLoc << 1 << BeginRangeRef.get()->getType();

2988 NoteForRangeBeginEndFunction(*this, BeginExpr.get(), BEF_begin);

2990 }

2991

2992

2993

2998 NoteForRangeBeginEndFunction(*this, BeginExpr.get(), BEF_begin);

2999 }

3000 }

3001

3002

3003

3006

3007

3008

3011

3013 InitStmt, RangeDS, cast_or_null(BeginDeclStmt.get()),

3014 cast_or_null(EndDeclStmt.get()), NotEqExpr.get(),

3015 IncrExpr.get(), LoopVarDS, nullptr, ForLoc, CoawaitLoc,

3016 ColonLoc, RParenLoc);

3017}

3018

3019

3020

3021

3022

3023

3024

3025

3030 if (!InitExpr)

3031 return;

3032

3034

3035 if (auto Cleanups = dyn_cast(InitExpr))

3036 if (!Cleanups->cleanupsHaveSideEffects())

3037 InitExpr = Cleanups->getSubExpr();

3038

3040 dyn_cast(InitExpr);

3041

3042

3043 if (!MTE)

3044 return;

3045

3047

3048

3049

3050 while (!isa(E) && !isa(E)) {

3051 if (const CXXConstructExpr *CCE = dyn_cast(E)) {

3052 E = CCE->getArg(0);

3054 const MemberExpr *ME = cast(Call->getCallee());

3056 } else {

3059 }

3061 }

3062

3063 QualType ReferenceReturnType;

3064 if (isa(E)) {

3066 } else {

3071 ReferenceReturnType = ReturnType;

3072 }

3073

3074 if (!ReferenceReturnType.isNull()) {

3075

3076

3077

3079 diag::warn_for_range_const_ref_binds_temp_built_from_ref)

3080 << VD << VariableType << ReferenceReturnType;

3085 SemaRef.Diag(VD->getBeginLoc(), diag::note_use_type_or_non_reference)

3086 << NonReferenceType << NewReferenceType << VD->getSourceRange()

3089

3090

3091

3092

3093 SemaRef.Diag(VD->getLocation(), diag::warn_for_range_ref_binds_ret_temp)

3094 << VD << RangeInitType;

3097 SemaRef.Diag(VD->getBeginLoc(), diag::note_use_non_reference_type)

3100 }

3101}

3102

3103

3104

3107 return RD->hasAttr();

3108

3109 return false;

3110}

3111

3112

3113

3114

3118 if (!InitExpr)

3119 return;

3120

3122

3123 if (const CXXConstructExpr *CE = dyn_cast(InitExpr)) {

3124 if (!CE->getConstructor()->isCopyConstructor())

3125 return;

3126 } else if (const CastExpr *CE = dyn_cast(InitExpr)) {

3127 if (CE->getCastKind() != CK_LValueToRValue)

3128 return;

3129 } else {

3130 return;

3131 }

3132

3133

3134

3135

3137 if (Ctx.getTypeSize(VariableType) <= 64 * 8 &&

3140 return;

3141

3142

3143

3144 SemaRef.Diag(VD->getLocation(), diag::warn_for_range_copy)

3145 << VD << VariableType;

3146 SemaRef.Diag(VD->getBeginLoc(), diag::note_use_reference_type)

3150}

3151

3152

3153

3154

3155

3156

3157

3158

3159

3163 return;

3164

3166 diag::warn_for_range_const_ref_binds_temp_built_from_ref,

3168 SemaRef.Diags.isIgnored(diag::warn_for_range_ref_binds_ret_temp,

3172 return;

3173 }

3174

3176 if (!VD)

3177 return;

3178

3180

3182 return;

3183

3185 if (!InitExpr)

3186 return;

3187

3189 return;

3190

3193 ForStmt->getRangeInit()->getType());

3196 }

3197}

3198

3200 if (!S || !B)

3202

3203 if (isa(S))

3205

3208

3210 diag::warn_empty_range_based_for_body);

3211

3213

3214 return S;

3215}

3216

3221

3222

3223

3224 if (getCurScope()->isInOpenACCComputeConstructScope())

3226

3228 return new (Context) GotoStmt(TheDecl, GotoLoc, LabelLoc);

3229}

3230

3234

3243 E = ExprRes.get();

3247 }

3248

3252 E = ExprRes.get();

3253

3255

3256

3257

3258 if (getCurScope()->isInOpenACCComputeConstructScope())

3260

3262}

3263

3265 const Scope &DestScope) {

3268 S.Diag(Loc, diag::warn_jump_out_of_seh_finally);

3269 }

3270}

3271

3275 if (!S) {

3276

3277 return StmtError(Diag(ContinueLoc, diag::err_continue_not_in_loop));

3278 }

3279 if (S->isConditionVarScope()) {

3280

3281

3282

3283 return StmtError(Diag(ContinueLoc, diag::err_continue_from_cond_var_init));

3284 }

3285

3286

3287

3288

3289 if (S->isOpenACCComputeConstructScope())

3291 Diag(ContinueLoc, diag::err_acc_branch_in_out_compute_construct)

3292 << 0 << 0);

3293

3295

3297}

3298

3302 if (!S) {

3303

3304 return StmtError(Diag(BreakLoc, diag::err_break_not_in_loop_or_switch));

3305 }

3306 if (S->isOpenMPLoopScope())

3307 return StmtError(Diag(BreakLoc, diag::err_omp_loop_cannot_use_stmt)

3308 << "break");

3309

3310

3311

3312

3313

3314

3315

3316

3317 if (S->isOpenACCComputeConstructScope() ||

3318 (S->isLoopScope() && S->getParent() &&

3319 S->getParent()->isOpenACCComputeConstructScope()))

3321 Diag(BreakLoc, diag::err_acc_branch_in_out_compute_construct)

3322 << 0 << 0);

3323

3325

3327}

3328

3331 if (E)

3333

3334

3335 const auto *DR = dyn_cast(E->IgnoreParens());

3336 if (!DR || DR->refersToEnclosingVariableOrCapture())

3338 const auto *VD = dyn_cast(DR->getDecl());

3339 if (!VD)

3351 }

3352 return Res;

3353}

3354

3357

3358

3359

3360

3361 if (VD->getKind() == Decl::ParmVar)

3363 else if (VD->getKind() != Decl::Var)

3365

3366

3369

3370

3373

3374

3375

3376 if (VD->hasAttr())

3378

3381

3382

3386

3387

3388

3394 } else {

3396 }

3397

3398

3399

3403

3404 return Info;

3405}

3406

3410 return nullptr;

3411

3412 auto invalidNRVO = [&] {

3414 return nullptr;

3415 };

3416

3417

3418

3419

3420

3421 if ((ReturnType->getTypeClass() == Type::TypeClass::Auto &&

3424 return invalidNRVO();

3425

3427

3428

3430 return invalidNRVO();

3431

3433

3434

3438 }

3440}

3441

3442

3443

3444

3445

3446

3447static bool

3450 const auto *Step = llvm::find_if(Seq.steps(), [](const auto &Step) {

3451 return Step.Kind == InitializationSequence::SK_ConstructorInitialization ||

3452 Step.Kind == InitializationSequence::SK_UserConversion;

3453 });

3454 if (Step != Seq.step_end()) {

3455 const auto *FD = Step->Function.Function;

3456 if (isa(FD)

3458 : cast(FD)->getRefQualifier() == RQ_None)

3459 return false;

3460 }

3461 return true;

3462}

3463

3466 bool SupressSimplerImplicitMoves) {

3472 Expr *InitExpr = &AsRvalue;

3474 Value->getBeginLoc());

3476 auto Res = Seq.getFailedOverloadResult();

3480

3481

3485

3486

3487 return Seq.Perform(*this, Entity, Kind, Value);

3488 }

3489 }

3490

3491

3492

3494}

3495

3496

3497

3502}

3503

3505 Expr *RetValExp,

3507 bool SupressSimplerImplicitMoves) {

3508

3509

3512 LambdaScopeInfo *CurLambda = dyn_cast(CurCap);

3515 bool HasDeducedReturnType =

3517

3518 if (ExprEvalContexts.back().isDiscardedStatementContext() &&

3520 if (RetValExp) {

3525 RetValExp = ER.get();

3526 }

3528 nullptr);

3529 }

3530

3531 if (HasDeducedReturnType) {

3533

3534

3535

3538

3539

3542

3544 assert(AT && "lost auto type from lambda return type");

3547

3549 }

3552

3553

3554

3555

3556 if (RetValExp && !isa(RetValExp)) {

3558 if (Result.isInvalid())

3560 RetValExp = Result.get();

3561

3562

3563

3564

3565

3568 else

3570 } else {

3571 if (RetValExp) {

3572

3573

3574

3575 Diag(ReturnLoc, diag::err_lambda_return_init_list)

3577 }

3578

3580 }

3581

3582

3583

3586 }

3588

3589 if (auto *CurBlock = dyn_cast(CurCap)) {

3591 Diag(ReturnLoc, diag::err_noreturn_block_has_return_expr);

3593 }

3594 } else if (auto *CurRegion = dyn_cast(CurCap)) {

3595 Diag(ReturnLoc, diag::err_return_in_captured_stmt) << CurRegion->getRegionName();

3597 } else {

3598 assert(CurLambda && "unknown kind of captured scope");

3602 Diag(ReturnLoc, diag::err_noreturn_lambda_has_return_expr);

3604 }

3605 }

3606

3607

3608

3609

3611

3612

3613 } else if (FnRetType->isVoidType()) {

3614 if (RetValExp && !isa(RetValExp) &&

3620 Diag(ReturnLoc, diag::ext_return_has_void_expr) << "literal" << 2;

3621 else {

3622 Diag(ReturnLoc, diag::err_return_block_has_expr);

3623 RetValExp = nullptr;

3624 }

3625 }

3626 } else if (!RetValExp) {

3627 return StmtError(Diag(ReturnLoc, diag::err_block_return_missing_expr));

3629

3630

3631

3632

3633

3634

3635

3636

3640 Entity, NRInfo, RetValExp, SupressSimplerImplicitMoves);

3642

3644 }

3645 RetValExp = Res.get();

3646 CheckReturnValExpr(RetValExp, FnRetType, ReturnLoc);

3647 }

3648

3649 if (RetValExp) {

3654 RetValExp = ER.get();

3655 }

3658

3659

3660

3661

3664

3665 if (FunctionScopes.back()->FirstReturnLoc.isInvalid())

3667

3668 if (auto *CurBlock = dyn_cast(CurCap);

3671 CurBlock->TheDecl->setInvalidDecl();

3672

3674}

3675

3676namespace {

3677

3678

3679

3680

3681

3682

3683

3684

3685

3686

3687

3688

3690public:

3691 LocalTypedefNameReferencer(Sema &S) : S(S) {}

3692 bool VisitRecordType(RecordType *RT) override;

3693

3694private:

3696};

3697bool LocalTypedefNameReferencer::VisitRecordType(RecordType *RT) {

3698 auto *R = dyn_cast(RT->getDecl());

3699 if (!R || !R->isLocalClass() || !R->isLocalClass()->isExternallyVisible() ||

3700 R->isDependentType())

3701 return true;

3702 for (auto *TmpD : R->decls())

3703 if (auto *T = dyn_cast(TmpD))

3704 if (T->getAccess() != AS_private || R->hasFriends())

3706 return true;

3707}

3708}

3709

3714 .getReturnLoc();

3715}

3716

3720

3721

3722

3724 return false;

3725

3726 if (isa_and_nonnull(RetExpr)) {

3727

3728

3730 getCurLambda() ? diag::err_lambda_return_init_list

3731 : diag::err_auto_fn_return_init_list)

3733 return true;

3734 }

3735

3737

3738

3739

3740

3741 assert(AT->isDeduced() && "should have deduced to dependent type");

3742 return false;

3743 }

3744

3746

3747

3749 if (!RetExpr) {

3750

3751

3752

3753

3755 Diag(ReturnLoc, diag::err_auto_fn_return_void_but_not_auto)

3756 << OrigResultType.getType();

3757 return true;

3758 }

3759 RetExpr = &VoidVal;

3760 }

3761

3763 {

3764

3765

3766 auto RetExprLoc = RetExpr->getExprLoc();

3771 if (FindResult.Expression)

3772 TemplateSpecLoc = FindResult.Expression->getNameLoc();

3773 }

3776 OrigResultType, RetExpr, Deduced, Info, false,

3777 false, &FailedTSC);

3779 return true;

3780 switch (Res) {

3782 break;

3784 return true;

3786

3787

3788

3789

3792 Diag(ReturnLoc, diag::err_typecheck_missing_return_type_incompatible)

3794 else

3795 Diag(ReturnLoc, diag::err_auto_fn_different_deductions)

3798 return true;

3799 }

3800 default:

3801 Diag(RetExpr->getExprLoc(), diag::err_auto_fn_deduction_failure)

3804 return true;

3805 }

3806 }

3807

3808

3809

3810 LocalTypedefNameReferencer(*this).TraverseType(RetExpr->getType());

3811

3812

3815 Diag(FD->getLocation(), diag::err_kern_type_not_void_return)

3817 return true;

3818 }

3819

3821

3823

3824 return false;

3825}

3826

3829 Scope *CurScope) {

3830

3831

3833 RetValExp, nullptr, true);

3836

3837 if (getCurScope()->isInOpenACCComputeConstructScope())

3839 Diag(ReturnLoc, diag::err_acc_branch_in_out_compute_construct)

3840 << 1 << 0);

3841

3842

3846 "first coroutine location not set");

3847 Diag(ReturnLoc, diag::err_return_in_coroutine);

3850 }

3851

3852 CheckInvalidBuiltinCountedByRef(RetVal.get(), ReturnArgKind);

3853

3857 return R;

3858

3860 const_cast<VarDecl *>(cast(R.get())->getNRVOCandidate());

3861

3863

3865

3866 return R;

3867}

3868

3870 const Expr *E) {

3872 return false;

3875 return false;

3878 return true;

3879 }

3880 return false;

3881}

3882

3884 bool AllowRecovery) {

3885

3888

3889

3890

3891

3892 bool SupressSimplerImplicitMoves =

3897

3900 SupressSimplerImplicitMoves);

3901

3904 const AttrVec *Attrs = nullptr;

3905 bool isObjCMethod = false;

3906

3912 Diag(ReturnLoc, diag::warn_noreturn_function_has_return_expr) << FD;

3913 if (FD->isMain() && RetValExp)

3914 if (isa(RetValExp))

3915 Diag(ReturnLoc, diag::warn_main_returns_bool_literal)

3917 if (FD->hasAttr() && RetValExp) {

3918 if (const auto *RT = dyn_cast(FnRetType.getCanonicalType())) {

3920 Diag(RetValExp->getBeginLoc(), diag::warn_cmse_nonsecure_union) << 1;

3921 }

3922 }

3925 isObjCMethod = true;

3929

3930

3931

3934 }

3935 } else

3937

3938 if (RetValExp) {

3939 const auto *ATy = dyn_cast(RetValExp->getType());

3940 if (ATy && ATy->getElementType().isWebAssemblyReferenceType()) {

3941 Diag(ReturnLoc, diag::err_wasm_table_art) << 1;

3943 }

3944 }

3945

3946

3947

3948 if (ExprEvalContexts.back().isDiscardedStatementContext() &&

3950 if (RetValExp) {

3955 RetValExp = ER.get();

3956 }

3958 nullptr);

3959 }

3960

3961

3962

3966

3967

3968

3969

3973 if (!AllowRecovery)

3975

3976 if (RetValExp) {

3977

3978

3981 AT->isDeduced() ? FnRetType : QualType());

3982 if (Recovery.isInvalid())

3984 RetValExp = Recovery.get();

3985 } else {

3986

3987 }

3988 } else {

3990 }

3991 }

3992 }

3994

3995 bool HasDependentReturnType = FnRetType->isDependentType();

3996

3999 if (RetValExp) {

4000 if (auto *ILE = dyn_cast(RetValExp)) {

4001

4002

4003

4005 int FunctionKind = 0;

4006 if (isa(CurDecl))

4007 FunctionKind = 1;

4008 else if (isa(CurDecl))

4009 FunctionKind = 2;

4010 else if (isa(CurDecl))

4011 FunctionKind = 3;

4012

4013 Diag(ReturnLoc, diag::err_return_init_list)

4014 << CurDecl << FunctionKind << RetValExp->getSourceRange();

4015

4016

4017 RetValExp = AllowRecovery

4019 ILE->getRBraceLoc(), ILE->inits())

4021 : nullptr;

4023

4024 unsigned D = diag::ext_return_has_expr;

4027 if (isa(CurDecl) ||

4028 isa(CurDecl))

4029 D = diag::err_ctor_dtor_returns_void;

4030 else

4031 D = diag::ext_return_has_void_expr;

4032 }

4033 else {

4036 if (Result.isInvalid())

4038 RetValExp = Result.get();

4041 }

4042

4043 if (D == diag::err_ctor_dtor_returns_void) {

4045 Diag(ReturnLoc, D) << CurDecl << isa(CurDecl)

4047 }

4048

4049 else if (D != diag::ext_return_has_void_expr ||

4052

4053 int FunctionKind = 0;

4054 if (isa(CurDecl))

4055 FunctionKind = 1;

4056 else if (isa(CurDecl))

4057 FunctionKind = 2;

4058 else if (isa(CurDecl))

4059 FunctionKind = 3;

4060

4061 Diag(ReturnLoc, D)

4062 << CurDecl << FunctionKind << RetValExp->getSourceRange();

4063 }

4064 }

4065

4066 if (RetValExp) {

4071 RetValExp = ER.get();

4072 }

4073 }

4074

4076 nullptr);

4077 } else if (!RetValExp && !HasDependentReturnType) {

4079

4081

4083

4084 Diag(ReturnLoc, diag::err_constexpr_return_missing_expr)

4087 } else {

4088

4089

4090 unsigned DiagID = getLangOpts().C99 ? diag::ext_return_missing_expr

4091 : diag::warn_return_missing_expr;

4092

4093

4095 "Not in a FunctionDecl or ObjCMethodDecl?");

4096 bool IsMethod = FD == nullptr;

4098 IsMethod ? cast(getCurMethodDecl()) : cast(FD);

4099 Diag(ReturnLoc, DiagID) << ND << IsMethod;

4100 }

4101

4103 nullptr);

4104 } else {

4105 assert(RetValExp || HasDependentReturnType);

4106 QualType RetType = RelatedRetType.isNull() ? FnRetType : RelatedRetType;

4107

4108

4109

4110

4111

4112

4113

4114 if (!HasDependentReturnType && !RetValExp->isTypeDependent()) {

4115

4119 Entity, NRInfo, RetValExp, SupressSimplerImplicitMoves);

4120 if (Res.isInvalid() && AllowRecovery)

4122 RetValExp->getEndLoc(), RetValExp, RetType);

4124

4126 }

4128

4129

4130

4131

4132

4133 if (!RelatedRetType.isNull()) {

4135 FnRetType);

4138

4140 }

4142 }

4143

4144 CheckReturnValExpr(RetValExp, FnRetType, ReturnLoc, isObjCMethod, Attrs,

4146 }

4147

4148 if (RetValExp) {

4153 RetValExp = ER.get();

4154 }

4156 }

4157

4158

4159

4160 if (Result->getNRVOCandidate())

4162

4163 if (FunctionScopes.back()->FirstReturnLoc.isInvalid())

4165

4167}

4168

4171 Stmt *HandlerBlock) {

4172

4174 CXXCatchStmt(CatchLoc, cast_or_null(ExDecl), HandlerBlock);

4175}

4176

4177namespace {

4178class CatchHandlerType {

4180 LLVM_PREFERRED_TYPE(bool)

4181 unsigned IsPointer : 1;

4182

4183

4184

4185 friend struct llvm::DenseMapInfo;

4186 enum Unique { ForDenseMap };

4187 CatchHandlerType(QualType QT, Unique) : QT(QT), IsPointer(false) {}

4188

4189public:

4190

4191

4192

4193 CatchHandlerType(QualType Q) : QT(Q), IsPointer(false) {

4195 IsPointer = true;

4196

4200 }

4201

4202

4203

4204

4205 CatchHandlerType(QualType QT, bool IsPointer)

4206 : QT(QT), IsPointer(IsPointer) {}

4207

4208 QualType underlying() const { return QT; }

4209 bool isPointer() const { return IsPointer; }

4210

4211 friend bool operator==(const CatchHandlerType &LHS,

4212 const CatchHandlerType &RHS) {

4213

4214 if (LHS.IsPointer != RHS.IsPointer)

4215 return false;

4216

4217 return LHS.QT == RHS.QT;

4218 }

4219};

4220}

4221

4222namespace llvm {

4223template <> struct DenseMapInfo {

4225 return CatchHandlerType(DenseMapInfo::getEmptyKey(),

4226 CatchHandlerType::ForDenseMap);

4227 }

4228

4230 return CatchHandlerType(DenseMapInfo::getTombstoneKey(),

4231 CatchHandlerType::ForDenseMap);

4232 }

4233

4235 return DenseMapInfo::getHashValue(Base.underlying());

4236 }

4237

4238 static bool isEqual(const CatchHandlerType &LHS,

4239 const CatchHandlerType &RHS) {

4240 return LHS == RHS;

4241 }

4242};

4243}

4244

4245namespace {

4246class CatchTypePublicBases {

4247 const llvm::DenseMap<QualType, CXXCatchStmt *> &TypesToCheck;

4248

4252

4253public:

4254 CatchTypePublicBases(const llvm::DenseMap<QualType, CXXCatchStmt *> &T,

4256 : TypesToCheck(T), FoundHandler(nullptr), TestAgainstType(QT) {}

4257

4258 CXXCatchStmt *getFoundHandler() const { return FoundHandler; }

4259 QualType getFoundHandlerType() const { return FoundHandlerType; }

4260

4262 if (S->getAccessSpecifier() == AccessSpecifier::AS_public) {

4263 QualType Check = S->getType().getCanonicalType();

4264 const auto &M = TypesToCheck;

4265 auto I = M.find(Check);

4266 if (I != M.end()) {

4267

4268

4269

4270

4271

4272

4273

4274

4275

4276

4277 if (I->second->getCaughtType()->isPointerType() ==

4279 FoundHandler = I->second;

4280 FoundHandlerType = Check;

4281 return true;

4282 }

4283 }

4284 }

4285 return false;

4286 }

4287};

4288}

4289

4293 const bool IsOpenMPGPUTarget =

4294 getLangOpts().OpenMPIsTargetDevice && (T.isNVPTX() || T.isAMDGCN());

4295

4296

4297 if (!IsOpenMPGPUTarget && getLangOpts().CXXExceptions &&

4299

4300 targetDiag(TryLoc, diag::err_exceptions_disabled) << "try";

4301 }

4302

4303

4304

4305 if (IsOpenMPGPUTarget)

4306 targetDiag(TryLoc, diag::warn_try_not_valid_on_target) << T.str();

4307

4308

4311 << "try" << llvm::to_underlying(CUDA().CurrentTarget());

4312

4314 Diag(TryLoc, diag::err_omp_simd_region_cannot_use_stmt) << "try";

4315

4317

4318

4320 Diag(TryLoc, diag::err_mixing_cxx_try_seh_try) << 0;

4321 Diag(FSI->FirstSEHTryLoc, diag::note_conflicting_try_here) << "'__try'";

4322 }

4323

4324 const unsigned NumHandlers = Handlers.size();

4325 assert(!Handlers.empty() &&

4326 "The parser shouldn't call this if there are no handlers.");

4327

4328 llvm::DenseMap<QualType, CXXCatchStmt *> HandledBaseTypes;

4329 llvm::DenseMap<CatchHandlerType, CXXCatchStmt *> HandledTypes;

4330 for (unsigned i = 0; i < NumHandlers; ++i) {

4331 CXXCatchStmt *H = cast(Handlers[i]);

4332

4333

4334

4335

4337 if (i < NumHandlers - 1)

4339 continue;

4341 continue;

4342

4343

4344

4345

4347

4348

4349

4350

4351 QualType Underlying = HandlerCHT.underlying();

4353 if (!RD->hasDefinition())

4354 continue;

4355

4356

4357

4358

4359

4361 Paths.setOrigin(RD);

4362 CatchTypePublicBases CTPB(HandledBaseTypes,

4364 if (RD->lookupInBases(CTPB, Paths)) {

4365 const CXXCatchStmt *Problem = CTPB.getFoundHandler();

4366 if (!Paths.isAmbiguous(

4369 diag::warn_exception_caught_by_earlier_handler)

4372 diag::note_previous_exception_handler)

4374 }

4375 }

4376

4377

4378

4380 }

4381

4382

4383

4384 auto R = HandledTypes.insert(

4386 if (!R.second) {

4387 const CXXCatchStmt *Problem = R.first->second;

4389 diag::warn_exception_caught_by_earlier_handler)

4392 diag::note_previous_exception_handler)

4394 }

4395 }

4396

4398

4400 Handlers);

4401}

4402

4404 Stmt *TryBlock, Stmt *Handler) {

4405 assert(TryBlock && Handler);

4406

4408

4409

4410

4413 Diag(TryLoc, diag::err_mixing_cxx_try_seh_try) << FSI->FirstTryType;

4416 ? "'try'"

4417 : "'@try'");

4418 }

4419 }

4420

4422

4423

4424

4428 FunctionDecl *FD = dyn_cast_or_null(DC);

4429 if (FD)

4431 else

4432 Diag(TryLoc, diag::err_seh_try_outside_functions);

4433

4434

4436 Diag(TryLoc, diag::err_seh_try_unsupported);

4437

4439}

4440

4443 assert(FilterExpr && Block);

4447 Diag(FilterExpr->getExprLoc(), diag::err_filter_expression_integral)

4448 << FTy);

4449 }

4451}

4452

4455}

4456

4459}

4460

4465}

4466

4469 Scope *SEHTryParent = CurScope;

4470 while (SEHTryParent && !SEHTryParent->isSEHTryScope())

4471 SEHTryParent = SEHTryParent->getParent();

4472 if (!SEHTryParent)

4473 return StmtError(Diag(Loc, diag::err_ms___leave_not_in___try));

4475

4477}

4478

4480 bool IsIfExists,

4483 Stmt *Nested)

4484{

4486 QualifierLoc, NameInfo,

4487 cast(Nested));

4488}

4489

4490

4492 bool IsIfExists,

4495 Stmt *Nested) {

4499 Nested);

4500}

4501

4504 unsigned NumParams) {

4508

4512 nullptr);

4513 else

4515 nullptr);

4516

4521

4522 assert(NumParams > 0 && "CapturedStmt requires context parameter");

4525 return RD;

4526}

4527

4528static bool

4534 continue;

4535

4536

4539

4540

4541

4542

4543

4545

4546

4551 Captures.push_back(

4553 } else {

4555

4559

4565 }

4566 CaptureInits.push_back(Init.get());

4567 }

4568 return false;

4569}

4570

4573 unsigned NumParams) {

4576

4577

4581 auto *Param =

4585

4587

4588

4590

4591 if (CurScope)

4593 else

4595

4598 ExprEvalContexts.back().InImmediateEscalatingFunctionContext = false;

4599}

4600

4604 unsigned OpenMPCaptureLevel) {

4607

4608

4610 bool ContextIsFound = false;

4611 unsigned ParamNum = 0;

4613 E = Params.end();

4614 I != E; ++I, ++ParamNum) {

4615 if (I->second.isNull()) {

4616 assert(!ContextIsFound &&

4617 "null type has been found already for '__context' parameter");

4622 auto *Param =

4627 ContextIsFound = true;

4628 } else {

4630 auto *Param =

4634 CD->setParam(ParamNum, Param);

4635 }

4636 }

4637 assert(ContextIsFound && "no null type for '__context' parameter");

4638 if (!ContextIsFound) {

4639

4642 auto *Param =

4647 }

4648

4650

4651 if (CurScope)

4653 else

4655

4658}

4659

4666

4669

4673}

4674

4676

4677

4683

4688

4691

4694 Captures, CaptureInits, CD, RD);

4695

4698

4699 return Res;

4700}

Defines the clang::ASTContext interface.

This file provides some common utility functions for processing Lambda related AST Constructs.

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

llvm::MachO::Record Record

Defines the clang::Preprocessor interface.

static std::string toString(const clang::SanitizerSet &Sanitizers)

Produce a string containing comma-separated names of sanitizers in Sanitizers set.

This file declares semantic analysis for CUDA constructs.

This file declares semantic analysis for Objective-C.

This file declares semantic analysis for OpenMP constructs and clauses.

static bool CmpEnumVals(const std::pair< llvm::APSInt, EnumConstantDecl * > &lhs, const std::pair< llvm::APSInt, EnumConstantDecl * > &rhs)

CmpEnumVals - Comparison predicate for sorting enumeration values.

static bool FinishForRangeVarDecl(Sema &SemaRef, VarDecl *Decl, Expr *Init, SourceLocation Loc, int DiagID)

Finish building a variable declaration for a for-range statement.

static bool CmpCaseVals(const std::pair< llvm::APSInt, CaseStmt * > &lhs, const std::pair< llvm::APSInt, CaseStmt * > &rhs)

CmpCaseVals - Comparison predicate for sorting case values.

SmallVector< std::pair< llvm::APSInt, EnumConstantDecl * >, 64 > EnumValsTy

static bool ShouldDiagnoseSwitchCaseNotInEnum(const Sema &S, const EnumDecl *ED, const Expr *CaseExpr, EnumValsTy::iterator &EI, EnumValsTy::iterator &EIEnd, const llvm::APSInt &Val)

Returns true if we should emit a diagnostic about this case expression not being a part of the enum u...

static bool DiagnoseUnusedComparison(Sema &S, const Expr *E)

Diagnose unused comparisons, both builtin and overloaded operators.

static bool EqEnumVals(const std::pair< llvm::APSInt, EnumConstantDecl * > &lhs, const std::pair< llvm::APSInt, EnumConstantDecl * > &rhs)

EqEnumVals - Comparison preficate for uniqing enumeration values.

static bool hasDeducedReturnType(FunctionDecl *FD)

Determine whether the declared return type of the specified function contains 'auto'.

static bool ObjCEnumerationCollection(Expr *Collection)

static void DiagnoseForRangeConstVariableCopies(Sema &SemaRef, const VarDecl *VD)

static StmtResult RebuildForRangeWithDereference(Sema &SemaRef, Scope *S, SourceLocation ForLoc, SourceLocation CoawaitLoc, Stmt *InitStmt, Stmt *LoopVarDecl, SourceLocation ColonLoc, Expr *Range, SourceLocation RangeLoc, SourceLocation RParenLoc)

Speculatively attempt to dereference an invalid range expression.

static void checkEnumTypesInSwitchStmt(Sema &S, const Expr *Cond, const Expr *Case)

static void DiagnoseForRangeReferenceVariableCopies(Sema &SemaRef, const VarDecl *VD, QualType RangeInitType)

static void DiagnoseForRangeVariableCopies(Sema &SemaRef, const CXXForRangeStmt *ForStmt)

DiagnoseForRangeVariableCopies - Diagnose three cases and fixes for them.

static bool CheckSimplerImplicitMovesMSVCWorkaround(const Sema &S, const Expr *E)

static bool VerifyInitializationSequenceCXX98(const Sema &S, const InitializationSequence &Seq)

Verify that the initialization sequence that was picked for the first overload resolution is permissi...

static QualType GetTypeBeforeIntegralPromotion(const Expr *&E)

GetTypeBeforeIntegralPromotion - Returns the pre-promotion type of potentially integral-promoted expr...

static Sema::ForRangeStatus BuildNonArrayForRange(Sema &SemaRef, Expr *BeginRange, Expr *EndRange, QualType RangeType, VarDecl *BeginVar, VarDecl *EndVar, SourceLocation ColonLoc, SourceLocation CoawaitLoc, OverloadCandidateSet *CandidateSet, ExprResult *BeginExpr, ExprResult *EndExpr, BeginEndFunction *BEF)

Create the initialization, compare, and increment steps for the range-based for loop expression.

static bool hasTrivialABIAttr(QualType VariableType)

Determines whether the VariableType's declaration is a record with the clang::trivial_abi attribute.

static void AdjustAPSInt(llvm::APSInt &Val, unsigned BitWidth, bool IsSigned)

static bool buildCapturedStmtCaptureList(Sema &S, CapturedRegionScopeInfo *RSI, SmallVectorImpl< CapturedStmt::Capture > &Captures, SmallVectorImpl< Expr * > &CaptureInits)

static bool DiagnoseNoDiscard(Sema &S, const NamedDecl *OffendingDecl, const WarnUnusedResultAttr *A, SourceLocation Loc, SourceRange R1, SourceRange R2, bool IsCtor)

static void checkCaseValue(Sema &S, SourceLocation Loc, const llvm::APSInt &Val, unsigned UnpromotedWidth, bool UnpromotedSign)

Check the specified case value is in range for the given unpromoted switch type.

static void CheckJumpOutOfSEHFinally(Sema &S, SourceLocation Loc, const Scope &DestScope)

Defines the Objective-C statement AST node classes.

enum clang::format::@1338::AnnotatingParser::Context::@353 ContextType

Defines the clang::TypeLoc interface and its subclasses.

Allows QualTypes to be sorted and hence used in maps and sets.

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

SourceManager & getSourceManager()

CharUnits getTypeAlignInChars(QualType T) const

Return the ABI-specified alignment of a (complete) type T, in characters.

unsigned getIntWidth(QualType T) const

QualType getObjCInterfaceType(const ObjCInterfaceDecl *Decl, ObjCInterfaceDecl *PrevDecl=nullptr) const

getObjCInterfaceType - Return the unique reference to the type for the specified ObjC interface decl.

QualType getAutoRRefDeductType() const

C++11 deduction pattern for 'auto &&' type.

QualType getTagDeclType(const TagDecl *Decl) const

Return the unique reference to the type for the specified TagDecl (struct/union/class/enum) decl.

bool hasSameType(QualType T1, QualType T2) const

Determine whether the given types T1 and T2 are equivalent.

QualType getPointerType(QualType T) const

Return the uniqued reference to the type for a pointer to the specified type.

QualType getLValueReferenceType(QualType T, bool SpelledAsLValue=true) const

Return the uniqued reference to the type for an lvalue reference to the specified type.

QualType getTypeDeclType(const TypeDecl *Decl, const TypeDecl *PrevDecl=nullptr) const

Return the unique reference to the type for the specified type declaration.

QualType getPointerDiffType() const

Return the unique type for "ptrdiff_t" (C99 7.17) defined in <stddef.h>.

TypeSourceInfo * getTrivialTypeSourceInfo(QualType T, SourceLocation Loc=SourceLocation()) const

Allocate a TypeSourceInfo where all locations have been initialized to a given location,...

QualType getObjCObjectPointerType(QualType OIT) const

Return a ObjCObjectPointerType type for the given ObjCObjectType.

CharUnits getDeclAlign(const Decl *D, bool ForAlignof=false) const

Return a conservative estimate of the alignment of the specified decl D.

bool hasSameUnqualifiedType(QualType T1, QualType T2) const

Determine whether the given types are equivalent after cvr-qualifiers have been removed.

uint64_t getTypeSize(QualType T) const

Return the size of the specified (complete) type T, in bits.

bool hasSimilarType(QualType T1, QualType T2) const

Determine if two types are similar, according to the C++ rules.

const TargetInfo & getTargetInfo() const

QualType getAutoDeductType() const

C++11 deduction pattern for 'auto' type.

void adjustDeducedFunctionResultType(FunctionDecl *FD, QualType ResultType)

Change the result type of a function type once it is deduced.

Represents an array type, per C99 6.7.5.2 - Array Declarators.

Attr - This represents one attribute.

SourceLocation getLocation() const

SourceRange getRange() const

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

Represents a C++11 auto or C++14 decltype(auto) type, possibly constrained by a type-constraint.

bool isDecltypeAuto() const

BinaryConditionalOperator - The GNU extension to the conditional operator which allows the middle ope...

A builtin binary operation expression such as "x + y" or "x <= y".

BreakStmt - This represents a break.

CStyleCastExpr - An explicit cast in C (C99 6.5.4) or a C-style cast in C++ (C++ [expr....

Represents a path from a specific derived class (which is not represented as part of the path) to a p...

BasePaths - Represents the set of paths from a derived class to one of its (direct or indirect) bases...

Represents a base class of a C++ class.

Represents binding an expression to a temporary.

A boolean literal, per ([C++ lex.bool] Boolean literals).

CXXCatchStmt - This represents a C++ catch block.

SourceLocation getBeginLoc() const LLVM_READONLY

VarDecl * getExceptionDecl() const

QualType getCaughtType() const

Represents a call to a C++ constructor.

Represents a C++ constructor within a class.

Represents a C++ conversion function within a class.

CXXForRangeStmt - This represents C++0x [stmt.ranged]'s ranged for statement, represented as 'for (ra...

Represents an explicit C++ type conversion that uses "functional" notation (C++ [expr....

Represents a call to a member function that may be written either with member call syntax (e....

Represents a static or instance method of a struct/union/class.

A call to an overloaded operator written using operator syntax.

Represents a C++ struct/union/class.

static CXXRecordDecl * Create(const ASTContext &C, TagKind TK, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, CXXRecordDecl *PrevDecl=nullptr, bool DelayTypeCreation=false)

An expression "T()" which creates an rvalue of a non-class type T.

Represents a C++ nested-name-specifier or a global scope specifier.

NestedNameSpecifierLoc getWithLocInContext(ASTContext &Context) const

Retrieve a nested-name-specifier with location information, copied into the given AST context.

static CXXTryStmt * Create(const ASTContext &C, SourceLocation tryLoc, CompoundStmt *tryBlock, ArrayRef< Stmt * > handlers)

CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).

static CanQual< Type > CreateUnsafe(QualType Other)

Builds a canonical type from a QualType.

QualType withConst() const

Retrieves a version of this type with const applied.

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

static DeclContext * castToDeclContext(const CapturedDecl *D)

void setContextParam(unsigned i, ImplicitParamDecl *P)

void setParam(unsigned i, ImplicitParamDecl *P)

static CapturedDecl * Create(ASTContext &C, DeclContext *DC, unsigned NumParams)

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

This captures a statement into a function.

Stmt * getCapturedStmt()

Retrieve the statement being captured.

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

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.

CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...

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

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

ConditionalOperator - The ?: ternary operator.

ConstEvaluatedExprVisitor - This class visits 'const Expr *'s.

Represents the canonical version of C arrays with a specified constant size.

ContinueStmt - This represents a continue.

DeclContext - This is used only as base class of specific decl types that can act as declaration cont...

DeclContext * getParent()

getParent - Returns the containing DeclContext.

bool isFileContext() const

bool isDependentContext() const

Determines whether this context is dependent on a template parameter.

void addDecl(Decl *D)

Add the declaration D into this context.

bool isStdNamespace() const

bool isFunctionOrMethod() const

void addHiddenDecl(Decl *D)

Add the declaration D to this context without modifying any lookup tables.

bool isSingleDecl() const

A reference to a declared variable, function, enum, etc.

SourceLocation getLocation() const

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

bool isSingleDecl() const

isSingleDecl - This method returns true if this DeclStmt refers to a single Decl.

const Decl * getSingleDecl() const

SourceLocation getBeginLoc() const LLVM_READONLY

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

void setInvalidDecl(bool Invalid=true)

setInvalidDecl - Indicates the Decl had a semantic error.

void markUsed(ASTContext &C)

Mark the declaration used, in the sense of odr-use.

static Decl * castFromDeclContext(const DeclContext *)

bool isInvalidDecl() const

SourceLocation getLocation() const

void setImplicit(bool I=true)

void setLocation(SourceLocation L)

DeclContext * getDeclContext()

SourceLocation getTypeSpecEndLoc() const

SourceLocation getTypeSpecStartLoc() const

SourceLocation getBeginLoc() const LLVM_READONLY

TypeSourceInfo * getTypeSourceInfo() const

QualType getDeducedType() const

Get the type deduced for this placeholder type, or null if it has not been deduced.

SourceLocation getDefaultLoc() const

DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)

Issue the message to the client.

bool isIgnored(unsigned DiagID, SourceLocation Loc) const

Determine whether the diagnostic is known to be ignored.

DoStmt - This represents a 'do/while' stmt.

Recursive AST visitor that supports extension via dynamic dispatch.

enumerator_range enumerators() const

bool isClosed() const

Returns true if this enum is either annotated with enum_extensibility(closed) or isn't annotated with...

bool isClosedNonFlag() const

Returns true if this enum is annotated with neither flag_enum nor enum_extensibility(open).

A helper class that allows the use of isa/cast/dyncast to detect TagType objects of enums.

EnumDecl * getDecl() const

EvaluatedExprVisitor - This class visits 'Expr *'s.

This represents one expression.

bool EvaluateAsInt(EvalResult &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects, bool InConstantContext=false) const

EvaluateAsInt - Return true if this is a constant which we can fold and convert to an integer,...

@ SE_AllowSideEffects

Allow any unmodeled side effect.

Expr * IgnoreParenCasts() LLVM_READONLY

Skip past any parentheses and casts which might surround this expression until reaching a fixed point...

bool isUnusedResultAWarning(const Expr *&WarnExpr, SourceLocation &Loc, SourceRange &R1, SourceRange &R2, ASTContext &Ctx) const

isUnusedResultAWarning - Return true if this immediate expression should be warned about if the resul...

bool isValueDependent() const

Determines whether the value of this expression depends on.

bool isTypeDependent() const

Determines whether the type of this expression depends on.

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

EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded integer.

Expr * IgnoreParenImpCasts() LLVM_READONLY

Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...

bool containsErrors() const

Whether this expression contains subexpressions which had errors, e.g.

Expr * IgnoreParens() LLVM_READONLY

Skip past any parentheses which might surround this expression until reaching a fixed point.

Decl * getReferencedDeclOfCallee()

bool isInstantiationDependent() const

Whether this expression is instantiation-dependent, meaning that it depends in some way on.

bool isIntegerConstantExpr(const ASTContext &Ctx, SourceLocation *Loc=nullptr) const

Expr * IgnoreImpCasts() LLVM_READONLY

Skip past any implicit casts which might surround this expression until reaching a fixed point.

SourceLocation getExprLoc() const LLVM_READONLY

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

bool isKnownToHaveBooleanValue(bool Semantic=true) const

isKnownToHaveBooleanValue - Return true if this is an integer expression that is known to return 0 or...

Represents difference between two FPOptions values.

FPOptionsOverride getChangesFrom(const FPOptions &Base) const

Return difference with the given option set.

Represents a member of a struct/union/class.

static FixItHint CreateReplacement(CharSourceRange RemoveRange, StringRef Code)

Create a code modification hint that replaces the given source range with the given code string.

static FixItHint CreateRemoval(CharSourceRange RemoveRange)

Create a code modification hint that removes the given source range.

static FixItHint CreateInsertion(SourceLocation InsertionLoc, StringRef Code, bool BeforePreviousInsertions=false)

Create a code modification hint that inserts the given code string at a specific location.

ForStmt - This represents a 'for (init;cond;inc)' stmt.

SourceLocation getRParenLoc() const

SourceLocation getBeginLoc() const

FullExpr - Represents a "full-expression" node.

Represents a function declaration or definition.

const ParmVarDecl * getParamDecl(unsigned i) const

void setUsesSEHTry(bool UST)

bool isNoReturn() const

Determines whether this function is known to be 'noreturn', through an attribute on its declaration o...

QualType getReturnType() const

bool isConstexpr() const

Whether this is a (C++11) constexpr function or constexpr constructor.

bool isMain() const

Determines whether this function is "main", which is the entry point into an executable program.

SourceRange getSourceRange() const override LLVM_READONLY

Source range that this declaration covers.

bool isOverloadedOperator() const

Whether this function declaration represents an C++ overloaded operator, e.g., "operator+".

OverloadedOperatorKind getOverloadedOperator() const

getOverloadedOperator - Which C++ overloaded operator this function represents, if any.

Represents a prototype with parameter type info, e.g.

Declaration of a template function.

FunctionType - C99 6.7.5.3 - Function Declarators.

static StringRef getNameForCallConv(CallingConv CC)

bool getNoReturnAttr() const

Determine whether this function type includes the GNU noreturn attribute.

QualType getReturnType() const

GNUNullExpr - Implements the GNU __null extension, which is a name for a null pointer constant that h...

GotoStmt - This represents a direct goto.

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

IdentifierInfo & get(StringRef Name)

Return the identifier token info for the specified named identifier.

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.

ImaginaryLiteral - We support imaginary integer and floating point literals, like "1....

ImplicitCastExpr - Allows us to explicitly represent implicit type conversions, which have no direct ...

static ImplicitCastExpr * Create(const ASTContext &Context, QualType T, CastKind Kind, Expr *Operand, const CXXCastPath *BasePath, ExprValueKind Cat, FPOptionsOverride FPO)

static ImplicitParamDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation IdLoc, IdentifierInfo *Id, QualType T, ImplicitParamKind ParamKind)

Create implicit parameter.

IndirectGotoStmt - This represents an indirect goto.

static InitializationKind CreateCopy(SourceLocation InitLoc, SourceLocation EqualLoc, bool AllowExplicitConvs=false)

Create a copy initialization.

Describes the sequence of initializations required to initialize a given object or reference with a s...

Describes an entity that is being initialized.

static InitializedEntity InitializeResult(SourceLocation ReturnLoc, QualType Type)

Create the initialization entity for the result of a function.

static InitializedEntity InitializeRelatedResult(ObjCMethodDecl *MD, QualType Type)

Create the initialization entity for a related result.

unsigned allocateManglingNumber() const

static InitializedEntity InitializeVariable(VarDecl *Var)

Create the initialization entity for a variable.

static InitializedEntity InitializeParameter(ASTContext &Context, ParmVarDecl *Parm)

Create the initialization entity for a parameter.

static IntegerLiteral * Create(const ASTContext &C, const llvm::APInt &V, QualType type, SourceLocation l)

Returns a new integer literal with value 'V' and type 'type'.

Represents the declaration of a label.

void setLocStart(SourceLocation L)

LabelStmt * getStmt() const

void setStmt(LabelStmt *T)

bool isMSAsmLabel() const

LabelStmt - Represents a label, which has a substatement.

Represents the results of name lookup.

bool empty() const

Return true if no decls were found.

Representation of a Microsoft __if_exists or __if_not_exists statement with a dependent name.

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

Expr * getSubExpr() const

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

MemberExpr - [C99 6.5.2.3] Structure and Union Members.

A pointer to member type per C++ 8.3.3 - Pointers to members.

This represents a decl that may have a name.

IdentifierInfo * getIdentifier() const

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

DeclarationName getDeclName() const

Get the actual, stored name of the declaration, which may be a special name.

ReservedIdentifierStatus isReserved(const LangOptions &LangOpts) const

Determine if the declaration obeys the reserved identifier rules of the given language.

A C++ nested-name-specifier augmented with source location information.

NullStmt - This is the null statement ";": C99 6.8.3p3.

Represents Objective-C's collection statement.

An expression that sends a message to the given Objective-C object or class.

ObjCMethodDecl - Represents an instance or class method declaration.

bool hasRelatedResultType() const

Determine whether this method has a result type that is related to the message receiver's type.

QualType getReturnType() const

ObjCInterfaceDecl * getClassInterface()

Represents a pointer to an Objective C object.

Wrapper for void* pointer.

void * getAsOpaquePtr() const

OverloadCandidateSet - A set of overload candidates, used in C++ overload resolution (C++ 13....

@ CSK_Normal

Normal lookup.

void NoteCandidates(PartialDiagnosticAt PA, Sema &S, OverloadCandidateDisplayKind OCD, ArrayRef< Expr * > Args, StringRef Opc="", SourceLocation Loc=SourceLocation(), llvm::function_ref< bool(OverloadCandidate &)> Filter=[](OverloadCandidate &) { return true;})

When overload resolution fails, prints diagnostic messages containing the candidates in the candidate...

static FindResult find(Expr *E)

Finds the overloaded expression in the given expression E of OverloadTy.

ParenExpr - This represents a parenthesized expression, e.g.

Represents a parameter to a function.

ParsedAttributes - A collection of parsed attributes.

Wrapper for source info for pointers.

SourceLocation getStarLoc() const

IdentifierTable & getIdentifierTable()

PseudoObjectExpr - An expression which accesses a pseudo-object l-value.

ArrayRef< Expr * > semantics()

A (possibly-)qualified type.

bool isVolatileQualified() const

Determine whether this type is volatile-qualified.

QualType withRestrict() const

QualType withConst() const

bool isTriviallyCopyConstructibleType(const ASTContext &Context) const

Return true if this is a trivially copyable type.

bool isNull() const

Return true if this QualType doesn't point to a type yet.

QualType getNonReferenceType() const

If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...

QualType getCanonicalType() const

QualType getUnqualifiedType() const

Retrieve the unqualified variant of the given type, removing as little sugar as possible.

bool isConstQualified() const

Determine whether this type is const-qualified.

@ OCL_Strong

Assigning into this object requires the old value to be released and the new value to be retained.

Represents a struct/union/class.

static RecordDecl * Create(const ASTContext &C, TagKind TK, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, RecordDecl *PrevDecl=nullptr)

bool isOrContainsUnion() const

Returns whether this record is a union, or contains (at any nesting level) a union member.

virtual void completeDefinition()

Note that the definition of this type is now complete.

void setCapturedRecord()

Mark the record as a record for captured variables in CapturedStmt construct.

A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...

RecordDecl * getDecl() const

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

void setRetValue(Expr *E)

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

Create a return statement.

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

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

Represents a __leave statement.

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

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

const Scope * getFnParent() const

getFnParent - Return the closest scope that is a function body.

bool Contains(const Scope &rhs) const

Returns if rhs has a higher scope depth than this.

unsigned getFlags() const

getFlags - Return the flags for this scope.

Scope * getContinueParent()

getContinueParent - Return the closest scope that a continue statement would be affected by.

bool isSEHTryScope() const

Determine whether this scope is a SEH '__try' block.

Scope * getBreakParent()

getBreakParent - Return the closest scope that a break statement would be affected by.

const Scope * getParent() const

getParent - Return the scope that this is nested in.

void updateNRVOCandidate(VarDecl *VD)

@ SwitchScope

This is a scope that corresponds to a switch statement.

A generic diagnostic builder for errors which may or may not be deferred.

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

Emit a diagnostic.

PartialDiagnostic PDiag(unsigned DiagID=0)

Build a partial diagnostic.

SemaDiagnosticBuilder DiagIfDeviceCode(SourceLocation Loc, unsigned DiagID)

Creates a SemaDiagnosticBuilder that emits the diagnostic if the current context is "used as device c...

StmtResult ActOnObjCForCollectionStmt(SourceLocation ForColLoc, Stmt *First, Expr *collection, SourceLocation RParenLoc)

StmtResult FinishObjCForCollectionStmt(Stmt *ForCollection, Stmt *Body)

FinishObjCForCollectionStmt - Attach the body to a objective-C foreach statement.

bool inferObjCARCLifetime(ValueDecl *decl)

void ActOnOpenMPLoopInitialization(SourceLocation ForLoc, Stmt *Init)

Check if the current region is an OpenMP loop region and if it is, mark loop control variable,...

void setOpenMPCaptureKind(FieldDecl *FD, const ValueDecl *D, unsigned Level)

Sets OpenMP capture kind (OMPC_private, OMPC_firstprivate, OMPC_map etc.) for FD based on DSA for the...

std::pair< VarDecl *, Expr * > get() const

RAII class used to determine whether SFINAE has trapped any errors that occur during template argumen...

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

ParsedType CreateParsedType(QualType T, TypeSourceInfo *TInfo)

Package the given type and TSI into a ParsedType.

SmallVector< Scope *, 2 > CurrentSEHFinally

Stack of active SEH __finally scopes. Can be empty.

LocalInstantiationScope * CurrentInstantiationScope

The current instantiation scope used to store local variables.

Scope * getCurScope() const

Retrieve the parser's current scope.

void DiagnoseDiscardedExprMarkedNodiscard(const Expr *E)

DiagnoseDiscardedExprMarkedNodiscard - Given an expression that is semantically a discarded-value exp...

void ProcessStmtAttributes(Stmt *Stmt, const ParsedAttributes &InAttrs, SmallVectorImpl< const Attr * > &OutAttrs)

Process the attributes before creating an attributed statement.

ExprResult ActOnUnaryOp(Scope *S, SourceLocation OpLoc, tok::TokenKind Op, Expr *Input, bool IsAfterAmp=false)

Unary Operators. 'Tok' is the token for the operator.

StmtResult BuildMSDependentExistsStmt(SourceLocation KeywordLoc, bool IsIfExists, NestedNameSpecifierLoc QualifierLoc, DeclarationNameInfo NameInfo, Stmt *Nested)

ExprResult IgnoredValueConversions(Expr *E)

IgnoredValueConversions - Given that an expression's result is syntactically ignored,...

@ LookupMemberName

Member name lookup, which finds the names of class/struct/union members.

bool ActOnCoroutineBodyStart(Scope *S, SourceLocation KwLoc, StringRef Keyword)

StmtResult BuildAttributedStmt(SourceLocation AttrsLoc, ArrayRef< const Attr * > Attrs, Stmt *SubStmt)

StmtResult ActOnSEHLeaveStmt(SourceLocation Loc, Scope *CurScope)

StmtResult ActOnForEachLValueExpr(Expr *E)

In an Objective C collection iteration statement: for (x in y) x can be an arbitrary l-value expressi...

void ActOnForEachDeclStmt(DeclGroupPtrTy Decl)

void PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext, Decl *LambdaContextDecl=nullptr, ExpressionEvaluationContextRecord::ExpressionKind Type=ExpressionEvaluationContextRecord::EK_Other)

ExprResult CheckBooleanCondition(SourceLocation Loc, Expr *E, bool IsConstexpr=false)

CheckBooleanCondition - Diagnose problems involving the use of the given expression as a boolean cond...

@ Switch

An integral condition for a 'switch' statement.

SmallVector< sema::FunctionScopeInfo *, 4 > FunctionScopes

Stack containing information about each of the nested function, block, and method scopes that are cur...

PoppedFunctionScopePtr PopFunctionScopeInfo(const sema::AnalysisBasedWarnings::Policy *WP=nullptr, const Decl *D=nullptr, QualType BlockType=QualType())

Pop a function (or block or lambda or captured region) scope from the stack.

bool checkAndRewriteMustTailAttr(Stmt *St, const Attr &MTA)

Check whether the given statement can have musttail applied to it, issuing a diagnostic and returning...

StmtResult ActOnGotoStmt(SourceLocation GotoLoc, SourceLocation LabelLoc, LabelDecl *TheDecl)

StmtResult ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp, Scope *CurScope)

void setFunctionHasBranchIntoScope()

ExprResult ActOnCaseExpr(SourceLocation CaseLoc, ExprResult Val)

ExprResult VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result, VerifyICEDiagnoser &Diagnoser, AllowFoldKind CanFold=NoFold)

VerifyIntegerConstantExpression - Verifies that an expression is an ICE, and reports the appropriate ...

StmtResult ActOnExprStmt(ExprResult Arg, bool DiscardedValue=true)

FieldDecl * BuildCaptureField(RecordDecl *RD, const sema::Capture &Capture)

Build a FieldDecl suitable to hold the given capture.

StmtResult BuildIfStmt(SourceLocation IfLoc, IfStatementKind StatementKind, SourceLocation LParenLoc, Stmt *InitStmt, ConditionResult Cond, SourceLocation RParenLoc, Stmt *ThenVal, SourceLocation ElseLoc, Stmt *ElseVal)

FunctionDecl * getCurFunctionDecl(bool AllowLambda=false) const

Returns a pointer to the innermost enclosing function, or nullptr if the current context is not insid...

ExprResult PerformContextualImplicitConversion(SourceLocation Loc, Expr *FromE, ContextualImplicitConverter &Converter)

Perform a contextual implicit conversion.

ExprResult UsualUnaryConversions(Expr *E)

UsualUnaryConversions - Performs various conversions that are common to most operators (C99 6....

void DiagnoseCommaOperator(const Expr *LHS, SourceLocation Loc)

Look for instances where it is likely the comma operator is confused with another operator.

ExprResult CheckSwitchCondition(SourceLocation SwitchLoc, Expr *Cond)

bool DiagIfReachable(SourceLocation Loc, ArrayRef< const Stmt * > Stmts, const PartialDiagnostic &PD)

Conditionally issue a diagnostic based on the statements's reachability analysis.

void FinalizeDeclaration(Decl *D)

FinalizeDeclaration - called by ParseDeclarationAfterDeclarator to perform any semantic actions neces...

void ActOnCapturedRegionError()

DeclGroupPtrTy ConvertDeclToDeclGroup(Decl *Ptr, Decl *OwnedType=nullptr)

ExprResult DefaultFunctionArrayLvalueConversion(Expr *E, bool Diagnose=true)

ASTContext & getASTContext() const

ExprResult BuildUnaryOp(Scope *S, SourceLocation OpLoc, UnaryOperatorKind Opc, Expr *Input, bool IsAfterAmp=false)

void PopExpressionEvaluationContext()

StmtResult ActOnSEHTryBlock(bool IsCXXTry, SourceLocation TryLoc, Stmt *TryBlock, Stmt *Handler)

ExprResult ImpCastExprToType(Expr *E, QualType Type, CastKind CK, ExprValueKind VK=VK_PRValue, const CXXCastPath *BasePath=nullptr, CheckedConversionKind CCK=CheckedConversionKind::Implicit)

ImpCastExprToType - If Expr is not of type 'Type', insert an implicit cast.

ObjCMethodDecl * getCurMethodDecl()

getCurMethodDecl - If inside of a method body, this returns a pointer to the method decl for the meth...

DeclRefExpr * BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK, SourceLocation Loc, const CXXScopeSpec *SS=nullptr)

ExprResult CheckConvertedConstantExpression(Expr *From, QualType T, llvm::APSInt &Value, CCEKind CCE)

void setFunctionHasIndirectGoto()

ExprResult BuildCaptureInit(const sema::Capture &Capture, SourceLocation ImplicitCaptureLoc, bool IsOpenMPMapping=false)

Initialize the given capture with a suitable expression.

StmtResult ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, Stmt *Body)

NamedReturnInfo getNamedReturnInfo(Expr *&E, SimplerImplicitMoveMode Mode=SimplerImplicitMoveMode::Normal)

Determine whether the given expression might be move-eligible or copy-elidable in either a (co_)retur...

std::unique_ptr< sema::FunctionScopeInfo, PoppedFunctionScopeDeleter > PoppedFunctionScopePtr

void DiagnoseUnusedExprResult(const Stmt *S, unsigned DiagID)

DiagnoseUnusedExprResult - If the statement passed in is an expression whose result is unused,...

FPOptions & getCurFPFeatures()

@ UPPC_Expression

An arbitrary expression.

const LangOptions & getLangOpts() const

StmtResult ActOnWhileStmt(SourceLocation WhileLoc, SourceLocation LParenLoc, ConditionResult Cond, SourceLocation RParenLoc, Stmt *Body)

bool DiagnoseUnexpandedParameterPack(SourceLocation Loc, TypeSourceInfo *T, UnexpandedParameterPackContext UPPC)

If the given type contains an unexpanded parameter pack, diagnose the error.

const LangOptions & LangOpts

sema::LambdaScopeInfo * getCurLambda(bool IgnoreNonLambdaCapturingScope=false)

Retrieve the current lambda scope info, if any.

void ActOnStartOfCompoundStmt(bool IsStmtExpr)

bool DeduceFunctionTypeFromReturnExpr(FunctionDecl *FD, SourceLocation ReturnLoc, Expr *RetExpr, const AutoType *AT)

Deduce the return type for a function from a returned expression, per C++1y [dcl.spec....

void MarkAnyDeclReferenced(SourceLocation Loc, Decl *D, bool MightBeOdrUse)

Perform marking for a reference to an arbitrary declaration.

TypeLoc getReturnTypeLoc(FunctionDecl *FD) const

StmtResult ActOnExprStmtError()

const VarDecl * getCopyElisionCandidate(NamedReturnInfo &Info, QualType ReturnType)

Updates given NamedReturnInfo's move-eligible and copy-elidable statuses, considering the function re...

NamedDecl * getCurFunctionOrMethodDecl() const

getCurFunctionOrMethodDecl - Return the Decl for the current ObjC method or C function we're in,...

StmtResult ActOnNullStmt(SourceLocation SemiLoc, bool HasLeadingEmptyMacro=false)

RecordDecl * CreateCapturedStmtRecordDecl(CapturedDecl *&CD, SourceLocation Loc, unsigned NumParams)

void ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope, CapturedRegionKind Kind, unsigned NumParams)

sema::FunctionScopeInfo * getCurFunction() const

void PushCompoundScope(bool IsStmtExpr)

DeclGroupPtrTy BuildDeclaratorGroup(MutableArrayRef< Decl * > Group)

BuildDeclaratorGroup - convert a list of declarations into a declaration group, performing any necess...

AssignConvertType CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &RHS, bool Diagnose=true, bool DiagnoseCFAudited=false, bool ConvertRHS=true)

Check assignment constraints for an assignment of RHS to LHSType.

void DiagnoseAssignmentEnum(QualType DstType, QualType SrcType, Expr *SrcExpr)

DiagnoseAssignmentEnum - Warn if assignment to enum is a constant integer not in the range of enum va...

ExprResult ActOnCoawaitExpr(Scope *S, SourceLocation KwLoc, Expr *E)

std::optional< sema::TemplateDeductionInfo * > isSFINAEContext() const

Determines whether we are currently in a context where template argument substitution failures are no...

bool findMacroSpelling(SourceLocation &loc, StringRef name)

Looks through the macro-expansion chain for the given location, looking for a macro expansion with th...

void DiagnoseEmptyStmtBody(SourceLocation StmtLoc, const Stmt *Body, unsigned DiagID)

Emit DiagID if statement located on StmtLoc has a suspicious null statement as a Body,...

void DiagnoseEmptyLoopBody(const Stmt *S, const Stmt *PossibleBody)

Warn if a for/while loop statement S, which is followed by PossibleBody, has a suspicious null statem...

ExprResult DefaultLvalueConversion(Expr *E)

DeclContext * CurContext

CurContext - This is the current declaration context of parsing.

DeclarationNameInfo GetNameFromUnqualifiedId(const UnqualifiedId &Name)

Retrieves the declaration name from a parsed unqualified-id.

bool isUnevaluatedContext() const

Determines whether we are currently in a context that is not evaluated as per C++ [expr] p5.

StmtResult ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp, NamedReturnInfo &NRInfo, bool SupressSimplerImplicitMoves)

ActOnCapScopeReturnStmt - Utility routine to type-check return statements for capturing scopes.

AssignConvertType

AssignConvertType - All of the 'assignment' semantic checks return this enum to indicate whether the ...

StmtResult ActOnCapturedRegionEnd(Stmt *S)

StmtResult ActOnForStmt(SourceLocation ForLoc, SourceLocation LParenLoc, Stmt *First, ConditionResult Second, FullExprArg Third, SourceLocation RParenLoc, Stmt *Body)

StmtResult ActOnIndirectGotoStmt(SourceLocation GotoLoc, SourceLocation StarLoc, Expr *DestExp)

ExprResult CheckPlaceholderExpr(Expr *E)

Check for operands with placeholder types and complain if found.

bool inTemplateInstantiation() const

Determine whether we are currently performing template instantiation.

SourceManager & getSourceManager() const

ExprResult PerformMoveOrCopyInitialization(const InitializedEntity &Entity, const NamedReturnInfo &NRInfo, Expr *Value, bool SupressSimplerImplicitMoves=false)

Perform the initialization of a potentially-movable value, which is the result of return value.

void ActOnInitializerError(Decl *Dcl)

ActOnInitializerError - Given that there was an error parsing an initializer for the given declaratio...

StmtResult ActOnCXXForRangeStmt(Scope *S, SourceLocation ForLoc, SourceLocation CoawaitLoc, Stmt *InitStmt, Stmt *LoopVar, SourceLocation ColonLoc, Expr *Collection, SourceLocation RParenLoc, BuildForRangeKind Kind, ArrayRef< MaterializeTemporaryExpr * > LifetimeExtendTemps={})

ActOnCXXForRangeStmt - Check and build a C++11 for-range statement.

StmtResult BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp, bool AllowRecovery=false)

ExprResult ActOnBinOp(Scope *S, SourceLocation TokLoc, tok::TokenKind Kind, Expr *LHSExpr, Expr *RHSExpr)

Binary Operators. 'Tok' is the token for the operator.

void PushCapturedRegionScope(Scope *RegionScope, CapturedDecl *CD, RecordDecl *RD, CapturedRegionKind K, unsigned OpenMPCaptureLevel=0)

void setFunctionHasMustTail()

void setFunctionHasBranchProtectedScope()

StmtResult ActOnFinishSEHFinallyBlock(SourceLocation Loc, Stmt *Block)

StmtResult ActOnContinueStmt(SourceLocation ContinueLoc, Scope *CurScope)

@ CCEK_CaseValue

Expression in a case label.

StmtResult BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation CoawaitLoc, Stmt *InitStmt, SourceLocation ColonLoc, Stmt *RangeDecl, Stmt *Begin, Stmt *End, Expr *Cond, Expr *Inc, Stmt *LoopVarDecl, SourceLocation RParenLoc, BuildForRangeKind Kind, ArrayRef< MaterializeTemporaryExpr * > LifetimeExtendTemps={})

BuildCXXForRangeStmt - Build or instantiate a C++11 for-range statement.

StmtResult ActOnDoStmt(SourceLocation DoLoc, Stmt *Body, SourceLocation WhileLoc, SourceLocation CondLParen, Expr *Cond, SourceLocation CondRParen)

StmtResult ActOnStartOfSwitchStmt(SourceLocation SwitchLoc, SourceLocation LParenLoc, Stmt *InitStmt, ConditionResult Cond, SourceLocation RParenLoc)

StmtResult ActOnMSDependentExistsStmt(SourceLocation KeywordLoc, bool IsIfExists, CXXScopeSpec &SS, UnqualifiedId &Name, Stmt *Nested)

@ PotentiallyEvaluated

The current expression is potentially evaluated at run time, which means that code may be generated t...

@ ImmediateFunctionContext

In addition of being constant evaluated, the current expression occurs in an immediate function conte...

StmtResult ActOnSEHExceptBlock(SourceLocation Loc, Expr *FilterExpr, Stmt *Block)

void ActOnAfterCompoundStatementLeadingPragmas()

StmtResult ActOnDeclStmt(DeclGroupPtrTy Decl, SourceLocation StartLoc, SourceLocation EndLoc)

bool RequireCompleteType(SourceLocation Loc, QualType T, CompleteTypeKind Kind, TypeDiagnoser &Diagnoser)

Ensure that the type T is a complete type.

void ActOnFields(Scope *S, SourceLocation RecLoc, Decl *TagDecl, ArrayRef< Decl * > Fields, SourceLocation LBrac, SourceLocation RBrac, const ParsedAttributesView &AttrList)

bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, bool InUnqualifiedLookup=false)

Perform qualified name lookup into a given context.

void DiscardCleanupsInEvaluationContext()

SmallVector< ExpressionEvaluationContextRecord, 8 > ExprEvalContexts

A stack of expression evaluation contexts.

void PushDeclContext(Scope *S, DeclContext *DC)

Set the current declaration context until it gets popped.

StmtResult ActOnAttributedStmt(const ParsedAttributes &AttrList, Stmt *SubStmt)

SourceManager & SourceMgr

DiagnosticsEngine & Diags

StmtResult ActOnBreakStmt(SourceLocation BreakLoc, Scope *CurScope)

void ActOnStartSEHFinallyBlock()

ExprResult PerformCopyInitialization(const InitializedEntity &Entity, SourceLocation EqualLoc, ExprResult Init, bool TopLevelOfInitList=false, bool AllowExplicit=false)

void ActOnAbortSEHFinallyBlock()

QualType SubstAutoTypeDependent(QualType TypeWithAuto)

@ BFRK_Check

Determining whether a for-range statement could be built.

@ BFRK_Build

Initial building of a for-range statement.

@ BFRK_Rebuild

Instantiation or recovery rebuild of a for-range statement.

StmtResult ActOnCXXCatchBlock(SourceLocation CatchLoc, Decl *ExDecl, Stmt *HandlerBlock)

ActOnCXXCatchBlock - Takes an exception declaration and a handler block and creates a proper catch ha...

void ActOnCaseStmtBody(Stmt *CaseStmt, Stmt *SubStmt)

ActOnCaseStmtBody - This installs a statement as the body of a case.

void AddInitializerToDecl(Decl *dcl, Expr *init, bool DirectInit)

AddInitializerToDecl - Adds the initializer Init to the declaration dcl.

bool DiagnoseAssignmentResult(AssignConvertType ConvTy, SourceLocation Loc, QualType DstType, QualType SrcType, Expr *SrcExpr, AssignmentAction Action, bool *Complained=nullptr)

DiagnoseAssignmentResult - Emit a diagnostic, if required, for the assignment conversion type specifi...

SemaDiagnosticBuilder targetDiag(SourceLocation Loc, unsigned DiagID, const FunctionDecl *FD=nullptr)

ExprResult CreateRecoveryExpr(SourceLocation Begin, SourceLocation End, ArrayRef< Expr * > SubExprs, QualType T=QualType())

Attempts to produce a RecoveryExpr after some AST node cannot be created.

StmtResult ActOnIfStmt(SourceLocation IfLoc, IfStatementKind StatementKind, SourceLocation LParenLoc, Stmt *InitStmt, ConditionResult Cond, SourceLocation RParenLoc, Stmt *ThenVal, SourceLocation ElseLoc, Stmt *ElseVal)

std::string getTemplateArgumentBindingsText(const TemplateParameterList *Params, const TemplateArgumentList &Args)

Produces a formatted string that describes the binding of template parameters to template arguments.

ExprResult ActOnUnaryExprOrTypeTraitExpr(SourceLocation OpLoc, UnaryExprOrTypeTrait ExprKind, bool IsType, void *TyOrEx, SourceRange ArgRange)

ActOnUnaryExprOrTypeTraitExpr - Handle sizeof(type) and sizeof expr and the same for alignof and __al...

ForRangeStatus BuildForRangeBeginEndCall(SourceLocation Loc, SourceLocation RangeLoc, const DeclarationNameInfo &NameInfo, LookupResult &MemberLookup, OverloadCandidateSet *CandidateSet, Expr *Range, ExprResult *CallExpr)

Build a call to 'begin' or 'end' for a C++11 for-range statement.

sema::CompoundScopeInfo & getCurCompoundScope() const

TemplateDeductionResult DeduceAutoType(TypeLoc AutoTypeLoc, Expr *Initializer, QualType &Result, sema::TemplateDeductionInfo &Info, bool DependentDeduction=false, bool IgnoreConstraints=false, TemplateSpecCandidateSet *FailedTSC=nullptr)

Deduce the type for an auto type-specifier (C++11 [dcl.spec.auto]p6)

void ActOnFinishOfCompoundStmt()

StmtResult ActOnCompoundStmt(SourceLocation L, SourceLocation R, ArrayRef< Stmt * > Elts, bool isStmtExpr)

bool IsValueInFlagEnum(const EnumDecl *ED, const llvm::APInt &Val, bool AllowMask) const

IsValueInFlagEnum - Determine if a value is allowed as part of a flag enum.

StmtResult ActOnLabelStmt(SourceLocation IdentLoc, LabelDecl *TheDecl, SourceLocation ColonLoc, Stmt *SubStmt)

StmtResult ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock, ArrayRef< Stmt * > Handlers)

ActOnCXXTryBlock - Takes a try compound-statement and a number of handlers and creates a try statemen...

StmtResult ActOnDefaultStmt(SourceLocation DefaultLoc, SourceLocation ColonLoc, Stmt *SubStmt, Scope *CurScope)

StmtResult ActOnCaseStmt(SourceLocation CaseLoc, ExprResult LHS, SourceLocation DotDotDotLoc, ExprResult RHS, SourceLocation ColonLoc)

StmtResult FinishCXXForRangeStmt(Stmt *ForRange, Stmt *Body)

FinishCXXForRangeStmt - Attach the body to a C++0x for-range statement.

ExprResult CorrectDelayedTyposInExpr(Expr *E, VarDecl *InitDecl=nullptr, bool RecoverUncorrectedTypos=false, llvm::function_ref< ExprResult(Expr *)> Filter=[](Expr *E) -> ExprResult { return E;})

Process any TypoExprs in the given Expr and its children, generating diagnostics as appropriate and r...

ExprResult ActOnFinishFullExpr(Expr *Expr, bool DiscardedValue)

Encodes a location in the source.

bool isValid() const

Return true if this is a valid SourceLocation object.

SourceLocation getLocWithOffset(IntTy Offset) const

Return a source location with the specified offset from this SourceLocation.

bool isMacroBodyExpansion(SourceLocation Loc) const

Tests whether the given source location represents the expansion of a macro body.

bool isInSystemMacro(SourceLocation loc) const

Returns whether Loc is expanded from a macro in a system header.

bool isInSystemHeader(SourceLocation Loc) const

Returns if a SourceLocation is in a system header.

A trivial tuple used to represent a source range.

SourceLocation getBegin() const

Stmt - This represents one statement.

SourceLocation getEndLoc() const LLVM_READONLY

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)

static const Attr * getLikelihoodAttr(const Stmt *S)

SourceLocation getBeginLoc() const LLVM_READONLY

const SwitchCase * getNextSwitchCase() const

SwitchStmt - This represents a 'switch' stmt.

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

Create a switch statement.

SwitchCase * getSwitchCaseList()

void setAllEnumCasesCovered()

Set a flag in the SwitchStmt indicating that if the 'switch (X)' is a switch over an enum value then ...

Represents the declaration of a struct/union/class/enum.

bool isCompleteDefinition() const

Return true if this decl has its body fully specified.

TypedefNameDecl * getTypedefNameForAnonDecl() const

void startDefinition()

Starts the definition of this tag declaration.

const llvm::Triple & getTriple() const

Returns the target triple of the primary target.

bool isSEHTrySupported() const

Whether the target supports SEH __try.

TemplateSpecCandidateSet - A set of generalized overload candidates, used in template specializations...

void NoteCandidates(Sema &S, SourceLocation Loc)

NoteCandidates - When no template specialization match is found, prints diagnostic messages containin...

Base wrapper for a particular "section" of type source info.

QualType getType() const

Get the type for which this source info wrapper provides information.

T castAs() const

Convert to the specified TypeLoc type, asserting that this TypeLoc is of the desired type.

T getAsAdjusted() const

Convert to the specified TypeLoc type, returning a null TypeLoc if this TypeLoc is not of the desired...

A container of type source information.

TypeLoc getTypeLoc() const

Return the TypeLoc wrapper for the type source info.

QualType getType() const

Return the type wrapped by this type source info.

The base class of the type hierarchy.

CXXRecordDecl * getAsCXXRecordDecl() const

Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...

bool isSignedIntegerOrEnumerationType() const

Determines whether this is an integer type that is signed or an enumeration types whose underlying ty...

bool isRValueReferenceType() const

bool isPointerType() const

bool isIntegerType() const

isIntegerType() does not include complex integers (a GCC extension).

const T * castAs() const

Member-template castAs.

bool isReferenceType() const

bool isEnumeralType() const

QualType getPointeeType() const

If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.

bool isIntegralOrEnumerationType() const

Determine whether this type is an integral or enumeration type.

AutoType * getContainedAutoType() const

Get the AutoType whose type will be deduced for a variable with an initializer of this type.

bool isSpecificBuiltinType(unsigned K) const

Test for a particular builtin type.

bool isDependentType() const

Whether this type is a dependent type, meaning that its definition somehow depends on a template para...

bool containsErrors() const

Whether this type is an error type.

const ArrayType * getAsArrayTypeUnsafe() const

A variant of getAs<> for array types which silently discards qualifiers from the outermost type.

bool isUndeducedType() const

Determine whether this type is an undeduced type, meaning that it somehow involves a C++11 'auto' typ...

bool isObjectType() const

Determine whether this type is an object type.

bool isIncompleteType(NamedDecl **Def=nullptr) const

Types are partitioned into 3 broad categories (C99 6.2.5p1): object types, function types,...

TypeClass getTypeClass() const

bool isCanonicalUnqualified() const

Determines if this type would be canonical if it had no further qualification.

const T * getAs() const

Member-template getAs'.

bool isRecordType() const

UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...

Represents a C++ unqualified-id that has been parsed.

void setType(QualType newType)

Represents a variable declaration or definition.

static VarDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S)

SourceRange getSourceRange() const override LLVM_READONLY

Source range that this declaration covers.

bool hasGlobalStorage() const

Returns true for all variables that do not have local storage.

bool isExceptionVariable() const

Determine whether this variable is the exception variable in a C++ catch statememt or an Objective-C ...

const Expr * getInit() const

bool hasLocalStorage() const

Returns true if a variable with function scope is a non-static local variable.

bool isLocalVarDecl() const

Returns true for local variable declarations other than parameters.

bool hasDependentAlignment() const

Determines if this variable's alignment is dependent.

Represents a C array with a specified size that is not an integer-constant-expression.

WhileStmt - This represents a 'while' stmt.

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

Create a while statement.

ValueDecl * getVariable() const

bool isVariableCapture() const

SourceLocation getLocation() const

Retrieve the location at which this variable was captured.

bool isVLATypeCapture() const

bool isThisCapture() const

bool isReferenceCapture() const

Retains information about a captured region.

unsigned short OpenMPLevel

unsigned short CapRegionKind

The kind of captured region.

RecordDecl * TheRecordDecl

The captured record type.

CapturedDecl * TheCapturedDecl

The CapturedDecl for this statement.

QualType ReturnType

ReturnType - The target type of return statements in this context, or null if unknown.

SmallVector< Capture, 4 > Captures

Captures - The captures.

bool HasImplicitReturnType

Contains information about the compound statement currently being parsed.

FPOptions InitialFPFeatures

FP options at the beginning of the compound statement, prior to any pragma.

void setHasEmptyLoopBodies()

Retains information about a function, method, or block that is currently being parsed.

llvm::PointerIntPair< SwitchStmt *, 1, bool > SwitchInfo

A SwitchStmt, along with a flag indicating if its list of case statements is incomplete (because we d...

SourceLocation FirstCXXOrObjCTryLoc

First C++ 'try' or ObjC @try statement in the current function.

SourceLocation FirstCoroutineStmtLoc

First coroutine statement in the current function.

enum clang::sema::FunctionScopeInfo::@247 FirstTryType

StringRef getFirstCoroutineStmtKeyword() const

SourceLocation FirstReturnLoc

First 'return' statement in the current function.

SourceLocation FirstSEHTryLoc

First SEH '__try' statement in the current function.

void setHasCXXTry(SourceLocation TryLoc)

SmallVector< CompoundScopeInfo, 4 > CompoundScopes

The stack of currently active compound statement scopes in the function.

void setHasSEHTry(SourceLocation TryLoc)

SmallVector< SwitchInfo, 8 > SwitchStack

SwitchStack - This is the current set of active switch statements in the block.

CXXMethodDecl * CallOperator

The lambda's compiler-generated operator().

Provides information about an attempted template argument deduction, whose success or failure was des...

TemplateArgument SecondArg

The second template argument to which the template argument deduction failure refers.

TemplateArgument FirstArg

The first template argument to which the template argument deduction failure refers.

Defines the clang::TargetInfo interface.

const internal::VariadicAllOfMatcher< Type > type

Matches Types in the clang AST.

const internal::VariadicAllOfMatcher< Decl > decl

Matches declarations.

bool This(InterpState &S, CodePtr OpPC)

bool Cast(InterpState &S, CodePtr OpPC)

void checkExprLifetimeMustTailArg(Sema &SemaRef, const InitializedEntity &Entity, Expr *Init)

Check that the lifetime of the given expr (and its subobjects) is sufficient, assuming that it is pas...

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

Expr * IgnoreElidableImplicitConstructorSingleStep(Expr *E)

@ OR_Deleted

Succeeded, but refers to a deleted function.

@ OR_Success

Overload resolution succeeded.

bool isReservedInAllContexts(ReservedIdentifierStatus Status)

Determine whether an identifier is reserved in all contexts.

IfStatementKind

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

Expr * IgnoreExprNodes(Expr *E, FnTys &&... Fns)

Given an expression E and functions Fn_1,...,Fn_n : Expr * -> Expr *, Recursively apply each of the f...

@ RQ_None

No ref-qualifier was provided.

@ OCD_AllCandidates

Requests that all candidates be shown.

@ Seq

'seq' clause, allowed on 'loop' and 'routine' directives.

bool operator==(const CallGraphNode::CallRecord &LHS, const CallGraphNode::CallRecord &RHS)

CapturedRegionKind

The different kinds of captured statement.

@ Result

The result type of a method or function.

ActionResult< Expr * > ExprResult

@ Struct

The "struct" keyword.

bool isLambdaConversionOperator(CXXConversionDecl *C)

ActionResult< Stmt * > StmtResult

@ VK_XValue

An x-value expression is a reference to an object with independent storage but which can be "moved",...

@ VK_LValue

An l-value expression is a reference to an object with independent storage.

Expr * IgnoreParensSingleStep(Expr *E)

const FunctionProtoType * T

Expr * IgnoreImplicitAsWrittenSingleStep(Expr *E)

std::pair< SourceLocation, PartialDiagnostic > PartialDiagnosticAt

A partial diagnostic along with the source location where this diagnostic occurs.

TemplateDeductionResult

Describes the result of template argument deduction.

@ Success

Template argument deduction was successful.

@ Inconsistent

Template argument deduction produced inconsistent deduced values for the given template parameter.

@ AlreadyDiagnosed

Some error which was already diagnosed.

@ CapturedContext

Parameter for captured context.

Diagnostic wrappers for TextAPI types for error reporting.

DeclarationNameInfo - A collector data type for bundling together a DeclarationName and the correspon...

EvalResult is a struct with detailed info about an evaluated expression.

@ MoveEligibleAndCopyElidable

bool isMoveEligible() const

bool isCopyElidable() const

const VarDecl * Candidate

static CatchHandlerType getEmptyKey()

static CatchHandlerType getTombstoneKey()

static unsigned getHashValue(const CatchHandlerType &Base)

static bool isEqual(const CatchHandlerType &LHS, const CatchHandlerType &RHS)