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

1

2

3

4

5

6

7

8

9

10

11

12

13

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

25#include "llvm/Support/Casting.h"

26

27using namespace clang;

28

29namespace {

32 switch (K) {

33 default:

35

36

37 break;

55 if (!IsStmt)

56 return S.Diag(StartLoc, diag::err_acc_construct_appertainment) << K;

57 break;

58 }

59 return false;

60}

61

62void CollectActiveReductionClauses(

65 for (auto *CurClause : CurClauses) {

66 if (auto *RedClause = dyn_cast(CurClause);

67 RedClause && !RedClause->getVarList().empty())

68 ActiveClauses.push_back(RedClause);

69 }

70}

71

72

73

75 switch (DK) {

83 return false;

87 return true;

98 llvm_unreachable("Doesn't have an associated stmt");

100 llvm_unreachable("Unhandled directive kind?");

101 }

102 llvm_unreachable("Unhandled directive kind?");

103}

104

105}

106

108

113 : SemaRef(S), OldActiveComputeConstructInfo(S.ActiveComputeConstructInfo),

118 ActiveReductionClauses(S.ActiveReductionClauses),

119 LoopRAII(SemaRef, PreserveLoopRAIIDepthInAssociatedStmtRAII(DirKind)) {

120

121

125 CollectActiveReductionClauses(S.ActiveReductionClauses, Clauses);

126 SemaRef.ActiveComputeConstructInfo.Kind = DirKind;

127 SemaRef.ActiveComputeConstructInfo.Clauses = Clauses;

128

129

130

131

132

133

134

135 SemaRef.LoopGangClauseOnKernel = {};

136 SemaRef.LoopWorkerClauseLoc = {};

137 SemaRef.LoopVectorClauseLoc = {};

138 SemaRef.LoopWithoutSeqInfo = {};

142 SemaRef.ActiveComputeConstructInfo.Kind = DirKind;

143 SemaRef.ActiveComputeConstructInfo.Clauses = Clauses;

144

145 CollectActiveReductionClauses(S.ActiveReductionClauses, Clauses);

148

149 SemaRef.LoopGangClauseOnKernel = {};

150 SemaRef.LoopWorkerClauseLoc = {};

151 SemaRef.LoopVectorClauseLoc = {};

152

153

154

155 SemaRef.LoopWithoutSeqInfo = {};

156 if (Clauses.end() ==

157 llvm::find_if(Clauses, llvm::IsaPred))

158 SemaRef.LoopWithoutSeqInfo = {DirKind, DirLoc};

159

160

161

162

163

164

165

166

167

169

170 auto *Itr = llvm::find_if(Clauses, llvm::IsaPred);

171 if (Itr != Clauses.end())

172 SemaRef.LoopGangClauseOnKernel = {(*Itr)->getBeginLoc(), DirKind};

173 }

174

175 if (UnInstClauses.empty()) {

176 auto *Itr = llvm::find_if(Clauses, llvm::IsaPred);

177 if (Itr != Clauses.end())

178 SemaRef.LoopWorkerClauseLoc = (*Itr)->getBeginLoc();

179

180 auto *Itr2 = llvm::find_if(Clauses, llvm::IsaPred);

181 if (Itr2 != Clauses.end())

182 SemaRef.LoopVectorClauseLoc = (*Itr2)->getBeginLoc();

183 }

185 CollectActiveReductionClauses(S.ActiveReductionClauses, Clauses);

188

189

190

191 SemaRef.LoopWithoutSeqInfo = {};

192 if (Clauses.end() ==

193 llvm::find_if(Clauses, llvm::IsaPred))

194 SemaRef.LoopWithoutSeqInfo = {DirKind, DirLoc};

195

196

197

198

199

200

201

202

203

204 if (SemaRef.getActiveComputeConstructInfo().Kind ==

206 UnInstClauses.empty()) {

207

208 auto *Itr = llvm::find_if(Clauses, llvm::IsaPred);

209 if (Itr != Clauses.end())

210 SemaRef.LoopGangClauseOnKernel = {(*Itr)->getBeginLoc(),

212 }

213

214 if (UnInstClauses.empty()) {

215 auto *Itr = llvm::find_if(Clauses, llvm::IsaPred);

216 if (Itr != Clauses.end())

217 SemaRef.LoopWorkerClauseLoc = (*Itr)->getBeginLoc();

218

219 auto *Itr2 = llvm::find_if(Clauses, llvm::IsaPred);

220 if (Itr2 != Clauses.end())

221 SemaRef.LoopVectorClauseLoc = (*Itr2)->getBeginLoc();

222 }

223 }

224}

225

226namespace {

227

228

229

234

235

236 if (New->getLoopCount())

237 return Old;

238

239

240 if (New->getLoopCount())

241 return Old;

242

243

244 if (New->getLoopCount()->isInstantiationDependent())

245 return Old;

246

247

248

249

251 return Old;

252

253

254

255 if (!Old)

256 return New;

257

258

259

262 return New;

263

264 return Old;

265}

266}

267

271

272

273 SemaRef.LoopInfo.CurLevelHasLoopAlready = false;

274 SemaRef.CollapseInfo.CollapseDepthSatisfied = true;

275 SemaRef.CollapseInfo.CurCollapseCount = 0;

276 SemaRef.TileInfo.TileDepthSatisfied = true;

277

278

279

280

281

282

283

284

285

286

287 auto *UnInstClauseItr =

288 llvm::find_if(UnInstClauses, llvm::IsaPred);

289 auto *ClauseItr =

290 llvm::find_if(Clauses, llvm::IsaPred);

292

293

294

295

296

297

298

299 while (ClauseItr != Clauses.end()) {

303 UnInstClauseItr == UnInstClauses.end()

306

307 FoundClause =

308 getBestCollapseCandidate(FoundClause, CurClause, UnInstCurClause);

309

310 UnInstClauseItr =

311 UnInstClauseItr == UnInstClauses.end()

312 ? UnInstClauseItr

313 : std::find_if(std::next(UnInstClauseItr), UnInstClauses.end(),

314 llvm::IsaPred);

315 ClauseItr = std::find_if(std::next(ClauseItr), Clauses.end(),

316 llvm::IsaPred);

317 }

318

319 if (!FoundClause)

320 return;

321

322 SemaRef.CollapseInfo.ActiveCollapse = FoundClause;

323 SemaRef.CollapseInfo.CollapseDepthSatisfied = false;

324 SemaRef.CollapseInfo.CurCollapseCount =

326 SemaRef.CollapseInfo.DirectiveKind = DirKind;

327}

328

332

333

334

335 if (UnInstClauses.size() > 0)

336 return;

337 auto *TileClauseItr =

338 llvm::find_if(Clauses, llvm::IsaPred);

339

340 if (Clauses.end() == TileClauseItr)

341 return;

342

344

345

346

347 while (Clauses.end() !=

348 (TileClauseItr = std::find_if(std::next(TileClauseItr), Clauses.end(),

349 llvm::IsaPred))) {

352 TileClause = NewClause;

353 }

354

355 SemaRef.TileInfo.ActiveTile = TileClause;

356 SemaRef.TileInfo.TileDepthSatisfied = false;

357 SemaRef.TileInfo.CurTileCount =

358 static_cast<unsigned>(TileClause->getSizeExprs().size());

359 SemaRef.TileInfo.DirectiveKind = DirKind;

360}

361

370 SemaRef.ActiveComputeConstructInfo = OldActiveComputeConstructInfo;

371 SemaRef.LoopGangClauseOnKernel = OldLoopGangClauseOnKernel;

372 SemaRef.LoopWorkerClauseLoc = OldLoopWorkerClauseLoc;

373 SemaRef.LoopVectorClauseLoc = OldLoopVectorClauseLoc;

374 SemaRef.LoopWithoutSeqInfo = OldLoopWithoutSeqInfo;

375 SemaRef.ActiveReductionClauses.swap(ActiveReductionClauses);

378

379

380 }

381}

382

385

386 SemaRef.PushExpressionEvaluationContext(

388

389

390

391}

392

395 Expr *IntExpr) {

396

403 "Only one of directive or clause kind should be provided");

404

408 Expr *IntExpr;

409

410

411

412 unsigned getDiagKind() const {

414 return 0;

416 return 1;

417 return 2;

418 }

419

420 public:

422 Expr *IntExpr)

423 : ICEConvertDiagnoser(false,

424 false,

425 true),

426 DirectiveKind(DK), ClauseKind(CK), IntExpr(IntExpr) {}

427

429

430

431 return T->isIntegerType();

432 }

435 return S.Diag(Loc, diag::err_acc_int_expr_requires_integer)

436 << getDiagKind() << ClauseKind << DirectiveKind << T;

437 }

438

441 return S.Diag(Loc, diag::err_acc_int_expr_incomplete_class_type)

443 }

444

448 return S.Diag(Loc, diag::err_acc_int_expr_explicit_conversion)

449 << T << ConvTy;

450 }

451

455 return S.Diag(Conv->getLocation(), diag::note_acc_int_expr_conversion)

457 }

458

461 return S.Diag(Loc, diag::err_acc_int_expr_multiple_conversions) << T;

462 }

463

466 return S.Diag(Conv->getLocation(), diag::note_acc_int_expr_conversion)

468 }

469

473 llvm_unreachable("conversion functions are permitted");

474 }

475 } IntExprDiagnoser(DK, CK, IntExpr);

476

477 if (!IntExpr)

479

480 ExprResult IntExprResult = SemaRef.PerformContextualImplicitConversion(

481 Loc, IntExpr, IntExprDiagnoser);

484

485 IntExpr = IntExprResult.get();

488

489

490

491 return IntExpr;

492}

493

495 Expr *VarExpr) {

496

497

498

499

500

502 return false;

503

506 Diag(VarExpr->getExprLoc(), diag::err_array_section_use) << 0;

507 Diag(VarExpr->getExprLoc(), diag::note_acc_expected_pointer_var);

508 return true;

509 }

510

513

514

516 return false;

517

519 return Diag(VarExpr->getExprLoc(), diag::err_acc_var_not_pointer_type)

520 << ClauseKind << Ty;

521 return false;

522}

523

527 CacheInfo.ParsingCacheVarList = true;

528 CacheInfo.IsInvalidCacheRef = false;

529 }

530}

531

533 CacheInfo.ParsingCacheVarList = false;

534 CacheInfo.IsInvalidCacheRef = false;

535}

536

539

540

541

542

543

544 bool WasParsingInvalidCacheRef =

545 CacheInfo.ParsingCacheVarList && CacheInfo.IsInvalidCacheRef;

546 CacheInfo.ParsingCacheVarList = false;

547 CacheInfo.IsInvalidCacheRef = false;

548

550 Diag(VarExpr->getExprLoc(), diag::err_acc_not_a_var_ref_cache);

552 }

553

554

555

557 if (auto *SubScrpt = dyn_cast(CurVarExpr))

559 else

560 CurVarExpr =

562 }

563

564

565 if (const auto *DRE = dyn_cast(CurVarExpr)) {

567 DRE->getFoundDecl()->getCanonicalDecl()))

568 return WasParsingInvalidCacheRef ? ExprEmpty() : VarExpr;

569 }

570

571 if (const auto *ME = dyn_cast(CurVarExpr)) {

572 if (isa(ME->getMemberDecl()->getCanonicalDecl())) {

573 return WasParsingInvalidCacheRef ? ExprEmpty() : VarExpr;

574 }

575 }

576

577

578

580 return WasParsingInvalidCacheRef ? ExprEmpty() : VarExpr;

581

582

583

586

587 Diag(VarExpr->getExprLoc(), diag::err_acc_not_a_var_ref_cache);

589}

590

592 if (getLangOpts().OpenACC || !CacheInfo.ParsingCacheVarList || !D ||

594 return;

595

596

597

598

599

600

601

602

603

605

606

607

608 if (CurScope->getDepth() == 0)

609 return;

610

611 while (CurScope) {

612

613

615 return;

616

618 Diag(Loc, diag::warn_acc_cache_var_not_outside_loop);

619

620 CacheInfo.IsInvalidCacheRef = true;

621 }

622

623 CurScope = CurScope->getParent();

624 }

625

626

627}

628

629namespace {

630

631

632

635

636

640 return VarExpr;

641

642

644 return VarExpr;

645

649

651

652

653 if (!ArrTy->isConstantArrayType()) {

654 S.Diag(InnerLoc, clang::diag::warn_acc_var_referenced_non_const_array)

655 << InnerTy << CK;

656 return VarExpr;

657 }

658

659 return CheckVarType(S, CK, VarExpr, InnerLoc, ArrTy->getElementType());

660 }

