19#include "llvm/ADT/StringExtras.h"
20#include "llvm/Support/Casting.h"
29 case OpenACCDirectiveKind::Invalid:
33 case OpenACCDirectiveKind::Parallel:
34 case OpenACCDirectiveKind::ParallelLoop:
35 case OpenACCDirectiveKind::Serial:
36 case OpenACCDirectiveKind::SerialLoop:
37 case OpenACCDirectiveKind::Kernels:
38 case OpenACCDirectiveKind::KernelsLoop:
39 case OpenACCDirectiveKind::Loop:
40 case OpenACCDirectiveKind::Data:
41 case OpenACCDirectiveKind::EnterData:
42 case OpenACCDirectiveKind::ExitData:
43 case OpenACCDirectiveKind::HostData:
44 case OpenACCDirectiveKind::Wait:
45 case OpenACCDirectiveKind::Update:
46 case OpenACCDirectiveKind::Init:
47 case OpenACCDirectiveKind::Shutdown:
48 case OpenACCDirectiveKind::Cache:
49 case OpenACCDirectiveKind::Atomic:
51 return S.
Diag(StartLoc, diag::err_acc_construct_appertainment) << K;
57void CollectActiveReductionClauses(
60 for (
auto *CurClause : CurClauses) {
61 if (
auto *RedClause = dyn_cast<OpenACCReductionClause>(CurClause);
62 RedClause && !RedClause->getVarList().empty())
63 ActiveClauses.push_back(RedClause);
71 case OpenACCDirectiveKind::Parallel:
72 case OpenACCDirectiveKind::ParallelLoop:
73 case OpenACCDirectiveKind::Serial:
74 case OpenACCDirectiveKind::SerialLoop:
75 case OpenACCDirectiveKind::Kernels:
76 case OpenACCDirectiveKind::KernelsLoop:
77 case OpenACCDirectiveKind::Loop:
79 case OpenACCDirectiveKind::Data:
80 case OpenACCDirectiveKind::HostData:
81 case OpenACCDirectiveKind::Atomic:
83 case OpenACCDirectiveKind::EnterData:
84 case OpenACCDirectiveKind::ExitData:
85 case OpenACCDirectiveKind::Wait:
86 case OpenACCDirectiveKind::Init:
87 case OpenACCDirectiveKind::Shutdown:
88 case OpenACCDirectiveKind::Set:
89 case OpenACCDirectiveKind::Update:
90 llvm_unreachable(
"Doesn't have an associated stmt");
92 case OpenACCDirectiveKind::Invalid:
93 llvm_unreachable(
"Unhandled directive kind?");
95 llvm_unreachable(
"Unhandled directive kind?");
106 : SemaRef(S), OldActiveComputeConstructInfo(S.ActiveComputeConstructInfo),
107 DirKind(DK), OldLoopGangClauseOnKernel(S.LoopGangClauseOnKernel),
108 OldLoopWorkerClauseLoc(S.LoopWorkerClauseLoc),
109 OldLoopVectorClauseLoc(S.LoopVectorClauseLoc),
110 OldLoopWithoutSeqInfo(S.LoopWithoutSeqInfo),
111 ActiveReductionClauses(S.ActiveReductionClauses),
112 LoopRAII(SemaRef, PreserveLoopRAIIDepthInAssociatedStmtRAII(DirKind)) {
118 CollectActiveReductionClauses(S.ActiveReductionClauses, Clauses);
119 SemaRef.ActiveComputeConstructInfo.Kind = DirKind;
120 SemaRef.ActiveComputeConstructInfo.Clauses = Clauses;
135 SemaRef.ActiveComputeConstructInfo.Kind = DirKind;
136 SemaRef.ActiveComputeConstructInfo.Clauses = Clauses;
138 CollectActiveReductionClauses(S.ActiveReductionClauses, Clauses);
150 llvm::find_if(Clauses, llvm::IsaPred<OpenACCSeqClause>))
163 auto *Itr = llvm::find_if(Clauses, llvm::IsaPred<OpenACCGangClause>);
164 if (Itr != Clauses.end())
168 if (UnInstClauses.empty()) {
169 auto *Itr = llvm::find_if(Clauses, llvm::IsaPred<OpenACCWorkerClause>);
170 if (Itr != Clauses.end())
173 auto *Itr2 = llvm::find_if(Clauses, llvm::IsaPred<OpenACCVectorClause>);
174 if (Itr2 != Clauses.end())
178 CollectActiveReductionClauses(S.ActiveReductionClauses, Clauses);
186 llvm::find_if(Clauses, llvm::IsaPred<OpenACCSeqClause>))
199 UnInstClauses.empty()) {
201 auto *Itr = llvm::find_if(Clauses, llvm::IsaPred<OpenACCGangClause>);
202 if (Itr != Clauses.end())
207 if (UnInstClauses.empty()) {
208 auto *Itr = llvm::find_if(Clauses, llvm::IsaPred<OpenACCWorkerClause>);
209 if (Itr != Clauses.end())
212 auto *Itr2 = llvm::find_if(Clauses, llvm::IsaPred<OpenACCVectorClause>);
213 if (Itr2 != Clauses.end())
224 SemaRef.LoopInfo.CurLevelHasLoopAlready =
false;
225 SemaRef.CollapseInfo.CollapseDepthSatisfied =
true;
226 SemaRef.TileInfo.TileDepthSatisfied =
true;
233 auto *CollapseClauseItr =
234 llvm::find_if(Clauses, llvm::IsaPred<OpenACCCollapseClause>);
235 auto *UnInstCollapseClauseItr =
236 llvm::find_if(UnInstClauses, llvm::IsaPred<OpenACCCollapseClause>);
238 if (Clauses.end() == CollapseClauseItr)
242 cast<OpenACCCollapseClause>(*CollapseClauseItr);
244 SemaRef.CollapseInfo.ActiveCollapse = CollapseClause;
254 if (UnInstCollapseClauseItr != UnInstClauses.end() &&
255 !cast<OpenACCCollapseClause>(*UnInstCollapseClauseItr)
257 ->isInstantiationDependent())
260 SemaRef.CollapseInfo.CollapseDepthSatisfied =
false;
261 SemaRef.CollapseInfo.CurCollapseCount =
262 cast<ConstantExpr>(LoopCount)->getResultAsAPSInt();
263 SemaRef.CollapseInfo.DirectiveKind = DirKind;
272 if (UnInstClauses.size() > 0)
274 auto *TileClauseItr =
275 llvm::find_if(Clauses, llvm::IsaPred<OpenACCTileClause>);
277 if (Clauses.end() == TileClauseItr)
281 SemaRef.TileInfo.ActiveTile = TileClause;
282 SemaRef.TileInfo.TileDepthSatisfied =
false;
284 SemaRef.TileInfo.DirectiveKind = DirKind;
295 SemaRef.ActiveComputeConstructInfo = OldActiveComputeConstructInfo;
296 SemaRef.LoopGangClauseOnKernel = OldLoopGangClauseOnKernel;
297 SemaRef.LoopWorkerClauseLoc = OldLoopWorkerClauseLoc;
298 SemaRef.LoopVectorClauseLoc = OldLoopVectorClauseLoc;
299 SemaRef.LoopWithoutSeqInfo = OldLoopWithoutSeqInfo;
300 SemaRef.ActiveReductionClauses.swap(ActiveReductionClauses);
345 Diag(DirLoc, diag::warn_acc_construct_unimplemented) << K;
360 "Only one of directive or clause kind should be provided");
369 unsigned getDiagKind()
const {
370 if (ClauseKind != OpenACCClauseKind::Invalid)
372 if (DirectiveKind != OpenACCDirectiveKind::Invalid)
380 : ICEConvertDiagnoser(
false,
383 DirectiveKind(DK), ClauseKind(CK), IntExpr(IntExpr) {}
392 return S.
Diag(
Loc, diag::err_acc_int_expr_requires_integer)
393 << getDiagKind() << ClauseKind << DirectiveKind <<
T;
398 return S.
Diag(
Loc, diag::err_acc_int_expr_incomplete_class_type)
405 return S.
Diag(
Loc, diag::err_acc_int_expr_explicit_conversion)
418 return S.
Diag(
Loc, diag::err_acc_int_expr_multiple_conversions) <<
T;
430 llvm_unreachable(
"conversion functions are permitted");
432 } IntExprDiagnoser(DK, CK, IntExpr);
438 Loc, IntExpr, IntExprDiagnoser);
442 IntExpr = IntExprResult.
get();
476 return Diag(VarExpr->
getExprLoc(), diag::err_acc_var_not_pointer_type)
488 isa<ArraySectionExpr, ArraySubscriptExpr>(CurVarExpr)) {
489 Diag(VarExpr->
getExprLoc(), diag::err_acc_not_a_var_ref_use_device);
495 while (isa<ArraySectionExpr, ArraySubscriptExpr>(CurVarExpr)) {
496 if (
auto *SubScrpt = dyn_cast<ArraySubscriptExpr>(CurVarExpr))
504 if (
const auto *DRE = dyn_cast<DeclRefExpr>(CurVarExpr)) {
505 if (isa<VarDecl, NonTypeTemplateParmDecl>(
506 DRE->getFoundDecl()->getCanonicalDecl()))
518 if (
const auto *ME = dyn_cast<MemberExpr>(CurVarExpr)) {
519 if (isa<FieldDecl>(ME->getMemberDecl()->getCanonicalDecl()))
531 if (isa<DependentScopeDeclRefExpr>(CurVarExpr) ||
533 isa<CXXDependentScopeMemberExpr>(CurVarExpr)))
538 if (isa<RecoveryExpr>(CurVarExpr))
542 Diag(VarExpr->
getExprLoc(), diag::err_acc_not_a_var_ref_use_device);
557 if (
Base->hasPlaceholderType() &&
558 !
Base->hasPlaceholderType(BuiltinType::ArraySection)) {
571 LowerBound =
Result.get();
573 if (Length && Length->getType()->isNonOverloadPlaceholderType()) {
587 if (!
Base->isTypeDependent()) {
594 Diag(
Base->getExprLoc(), diag::err_acc_typecheck_subarray_value)
595 <<
Base->getSourceRange());
599 Diag(
Base->getExprLoc(), diag::err_acc_subarray_function_type)
600 << ResultTy <<
Base->getSourceRange();
605 diag::err_acc_subarray_incomplete_type,
609 if (!
Base->hasPlaceholderType(BuiltinType::ArraySection)) {
620 return Recovery.
isUsable() ? Recovery.
get() :
nullptr;
635 if (Length && !Length->isTypeDependent()) {
638 Length->getExprLoc(), Length);
647 if (!Length && (OriginalBaseTy.
isNull() ||
652 Diag(ColonLoc, diag::err_acc_subarray_no_length) << IsArray;
657 Length = Recovery.
isUsable() ? Recovery.
get() :
nullptr;
668 std::optional<llvm::APSInt> BaseSize;
674 auto GetBoundValue = [&](
Expr *
E) -> std::optional<llvm::APSInt> {
684 std::optional<llvm::APSInt> LowerBoundValue = GetBoundValue(LowerBound);
685 std::optional<llvm::APSInt> LengthValue = GetBoundValue(Length);
688 if (LowerBoundValue.has_value()) {
689 if (LowerBoundValue->isNegative()) {
691 << 0 <<
toString(*LowerBoundValue, 10);
692 LowerBoundValue.reset();
693 LowerBound = GetRecovery(LowerBound, LowerBound->
getType());
694 }
else if (BaseSize.has_value() &&
695 llvm::APSInt::compareValues(*LowerBoundValue, *BaseSize) >= 0) {
697 Diag(LowerBound->
getExprLoc(), diag::err_acc_subarray_out_of_range)
698 << 0 <<
toString(*LowerBoundValue, 10)
700 LowerBoundValue.reset();
701 LowerBound = GetRecovery(LowerBound, LowerBound->
getType());
706 if (LengthValue.has_value()) {
707 if (LengthValue->isNegative()) {
708 Diag(Length->getExprLoc(), diag::err_acc_subarray_negative)
711 Length = GetRecovery(Length, Length->getType());
712 }
else if (BaseSize.has_value() &&
713 llvm::APSInt::compareValues(*LengthValue, *BaseSize) > 0) {
715 Diag(Length->getExprLoc(), diag::err_acc_subarray_out_of_range)
719 Length = GetRecovery(Length, Length->getType());
724 auto AddAPSInt = [](llvm::APSInt LHS, llvm::APSInt RHS) -> llvm::APSInt {
725 if (LHS.isSigned() == RHS.isSigned())
728 unsigned Width = std::max(LHS.getBitWidth(), RHS.getBitWidth()) + 1;
729 return llvm::APSInt(LHS.sext(Width) + RHS.sext(Width),
true);
734 if (BaseSize.has_value() && LowerBoundValue.has_value() &&
735 LengthValue.has_value() &&
736 llvm::APSInt::compareValues(AddAPSInt(*LowerBoundValue, *LengthValue),
739 diag::err_acc_subarray_base_plus_length_out_of_range)
744 LowerBoundValue.reset();
745 LowerBound = GetRecovery(LowerBound, LowerBound->
getType());
747 Length = GetRecovery(Length, Length->getType());
752 if (
Base->isTypeDependent() ||
754 (Length && Length->isInstantiationDependent()))
766 if (!LoopInfo.TopLevelLoopSeen)
769 if (CollapseInfo.CurCollapseCount && *CollapseInfo.CurCollapseCount > 0) {
770 Diag(WhileLoc, diag::err_acc_invalid_in_loop)
771 << 1 << CollapseInfo.DirectiveKind
773 assert(CollapseInfo.ActiveCollapse &&
"Collapse count without object?");
774 Diag(CollapseInfo.ActiveCollapse->getBeginLoc(),
775 diag::note_acc_active_clause_here)
780 CollapseInfo.CurCollapseCount = std::nullopt;
783 if (TileInfo.CurTileCount && *TileInfo.CurTileCount > 0) {
784 Diag(WhileLoc, diag::err_acc_invalid_in_loop)
785 << 1 << TileInfo.DirectiveKind
787 assert(TileInfo.ActiveTile &&
"tile count without object?");
788 Diag(TileInfo.ActiveTile->getBeginLoc(), diag::note_acc_active_clause_here)
793 TileInfo.CurTileCount = std::nullopt;
801 if (!LoopInfo.TopLevelLoopSeen)
804 if (CollapseInfo.CurCollapseCount && *CollapseInfo.CurCollapseCount > 0) {
805 Diag(DoLoc, diag::err_acc_invalid_in_loop)
806 << 2 << CollapseInfo.DirectiveKind
808 assert(CollapseInfo.ActiveCollapse &&
"Collapse count without object?");
809 Diag(CollapseInfo.ActiveCollapse->getBeginLoc(),
810 diag::note_acc_active_clause_here)
815 CollapseInfo.CurCollapseCount = std::nullopt;
818 if (TileInfo.CurTileCount && *TileInfo.CurTileCount > 0) {
819 Diag(DoLoc, diag::err_acc_invalid_in_loop)
821 assert(TileInfo.ActiveTile &&
"tile count without object?");
822 Diag(TileInfo.ActiveTile->getBeginLoc(), diag::note_acc_active_clause_here)
827 TileInfo.CurTileCount = std::nullopt;
832 ForStmtBeginChecker &
C) {
833 assert(
getLangOpts().OpenACC &&
"Check enabled when not OpenACC?");
836 LoopInfo.TopLevelLoopSeen =
true;
838 if (CollapseInfo.CurCollapseCount && *CollapseInfo.CurCollapseCount > 0) {
846 if (LoopInfo.CurLevelHasLoopAlready) {
847 Diag(ForLoc, diag::err_acc_clause_multiple_loops)
849 assert(CollapseInfo.ActiveCollapse &&
"No collapse object?");
850 Diag(CollapseInfo.ActiveCollapse->getBeginLoc(),
851 diag::note_acc_active_clause_here)
854 --(*CollapseInfo.CurCollapseCount);
858 if (*CollapseInfo.CurCollapseCount == 0)
859 CollapseInfo.CollapseDepthSatisfied =
true;
863 if (TileInfo.CurTileCount && *TileInfo.CurTileCount > 0) {
866 if (LoopInfo.CurLevelHasLoopAlready) {
867 Diag(ForLoc, diag::err_acc_clause_multiple_loops)
869 assert(TileInfo.ActiveTile &&
"No tile object?");
870 Diag(TileInfo.ActiveTile->getBeginLoc(),
871 diag::note_acc_active_clause_here)
874 --(*TileInfo.CurTileCount);
877 if (*TileInfo.CurTileCount == 0)
878 TileInfo.TileDepthSatisfied =
true;
884 LoopInfo.CurLevelHasLoopAlready =
false;
888bool isValidLoopVariableType(
QualType LoopVarTy) {
911 for (
const auto *TD :
912 llvm::make_filter_range(RD->decls(), llvm::IsaPred<TypedefNameDecl>)) {
913 const auto *TDND = cast<TypedefNameDecl>(TD)->getCanonicalDecl();
915 if (TDND->getName() !=
"iterator_category")
919 if (TDND->getUnderlyingType().isNull())
923 TDND->getUnderlyingType()->getAsCXXRecordDecl();
926 if (!ItrCategoryDecl)
929 auto IsRandomAccessIteratorTag = [](
const CXXRecordDecl *RD) {
930 if (RD->getName() !=
"random_access_iterator_tag")
936 if (IsRandomAccessIteratorTag(ItrCategoryDecl))
943 if (IsRandomAccessIteratorTag(BS.getType()->getAsCXXRecordDecl()))
956void SemaOpenACC::ForStmtBeginChecker::check() {
962 AlreadyChecked =
true;
982 if (!RangeFor.has_value())
986 const DeclStmt *RangeStmt = (*RangeFor)->getBeginStmt();
995 if (!isValidLoopVariableType(VarType)) {
997 <<
SemaRef.LoopWithoutSeqInfo.Kind << VarType;
999 diag::note_acc_construct_here)
1000 <<
SemaRef.LoopWithoutSeqInfo.Kind;
1009 if (Cond.has_value())
1011 if (
Inc.has_value())
1014const ValueDecl *SemaOpenACC::ForStmtBeginChecker::checkInit() {
1018 <<
SemaRef.LoopWithoutSeqInfo.Kind;
1020 diag::note_acc_construct_here)
1021 <<
SemaRef.LoopWithoutSeqInfo.Kind;
1026 auto DiagLoopVar = [&]() {
1029 <<
SemaRef.LoopWithoutSeqInfo.Kind;
1031 diag::note_acc_construct_here)
1032 <<
SemaRef.LoopWithoutSeqInfo.Kind;
1037 if (
const auto *ExprTemp = dyn_cast<ExprWithCleanups>(
Init))
1038 Init = ExprTemp->getSubExpr();
1039 if (
const auto *
E = dyn_cast<Expr>(
Init))
1044 if (
const auto *BO = dyn_cast<BinaryOperator>(
Init)) {
1047 if (!BO->isAssignmentOp())
1048 return DiagLoopVar();
1052 if (
const auto *DRE = dyn_cast<DeclRefExpr>(LHS))
1053 InitVar = DRE->getDecl();
1054 }
else if (
const auto *DS = dyn_cast<DeclStmt>(
Init)) {
1056 if (!DS->isSingleDecl())
1057 return DiagLoopVar();
1059 InitVar = dyn_cast<ValueDecl>(DS->getSingleDecl());
1064 if (!isa<VarDecl>(InitVar))
1065 return DiagLoopVar();
1069 !cast<VarDecl>(InitVar)->hasInit())
1070 return DiagLoopVar();
1072 }
else if (
auto *CE = dyn_cast<CXXOperatorCallExpr>(
Init)) {
1074 if (CE->getOperator() != OO_Equal)
1075 return DiagLoopVar();
1079 if (
auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
1080 InitVar = DRE->getDecl();
1081 }
else if (
auto *ME = dyn_cast<MemberExpr>(LHS)) {
1082 if (isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
1083 InitVar = ME->getMemberDecl();
1088 return DiagLoopVar();
1094 if (!isValidLoopVariableType(VarType)) {
1097 <<
SemaRef.LoopWithoutSeqInfo.Kind << VarType;
1099 diag::note_acc_construct_here)
1100 <<
SemaRef.LoopWithoutSeqInfo.Kind;
1107void SemaOpenACC::ForStmtBeginChecker::checkCond() {
1109 SemaRef.
Diag(ForLoc, diag::err_acc_loop_terminating_condition)
1110 <<
SemaRef.LoopWithoutSeqInfo.Kind;
1112 <<
SemaRef.LoopWithoutSeqInfo.Kind;
1121void SemaOpenACC::ForStmtBeginChecker::checkInc(
const ValueDecl *
Init) {
1124 SemaRef.
Diag(ForLoc, diag::err_acc_loop_not_monotonic)
1125 <<
SemaRef.LoopWithoutSeqInfo.Kind;
1127 <<
SemaRef.LoopWithoutSeqInfo.Kind;
1130 auto DiagIncVar = [
this] {
1131 SemaRef.
Diag((*Inc)->getBeginLoc(), diag::err_acc_loop_not_monotonic)
1132 <<
SemaRef.LoopWithoutSeqInfo.Kind;
1134 <<
SemaRef.LoopWithoutSeqInfo.Kind;
1138 if (
const auto *ExprTemp = dyn_cast<ExprWithCleanups>(*Inc))
1139 Inc = ExprTemp->getSubExpr();
1140 if (
const auto *
E = dyn_cast<Expr>(*Inc))
1145 if (
const auto *FE = dyn_cast<FullExpr>(
E))
1146 E = FE->getSubExpr();
1152 if (
const auto *DRE = dyn_cast<DeclRefExpr>(
E))
1153 return dyn_cast<ValueDecl>(DRE->getDecl());
1155 if (
const auto *ME = dyn_cast<MemberExpr>(
E))
1156 if (isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
1157 return ME->getMemberDecl();
1165 if (
const auto *UO = dyn_cast<UnaryOperator>(*Inc)) {
1167 if (!UO->isIncrementDecrementOp())
1168 return DiagIncVar();
1170 }
else if (
const auto *BO = dyn_cast<BinaryOperator>(*Inc)) {
1171 switch (BO->getOpcode()) {
1173 return DiagIncVar();
1187 }
else if (
const auto *CE = dyn_cast<CXXOperatorCallExpr>(*Inc)) {
1188 switch (CE->getOperator()) {
1190 return DiagIncVar();
1208 }
else if (
const auto *ME = dyn_cast<CXXMemberCallExpr>(*Inc)) {
1215 return DiagIncVar();
1221 return DiagIncVar();
1228 const Stmt *Second,
const Stmt *OldThird,
1229 const Stmt *Third) {
1233 std::optional<const Stmt *> S;
1234 if (OldSecond == Second)
1238 std::optional<const Stmt *>
T;
1239 if (OldThird == Third)
1244 bool InitChanged =
false;
1245 if (OldFirst !=
First) {
1253 if (
const auto *DS = dyn_cast<DeclStmt>(OldFirst))
1254 if (
const VarDecl *VD = dyn_cast_if_present<VarDecl>(
1255 DS->isSingleDecl() ? DS->getSingleDecl() :
nullptr))
1256 OldVDTy = VD->getType();
1257 if (
const auto *DS = dyn_cast<DeclStmt>(
First))
1258 if (
const VarDecl *VD = dyn_cast_if_present<VarDecl>(
1259 DS->isSingleDecl() ? DS->getSingleDecl() :
nullptr))
1260 NewVDTy = VD->getType();
1267 ForStmtBeginChecker FSBC{*
this, ForLoc,
First, InitChanged, S,
T};
1268 if (!LoopInfo.TopLevelLoopSeen) {
1272 ForStmtBeginHelper(ForLoc, FSBC);
1276 const Stmt *Second,
const Stmt *Third) {
1280 ForStmtBeginChecker FSBC{*
this, ForLoc,
First,
true,
1282 if (!LoopInfo.TopLevelLoopSeen) {
1286 ForStmtBeginHelper(ForLoc, FSBC);
1290 const Stmt *OldRangeFor,
1291 const Stmt *RangeFor) {
1295 std::optional<const CXXForRangeStmt *> RF;
1297 if (OldRangeFor == RangeFor)
1300 RF = cast<CXXForRangeStmt>(RangeFor);
1302 ForStmtBeginChecker FSBC{*
this, ForLoc, RF};
1303 if (!LoopInfo.TopLevelLoopSeen) {
1306 ForStmtBeginHelper(ForLoc, FSBC);
1310 const Stmt *RangeFor) {
1314 ForStmtBeginChecker FSBC{*
this, ForLoc, cast<CXXForRangeStmt>(RangeFor)};
1315 if (!LoopInfo.TopLevelLoopSeen) {
1318 ForStmtBeginHelper(ForLoc, FSBC);
1328 isa<ForStmt, NullStmt, ForStmt, CXXForRangeStmt, WhileStmt, DoStmt>(
1333 if (isa<OpenACCConstructStmt>(CurStmt))
1338 if (
const auto *CS = dyn_cast<CompoundStmt>(CurStmt)) {
1339 for (
const auto *ChildStmt : CS->children()) {
1340 SourceLocation ChildStmtLoc = FindInterveningCodeInLoop(ChildStmt);
1342 return ChildStmtLoc;
1356 LoopInfo.CurLevelHasLoopAlready =
true;
1361 bool IsActiveCollapse = CollapseInfo.CurCollapseCount &&
1362 *CollapseInfo.CurCollapseCount > 0 &&
1363 !CollapseInfo.ActiveCollapse->hasForce();
1364 bool IsActiveTile = TileInfo.CurTileCount && *TileInfo.CurTileCount > 0;
1366 if (IsActiveCollapse || IsActiveTile) {
1369 if (OtherStmtLoc.
isValid() && IsActiveCollapse) {
1370 Diag(OtherStmtLoc, diag::err_acc_intervening_code)
1372 Diag(CollapseInfo.ActiveCollapse->getBeginLoc(),
1373 diag::note_acc_active_clause_here)
1377 if (OtherStmtLoc.
isValid() && IsActiveTile) {
1378 Diag(OtherStmtLoc, diag::err_acc_intervening_code)
1380 Diag(TileInfo.ActiveTile->getBeginLoc(),
1381 diag::note_acc_active_clause_here)
1391 assert(!Clauses.empty() &&
"empty clause list not supported");
1394 llvm::raw_string_ostream OS{Output};
1396 if (Clauses.size() == 1) {
1397 OS <<
'\'' << Clauses[0] <<
'\'';
1406 [&] { OS <<
", "; });
1408 OS <<
" or \'" << Clauses.back() <<
'\'';
1424 if (CollapseInfo.CurCollapseCount && *CollapseInfo.CurCollapseCount > 0) {
1425 Diag(StartLoc, diag::err_acc_invalid_in_loop)
1426 << 0 << CollapseInfo.DirectiveKind
1428 assert(CollapseInfo.ActiveCollapse &&
"Collapse count without object?");
1429 Diag(CollapseInfo.ActiveCollapse->getBeginLoc(),
1430 diag::note_acc_active_clause_here)
1433 if (TileInfo.CurTileCount && *TileInfo.CurTileCount > 0) {
1434 Diag(StartLoc, diag::err_acc_invalid_in_loop)
1435 << 0 << TileInfo.DirectiveKind
1437 assert(TileInfo.ActiveTile &&
"Tile count without object?");
1438 Diag(TileInfo.ActiveTile->getBeginLoc(), diag::note_acc_active_clause_here)
1446 llvm::find_if(Clauses,
1452 return Diag(StartLoc, diag::err_acc_construct_one_clause_of)
1454 << GetListOfClauses(
1464 llvm::find_if(Clauses,
1467 return Diag(StartLoc, diag::err_acc_construct_one_clause_of)
1469 << GetListOfClauses({
1477 llvm::find_if(Clauses,
1480 return Diag(StartLoc, diag::err_acc_construct_one_clause_of)
1482 << GetListOfClauses({
1490 llvm::find_if(Clauses, llvm::IsaPred<OpenACCUseDeviceClause>) ==
1492 return Diag(StartLoc, diag::err_acc_construct_one_clause_of)
1503 return Diag(StartLoc, diag::err_acc_construct_one_clause_of)
1516 return Diag(StartLoc, diag::err_acc_construct_one_clause_of)
1522 return diagnoseConstructAppertainment(*
this, K, StartLoc,
true);
1541 AssocStmt.
isUsable() ? AssocStmt.
get() :
nullptr);
1548 AssocStmt.
isUsable() ? AssocStmt.
get() :
nullptr);
1552 getASTContext(), ActiveComputeConstructInfo.Kind, StartLoc, DirLoc,
1553 EndLoc, Clauses, AssocStmt.
isUsable() ? AssocStmt.
get() :
nullptr);
1558 AssocStmt.
isUsable() ? AssocStmt.
get() :
nullptr);
1571 AssocStmt.
isUsable() ? AssocStmt.
get() :
nullptr);
1575 getASTContext(), StartLoc, DirLoc, LParenLoc, Exprs.front(), MiscLoc,
1576 Exprs.drop_front(), RParenLoc, EndLoc, Clauses);
1595 assert(Clauses.empty() &&
"Atomic doesn't allow clauses");
1598 AssocStmt.
isUsable() ? AssocStmt.
get() :
nullptr);
1601 llvm_unreachable(
"Unhandled case in directive handling?");
1610 llvm_unreachable(
"Unimplemented associated statement application");
1618 "these don't have associated statements, so shouldn't get here");
1643 if (!isa<CXXForRangeStmt, ForStmt>(AssocStmt.
get())) {
1646 Diag(DirectiveLoc, diag::note_acc_construct_here) << K;
1650 if (!CollapseInfo.CollapseDepthSatisfied || !TileInfo.TileDepthSatisfied) {
1651 if (!CollapseInfo.CollapseDepthSatisfied) {
1652 Diag(DirectiveLoc, diag::err_acc_insufficient_loops)
1654 assert(CollapseInfo.ActiveCollapse &&
"Collapse count without object?");
1655 Diag(CollapseInfo.ActiveCollapse->getBeginLoc(),
1656 diag::note_acc_active_clause_here)
1660 if (!TileInfo.TileDepthSatisfied) {
1661 Diag(DirectiveLoc, diag::err_acc_insufficient_loops)
1663 assert(TileInfo.ActiveTile &&
"Collapse count without object?");
1664 Diag(TileInfo.ActiveTile->getBeginLoc(),
1665 diag::note_acc_active_clause_here)
1671 return AssocStmt.
get();
1673 llvm_unreachable(
"Invalid associated statement application");
1683 return diagnoseConstructAppertainment(*
this, K, StartLoc,
false);
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.
static NamedDecl * getDeclFromExpr(Expr *E)
This file declares semantic analysis for OpenACC constructs and clauses.
This file defines OpenACC AST classes for statement-level contructs.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
const ConstantArrayType * getAsConstantArrayType(QualType T) const
CanQualType ArraySectionTy
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.
QualType getElementType() const
Represents a base class of a C++ class.
Represents a C++ conversion function within a class.
Represents a C++ struct/union/class.
llvm::APInt getSize() const
Return the constant array size as an APInt.
bool isStdNamespace() const
DeclContext * getEnclosingNamespaceContext()
Retrieve the nearest enclosing namespace context.
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
const Decl * getSingleDecl() const
SourceLocation getLocation() const
SourceLocation getBeginLoc() const LLVM_READONLY
virtual Decl * getCanonicalDecl()
Retrieves the "canonical" declaration of the given declaration.
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, e.g.
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.
static OpenACCAsteriskSizeExpr * Create(const ASTContext &C, SourceLocation Loc)
static OpenACCAtomicConstruct * Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc, OpenACCAtomicKind AtKind, SourceLocation End, Stmt *AssociatedStmt)
Represents a 'collapse' clause on a 'loop' construct.
const Expr * getLoopCount() const
static OpenACCCombinedConstruct * Create(const ASTContext &C, OpenACCDirectiveKind K, SourceLocation Start, SourceLocation DirectiveLoc, SourceLocation End, ArrayRef< const OpenACCClause * > Clauses, Stmt *StructuredBlock)
static OpenACCComputeConstruct * Create(const ASTContext &C, OpenACCDirectiveKind K, SourceLocation BeginLoc, SourceLocation DirectiveLoc, SourceLocation EndLoc, ArrayRef< const OpenACCClause * > Clauses, Stmt *StructuredBlock)
static OpenACCDataConstruct * Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc, SourceLocation End, ArrayRef< const OpenACCClause * > Clauses, Stmt *StructuredBlock)
A 'default' clause, has the optional 'none' or 'present' argument.
A 'device_type' or 'dtype' clause, takes a list of either an 'asterisk' or an identifier.
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)
An 'if' clause, which has a required condition expression.
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)
A 'self' clause, which has an optional condition expression, or, in the event of an 'update' directiv...
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)
llvm::ArrayRef< Expr * > getSizeExprs()
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 (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 getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
A generic diagnostic builder for errors which may or may not be deferred.
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, bool DeferHint=false)
Emit a diagnostic.
ASTContext & getASTContext() const
const LangOptions & getLangOpts() const
AssociatedStmtRAII(SemaOpenACC &, OpenACCDirectiveKind, SourceLocation, ArrayRef< const OpenACCClause * >, ArrayRef< OpenACCClause * >)
void SetTileInfoBeforeAssociatedStmt(ArrayRef< const OpenACCClause * > UnInstClauses, ArrayRef< OpenACCClause * > Clauses)
void SetCollapseInfoBeforeAssociatedStmt(ArrayRef< const OpenACCClause * > UnInstClauses, ArrayRef< OpenACCClause * > Clauses)
ExprResult ActOnVar(OpenACCClauseKind CK, Expr *VarExpr)
Called when encountering a 'var' for OpenACC, ensures it is actually a declaration reference to a var...
ComputeConstructInfo & getActiveComputeConstructInfo()
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...
ExprResult BuildOpenACCAsteriskSizeExpr(SourceLocation AsteriskLoc)
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'.
void ActOnWhileStmt(SourceLocation WhileLoc)
SourceLocation LoopWorkerClauseLoc
If there is a current 'active' loop construct with a 'worker' clause on it (on any sort of construct)...
bool ActOnStartDeclDirective(OpenACCDirectiveKind K, SourceLocation StartLoc)
Called after the directive, including its clauses, have been parsed and parsing has consumed the 'ann...
bool CheckVarIsPointerType(OpenACCClauseKind ClauseKind, Expr *VarExpr)
Called to check the 'var' type is a variable of pointer type, necessary for 'deviceptr' and 'attach' ...
struct clang::SemaOpenACC::LoopGangOnKernelTy LoopGangClauseOnKernel
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...
struct clang::SemaOpenACC::LoopWithoutSeqCheckingInfo LoopWithoutSeqInfo
DeclGroupRef ActOnEndDeclDirective()
Called after the directive has been completely parsed, including the declaration group or associated ...
SourceLocation LoopVectorClauseLoc
If there is a current 'active' loop construct with a 'vector' clause on it (on any sort of construct)...
void ActOnConstruct(OpenACCDirectiveKind K, SourceLocation DirLoc)
Called after the construct has been parsed, but clauses haven't been parsed.
ExprResult ActOnOpenACCAsteriskSizeExpr(SourceLocation AsteriskLoc)
void ActOnDoStmt(SourceLocation DoLoc)
void ActOnRangeForStmtBegin(SourceLocation ForLoc, const Stmt *OldRangeFor, const Stmt *RangeFor)
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 ...
void ActOnForStmtEnd(SourceLocation ForLoc, StmtResult Body)
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)
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.
Sema - This implements semantic analysis and AST building for C.
void PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext, Decl *LambdaContextDecl=nullptr, ExpressionEvaluationContextRecord::ExpressionKind Type=ExpressionEvaluationContextRecord::EK_Other)
ExprResult PerformContextualImplicitConversion(SourceLocation Loc, Expr *FromE, ContextualImplicitConverter &Converter)
Perform a contextual implicit conversion.
ExprResult DefaultFunctionArrayLvalueConversion(Expr *E, bool Diagnose=true)
void PopExpressionEvaluationContext()
ExprResult DefaultLvalueConversion(Expr *E)
ExprResult CheckPlaceholderExpr(Expr *E)
Check for operands with placeholder types and complain if found.
@ PotentiallyEvaluated
The current expression is potentially evaluated at run time, which means that code may be generated t...
bool RequireCompleteType(SourceLocation Loc, QualType T, CompleteTypeKind Kind, TypeDiagnoser &Diagnoser)
Ensure that the type T is a complete type.
void DiscardCleanupsInEvaluationContext()
ExprResult CreateRecoveryExpr(SourceLocation Begin, SourceLocation End, ArrayRef< Expr * > SubExprs, QualType T=QualType())
Attempts to produce a RecoveryExpr after some AST node cannot be created.
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
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
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
bool isDependentSizedArrayType() const
bool isConstantArrayType() const
bool isPointerType() const
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
bool isEnumeralType() 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 isAnyPointerType() const
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.
SmallVector< BoundNodes, 1 > match(MatcherT Matcher, const NodeT &Node, ASTContext &Context)
Returns the results of matching Matcher on Node.
bool Inc(InterpState &S, CodePtr OpPC)
1) Pops a pointer from the stack 2) Load the value from the pointer 3) Writes the value increased by ...
The JSON file list parser is used to communicate input to InstallAPI.
@ OK_Ordinary
An ordinary object is located at an address in memory.
OpenACCClauseKind
Represents the kind of an OpenACC clause.
@ DevicePtr
'deviceptr' clause, allowed on Compute and Combined Constructs, plus 'data' and 'declare'.
@ Collapse
'collapse' clause, allowed on 'loop' and Combined constructs.
@ DeviceNum
'device_num' clause, allowed on 'init', 'shutdown', and 'set' constructs.
@ Invalid
Represents an invalid clause, for the purposes of parsing.
@ Copy
'copy' clause, allowed on Compute and Combined Constructs, plus 'data' and 'declare'.
@ Create
'create' clause, allowed on Compute and Combined constructs, plus 'data', 'enter data',...
@ DeviceType
'device_type' clause, allowed on Compute, 'data', 'init', 'shutdown', 'set', update',...
@ DefaultAsync
'default_async' clause, allowed on 'set' construct.
@ Attach
'attach' clause, allowed on Compute and Combined constructs, plus 'data' and 'enter data'.
@ If
'if' clause, allowed on all the Compute Constructs, Data Constructs, Executable Constructs,...
@ Default
'default' clause, allowed on parallel, serial, kernel (and compound) constructs.
@ UseDevice
'use_device' clause, allowed on 'host_data' construct.
@ NoCreate
'no_create' clause, allowed on allowed on Compute and Combined constructs, plus 'data'.
@ Reduction
'reduction' clause, allowed on Parallel, Serial, Loop, and the combined constructs.
@ Self
'self' clause, allowed on Compute and Combined Constructs, plus 'update'.
@ CopyOut
'copyout' clause, allowed on Compute and Combined constructs, plus 'data', 'exit data',...
@ Host
'host' clause, allowed on 'update' construct.
@ Tile
'tile' clause, allowed on 'loop' and Combined constructs.
@ Present
'present' clause, allowed on Compute and Combined constructs, plus 'data' and 'declare'.
@ CopyIn
'copyin' clause, allowed on Compute and Combined constructs, plus 'data', 'enter data',...
@ Device
'device' clause, allowed on the 'update' construct.
@ Detach
'detach' clause, allowed on the 'exit data' construct.
@ Delete
'delete' clause, allowed on the 'exit data' construct.
@ Result
The result type of a method or function.
@ VK_LValue
An l-value expression is a reference to an object with independent storage.
const FunctionProtoType * T
EvalResult is a struct with detailed info about an evaluated expression.
APValue Val
Val - This is the value the expression can be folded to.