@@ -748,7 +748,9 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitNumGangsClause(
748748 for (auto *GC : GangClauses) {
749749 if (cast<OpenACCGangClause>(GC)->hasExprOfKind (OpenACCGangKind::Num)) {
750750 SemaRef.Diag (Clause.getBeginLoc (),
751- diag::err_acc_num_arg_conflict_reverse);
751+ diag::err_acc_num_arg_conflict_reverse)
752+ << OpenACCClauseKind::NumGangs << OpenACCClauseKind::Gang
753+ << /* Num argument*/ 1 ;
752754 SemaRef.Diag (GC->getBeginLoc (), diag::note_acc_previous_clause_here);
753755 return nullptr ;
754756 }
@@ -768,6 +770,25 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitNumWorkersClause(
768770 if (checkAlreadyHasClauseOfKind (SemaRef, ExistingClauses, Clause))
769771 return nullptr ;
770772
773+ // OpenACC 3.3 Section 2.9.2:
774+ // An argument is allowed only when the 'num_workers' does not appear on the
775+ // kernels construct.
776+ if (Clause.getDirectiveKind () == OpenACCDirectiveKind::KernelsLoop) {
777+ auto WorkerClauses = llvm::make_filter_range (
778+ ExistingClauses, llvm::IsaPred<OpenACCWorkerClause>);
779+
780+ for (auto *WC : WorkerClauses) {
781+ if (cast<OpenACCWorkerClause>(WC)->hasIntExpr ()) {
782+ SemaRef.Diag (Clause.getBeginLoc (),
783+ diag::err_acc_num_arg_conflict_reverse)
784+ << OpenACCClauseKind::NumWorkers << OpenACCClauseKind::Worker
785+ << /* num argument*/ 0 ;
786+ SemaRef.Diag (WC->getBeginLoc (), diag::note_acc_previous_clause_here);
787+ return nullptr ;
788+ }
789+ }
790+ }
791+
771792 assert (Clause.getIntExprs ().size () == 1 &&
772793 " Invalid number of expressions for NumWorkers" );
773794 return OpenACCNumWorkersClause::Create (
@@ -1254,74 +1275,107 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitWorkerClause(
12541275 if (DiagIfSeqClause (Clause))
12551276 return nullptr ;
12561277
1257- // Restrictions only properly implemented on 'loop' constructs, and it is
1258- // the only construct that can do anything with this, so skip/treat as
1259- // unimplemented for the combined constructs.
1260- if (Clause.getDirectiveKind () != OpenACCDirectiveKind::Loop)
1278+ // Restrictions only properly implemented on 'loop'/'combined' constructs, and
1279+ // it is the only construct that can do anything with this, so skip/treat as
1280+ // unimplemented for the routine constructs.
1281+ if (Clause.getDirectiveKind () != OpenACCDirectiveKind::Loop &&
1282+ !isOpenACCCombinedDirectiveKind (Clause.getDirectiveKind ()))
12611283 return isNotImplemented ();
12621284
12631285 Expr *IntExpr =
12641286 Clause.getNumIntExprs () != 0 ? Clause.getIntExprs ()[0 ] : nullptr ;
12651287
12661288 if (IntExpr) {
1267- switch (SemaRef.getActiveComputeConstructInfo ().Kind ) {
1268- case OpenACCDirectiveKind::Invalid:
1269- case OpenACCDirectiveKind::Parallel:
1270- case OpenACCDirectiveKind::Serial:
1271- DiagIntArgInvalid (SemaRef, IntExpr, OpenACCGangKind::Num,
1272- OpenACCClauseKind::Worker, Clause.getDirectiveKind (),
1273- SemaRef.getActiveComputeConstructInfo ().Kind );
1274- IntExpr = nullptr ;
1275- break ;
1276- case OpenACCDirectiveKind::Kernels: {
1277- const auto *Itr =
1278- llvm::find_if (SemaRef.getActiveComputeConstructInfo ().Clauses ,
1279- llvm::IsaPred<OpenACCNumWorkersClause>);
1280- if (Itr != SemaRef.getActiveComputeConstructInfo ().Clauses .end ()) {
1281- SemaRef.Diag (IntExpr->getBeginLoc (), diag::err_acc_num_arg_conflict)
1282- << OpenACCClauseKind::Worker << Clause.getDirectiveKind ()
1283- << HasAssocKind (Clause.getDirectiveKind (),
1284- SemaRef.getActiveComputeConstructInfo ().Kind )
1285- << SemaRef.getActiveComputeConstructInfo ().Kind
1286- << OpenACCClauseKind::NumWorkers;
1287- SemaRef.Diag ((*Itr)->getBeginLoc (),
1288- diag::note_acc_previous_clause_here);
1289-
1289+ if (!isOpenACCCombinedDirectiveKind (Clause.getDirectiveKind ())) {
1290+ switch (SemaRef.getActiveComputeConstructInfo ().Kind ) {
1291+ case OpenACCDirectiveKind::Invalid:
1292+ case OpenACCDirectiveKind::ParallelLoop:
1293+ case OpenACCDirectiveKind::SerialLoop:
1294+ case OpenACCDirectiveKind::Parallel:
1295+ case OpenACCDirectiveKind::Serial:
1296+ DiagIntArgInvalid (SemaRef, IntExpr, OpenACCGangKind::Num,
1297+ OpenACCClauseKind::Worker, Clause.getDirectiveKind (),
1298+ SemaRef.getActiveComputeConstructInfo ().Kind );
12901299 IntExpr = nullptr ;
1300+ break ;
1301+ case OpenACCDirectiveKind::KernelsLoop:
1302+ case OpenACCDirectiveKind::Kernels: {
1303+ const auto *Itr =
1304+ llvm::find_if (SemaRef.getActiveComputeConstructInfo ().Clauses ,
1305+ llvm::IsaPred<OpenACCNumWorkersClause>);
1306+ if (Itr != SemaRef.getActiveComputeConstructInfo ().Clauses .end ()) {
1307+ SemaRef.Diag (IntExpr->getBeginLoc (), diag::err_acc_num_arg_conflict)
1308+ << OpenACCClauseKind::Worker << Clause.getDirectiveKind ()
1309+ << HasAssocKind (Clause.getDirectiveKind (),
1310+ SemaRef.getActiveComputeConstructInfo ().Kind )
1311+ << SemaRef.getActiveComputeConstructInfo ().Kind
1312+ << OpenACCClauseKind::NumWorkers;
1313+ SemaRef.Diag ((*Itr)->getBeginLoc (),
1314+ diag::note_acc_previous_clause_here);
1315+
1316+ IntExpr = nullptr ;
1317+ }
1318+ break ;
1319+ }
1320+ default :
1321+ llvm_unreachable (" Non compute construct in active compute construct" );
1322+ }
1323+ } else {
1324+ if (Clause.getDirectiveKind () == OpenACCDirectiveKind::ParallelLoop ||
1325+ Clause.getDirectiveKind () == OpenACCDirectiveKind::SerialLoop) {
1326+ DiagIntArgInvalid (SemaRef, IntExpr, OpenACCGangKind::Num,
1327+ OpenACCClauseKind::Worker, Clause.getDirectiveKind (),
1328+ SemaRef.getActiveComputeConstructInfo ().Kind );
1329+ IntExpr = nullptr ;
1330+ } else {
1331+ assert (Clause.getDirectiveKind () == OpenACCDirectiveKind::KernelsLoop &&
1332+ " Unknown combined directive kind?" );
1333+ const auto *Itr = llvm::find_if (ExistingClauses,
1334+ llvm::IsaPred<OpenACCNumWorkersClause>);
1335+ if (Itr != ExistingClauses.end ()) {
1336+ SemaRef.Diag (IntExpr->getBeginLoc (), diag::err_acc_num_arg_conflict)
1337+ << OpenACCClauseKind::Worker << Clause.getDirectiveKind ()
1338+ << HasAssocKind (Clause.getDirectiveKind (),
1339+ SemaRef.getActiveComputeConstructInfo ().Kind )
1340+ << SemaRef.getActiveComputeConstructInfo ().Kind
1341+ << OpenACCClauseKind::NumWorkers;
1342+ SemaRef.Diag ((*Itr)->getBeginLoc (),
1343+ diag::note_acc_previous_clause_here);
1344+
1345+ IntExpr = nullptr ;
1346+ }
12911347 }
1292- break ;
1293- }
1294- default :
1295- llvm_unreachable (" Non compute construct in active compute construct" );
12961348 }
12971349 }
12981350
1299- // OpenACC 3.3 2.9.3: The region of a loop with a 'worker' clause may not
1300- // contain a loop with a gang or worker clause unless within a nested compute
1301- // region.
1302- if (SemaRef.LoopWorkerClauseLoc .isValid ()) {
1303- // This handles the 'inner loop' diagnostic, but we cannot set that we're on
1304- // one of these until we get to the end of the construct.
1305- SemaRef.Diag (Clause.getBeginLoc (), diag::err_acc_clause_in_clause_region)
1306- << OpenACCClauseKind::Worker << OpenACCClauseKind::Worker
1307- << /* skip kernels construct info*/ 0 ;
1308- SemaRef.Diag (SemaRef.LoopWorkerClauseLoc ,
1309- diag::note_acc_previous_clause_here);
1310- return nullptr ;
1311- }
1351+ if (!isOpenACCCombinedDirectiveKind (Clause.getDirectiveKind ())) {
1352+ // OpenACC 3.3 2.9.3: The region of a loop with a 'worker' clause may not
1353+ // contain a loop with a gang or worker clause unless within a nested
1354+ // compute region.
1355+ if (SemaRef.LoopWorkerClauseLoc .isValid ()) {
1356+ // This handles the 'inner loop' diagnostic, but we cannot set that we're
1357+ // on one of these until we get to the end of the construct.
1358+ SemaRef.Diag (Clause.getBeginLoc (), diag::err_acc_clause_in_clause_region)
1359+ << OpenACCClauseKind::Worker << OpenACCClauseKind::Worker
1360+ << /* skip kernels construct info*/ 0 ;
1361+ SemaRef.Diag (SemaRef.LoopWorkerClauseLoc ,
1362+ diag::note_acc_previous_clause_here);
1363+ return nullptr ;
1364+ }
13121365
1313- // OpenACC 3.3 2.9.4: The region of a loop with a 'vector' clause may not
1314- // contain a loop with a gang, worker, or vector clause unless within a nested
1315- // compute region.
1316- if (SemaRef.LoopVectorClauseLoc .isValid ()) {
1317- // This handles the 'inner loop' diagnostic, but we cannot set that we're on
1318- // one of these until we get to the end of the construct.
1319- SemaRef.Diag (Clause.getBeginLoc (), diag::err_acc_clause_in_clause_region)
1320- << OpenACCClauseKind::Worker << OpenACCClauseKind::Vector
1321- << /* skip kernels construct info*/ 0 ;
1322- SemaRef.Diag (SemaRef.LoopVectorClauseLoc ,
1323- diag::note_acc_previous_clause_here);
1324- return nullptr ;
1366+ // OpenACC 3.3 2.9.4: The region of a loop with a 'vector' clause may not
1367+ // contain a loop with a gang, worker, or vector clause unless within a
1368+ // nested compute region.
1369+ if (SemaRef.LoopVectorClauseLoc .isValid ()) {
1370+ // This handles the 'inner loop' diagnostic, but we cannot set that we're
1371+ // on one of these until we get to the end of the construct.
1372+ SemaRef.Diag (Clause.getBeginLoc (), diag::err_acc_clause_in_clause_region)
1373+ << OpenACCClauseKind::Worker << OpenACCClauseKind::Vector
1374+ << /* skip kernels construct info*/ 0 ;
1375+ SemaRef.Diag (SemaRef.LoopVectorClauseLoc ,
1376+ diag::note_acc_previous_clause_here);
1377+ return nullptr ;
1378+ }
13251379 }
13261380
13271381 return OpenACCWorkerClause::Create (Ctx, Clause.getBeginLoc (),
0 commit comments