661

663

664

665

666 if (!RD)

667 return VarExpr;

668

670 bool HasNonDeletedDefaultCtor =

671 llvm::find_if(RD->ctors(), [](const CXXConstructorDecl *CD) {

672 return CD->isDefaultConstructor() && !CD->isDeleted();

673 }) != RD->ctors().end();

674 if (!HasNonDeletedDefaultCtor && !RD->needsImplicitDefaultConstructor()) {

675 S.Diag(InnerLoc, clang::diag::warn_acc_var_referenced_lacks_op)

676 << InnerTy << CK << clang::diag::AccVarReferencedReason::DefCtor;

678 }

680 if (!RD->hasSimpleCopyConstructor()) {

683 false, false, false,

684 false);

685

688 S.Diag(InnerLoc, clang::diag::warn_acc_var_referenced_lacks_op)

689 << InnerTy << CK << clang::diag::AccVarReferencedReason::CopyCtor;

691 }

692 }

694

695

696

697 }

698

699

700 bool DestructorDeleted =

701 RD->getDestructor() && RD->getDestructor()->isDeleted();

702 if (DestructorDeleted && !RD->needsImplicitDestructor()) {

703 S.Diag(InnerLoc, clang::diag::warn_acc_var_referenced_lacks_op)

704 << InnerTy << CK << clang::diag::AccVarReferencedReason::Dtor;

706 }

707 return VarExpr;

708}

709

711 Expr *InnerExpr) {

712 if (!InnerExpr)

713 return VarExpr;

714 return CheckVarType(S, CK, VarExpr, InnerExpr->getBeginLoc(),

716}

717}

718

720 Expr *VarExpr) {

721

722

725

727

728

729

730

731

732

737 diag::err_acc_not_a_var_ref_use_device_declare)

740 }

741

742

745 diag::ext_acc_array_section_use_device_declare)

747 }

748

749

750

752 if (auto *SubScrpt = dyn_cast(CurVarExpr))

754 else

755 CurVarExpr =

757 }

758

759

760 if (const auto *DRE = dyn_cast(CurVarExpr)) {

762 DRE->getFoundDecl()->getCanonicalDecl()))

763 return CheckVarType(*this, CK, VarExpr, CurVarExpr);

764 }

765

766

767

768

769

770

771

772 if (const auto *ME = dyn_cast(CurVarExpr)) {

773 if (isa(ME->getMemberDecl()->getCanonicalDecl())) {

777

778

779

780 const auto *This = dyn_cast(ME->getBase());

781 if (This && This->isImplicit())

782 return CheckVarType(*this, CK, VarExpr, CurVarExpr);

783 } else {

784 return CheckVarType(*this, CK, VarExpr, CurVarExpr);

785 }

786 }

787 }

788

789

790

793 return CheckVarType(*this, CK, VarExpr, CurVarExpr);

794

795

796

800 return CheckVarType(*this, CK, VarExpr, CurVarExpr);

801

802

803

806

808 Diag(VarExpr->getExprLoc(), diag::err_acc_not_a_var_ref_use_device_declare)

809 << 1;

811 Diag(VarExpr->getExprLoc(), diag::err_acc_not_a_var_ref_use_device_declare)

812 << 0;

813 else

814 Diag(VarExpr->getExprLoc(), diag::err_acc_not_a_var_ref)

817}

818

820 Expr *LowerBound,

822 Expr *Length,

825

826

827 if (Base->hasPlaceholderType() &&

828 Base->hasPlaceholderType(BuiltinType::ArraySection)) {

830 if (Result.isInvalid())

833 }

836 if (Result.isInvalid())

839 if (Result.isInvalid())

841 LowerBound = Result.get();

842 }

843 if (Length && Length->getType()->isNonOverloadPlaceholderType()) {

845 if (Result.isInvalid())

848 if (Result.isInvalid())

850 Length = Result.get();

851 }

852

853

854

857 if (Base->isTypeDependent()) {

860 } else if (OriginalBaseTy->isArrayType()) {

862 } else {

864 Diag(Base->getExprLoc(), diag::err_acc_typecheck_subarray_value)

865 << Base->getSourceRange());

866 }

867

869 Diag(Base->getExprLoc(), diag::err_acc_subarray_function_type)

870 << ResultTy << Base->getSourceRange();

872 }

873

874 if (SemaRef.RequireCompleteType(Base->getExprLoc(), ResultTy,

875 diag::err_acc_subarray_incomplete_type,

878

879 if (Base->hasPlaceholderType(BuiltinType::ArraySection)) {

881 if (Result.isInvalid())

884 }

885 }

886

887 auto GetRecovery = [&](Expr *E, QualType Ty) {

890 return Recovery.isUsable() ? Recovery.get() : nullptr;

891 };

892

893

897 LowerBound->getExprLoc(), LowerBound);

898

900 LBRes = SemaRef.DefaultLvalueConversion(LBRes.get());

901 LowerBound =

902 LBRes.isUsable() ? LBRes.get() : GetRecovery(LowerBound, Context.IntTy);

903 }

904

905 if (Length && !Length->isTypeDependent()) {

908 Length->getExprLoc(), Length);

909

911 LenRes = SemaRef.DefaultLvalueConversion(LenRes.get());

912 Length =

913 LenRes.isUsable() ? LenRes.get() : GetRecovery(Length, Context.IntTy);

914 }

915

916

917 if (!Length && (OriginalBaseTy.isNull() ||

921 bool IsArray = !OriginalBaseTy.isNull() && OriginalBaseTy->isArrayType();

923 Diag(DiagLoc, diag::err_acc_subarray_no_length) << IsArray;

924

925

928 Length = Recovery.isUsable() ? Recovery.get() : nullptr;

929 }

930

931

932

933

934

935

936

937

938

939 std::optionalllvm::APSInt BaseSize;

941 const auto *ArrayTy = Context.getAsConstantArrayType(OriginalBaseTy);

942 BaseSize = ArrayTy->getSize();

943 }

944

945 auto GetBoundValue = [&](Expr *E) -> std::optionalllvm::APSInt {

947 return std::nullopt;

948

951 return std::nullopt;

953 };

954

955 std::optionalllvm::APSInt LowerBoundValue = GetBoundValue(LowerBound);

956 std::optionalllvm::APSInt LengthValue = GetBoundValue(Length);

957

958

959 if (LowerBoundValue.has_value()) {

960 if (LowerBoundValue->isNegative()) {

961 Diag(LowerBound->getExprLoc(), diag::err_acc_subarray_negative)

962 << 0 << toString(*LowerBoundValue, 10);

963 LowerBoundValue.reset();

964 LowerBound = GetRecovery(LowerBound, LowerBound->getType());

965 } else if (BaseSize.has_value() &&

966 llvm::APSInt::compareValues(*LowerBoundValue, *BaseSize) >= 0) {

967

968 Diag(LowerBound->getExprLoc(), diag::err_acc_subarray_out_of_range)

969 << 0 << toString(*LowerBoundValue, 10)

970 << toString(*BaseSize, 10);

971 LowerBoundValue.reset();

972 LowerBound = GetRecovery(LowerBound, LowerBound->getType());

973 }

974 }

975

976

977 if (LengthValue.has_value()) {

978 if (LengthValue->isNegative()) {

979 Diag(Length->getExprLoc(), diag::err_acc_subarray_negative)

980 << 1 << toString(*LengthValue, 10);

981 LengthValue.reset();

982 Length = GetRecovery(Length, Length->getType());

983 } else if (BaseSize.has_value() &&

984 llvm::APSInt::compareValues(*LengthValue, *BaseSize) > 0) {

985

986 Diag(Length->getExprLoc(), diag::err_acc_subarray_out_of_range)

987 << 1 << toString(*LengthValue, 10)

988 << toString(*BaseSize, 10);

989 LengthValue.reset();

990 Length = GetRecovery(Length, Length->getType());

991 }

992 }

993

994

995 auto AddAPSInt = [](llvm::APSInt LHS, llvm::APSInt RHS) -> llvm::APSInt {

996 if (LHS.isSigned() == RHS.isSigned())

997 return LHS + RHS;

998

999 unsigned Width = std::max(LHS.getBitWidth(), RHS.getBitWidth()) + 1;

1000 return llvm::APSInt(LHS.sext(Width) + RHS.sext(Width), true);

1001 };

1002

1003

1004

1005 if (BaseSize.has_value() && LowerBoundValue.has_value() &&

1006 LengthValue.has_value() &&

1007 llvm::APSInt::compareValues(AddAPSInt(*LowerBoundValue, *LengthValue),

1008 *BaseSize) > 0) {

1010 diag::err_acc_subarray_base_plus_length_out_of_range)

1011 << toString(*LowerBoundValue, 10)

1012 << toString(*LengthValue, 10)

1013 << toString(*BaseSize, 10);

1014

1015 LowerBoundValue.reset();

1016 LowerBound = GetRecovery(LowerBound, LowerBound->getType());

1017 LengthValue.reset();

1018 Length = GetRecovery(Length, Length->getType());

1019 }

1020

1021

1022 QualType ArrayExprTy = Context.ArraySectionTy;

1023 if (Base->isTypeDependent() ||

1025 (Length && Length->isTypeDependent()))

1026 ArrayExprTy = Context.DependentTy;

1027

1028 return new (Context)

1031}

1032

1035 return;

1036

1037 if (!LoopInfo.TopLevelLoopSeen)

1038 return;

1039

1040 if (CollapseInfo.CurCollapseCount && *CollapseInfo.CurCollapseCount > 0) {

1041 Diag(WhileLoc, diag::err_acc_invalid_in_loop)

1042 << 1 << CollapseInfo.DirectiveKind

1044 assert(CollapseInfo.ActiveCollapse && "Collapse count without object?");

1045 Diag(CollapseInfo.ActiveCollapse->getBeginLoc(),

1046 diag::note_acc_active_clause_here)

1048

1049

1050

1051 CollapseInfo.CurCollapseCount = std::nullopt;

1052 }

1053

1054 if (TileInfo.CurTileCount && *TileInfo.CurTileCount > 0) {

1055 Diag(WhileLoc, diag::err_acc_invalid_in_loop)

1056 << 1 << TileInfo.DirectiveKind

1058 assert(TileInfo.ActiveTile && "tile count without object?");

1059 Diag(TileInfo.ActiveTile->getBeginLoc(), diag::note_acc_active_clause_here)

1061

1062

1063

1064 TileInfo.CurTileCount = std::nullopt;

1065 }

1066}

1067

1070 return;

1071

1072 if (!LoopInfo.TopLevelLoopSeen)

1073 return;

1074

1075 if (CollapseInfo.CurCollapseCount && *CollapseInfo.CurCollapseCount > 0) {

1076 Diag(DoLoc, diag::err_acc_invalid_in_loop)

1077 << 2 << CollapseInfo.DirectiveKind

1079 assert(CollapseInfo.ActiveCollapse && "Collapse count without object?");

1080 Diag(CollapseInfo.ActiveCollapse->getBeginLoc(),

1081 diag::note_acc_active_clause_here)

1083

1084

1085

1086 CollapseInfo.CurCollapseCount = std::nullopt;

1087 }

1088

1089 if (TileInfo.CurTileCount && *TileInfo.CurTileCount > 0) {

1090 Diag(DoLoc, diag::err_acc_invalid_in_loop)

1092 assert(TileInfo.ActiveTile && "tile count without object?");

1093 Diag(TileInfo.ActiveTile->getBeginLoc(), diag::note_acc_active_clause_here)

1095

1096

1097

1098 TileInfo.CurTileCount = std::nullopt;

1099 }

1100}

1101

1102void SemaOpenACC::ForStmtBeginHelper(SourceLocation ForLoc,

1103 ForStmtBeginChecker &C) {

1104 assert(getLangOpts().OpenACC && "Check enabled when not OpenACC?");

1105

1106

1107 LoopInfo.TopLevelLoopSeen = true;

1108

1109 if (CollapseInfo.CurCollapseCount && *CollapseInfo.CurCollapseCount > 0) {

1110

1111 C.check();

1112

1113

1114

1115

1116

1117

1118 if (LoopInfo.CurLevelHasLoopAlready) {

1119 Diag(ForLoc, diag::err_acc_clause_multiple_loops)

1121 assert(CollapseInfo.ActiveCollapse && "No collapse object?");

1123 diag::note_acc_active_clause_here)

1125 } else {

1126 --(*CollapseInfo.CurCollapseCount);

1127

1128

1129

1130 if (*CollapseInfo.CurCollapseCount == 0)

1131 CollapseInfo.CollapseDepthSatisfied = true;

1132 }

1133 }

