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 (->getLoopCount())
237 return Old;
238
239
240 if (->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 (().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 ->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 (->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 (->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 (().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 (().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->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()