1134

1135 if (TileInfo.CurTileCount && *TileInfo.CurTileCount > 0) {

1136

1137 C.check();

1138

1139 if (LoopInfo.CurLevelHasLoopAlready) {

1140 Diag(ForLoc, diag::err_acc_clause_multiple_loops)

1142 assert(TileInfo.ActiveTile && "No tile object?");

1143 Diag(TileInfo.ActiveTile->getBeginLoc(),

1144 diag::note_acc_active_clause_here)

1146 } else {

1147 TileInfo.CurTileCount = *TileInfo.CurTileCount - 1;

1148

1149

1150 if (*TileInfo.CurTileCount == 0)

1151 TileInfo.TileDepthSatisfied = true;

1152 }

1153 }

1154

1155

1156

1157 LoopInfo.CurLevelHasLoopAlready = false;

1158}

1159

1160namespace {

1161bool isValidLoopVariableType(QualType LoopVarTy) {

1162

1164 return true;

1165

1166

1168 return true;

1169

1170

1172 return true;

1173

1174

1176

1177

1178

1179

1180

1181

1182

1183

1184 for (const auto *TD :

1185 llvm::make_filter_range(RD->decls(), llvm::IsaPred)) {

1187

1188 if (TDND->getName() != "iterator_category")

1189 continue;

1190

1191

1192 if (TDND->getUnderlyingType().isNull())

1193 return false;

1194

1195 const CXXRecordDecl *ItrCategoryDecl =

1196 TDND->getUnderlyingType()->getAsCXXRecordDecl();

1197

1198

1199 if (!ItrCategoryDecl)

1200 return false;

1201

1202 auto IsRandomAccessIteratorTag = [](const CXXRecordDecl *RD) {

1203 if (RD->getName() != "random_access_iterator_tag")

1204 return false;

1205

1206 return RD->getEnclosingNamespaceContext()->isStdNamespace();

1207 };

1208

1209 if (IsRandomAccessIteratorTag(ItrCategoryDecl))

1210 return true;

1211

1212

1213

1214 for (CXXBaseSpecifier BS : ItrCategoryDecl->bases())

1215 if (IsRandomAccessIteratorTag(BS.getType()->getAsCXXRecordDecl()))

1216 return true;

1217

1218 return false;

1219 }

1220 }

1221

1222 return false;

1223}

1224const ValueDecl *getDeclFromExpr(const Expr *E) {

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

1227 E = FE->getSubExpr();

1228

1230

1231 if (!E)

1232 return nullptr;

1233 if (const auto *DRE = dyn_cast(E))

1234 return dyn_cast(DRE->getDecl());

1235

1236 if (const auto *ME = dyn_cast(E))

1238 return ME->getMemberDecl();

1239

1240 return nullptr;

1241}

1242}

1243

1244void SemaOpenACC::ForStmtBeginChecker::checkRangeFor() {

1245 const RangeForInfo &RFI = std::get(Info);

1246

1247 if (RFI.Uninstantiated == RFI.CurrentVersion)

1248 return;

1249

1250 const DeclStmt *UninstRangeStmt =

1251 IsInstantiation ? RFI.Uninstantiated->getBeginStmt() : nullptr;

1252 const DeclStmt *RangeStmt = RFI.CurrentVersion->getBeginStmt();

1253

1254

1255

1256 if (UninstRangeStmt) {

1257 const ValueDecl *InitVar =

1260

1261 if (!isValidLoopVariableType(VarType))

1262 return;

1263 }

1264

1265

1266

1267 if (RangeStmt) {

1270

1271 if (!isValidLoopVariableType(VarType)) {

1272 SemaRef.Diag(InitVar->getBeginLoc(), diag::err_acc_loop_variable_type)

1273 << SemaRef.LoopWithoutSeqInfo.Kind << VarType;

1275 diag::note_acc_construct_here)

1276 << SemaRef.LoopWithoutSeqInfo.Kind;

1277 return;

1278 }

1279 }

1280}

1281bool SemaOpenACC::ForStmtBeginChecker::checkForInit(const Stmt *InitStmt,

1282 const ValueDecl *&InitVar,

1283 bool Diag) {

1284

1285 if (!InitStmt) {

1287 SemaRef.Diag(ForLoc, diag::err_acc_loop_variable)

1288 << SemaRef.LoopWithoutSeqInfo.Kind;

1290 diag::note_acc_construct_here)

1291 << SemaRef.LoopWithoutSeqInfo.Kind;

1292 }

1293 return true;

1294 }

1295 auto DiagLoopVar = [this, Diag, InitStmt]() {

1298 << SemaRef.LoopWithoutSeqInfo.Kind;

1300 diag::note_acc_construct_here)

1301 << SemaRef.LoopWithoutSeqInfo.Kind;

1302 }

1303 return true;

1304 };

1305

1306 if (const auto *ExprTemp = dyn_cast(InitStmt))

1307 InitStmt = ExprTemp->getSubExpr();

1308 if (const auto *E = dyn_cast(InitStmt))

1310

1311 InitVar = nullptr;

1312 if (const auto *BO = dyn_cast(InitStmt)) {

1313

1314

1315 if (!BO->isAssignmentOp())

1316 return DiagLoopVar();

1317

1318 const Expr *LHS = BO->getLHS()->IgnoreParenImpCasts();

1319 if (const auto *DRE = dyn_cast(LHS))

1320 InitVar = DRE->getDecl();

1321 } else if (const auto *DS = dyn_cast(InitStmt)) {

1322

1323 if (!DS->isSingleDecl())

1324 return DiagLoopVar();

1325 InitVar = dyn_cast(DS->getSingleDecl());

1326

1327

1328 if (InitVar) {

1330 return DiagLoopVar();

1331

1335 return DiagLoopVar();

1336 }

1337 } else if (auto *CE = dyn_cast(InitStmt)) {

1338

1339 if (CE->getOperator() != OO_Equal)

1340 return DiagLoopVar();

1341

1343 if (auto *DRE = dyn_cast(LHS)) {

1344 InitVar = DRE->getDecl();

1345 } else if (auto *ME = dyn_cast(LHS)) {

1347 InitVar = ME->getMemberDecl();

1348 }

1349 }

1350

1351

1352 if (!InitVar)

1353 return DiagLoopVar();

1354

1357

1358

1359 if (!isValidLoopVariableType(VarType)) {

1361 SemaRef.Diag(InitVar->getBeginLoc(), diag::err_acc_loop_variable_type)

1362 << SemaRef.LoopWithoutSeqInfo.Kind << VarType;

1364 diag::note_acc_construct_here)

1365 << SemaRef.LoopWithoutSeqInfo.Kind;

1366 }

1367 return true;

1368 }

1369

1370 return false;

1371}

1372

1373bool SemaOpenACC::ForStmtBeginChecker::checkForCond(const Stmt *CondStmt,

1374 const ValueDecl *InitVar,

1375 bool Diag) {

1376

1377 if (!CondStmt) {

1379 SemaRef.Diag(ForLoc, diag::err_acc_loop_terminating_condition)

1380 << SemaRef.LoopWithoutSeqInfo.Kind;

1382 diag::note_acc_construct_here)

1383 << SemaRef.LoopWithoutSeqInfo.Kind;

1384 }

1385

1386 return true;

1387 }

1388 auto DiagCondVar = [this, Diag, CondStmt] {

1391 diag::err_acc_loop_terminating_condition)

1392 << SemaRef.LoopWithoutSeqInfo.Kind;

1394 diag::note_acc_construct_here)

1395 << SemaRef.LoopWithoutSeqInfo.Kind;

1396 }

1397 return true;

1398 };

1399

1400 if (const auto *ExprTemp = dyn_cast(CondStmt))

1401 CondStmt = ExprTemp->getSubExpr();

1402 if (const auto *E = dyn_cast(CondStmt))

1404

1405 const ValueDecl *CondVar = nullptr;

1406 if (const auto *BO = dyn_cast(CondStmt)) {

1407 switch (BO->getOpcode()) {

1408 default:

1409 return DiagCondVar();

1410 case BO_EQ:

1411 case BO_LT:

1412 case BO_GT:

1413 case BO_NE:

1414 case BO_LE:

1415 case BO_GE:

1416 break;

1417 }

1418

1419

1420

1421

1422 CondVar = getDeclFromExpr(BO->getLHS());

1423 if (!CondVar ||

1425 CondVar = getDeclFromExpr(BO->getRHS());

1426

1427 } else if (const auto *CE = dyn_cast(CondStmt)) {

1428

1429

1430 if (!CE->isComparisonOp() || CE->getOperator() == OO_Spaceship)

1431 return DiagCondVar();

1432

1433

1434

1435 CondVar = getDeclFromExpr(CE->getArg(0));

1436 if (!CondVar ||

1437 (InitVar &&

1439 CE->getNumArgs() > 1))

1440 CondVar = getDeclFromExpr(CE->getArg(1));

1441 } else {

1442 return DiagCondVar();

1443 }

1444

1445 if (!CondVar)

1446 return DiagCondVar();

1447

1448

1449

1451 return DiagCondVar();

1452

1453 return false;

1454}

1455

1456namespace {

1457

1458

1459

1460bool isValidForIncRHSAssign(const ValueDecl *InitVar, const Expr *RHS) {

1461

1462 auto isValid = [](const ValueDecl *InitVar, const Expr *InnerLHS,

1463 const Expr *InnerRHS, bool IsAddition) {

1464

1465 if (!InnerLHS->getType()->isIntegerType() &&

1466 !InnerRHS->getType()->isIntegerType())

1467 return false;

1468

1469

1470

1471 if (!InitVar)

1472 return true;

1473

1474 const ValueDecl *LHSDecl = getDeclFromExpr(InnerLHS);

1475 const ValueDecl *RHSDecl = getDeclFromExpr(InnerRHS);

1476

1477 if (!LHSDecl || !RHSDecl)

1478 return true;

1479

1480

1483 return true;

1484

1485

1486 if (!IsAddition)

1487 return false;

1488

1491 };

1492

1493 if (const auto *BO = dyn_cast(RHS)) {

1495 if (OpC != BO_Add && OpC != BO_Sub)

1496 return false;

1497 return isValid(InitVar, BO->getLHS(), BO->getRHS(), OpC == BO_Add);

1498 } else if (const auto *CE = dyn_cast(RHS)) {

1500 if (Op != OO_Plus && Op != OO_Minus)

1501 return false;

1502 return isValid(InitVar, CE->getArg(0), CE->getArg(1), Op == OO_Plus);

1503 }

1504

1505 return false;

1506}

1507}

1508

1509bool SemaOpenACC::ForStmtBeginChecker::checkForInc(const Stmt *IncStmt,

1510 const ValueDecl *InitVar,

1511 bool Diag) {

1512 if (!IncStmt) {

1514 SemaRef.Diag(ForLoc, diag::err_acc_loop_not_monotonic)

1515 << SemaRef.LoopWithoutSeqInfo.Kind;

1517 diag::note_acc_construct_here)

1518 << SemaRef.LoopWithoutSeqInfo.Kind;

1519 }

1520 return true;

1521 }

1522 auto DiagIncVar = [this, Diag, IncStmt] {

1524 SemaRef.Diag(IncStmt->getBeginLoc(), diag::err_acc_loop_not_monotonic)

1525 << SemaRef.LoopWithoutSeqInfo.Kind;

1527 diag::note_acc_construct_here)

1528 << SemaRef.LoopWithoutSeqInfo.Kind;

1529 }

1530 return true;

1531 };

1532

1533 if (const auto *ExprTemp = dyn_cast(IncStmt))

1534 IncStmt = ExprTemp->getSubExpr();

1535 if (const auto *E = dyn_cast(IncStmt))

1537

1538 const ValueDecl *IncVar = nullptr;

1539

1540 if (const auto *UO = dyn_cast(IncStmt)) {

1541

1542 if (!UO->isIncrementDecrementOp())

1543 return DiagIncVar();

1544 IncVar = getDeclFromExpr(UO->getSubExpr());

1545 } else if (const auto *BO = dyn_cast(IncStmt)) {

1546 switch (BO->getOpcode()) {

1547 default:

1548 return DiagIncVar();

1549 case BO_AddAssign:

1550 case BO_SubAssign:

1551 break;

1552 case BO_Assign:

1553

1554

1555 if (!isValidForIncRHSAssign(InitVar, BO->getRHS()))

1556 return DiagIncVar();

1557 break;

1558 }

1559 IncVar = getDeclFromExpr(BO->getLHS());

1560 } else if (const auto *CE = dyn_cast(IncStmt)) {

1561 switch (CE->getOperator()) {

1562 default:

1563 return DiagIncVar();

1564 case OO_PlusPlus:

1565 case OO_MinusMinus:

1566 case OO_PlusEqual:

1567 case OO_MinusEqual:

1568 break;

1569 case OO_Equal:

1570

1571

1572 if (!isValidForIncRHSAssign(InitVar, CE->getArg(1)))

1573 return DiagIncVar();

1574 break;

1575 }

1576

1577 IncVar = getDeclFromExpr(CE->getArg(0));

1578 } else {

1579 return DiagIncVar();

1580 }

1581

1582 if (!IncVar)

1583 return DiagIncVar();

1584

1585

1586

1587

1589 return DiagIncVar();

1590

1591 return false;

1592}

1593

1594void SemaOpenACC::ForStmtBeginChecker::checkFor() {

1595 const CheckForInfo &CFI = std::get(Info);

1596

1597 if (!IsInstantiation) {

1598

1599

1600 const ValueDecl *CurInitVar = nullptr;

1601 checkForInit(CFI.Current.Init, CurInitVar, true);

1602 checkForCond(CFI.Current.Condition, CurInitVar, true);

1603 checkForInc(CFI.Current.Increment, CurInitVar, true);

1604 } else {

1605 const ValueDecl *UninstInitVar = nullptr;

1606

1607

1608

1609 bool UninstInitFailed =

1610 checkForInit(CFI.Uninst.Init, UninstInitVar, false);

1611

1612

1613

1614

1615

1616 auto InitChanged = [=]() {

1617 if (CFI.Uninst.Init == CFI.Current.Init)

1618 return false;

1619

1620 QualType OldVDTy;

1621 QualType NewVDTy;

1622

1623 if (const auto *DS = dyn_cast(CFI.Uninst.Init))

1624 if (const VarDecl *VD = dyn_cast_if_present(

1625 DS->isSingleDecl() ? DS->getSingleDecl() : nullptr))

1626 OldVDTy = VD->getType();

1627 if (const auto *DS = dyn_cast(CFI.Current.Init))

1628 if (const VarDecl *VD = dyn_cast_if_present(

1629 DS->isSingleDecl() ? DS->getSingleDecl() : nullptr))

1630 NewVDTy = VD->getType();

1631

1633 return true;

1634

1637 };

1638

1639

1640

1641 bool ShouldDiagNewInit = !UninstInitFailed && InitChanged();

1642 const ValueDecl *CurInitVar = nullptr;

1643 checkForInit(CFI.Current.Init, CurInitVar, ShouldDiagNewInit);

1644

1645

1646

1647 if (CFI.Uninst.Condition != CFI.Current.Condition &&

1648 !checkForCond(CFI.Uninst.Condition, UninstInitVar, false))

1649 checkForCond(CFI.Current.Condition, CurInitVar, true);

1650 if (CFI.Uninst.Increment != CFI.Current.Increment &&

1651 !checkForInc(CFI.Uninst.Increment, UninstInitVar, false))

1652 checkForInc(CFI.Current.Increment, CurInitVar, true);

1653 }

1654}

1655

1656void SemaOpenACC::ForStmtBeginChecker::check() {

1657

1658

1660 return;

1661

1662

1663

1664

1665 if (AlreadyChecked)

1666 return;

1667 AlreadyChecked = true;

1668

1669

1670

1671

1672

1673

1674

1675

1676

1677

1678

1679

1680

1681

1682

1683

1684 if (std::holds_alternative(Info))

1685 return checkRangeFor();

1686

1687 return checkFor();

1688}

1689

1692 const Stmt *Second, const Stmt *OldThird,

1693 const Stmt *Third) {

1695 return;

1696

1697 ForStmtBeginChecker FSBC{*this, ForLoc, OldFirst, OldSecond,

1698 OldThird, First, Second, Third};

1699

1700

1701 if (!LoopInfo.TopLevelLoopSeen) {

1702 FSBC.check();

1703 }

1704

1705 ForStmtBeginHelper(ForLoc, FSBC);

1706}

1707

1709 const Stmt *Second, const Stmt *Third) {

1711 return;

1712

1713 ForStmtBeginChecker FSBC{*this, ForLoc, First, Second, Third};

1714

1715

1716

1717 if (!LoopInfo.TopLevelLoopSeen)

1718 FSBC.check();

1719

1720 ForStmtBeginHelper(ForLoc, FSBC);

1721}

1722

1724 const Stmt *OldRangeFor,

1725 const Stmt *RangeFor) {

1726 if (getLangOpts().OpenACC || OldRangeFor == nullptr || RangeFor == nullptr)

1727 return;

1728

1729 ForStmtBeginChecker FSBC{*this, ForLoc,

1730 cast_if_present(OldRangeFor),

1731 cast_if_present(RangeFor)};

1732

1733

1734 if (!LoopInfo.TopLevelLoopSeen) {

1735 FSBC.check();

1736 }

1737 ForStmtBeginHelper(ForLoc, FSBC);

1738}

1739

1741 const Stmt *RangeFor) {

1742 if (getLangOpts().OpenACC || RangeFor == nullptr)

1743 return;

1744

1745 ForStmtBeginChecker FSBC = {*this, ForLoc,

1746 cast_if_present(RangeFor)};

1747

1748

1749

1750 if (!LoopInfo.TopLevelLoopSeen)

1751 FSBC.check();

1752

1753 ForStmtBeginHelper(ForLoc, FSBC);

1754}

1755

1756namespace {

1758

1759

1760

1761

1762 if (!CurStmt ||

1764 CurStmt))

1766

1767

1770

1771

1772

1773 if (const auto *CS = dyn_cast(CurStmt)) {

1774 for (const auto *ChildStmt : CS->children()) {

1775 SourceLocation ChildStmtLoc = FindInterveningCodeInLoop(ChildStmt);

1776 if (ChildStmtLoc.isValid())

1777 return ChildStmtLoc;

1778 }

1779

1780 return SourceLocation{};

1781 }

1783}

1784}

1785

1788 return;

1789

1790

1791 LoopInfo.CurLevelHasLoopAlready = true;

1792

1794 return;

1795

1796 bool IsActiveCollapse = CollapseInfo.CurCollapseCount &&

1797 *CollapseInfo.CurCollapseCount > 0 &&

1798 !CollapseInfo.ActiveCollapse->hasForce();

1799 bool IsActiveTile = TileInfo.CurTileCount && *TileInfo.CurTileCount > 0;

1800

1801 if (IsActiveCollapse || IsActiveTile) {

1802 SourceLocation OtherStmtLoc = FindInterveningCodeInLoop(Body.get());

1803

1804 if (OtherStmtLoc.isValid() && IsActiveCollapse) {

1805 Diag(OtherStmtLoc, diag::err_acc_intervening_code)

1807 Diag(CollapseInfo.ActiveCollapse->getBeginLoc(),

1808 diag::note_acc_active_clause_here)

1810 }

1811

1812 if (OtherStmtLoc.isValid() && IsActiveTile) {

1813 Diag(OtherStmtLoc, diag::err_acc_intervening_code)

1815 Diag(TileInfo.ActiveTile->getBeginLoc(),

1816 diag::note_acc_active_clause_here)

1818 }

1819 }

1820}

1821

1822namespace {

1823

1824

1825FunctionDecl *getFunctionFromRoutineName(Expr *RoutineName) {

1826 if (!RoutineName)

1827 return nullptr;

1830

1831 return nullptr;

1833 RoutineName)) {

1834

1835 return nullptr;

1836 } else if (auto *DRE = dyn_cast(RoutineName)) {

1837 ValueDecl *VD = DRE->getDecl();

1838

1839 if (auto *FD = dyn_cast(VD))

1840 return FD;

1841

1842

1843 if (auto *VarD = dyn_cast(VD)) {

1844 QualType VarDTy = VarD->getType();

1845 if (!VarDTy.isNull()) {

1847 if (RD->isGenericLambda())

1848 return nullptr;

1849 if (RD->isLambda())

1850 return RD->getLambdaCallOperator();

1852

1853 return nullptr;

1854 }

1855 }

1856 return nullptr;

1858 return nullptr;

1859 }

1860 }

1861 return nullptr;

1862}

1863}

1864

1866 assert(RoutineName && "Routine name cannot be null here");

1868

1870

1873 RoutineName)) {

1874

1875

1876 return RoutineName;

1877 } else if (const auto *DRE = dyn_cast(RoutineName)) {

1878 const ValueDecl *VD = DRE->getDecl();

1879

1881 return RoutineName;

1882

1883

1884 if (const auto *VarD = dyn_cast(VD)) {

1885 QualType VarDTy = VarD->getType();

1886 if (!VarDTy.isNull()) {

1888 if (RD->isGenericLambda()) {

1889 Diag(RoutineName->getBeginLoc(), diag::err_acc_routine_overload_set)

1890 << RoutineName;

1892 }

1893 if (RD->isLambda())

1894 return RoutineName;

1896

1897

1898 return RoutineName;

1899 }

1900 }

1901 }

1902

1903 Diag(RoutineName->getBeginLoc(), diag::err_acc_routine_not_func)

1904 << RoutineName;

1907

1908

1909

1910

1911 Diag(RoutineName->getBeginLoc(), diag::err_acc_routine_overload_set)

1912 << RoutineName;

1914 }

1915

1916 Diag(RoutineName->getBeginLoc(), diag::err_acc_routine_not_func)

1917 << RoutineName;

1919}

1922 return;

1923

1924

1925

1926

1927

1928 auto *ContextDecl = dyn_cast(getCurContext());

1929

1930 if (!ContextDecl)

1931 return;

1932

1933

1934

1935

1936 for (const auto *A : ContextDecl->attrs()) {

1938 Diag(VD->getBeginLoc(), diag::err_acc_magic_static_in_routine);

1939 Diag(A->getLocation(), diag::note_acc_construct_here)

1941 return;

1942 }

1943 }

1944

1945 MagicStaticLocs.insert({ContextDecl->getCanonicalDecl(), VD->getBeginLoc()});

1946}

1947void SemaOpenACC::CheckLastRoutineDeclNameConflict(const NamedDecl *ND) {

1948

1949

1950

1951

1952

1953

1954

1955

1956 if (!LastRoutineDecl)

1957 return;

1958

1959

1960

1962 return;

1963

1964

1965

1967 return;

1968

1969

1972 if (!RoutineTarget)

1973 return;

1974

1975

1977 return;

1978

1979

1981 return;

1982

1984 long LastLine =

1986

1987

1988

1989 if (NDLine - LastLine > 1)

1990 return;

1991

1992

1994 return;

1995

1997 diag::warn_acc_confusing_routine_name);

1998 Diag(RoutineTarget->getBeginLoc(), diag::note_previous_decl) << ND;

1999}

2000

2003 return;

2004

2005

2006

2007

2009 return;

2010

2012

2013 if (!RD || !RD->isLambda())

2014 return;

2015

2016 CheckLastRoutineDeclNameConflict(VD);

2017}

2018

2021 return;

2022 CheckLastRoutineDeclNameConflict(FD);

2023}

2024

2028

2029

2030

2033

2034 SemaRef.DiscardCleanupsInEvaluationContext();

2035 SemaRef.PopExpressionEvaluationContext();

2036

2037

2038

2039

2040

2041

2042 if (CollapseInfo.CurCollapseCount && *CollapseInfo.CurCollapseCount > 0) {

2043 Diag(StartLoc, diag::err_acc_invalid_in_loop)

2044 << 0 << CollapseInfo.DirectiveKind

2046 assert(CollapseInfo.ActiveCollapse && "Collapse count without object?");

2047 Diag(CollapseInfo.ActiveCollapse->getBeginLoc(),

2048 diag::note_acc_active_clause_here)

2050 }

2051 if (TileInfo.CurTileCount && *TileInfo.CurTileCount > 0) {

2052 Diag(StartLoc, diag::err_acc_invalid_in_loop)

2053 << 0 << TileInfo.DirectiveKind

2055 assert(TileInfo.ActiveTile && "Tile count without object?");

2056 Diag(TileInfo.ActiveTile->getBeginLoc(), diag::note_acc_active_clause_here)

2058 }

2059

2060 if (DiagnoseRequiredClauses(K, StartLoc, Clauses))

2061 return true;

2062 return diagnoseConstructAppertainment(*this, K, StartLoc, true);

2063}

2064

2071 switch (K) {

2077 return OpenACCComputeConstruct::Create(

2078 getASTContext(), K, StartLoc, DirLoc, EndLoc, Clauses,

2079 AssocStmt.isUsable() ? AssocStmt.get() : nullptr);

2080 }

2085 getASTContext(), K, StartLoc, DirLoc, EndLoc, Clauses,

2086 AssocStmt.isUsable() ? AssocStmt.get() : nullptr);

2087 }

2090 getASTContext(), ActiveComputeConstructInfo.Kind, StartLoc, DirLoc,

2091 EndLoc, Clauses, AssocStmt.isUsable() ? AssocStmt.get() : nullptr);

2092 }

2095 getASTContext(), StartLoc, DirLoc, EndLoc, Clauses,

2096 AssocStmt.isUsable() ? AssocStmt.get() : nullptr);

2097 }

2100 EndLoc, Clauses);

2101 }

2104 EndLoc, Clauses);

2105 }

2108 getASTContext(), StartLoc, DirLoc, EndLoc, Clauses,

2109 AssocStmt.isUsable() ? AssocStmt.get() : nullptr);

2110 }

2113 getASTContext(), StartLoc, DirLoc, LParenLoc, Exprs.front(), MiscLoc,

2114 Exprs.drop_front(), RParenLoc, EndLoc, Clauses);

2115 }

2118 EndLoc, Clauses);

2119 }

2122 EndLoc, Clauses);

2123 }

2126 EndLoc, Clauses);

2127 }

2130 EndLoc, Clauses);

2131 }

2134 getASTContext(), StartLoc, DirLoc, AtomicKind, EndLoc, Clauses,

2135 AssocStmt.isUsable() ? AssocStmt.get() : nullptr);

2136 }

2138 assert(Clauses.empty() && "Cache doesn't allow clauses");

2140 LParenLoc, MiscLoc, Exprs, RParenLoc,

2141 EndLoc);

2142 }

2144 llvm_unreachable("routine shouldn't handled here");

2146

2147

2149 RParenLoc, EndLoc, Clauses);

2150

2152 }

2153 }

2154 llvm_unreachable("Unhandled case in directive handling?");

2155}

2156

2161 switch (K) {

2162 default:

2163 llvm_unreachable("Unimplemented associated statement application");

2171 llvm_unreachable(

2172 "these don't have associated statements, so shouldn't get here");

2180

2181

2182

2183

2184

2185

2186

2187

2188

2189 return AssocStmt;

2196

2198 Diag(AssocStmt.get()->getBeginLoc(), diag::err_acc_loop_not_for_loop)

2199 << K;

2200 Diag(DirectiveLoc, diag::note_acc_construct_here) << K;

2202 }

2203

2204 if (!CollapseInfo.CollapseDepthSatisfied || !TileInfo.TileDepthSatisfied) {

2205 if (!CollapseInfo.CollapseDepthSatisfied) {

2206 Diag(DirectiveLoc, diag::err_acc_insufficient_loops)

2208 assert(CollapseInfo.ActiveCollapse && "Collapse count without object?");

2209 Diag(CollapseInfo.ActiveCollapse->getBeginLoc(),

2210 diag::note_acc_active_clause_here)

2212 }

2213

2214 if (!TileInfo.TileDepthSatisfied) {

2215 Diag(DirectiveLoc, diag::err_acc_insufficient_loops)

2217 assert(TileInfo.ActiveTile && "Collapse count without object?");

2218 Diag(TileInfo.ActiveTile->getBeginLoc(),

2219 diag::note_acc_active_clause_here)

2221 }

2223 }

2224

2225 return AssocStmt.get();

2226 }

2227 llvm_unreachable("Invalid associated statement application");

2228}

2229

2230namespace {

2231

2232

2233

2234

2235bool CheckValidRoutineGangWorkerVectorSeqClauses(

2240

2241

2242

2243

2244

2245

2246

2247 auto *FirstDeviceType =

2248 llvm::find_if(Clauses, llvm::IsaPred);

2249

2250

2251

2252 auto *ClauseItr =

2253 std::find_if(Clauses.begin(), FirstDeviceType, RequiredPred);

2254

2255 if (ClauseItr != FirstDeviceType)

2256 return false;

2257

2258

2259 if (FirstDeviceType == Clauses.end())

2260 return SemaRef.Diag(DirectiveLoc, diag::err_acc_construct_one_clause_of)

2262 << "'gang', 'seq', 'vector', or 'worker'";

2263

2264

2265

2266 auto *PrevDeviceType = FirstDeviceType;

2267

2268 while (PrevDeviceType != Clauses.end()) {

2269 auto *NextDeviceType =

2270 std::find_if(std::next(PrevDeviceType), Clauses.end(),

2271 llvm::IsaPred);

2272

2273 ClauseItr = std::find_if(PrevDeviceType, NextDeviceType, RequiredPred);

2274

2275 if (ClauseItr == NextDeviceType)

2276 return SemaRef.Diag((*PrevDeviceType)->getBeginLoc(),

2277 diag::err_acc_clause_routine_one_of_in_region);

2278

2279 PrevDeviceType = NextDeviceType;

2280 }

2281

2282 return false;

2283}

2284}

2285

2289

2290

2291

2292 SemaRef.DiscardCleanupsInEvaluationContext();

2293 SemaRef.PopExpressionEvaluationContext();

2294

2295 if (DiagnoseRequiredClauses(K, StartLoc, Clauses))

2296 return true;

2298 CheckValidRoutineGangWorkerVectorSeqClauses(*this, StartLoc, Clauses))

2299 return true;

2300

2301 return diagnoseConstructAppertainment(*this, K, StartLoc, false);

2302}

2303

2308 switch (K) {

2309 default:

2313

2314 if (Clauses.empty()) {

2315 Diag(EndLoc, diag::err_acc_declare_required_clauses);

2316

2317

2318

2320 }

2321

2324 DeclareDecl->setAccess(AS_public);

2327 }

2329 llvm_unreachable("routine shouldn't be handled here");

2330 }

2331 llvm_unreachable("unhandled case in directive handling?");

2332}

2333

2334namespace {

2335

2336

2338 if (!D)

2339 return nullptr;

2340

2341

2342 if (auto *FD = dyn_cast(D))

2343 return FD;

2344

2345

2346 if (auto *FTD = dyn_cast(D))

2347 return FTD->getTemplatedDecl();

2348

2349 if (auto *FD = dyn_cast(D)) {

2350 auto *RD =

2351 FD->getType().isNull() ? nullptr : FD->getType()->getAsCXXRecordDecl();

2352

2353 if (RD && RD->isGenericLambda())

2354 return RD->getDependentLambdaCallOperator()->getTemplatedDecl();

2355 if (RD && RD->isLambda())

2356 return RD->getLambdaCallOperator();

2357 }

2358

2359

2360 if (auto *VD = dyn_cast(D)) {

2362 if (Init || Init->getType().isNull())

2363 return nullptr;

2364

2365 const auto *RD = Init->getType()->getAsCXXRecordDecl();

2366 if (RD && RD->isGenericLambda())

2367 return RD->getDependentLambdaCallOperator()->getTemplatedDecl();

2368 if (RD && RD->isLambda())

2369 return RD->getLambdaCallOperator();

2370

2371

2372

2373

2374

2375

2376

2377

2378

2379 }

2380 return nullptr;

2381}

2382

2383void CreateRoutineDeclAttr(SemaOpenACC &SemaRef, SourceLocation DirLoc,

2384 ArrayRef<const OpenACCClause *> Clauses,

2385 ValueDecl *AddTo) {

2386 OpenACCRoutineDeclAttr *A =

2387 OpenACCRoutineDeclAttr::Create(SemaRef.getASTContext(), DirLoc);

2388 A->Clauses.assign(Clauses.begin(), Clauses.end());

2390}

2391}

2392

2393

2396 Decl *NextParsedDecl) {

2397

2398 FunctionDecl *NextParsedFDecl = LegalizeNextParsedDecl(NextParsedDecl);

2399

2400 if (!NextParsedFDecl) {

2401

2402 SemaRef.Diag(DirLoc, diag::err_acc_decl_for_routine);

2403 return;

2404 }

2405

2406

2407

2408

2409 if (auto Itr = MagicStaticLocs.find(NextParsedFDecl->getCanonicalDecl());

2410 Itr != MagicStaticLocs.end()) {

2411 Diag(Itr->second, diag::err_acc_magic_static_in_routine);

2412 Diag(DirLoc, diag::note_acc_construct_here)

2414

2415 return;

2416 }

2417

2418 auto BindItr = llvm::find_if(Clauses, llvm::IsaPred);

2419 for (auto *A : NextParsedFDecl->attrs()) {

2420

2421

2422

2423 if (auto *RA = dyn_cast(A)) {

2424 auto OtherBindItr =

2425 llvm::find_if(RA->Clauses, llvm::IsaPred);

2426 if (OtherBindItr != RA->Clauses.end() &&

2429 Diag((*BindItr)->getBeginLoc(), diag::err_acc_duplicate_unnamed_bind);

2430 Diag((*OtherBindItr)->getEndLoc(), diag::note_acc_previous_clause_here)

2431 << (*BindItr)->getClauseKind();

2432 return;

2433 }

2434 }

2435

2436

2437

2438

2439

2440

2441

2442 if (auto *RA = dyn_cast(A);

2443 RA && RA->getRange().getEnd().isValid()) {

2444 Diag((*BindItr)->getBeginLoc(), diag::err_acc_duplicate_bind);

2445 Diag(RA->getRange().getEnd(), diag::note_acc_previous_clause_here)

2446 << "bind";

2447 return;

2448 }

2449 }

2450

2451 CreateRoutineDeclAttr(*this, DirLoc, Clauses, NextParsedFDecl);

2452}

2453

2454

2459 assert(LParenLoc.isValid());

2460

2462 if ((FD = getFunctionFromRoutineName(FuncRef))) {

2463

2464

2465

2466 if (auto Itr = MagicStaticLocs.find(FD->getCanonicalDecl());

2467 Itr != MagicStaticLocs.end()) {

2468 Diag(Itr->second, diag::err_acc_magic_static_in_routine);

2469 Diag(DirLoc, diag::note_acc_construct_here)

2471

2472 return nullptr;

2473 }

2474

2475

2476

2477

2478 auto BindItr = llvm::find_if(Clauses, llvm::IsaPred);

2480 if (BindItr != Clauses.end()) {

2481 BindLoc = (*BindItr)->getBeginLoc();

2482

2483

2484

2485 for (auto *A : FD->attrs()) {

2486 if (auto *RA = dyn_cast(A)) {

2487 auto OtherBindItr =

2488 llvm::find_if(RA->Clauses, llvm::IsaPred);

2489 if (OtherBindItr != RA->Clauses.end()) {

2490 Diag((*BindItr)->getBeginLoc(), diag::err_acc_duplicate_bind);

2491 Diag((*OtherBindItr)->getEndLoc(),

2492 diag::note_acc_previous_clause_here)

2493 << (*BindItr)->getClauseKind();

2494 return nullptr;

2495 }

2496 }

2497

2498 if (auto *RA = dyn_cast(A);

2499 RA && RA->getRange().getEnd().isValid()) {

2500 Diag((*BindItr)->getBeginLoc(), diag::err_acc_duplicate_bind);

2501 Diag(RA->getRange().getEnd(), diag::note_acc_previous_clause_here)

2502 << (*BindItr)->getClauseKind();

2503 return nullptr;

2504 }

2505 }

2506 }

2507

2508

2509

2510 auto *RAA = OpenACCRoutineAnnotAttr::CreateImplicit(getASTContext(),

2511 {DirLoc, BindLoc});

2513

2514

2515 for (auto *CurFD : FD->redecls())

2517 }

2518

2521 RParenLoc, EndLoc, Clauses);

2522 LastRoutineDecl->setAccess(AS_public);

2524

2525 if (FD) {

2526

2527

2528

2529 RoutineRefList.emplace_back(FD, LastRoutineDecl);

2530 }

2531 return LastRoutineDecl;

2532}

2533

2535 for (auto [FD, RoutineDecl] : RoutineRefList)

2536 SemaRef.Consumer.HandleOpenACCRoutineReference(FD, RoutineDecl);

2537}

2538

2544 assert((!ReferencedFunc || !NextDecl) &&

2545 "Only one of these should be filled");

2546

2548 Decl *NextLineDecl = nullptr;

2551

2553

2554 return NextDecl.get();

2555 }

2556

2558 StartLoc, DirLoc, LParenLoc, ReferencedFunc, RParenLoc, Clauses, EndLoc)};

2559}

2560

2565 Stmt *NextStmt) {

2566 assert((!ReferencedFunc || !NextStmt) &&

2567 "Only one of these should be filled");

2568

2570 Decl *NextLineDecl = nullptr;

2571 if (NextStmt)

2573 NextLineDecl = DS->getSingleDecl();

2574

2576 return NextStmt;

2577 }

2578

2580 RParenLoc, Clauses, EndLoc)};

2582}

2583

2584OpenACCRoutineDeclAttr *

2586 OpenACCRoutineDeclAttr *New =

2587 OpenACCRoutineDeclAttr::Create(getASTContext(), Old.getLocation());

2588

2589

2590 New->Clauses = Old.Clauses;

2591 return New;

2592}

2597

2602

2603namespace {

2604enum class InitKind { Invalid, Zero, One, AllOnes, Least, Largest };

2605llvm::APFloat getInitFloatValue(ASTContext &Context, InitKind IK, QualType Ty) {

2606 switch (IK) {

2607 case InitKind::Invalid:

2608 llvm_unreachable("invalid init kind");

2609 case InitKind::Zero:

2610 return llvm::APFloat::getZero(Context.getFloatTypeSemantics(Ty));

2611 case InitKind::One:

2612 return llvm::APFloat::getOne(Context.getFloatTypeSemantics(Ty));

2613 case InitKind::AllOnes:

2614 return llvm::APFloat::getAllOnesValue(Context.getFloatTypeSemantics(Ty));

2615 case InitKind::Least:

2616 return llvm::APFloat::getLargest(Context.getFloatTypeSemantics(Ty),

2617 true);

2618 case InitKind::Largest:

2619 return llvm::APFloat::getLargest(Context.getFloatTypeSemantics(Ty));

2620 }

2621 llvm_unreachable("unknown init kind");

2622}

2623

2624llvm::APInt getInitIntValue(ASTContext &Context, InitKind IK, QualType Ty) {

2625 switch (IK) {

2626 case InitKind::Invalid:

2627 llvm_unreachable("invalid init kind");

2628 case InitKind::Zero:

2629 return llvm::APInt(Context.getIntWidth(Ty), 0);

2630 case InitKind::One:

2631 return llvm::APInt(Context.getIntWidth(Ty), 1);

2632 case InitKind::AllOnes:

2633 return llvm::APInt::getAllOnes(Context.getIntWidth(Ty));

2634 case InitKind::Least:

2636 return llvm::APInt::getSignedMinValue(Context.getIntWidth(Ty));

2637 return llvm::APInt::getMinValue(Context.getIntWidth(Ty));

2638 case InitKind::Largest:

2640 return llvm::APInt::getSignedMaxValue(Context.getIntWidth(Ty));

2641 return llvm::APInt::getMaxValue(Context.getIntWidth(Ty));

2642 }

2643 llvm_unreachable("unknown init kind");

2644}

2645

2646

2647

2648Expr *GenerateReductionInitRecipeExpr(ASTContext &Context,

2649 SourceRange ExprRange, QualType Ty,

2650 InitKind IK) {

2651 if (IK == InitKind::Invalid)

2652 return nullptr;

2653

2654 if (IK == InitKind::Zero) {

2655 Expr *InitExpr = new (Context)

2656 InitListExpr(Context, ExprRange.getBegin(), {}, ExprRange.getEnd());

2658 return InitExpr;

2659 }

2660

2662 llvm::SmallVector<Expr *> Exprs;

2663

2665 for (auto *F : RD->fields()) {

2666 if (Expr *NewExpr = GenerateReductionInitRecipeExpr(Context, ExprRange,

2667 F->getType(), IK))

2668 Exprs.push_back(NewExpr);

2669 else

2670 return nullptr;

2671 }

2673 for (uint64_t Idx = 0; Idx < AT->getZExtSize(); ++Idx) {

2674 if (Expr *NewExpr = GenerateReductionInitRecipeExpr(

2675 Context, ExprRange, AT->getElementType(), IK))

2676 Exprs.push_back(NewExpr);

2677 else

2678 return nullptr;

2679 }

2680

2682

2683

2684

2685

2686

2687

2688

2689

2690 return nullptr;

2691 } else {

2693

2694 if (const auto *Cplx = Ty->getAs()) {

2695

2696

2697

2698

2699 QualType EltTy = Cplx->getElementType();

2702 Context, getInitFloatValue(Context, InitKind::Zero, EltTy),

2703 true, EltTy, ExprRange.getBegin()));

2705 Context, getInitFloatValue(Context, InitKind::Zero, EltTy),

2706 true, EltTy, ExprRange.getBegin()));

2707 } else {

2709 Context, getInitIntValue(Context, InitKind::Zero, EltTy), EltTy,

2712 Context, getInitIntValue(Context, InitKind::Zero, EltTy), EltTy,

2714 }

2715

2717 Exprs.push_back(

2719 true, Ty, ExprRange.getBegin()));

2722 (IK == InitKind::One ||

2723 IK == InitKind::AllOnes ||

2724 IK == InitKind::Largest),

2726 } else {

2728 Context, getInitIntValue(Context, IK, Ty), Ty, ExprRange.getBegin()));

2729 }

2730 }

2731

2732 Expr *InitExpr = new (Context)

2733 InitListExpr(Context, ExprRange.getBegin(), Exprs, ExprRange.getEnd());

2735 return InitExpr;

2736}

2737

2738VarDecl *CreateAllocaDecl(ASTContext &Ctx, DeclContext *DC,

2739 SourceLocation BeginLoc, IdentifierInfo *VarName,

2740 QualType VarTy) {

2741 return VarDecl::Create(Ctx, DC, BeginLoc, BeginLoc, VarName, VarTy,

2743}

2744

2745ExprResult FinishValueInit(Sema &S, InitializedEntity &Entity,

2746 SourceLocation Loc, QualType VarTy, Expr *InitExpr) {

2747 if (!InitExpr)

2749

2750 InitializationKind Kind =

2752 InitializationSequence InitSeq(S, Entity, Kind, InitExpr,

2753 false,

2754 false);

2755

2756 return InitSeq.Perform(S, Entity, Kind, InitExpr, &VarTy);

2757}

2758

2759}

2760

2762

2763

2766

2769

2770

2771 if (const auto *ASE =

2773 VarTy = ASE->getElementType();

2774

2775 VarDecl *AllocaDecl = CreateAllocaDecl(

2777 &getASTContext().Idents.get("openacc.private.init"), VarTy);

2778

2785

2786

2787

2788 if (Init.isUsable()) {

2791 }

2792

2794}

2795

2798

2799

2802

2805

2806

2807 if (const auto *ASE =

2809 VarTy = ASE->getElementType();

2810

2811 VarDecl *AllocaDecl = CreateAllocaDecl(

2813 &getASTContext().Idents.get("openacc.firstprivate.init"), VarTy);

2814

2815 VarDecl *Temporary = CreateAllocaDecl(

2817 &getASTContext().Idents.get("openacc.temp"), VarTy);

2818

2821 false,

2825

2828

2830 if (!ArrTy) {

2832 SemaRef.SemaRef, Entity, VarExpr->getBeginLoc(), VarTy, TemporaryDRE);

2833

2834

2835

2836 if (Init.isUsable()) {

2839 }

2841 }

2842

2843

2844

2845

2847

2850 CK_ArrayToPointerDecay, TemporaryDRE, nullptr,

2852

2853 for (std::size_t I = 0; I < ArrTy->getLimitedSize(); ++I) {

2854

2855

2856

2860 I),

2862

2866

2867

2873 Subscript,

2874 true);

2876 CopySeq.Perform(SemaRef.SemaRef, CopyEntity, CopyKind, Subscript);

2877 Args.push_back(ElemRes.get());

2878 }

2879

2882 InitExpr->setType(VarTy);

2883

2885 VarExpr->getBeginLoc(), VarTy, InitExpr);

2886

2887

2888

2889 if (Init.isUsable()) {

2892 }

2893

2895}

2896

2899

2900

2903

2906

2907

2908 if (const auto *ASE =

2910 VarTy = ASE->getElementType();

2911

2913

2914

2915

2916

2917 if (CreateReductionCombinerRecipe(VarExpr->getBeginLoc(), ReductionOperator,

2918 VarTy, CombinerRecipes))

2920

2921 VarDecl *AllocaDecl = CreateAllocaDecl(

2923 &getASTContext().Idents.get("openacc.reduction.init"), VarTy);

2924

2927

2928 InitKind IK = InitKind::Invalid;

2929 switch (ReductionOperator) {

2931

2932

2933

2934 IK = InitKind::Invalid;

2935 break;

2937 IK = InitKind::Least;

2938 break;

2940 IK = InitKind::Largest;

2941 break;

2943 IK = InitKind::AllOnes;

2944 break;

2947 IK = InitKind::One;

2948 break;

2953 IK = InitKind::Zero;

2954 break;

2955 }

2956

2957 Expr *InitExpr = GenerateReductionInitRecipeExpr(

2959

2961 VarExpr->getBeginLoc(), VarTy, InitExpr);

2962

2963

2964

2965 if (Init.isUsable()) {

2968 }

2969

2971}

2972

2973bool SemaOpenACC::CreateReductionCombinerRecipe(

2977 &CombinerRecipes) {

2978

2979

2980

2981

2982

2983

2985 switch (ReductionOperator) {

2987

2988

2989

2990 CombinerRecipes.push_back({nullptr, nullptr, nullptr});

2991 return false;

2993 BinOp = BinaryOperatorKind::BO_AddAssign;

2994 break;

2996 BinOp = BinaryOperatorKind::BO_MulAssign;

2997 break;

2999 BinOp = BinaryOperatorKind::BO_AndAssign;

3000 break;

3002 BinOp = BinaryOperatorKind::BO_OrAssign;

3003 break;

3005 BinOp = BinaryOperatorKind::BO_XorAssign;

3006 break;

3007

3010 BinOp = BinaryOperatorKind::BO_LT;

3011 break;

3013 BinOp = BinaryOperatorKind::BO_LAnd;

3014 break;

3016 BinOp = BinaryOperatorKind::BO_LOr;

3017 break;

3018 }

3019

3020

3021

3022 if (auto *AT = getASTContext().getAsArrayType(VarTy))

3023 VarTy = AT->getElementType();

3024

3025 assert(!VarTy->isArrayType() && "Only 1 level of array allowed");

3026

3027 enum class CombinerFailureKind {

3029 BinOp = 1,

3032 };

3033

3034 auto genCombiner = [&, this](DeclRefExpr *LHSDRE, DeclRefExpr *RHSDRE)

3035 -> std::pair<ExprResult, CombinerFailureKind> {

3037 SemaRef.BuildBinOp(SemaRef.getCurScope(), Loc, BinOp, LHSDRE, RHSDRE,

3038 false);

3039 switch (ReductionOperator) {

3045

3046

3047 return {BinOpRes, BinOpRes.isUsable() ? CombinerFailureKind::None

3048 : CombinerFailureKind::BinOp};

3051

3052

3053

3054

3055

3057 return {BinOpRes, CombinerFailureKind::BinOp};

3058

3059

3060

3063 CondRes = SemaRef.ActOnConditionalOp(Loc, Loc, BinOpRes.get(), LHSDRE,

3064 RHSDRE);

3065 else

3066 CondRes = SemaRef.ActOnConditionalOp(Loc, Loc, BinOpRes.get(), RHSDRE,

3067 LHSDRE);

3068

3070 return {CondRes, CombinerFailureKind::Conditional};

3071

3072

3074 BinaryOperatorKind::BO_Assign,

3075 LHSDRE, CondRes.get(),

3076 false);

3078 ? CombinerFailureKind::None

3079 : CombinerFailureKind::Assignment};

3080 }

3083

3084

3086 return {BinOpRes, CombinerFailureKind::BinOp};

3087

3088

3090 BinaryOperatorKind::BO_Assign,

3091 LHSDRE, BinOpRes.get(),

3092 false);

3094 ? CombinerFailureKind::None

3095 : CombinerFailureKind::Assignment};

3096 }

3098 llvm_unreachable("Invalid should have been caught above");

3099 }

3100 llvm_unreachable("Unhandled case");

3101 };

3102

3103 auto tryCombiner = [&, this](DeclRefExpr *LHSDRE, DeclRefExpr *RHSDRE,

3104 bool IncludeTrap) {

3105 if (IncludeTrap) {

3106

3107 Sema::TentativeAnalysisScope Trap{SemaRef};

3108 return genCombiner(LHSDRE, RHSDRE);

3109 }

3110 return genCombiner(LHSDRE, RHSDRE);

3111 };

3112

3113 struct CombinerAttemptTy {

3114 CombinerFailureKind FailKind;

3115 VarDecl *LHS;

3116 DeclRefExpr *LHSDRE;

3117 VarDecl *RHS;

3118 DeclRefExpr *RHSDRE;

3119 Expr *Op;

3120 };

3121

3122 auto formCombiner = [&, this](QualType Ty) -> CombinerAttemptTy {

3123 VarDecl *LHSDecl = CreateAllocaDecl(

3125 &getASTContext().Idents.get("openacc.reduction.combiner.lhs"), Ty);

3127 getASTContext(), NestedNameSpecifierLoc{}, SourceLocation{}, LHSDecl,

3128 false,

3129 DeclarationNameInfo{DeclarationName{LHSDecl->getDeclName()},

3132 VarDecl *RHSDecl = CreateAllocaDecl(

3134 &getASTContext().Idents.get("openacc.reduction.combiner.lhs"), Ty);

3136 getASTContext(), NestedNameSpecifierLoc{}, SourceLocation{}, RHSDecl,

3137 false,

3138 DeclarationNameInfo{DeclarationName{RHSDecl->getDeclName()},

3139 RHSDecl->getBeginLoc()},

3141

3142 std::pair<ExprResult, CombinerFailureKind> BinOpResult =

3143 tryCombiner(LHSDRE, RHSDRE, true);

3144

3145 return {BinOpResult.second, LHSDecl, LHSDRE, RHSDecl, RHSDRE,

3146 BinOpResult.first.get()};

3147 };

3148

3149 CombinerAttemptTy TopLevelCombinerInfo = formCombiner(VarTy);

3150

3151 if (TopLevelCombinerInfo.Op) {

3152 if (!TopLevelCombinerInfo.Op->containsErrors() &&

3153 TopLevelCombinerInfo.Op->isInstantiationDependent()) {

3154

3155

3156 CombinerRecipes.push_back({nullptr, nullptr, nullptr});

3157 return false;

3158 } else if (!TopLevelCombinerInfo.Op->containsErrors()) {

3159

3160 CombinerRecipes.push_back({TopLevelCombinerInfo.LHS,

3161 TopLevelCombinerInfo.RHS,

3162 TopLevelCombinerInfo.Op});

3163 return false;

3164 }

3165 }

3166

3167 auto EmitFailureNote = [&](CombinerFailureKind CFK) {

3168 if (CFK == CombinerFailureKind::BinOp)

3169 return Diag(Loc, diag::note_acc_reduction_combiner_forming)

3171 return Diag(Loc, diag::note_acc_reduction_combiner_forming) << CFK;

3172 };

3173

3174

3175

3176

3178 if (!RD) {

3179 Diag(Loc, diag::err_acc_reduction_recipe_no_op) << VarTy;

3180 EmitFailureNote(TopLevelCombinerInfo.FailKind);

3181 tryCombiner(TopLevelCombinerInfo.LHSDRE, TopLevelCombinerInfo.RHSDRE,

3182 false);

3183 return true;

3184 }

3185

3186 for (const FieldDecl *FD : RD->fields()) {

3187 CombinerAttemptTy FieldCombinerInfo = formCombiner(FD->getType());

3188

3189 if (!FieldCombinerInfo.Op || FieldCombinerInfo.Op->containsErrors()) {

3190 Diag(Loc, diag::err_acc_reduction_recipe_no_op) << FD->getType();

3191 Diag(FD->getBeginLoc(), diag::note_acc_reduction_recipe_noop_field) << RD;

3192 EmitFailureNote(FieldCombinerInfo.FailKind);

3193 tryCombiner(FieldCombinerInfo.LHSDRE, FieldCombinerInfo.RHSDRE,

3194 false);

3195 return true;

3196 }

3197

3198 if (FieldCombinerInfo.Op->isInstantiationDependent()) {

3199

3200

3201 CombinerRecipes.push_back({nullptr, nullptr, nullptr});

3202 } else {

3203 CombinerRecipes.push_back(

3204 {FieldCombinerInfo.LHS, FieldCombinerInfo.RHS, FieldCombinerInfo.Op});

3205 }

3206 }

3207

3208 return false;

3209}

This file defines OpenACC nodes for declarative directives.

Defines some OpenACC-specific enums and functions.

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 OpenACC constructs and clauses.

Defines the SourceManager interface.

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

static OpenACCAtomicConstruct * Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc, OpenACCAtomicKind AtKind, SourceLocation End, ArrayRef< const OpenACCClause * > Clauses, Stmt *AssociatedStmt)

static OpenACCCacheConstruct * Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc, SourceLocation LParenLoc, SourceLocation ReadOnlyLoc, ArrayRef< Expr * > VarList, SourceLocation RParenLoc, SourceLocation End)

static OpenACCCombinedConstruct * Create(const ASTContext &C, OpenACCDirectiveKind K, SourceLocation Start, SourceLocation DirectiveLoc, SourceLocation End, ArrayRef< const OpenACCClause * > Clauses, Stmt *StructuredBlock)

static OpenACCDataConstruct * Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc, SourceLocation End, ArrayRef< const OpenACCClause * > Clauses, Stmt *StructuredBlock)

static OpenACCEnterDataConstruct * Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc, SourceLocation End, ArrayRef< const OpenACCClause * > Clauses)

static OpenACCExitDataConstruct * Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc, SourceLocation End, ArrayRef< const OpenACCClause * > Clauses)

static OpenACCHostDataConstruct * Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc, SourceLocation End, ArrayRef< const OpenACCClause * > Clauses, Stmt *StructuredBlock)

static OpenACCInitConstruct * Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc, SourceLocation End, ArrayRef< const OpenACCClause * > Clauses)

static OpenACCLoopConstruct * Create(const ASTContext &C, OpenACCDirectiveKind ParentKind, SourceLocation BeginLoc, SourceLocation DirLoc, SourceLocation EndLoc, ArrayRef< const OpenACCClause * > Clauses, Stmt *Loop)

static OpenACCSetConstruct * Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc, SourceLocation End, ArrayRef< const OpenACCClause * > Clauses)

static OpenACCShutdownConstruct * Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc, SourceLocation End, ArrayRef< const OpenACCClause * > Clauses)

static OpenACCUpdateConstruct * Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc, SourceLocation End, ArrayRef< const OpenACCClause * > Clauses)

static OpenACCWaitConstruct * Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc, SourceLocation LParenLoc, Expr *DevNumExpr, SourceLocation QueuesLoc, ArrayRef< Expr * > QueueIdExprs, SourceLocation RParenLoc, SourceLocation End, ArrayRef< const OpenACCClause * > Clauses)

a trap message and trap category.

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

const ConstantArrayType * getAsConstantArrayType(QualType T) const

unsigned getIntWidth(QualType T) const

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

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

This class represents BOTH the OpenMP Array Section and OpenACC 'subarray', with a boolean differenti...

static QualType getBaseOriginalType(const Expr *Base)

Return original type of the base expression for array section.

ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.

QualType getElementType() const

StringRef getOpcodeStr() const

static CXXBoolLiteralExpr * Create(const ASTContext &C, bool Val, QualType Ty, SourceLocation Loc)

Represents a C++ conversion function within a class.

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 isSingleDecl() const

static DeclRefExpr * Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, ValueDecl *D, bool RefersToEnclosingVariableOrCapture, SourceLocation NameLoc, QualType T, ExprValueKind VK, NamedDecl *FoundD=nullptr, const TemplateArgumentListInfo *TemplateArgs=nullptr, NonOdrUseReason NOUR=NOUR_None)

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

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

bool isInvalidDecl() const

SourceLocation getLocation() const

DeclContext * getDeclContext()

SourceLocation getBeginLoc() const LLVM_READONLY

DeclContext * getLexicalDeclContext()

getLexicalDeclContext - The declaration context where this Decl was lexically declared (LexicalDC).

virtual Decl * getCanonicalDecl()

Retrieves the "canonical" declaration of the given declaration.

The name of a declaration.

bool isIdentifier() const

Predicate functions for querying what type of name this is.

SourceLocation getBeginLoc() const LLVM_READONLY

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

bool isTypeDependent() const

Determines whether the type of this expression depends on.

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.

bool isInstantiationDependent() const

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

SourceLocation getExprLoc() const LLVM_READONLY

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

bool hasPlaceholderType() const

Returns whether this expression has a placeholder type.

Represents difference between two FPOptions values.

static FloatingLiteral * Create(const ASTContext &C, const llvm::APFloat &V, bool isexact, QualType Type, SourceLocation L)

Represents a function declaration or definition.

FunctionDecl * getCanonicalDecl() override

Retrieves the "canonical" declaration of the given declaration.

bool isDeleted() const

Whether this function has been deleted.

redecl_range redecls() const

Returns an iterator range for all the redeclarations of the same decl.

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

Describes an C or C++ initializer list.

Describes the kind of initialization being performed, along with location information for tokens rela...

static InitializationKind CreateDefault(SourceLocation InitLoc)

Create a default initialization.

static InitializationKind CreateForInit(SourceLocation Loc, bool DirectInit, Expr *Init)

Create an initialization from an initializer (which, for direct initialization from a parenthesized l...

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

ExprResult Perform(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, MultiExprArg Args, QualType *ResultType=nullptr)

Perform the actual initialization of the given entity based on the computed initialization sequence.

Describes an entity that is being initialized.

static InitializedEntity InitializeElement(ASTContext &Context, unsigned Index, const InitializedEntity &Parent)

Create the initialization entity for an array element.

static InitializedEntity InitializeVariable(VarDecl *Var)

Create the initialization entity for a variable.

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

This represents a decl that may have a name.

StringRef getName() const

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

DeclarationName getDeclName() const

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

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

static OpaquePtr make(DeclGroupRef P)

static OpenACCAsteriskSizeExpr * Create(const ASTContext &C, SourceLocation Loc)

SourceLocation getBeginLoc() const

Represents a 'collapse' clause on a 'loop' construct.

const Expr * getLoopCount() const

static OpenACCDeclareDecl * Create(ASTContext &Ctx, DeclContext *DC, SourceLocation StartLoc, SourceLocation DirLoc, SourceLocation EndLoc, ArrayRef< const OpenACCClause * > Clauses)

static OpenACCRoutineDecl * Create(ASTContext &Ctx, DeclContext *DC, SourceLocation StartLoc, SourceLocation DirLoc, SourceLocation LParenLoc, Expr *FuncRef, SourceLocation RParenLoc, SourceLocation EndLoc, ArrayRef< const OpenACCClause * > Clauses)

const Expr * getFunctionReference() const

ArrayRef< Expr * > getSizeExprs()

A (possibly-)qualified 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.

field_range fields() const

Base for LValueReferenceType and RValueReferenceType.

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

unsigned getDepth() const

Returns the depth of this scope. The translation-unit has scope depth 0.

bool isOpenACCLoopConstructScope() const

bool isDeclScope(const Decl *D) const

isDeclScope - Return true if this is the scope that the specified decl is declared in.

const Scope * getParent() const

getParent - Return the scope that this is nested in.

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

ASTContext & getASTContext() const

const LangOptions & getLangOpts() const

DeclContext * getCurContext() const

SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)

Emit a diagnostic.

AssociatedStmtRAII(SemaOpenACC &, OpenACCDirectiveKind, SourceLocation, ArrayRef< const OpenACCClause * >, ArrayRef< OpenACCClause * >)

Definition SemaOpenACC.cpp:109

void SetTileInfoBeforeAssociatedStmt(ArrayRef< const OpenACCClause * > UnInstClauses, ArrayRef< OpenACCClause * > Clauses)

Definition SemaOpenACC.cpp:329

~AssociatedStmtRAII()

Definition SemaOpenACC.cpp:362

void SetCollapseInfoBeforeAssociatedStmt(ArrayRef< const OpenACCClause * > UnInstClauses, ArrayRef< OpenACCClause * > Clauses)

Definition SemaOpenACC.cpp:268

ExprResult ActOnRoutineName(Expr *RoutineName)

Definition SemaOpenACC.cpp:1865

OpenACCPrivateRecipe CreatePrivateInitRecipe(const Expr *VarExpr)

Definition SemaOpenACC.cpp:2761

bool ActOnStartDeclDirective(OpenACCDirectiveKind K, SourceLocation StartLoc, ArrayRef< const OpenACCClause * > Clauses)

Called after the directive, including its clauses, have been parsed and parsing has consumed the 'ann...

Definition SemaOpenACC.cpp:2286

bool ActOnStartStmtDirective(OpenACCDirectiveKind K, SourceLocation StartLoc, ArrayRef< const OpenACCClause * > Clauses)

Called after the directive, including its clauses, have been parsed and parsing has consumed the 'ann...

Definition SemaOpenACC.cpp:2025

ExprResult BuildOpenACCAsteriskSizeExpr(SourceLocation AsteriskLoc)

Definition SemaOpenACC.cpp:2594

ExprResult ActOnIntExpr(OpenACCDirectiveKind DK, OpenACCClauseKind CK, SourceLocation Loc, Expr *IntExpr)

Called when encountering an 'int-expr' for OpenACC, and manages conversions and diagnostics to 'int'.

Definition SemaOpenACC.cpp:393

void ActOnVariableDeclarator(VarDecl *VD)

Function called when a variable declarator is created, which lets us implement the 'routine' 'functio...

Definition SemaOpenACC.cpp:1920

void ActOnWhileStmt(SourceLocation WhileLoc)

Definition SemaOpenACC.cpp:1033

SourceLocation LoopWorkerClauseLoc

If there is a current 'active' loop construct with a 'worker' clause on it (on any sort of construct)...

DeclGroupRef ActOnEndRoutineDeclDirective(SourceLocation StartLoc, SourceLocation DirLoc, SourceLocation LParenLoc, Expr *ReferencedFunc, SourceLocation RParenLoc, ArrayRef< const OpenACCClause * > Clauses, SourceLocation EndLoc, DeclGroupPtrTy NextDecl)

Definition SemaOpenACC.cpp:2539

void ActOnInvalidParseVar()

Called only if the parse of a 'var' was invalid, else 'ActOnVar' should be called.

Definition SemaOpenACC.cpp:532

void CheckRoutineDecl(SourceLocation DirLoc, ArrayRef< const OpenACCClause * > Clauses, Decl *NextParsedDecl)

Definition SemaOpenACC.cpp:2394

void ActOnEndOfTranslationUnit(TranslationUnitDecl *TU)

Definition SemaOpenACC.cpp:2534

OpaquePtr< DeclGroupRef > DeclGroupPtrTy

bool CheckVarIsPointerType(OpenACCClauseKind ClauseKind, Expr *VarExpr)

Called to check the 'var' type is a variable of pointer type, necessary for 'deviceptr' and 'attach' ...

Definition SemaOpenACC.cpp:494

struct clang::SemaOpenACC::LoopGangOnKernelTy LoopGangClauseOnKernel

StmtResult ActOnEndRoutineStmtDirective(SourceLocation StartLoc, SourceLocation DirLoc, SourceLocation LParenLoc, Expr *ReferencedFunc, SourceLocation RParenLoc, ArrayRef< const OpenACCClause * > Clauses, SourceLocation EndLoc, Stmt *NextStmt)

Definition SemaOpenACC.cpp:2561

SemaOpenACC(Sema &S)

Definition SemaOpenACC.cpp:107

void CheckDeclReference(SourceLocation Loc, Expr *E, Decl *D)

Definition SemaOpenACC.cpp:591

StmtResult ActOnAssociatedStmt(SourceLocation DirectiveLoc, OpenACCDirectiveKind K, OpenACCAtomicKind AtKind, ArrayRef< const OpenACCClause * > Clauses, StmtResult AssocStmt)

Called when we encounter an associated statement for our construct, this should check legality of the...

Definition SemaOpenACC.cpp:2157

OpenACCRoutineDeclAttr * mergeRoutineDeclAttr(const OpenACCRoutineDeclAttr &Old)

Definition SemaOpenACC.cpp:2585

void ActOnFunctionDeclarator(FunctionDecl *FD)

Called when a function decl is created, which lets us implement the 'routine' 'doesn't match next thi...

Definition SemaOpenACC.cpp:2019

ExprResult ActOnCacheVar(Expr *VarExpr)

Helper function called by ActonVar that is used to check a 'cache' var.

Definition SemaOpenACC.cpp:537

struct clang::SemaOpenACC::LoopWithoutSeqCheckingInfo LoopWithoutSeqInfo

DeclGroupRef ActOnEndDeclDirective(OpenACCDirectiveKind K, SourceLocation StartLoc, SourceLocation DirLoc, SourceLocation LParenLoc, SourceLocation RParenLoc, SourceLocation EndLoc, ArrayRef< OpenACCClause * > Clauses)

Called after the directive has been completely parsed, including the declaration group or associated ...

Definition SemaOpenACC.cpp:2304

SourceLocation LoopVectorClauseLoc

If there is a current 'active' loop construct with a 'vector' clause on it (on any sort of construct)...

ExprResult ActOnVar(OpenACCDirectiveKind DK, OpenACCClauseKind CK, Expr *VarExpr)

Called when encountering a 'var' for OpenACC, ensures it is actually a declaration reference to a var...

Definition SemaOpenACC.cpp:719

void ActOnConstruct(OpenACCDirectiveKind K, SourceLocation DirLoc)

Called after the construct has been parsed, but clauses haven't been parsed.

Definition SemaOpenACC.cpp:383

ExprResult ActOnOpenACCAsteriskSizeExpr(SourceLocation AsteriskLoc)

Definition SemaOpenACC.cpp:2599

void ActOnDoStmt(SourceLocation DoLoc)

Definition SemaOpenACC.cpp:1068

void ActOnVariableInit(VarDecl *VD, QualType InitType)

Called when a variable is initialized, so we can implement the 'routine 'doesn't match the next thing...

Definition SemaOpenACC.cpp:2001

void ActOnRangeForStmtBegin(SourceLocation ForLoc, const Stmt *OldRangeFor, const Stmt *RangeFor)

Definition SemaOpenACC.cpp:1723

void ActOnStartParseVar(OpenACCDirectiveKind DK, OpenACCClauseKind CK)

Called right before a 'var' is parsed, so we can set the state for parsing a 'cache' var.

Definition SemaOpenACC.cpp:524

OpenACCFirstPrivateRecipe CreateFirstPrivateInitRecipe(const Expr *VarExpr)

Definition SemaOpenACC.cpp:2797

StmtResult ActOnEndStmtDirective(OpenACCDirectiveKind K, SourceLocation StartLoc, SourceLocation DirLoc, SourceLocation LParenLoc, SourceLocation MiscLoc, ArrayRef< Expr * > Exprs, OpenACCAtomicKind AK, SourceLocation RParenLoc, SourceLocation EndLoc, ArrayRef< OpenACCClause * > Clauses, StmtResult AssocStmt)

Called after the directive has been completely parsed, including the declaration group or associated ...

Definition SemaOpenACC.cpp:2065

void ActOnForStmtEnd(SourceLocation ForLoc, StmtResult Body)

Definition SemaOpenACC.cpp:1786

StmtResult CheckAtomicAssociatedStmt(SourceLocation AtomicDirLoc, OpenACCAtomicKind AtKind, StmtResult AssocStmt)

Called to check the form of the atomic construct which has some fairly sizable restrictions.

void ActOnForStmtBegin(SourceLocation ForLoc, const Stmt *First, const Stmt *Second, const Stmt *Third)

Definition SemaOpenACC.cpp:1708

ExprResult ActOnArraySectionExpr(Expr *Base, SourceLocation LBLoc, Expr *LowerBound, SourceLocation ColonLocFirst, Expr *Length, SourceLocation RBLoc)

Checks and creates an Array Section used in an OpenACC construct/clause.

Definition SemaOpenACC.cpp:819

OpenACCReductionRecipeWithStorage CreateReductionInitRecipe(OpenACCReductionOperator ReductionOperator, const Expr *VarExpr)

Definition SemaOpenACC.cpp:2897

CXXMethodDecl * getMethod() const

RAII class used to indicate that we are performing provisional semantic analysis to determine the val...

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

@ PotentiallyEvaluated

The current expression is potentially evaluated at run time, which means that code may be generated t...

SourceManager & SourceMgr

SpecialMemberOverloadResult LookupSpecialMember(CXXRecordDecl *D, CXXSpecialMemberKind SM, bool ConstArg, bool VolatileArg, bool RValueThis, bool ConstThis, bool VolatileThis)

Encodes a location in the source.

bool isValid() const

Return true if this is a valid SourceLocation object.

unsigned getSpellingLineNumber(SourceLocation Loc, bool *Invalid=nullptr) const

SourceLocation getEnd() const

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

SourceLocation getBeginLoc() const LLVM_READONLY

The top declaration context.

bool isDependentSizedArrayType() const

bool isBooleanType() const

bool isSignedIntegerOrEnumerationType() const

Determines whether this is an integer type that is signed or an enumeration types whose underlying ty...

CXXRecordDecl * getAsCXXRecordDecl() const

Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...

bool isConstantArrayType() const

RecordDecl * getAsRecordDecl() const

Retrieves the RecordDecl this type refers to.

bool isPointerType() const

bool isIntegerType() const

isIntegerType() does not include complex integers (a GCC extension).

bool isEnumeralType() const

bool isScalarType() const

QualType getPointeeType() const

If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.

bool isNonOverloadPlaceholderType() const

Test for a placeholder type other than Overload; see BuiltinType::isNonOverloadPlaceholderType.

bool isInstantiationDependentType() const

Determine whether this type is an instantiation-dependent type, meaning that the type involves a temp...

bool isDependentType() const

Whether this type is a dependent type, meaning that its definition somehow depends on a template para...

const ArrayType * getAsArrayTypeUnsafe() const

A variant of getAs<> for array types which silently discards qualifiers from the outermost type.

bool isFunctionType() const

bool isFloatingType() const

bool isAnyPointerType() const

const T * getAs() const

Member-template getAs'.

bool isRecordType() const

Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...

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)

void setInitStyle(InitializationStyle Style)

@ CallInit

Call-style initialization (C++98)

bool isStaticLocal() const

Returns true if a variable with function scope is a static local variable.

SmallVector< BoundNodes, 1 > match(MatcherT Matcher, const NodeT &Node, ASTContext &Context)

Returns the results of matching Matcher on Node.

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

OverloadedOperatorKind

Enumeration specifying the different kinds of C++ overloaded operators.

@ Invalid

Invalid Reduction Clause Kind.

bool isa(CodeGen::Address addr)

@ Conditional

A conditional (?:) operator.

@ OK_Ordinary

An ordinary object is located at an address in memory.

OpenACCClauseKind

Represents the kind of an OpenACC clause.

@ Collapse

'collapse' clause, allowed on 'loop' and Combined constructs.

@ Private

'private' clause, allowed on 'parallel', 'serial', 'loop', 'parallel loop', and 'serial loop' constru...

@ Invalid

Represents an invalid clause, for the purposes of parsing.

@ UseDevice

'use_device' clause, allowed on 'host_data' construct.

@ Reduction

'reduction' clause, allowed on Parallel, Serial, Loop, and the combined constructs.

@ FirstPrivate

'firstprivate' clause, allowed on 'parallel', 'serial', 'parallel loop', and 'serial loop' constructs...

@ Tile

'tile' clause, allowed on 'loop' and Combined constructs.

nullptr

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

@ Result

The result type of a method or function.

const FunctionProtoType * T

@ VK_LValue

An l-value expression is a reference to an object with independent storage.

U cast(CodeGen::Address addr)

@ None

The alignment was not explicit in code.

ActionResult< Expr * > ExprResult

ActionResult< Stmt * > StmtResult

@ NOUR_None

This is an odr-use.

DeclarationNameInfo - A collector data type for bundling together a DeclarationName and the correspon...

EvalResult is a struct with detailed info about an evaluated expression.

APValue Val

Val - This is the value the expression can be folded to.

static OpenACCFirstPrivateRecipe Empty()

static OpenACCPrivateRecipe Empty()

static OpenACCReductionRecipeWithStorage Empty()