@@ -586,33 +586,40 @@ void OmpStructureChecker::CheckPredefinedAllocatorRestriction(
586586
587587template <class D >
588588void OmpStructureChecker::CheckHintClause (
589- D *leftOmpClauseList, D *rightOmpClauseList) {
589+ D *leftOmpClauseList, D *rightOmpClauseList, std::string_view dirName) {
590+ bool foundHint{false };
591+
590592 auto checkForValidHintClause = [&](const D *clauseList) {
591593 for (const auto &clause : clauseList->v ) {
592- const parser::OmpClause *ompClause = nullptr ;
594+ const parser::OmpHintClause *ompHintClause = nullptr ;
593595 if constexpr (std::is_same_v<D, const parser::OmpAtomicClauseList>) {
594- ompClause = std::get_if<parser::OmpClause>(&clause.u );
595- if (!ompClause)
596- continue ;
596+ ompHintClause = std::get_if<parser::OmpHintClause>(&clause.u );
597597 } else if constexpr (std::is_same_v<D, const parser::OmpClauseList>) {
598- ompClause = &clause;
598+ if (auto *hint{std::get_if<parser::OmpClause::Hint>(&clause.u )}) {
599+ ompHintClause = &hint->v ;
600+ }
599601 }
600- if (const parser::OmpClause::Hint *hintClause{
601- std::get_if<parser::OmpClause::Hint>(&ompClause->u )}) {
602- std::optional<std::int64_t > hintValue = GetIntValue (hintClause->v );
603- if (hintValue && *hintValue >= 0 ) {
604- /* `omp_sync_hint_nonspeculative` and `omp_lock_hint_speculative`*/
605- if ((*hintValue & 0xC ) == 0xC
606- /* `omp_sync_hint_uncontended` and omp_sync_hint_contended*/
607- || (*hintValue & 0x3 ) == 0x3 )
608- context_.Say (clause.source ,
609- " Hint clause value "
610- " is not a valid OpenMP synchronization value" _err_en_US);
611- } else {
602+ if (!ompHintClause)
603+ continue ;
604+ if (foundHint) {
605+ context_.Say (clause.source ,
606+ " At most one HINT clause can appear on the %s directive" _err_en_US,
607+ parser::ToUpperCaseLetters (dirName));
608+ }
609+ foundHint = true ;
610+ std::optional<std::int64_t > hintValue = GetIntValue (ompHintClause->v );
611+ if (hintValue && *hintValue >= 0 ) {
612+ /* `omp_sync_hint_nonspeculative` and `omp_lock_hint_speculative`*/
613+ if ((*hintValue & 0xC ) == 0xC
614+ /* `omp_sync_hint_uncontended` and omp_sync_hint_contended*/
615+ || (*hintValue & 0x3 ) == 0x3 )
612616 context_.Say (clause.source ,
613- " Hint clause must have non-negative constant "
614- " integer expression" _err_en_US);
615- }
617+ " Hint clause value "
618+ " is not a valid OpenMP synchronization value" _err_en_US);
619+ } else {
620+ context_.Say (clause.source ,
621+ " Hint clause must have non-negative constant "
622+ " integer expression" _err_en_US);
616623 }
617624 }
618625 };
@@ -2375,7 +2382,7 @@ void OmpStructureChecker::Enter(const parser::OpenMPCriticalConstruct &x) {
23752382 " Hint clause other than omp_sync_hint_none cannot be specified for "
23762383 " an unnamed CRITICAL directive" _err_en_US});
23772384 }
2378- CheckHintClause<const parser::OmpClauseList>(&ompClause, nullptr );
2385+ CheckHintClause<const parser::OmpClauseList>(&ompClause, nullptr , " CRITICAL " );
23792386}
23802387
23812388void OmpStructureChecker::Leave (const parser::OpenMPCriticalConstruct &) {
@@ -2950,7 +2957,7 @@ void OmpStructureChecker::Enter(const parser::OpenMPAtomicConstruct &x) {
29502957 nullptr );
29512958 CheckHintClause<const parser::OmpAtomicClauseList>(
29522959 &std::get<parser::OmpAtomicClauseList>(atomicConstruct.t ),
2953- nullptr );
2960+ nullptr , " ATOMIC " );
29542961 },
29552962 [&](const parser::OmpAtomicUpdate &atomicUpdate) {
29562963 const auto &dir{std::get<parser::Verbatim>(atomicUpdate.t )};
@@ -2963,7 +2970,8 @@ void OmpStructureChecker::Enter(const parser::OpenMPAtomicConstruct &x) {
29632970 CheckAtomicMemoryOrderClause (
29642971 &std::get<0 >(atomicUpdate.t ), &std::get<2 >(atomicUpdate.t ));
29652972 CheckHintClause<const parser::OmpAtomicClauseList>(
2966- &std::get<0 >(atomicUpdate.t ), &std::get<2 >(atomicUpdate.t ));
2973+ &std::get<0 >(atomicUpdate.t ), &std::get<2 >(atomicUpdate.t ),
2974+ " UPDATE" );
29672975 },
29682976 [&](const parser::OmpAtomicRead &atomicRead) {
29692977 const auto &dir{std::get<parser::Verbatim>(atomicRead.t )};
@@ -2972,7 +2980,7 @@ void OmpStructureChecker::Enter(const parser::OpenMPAtomicConstruct &x) {
29722980 CheckAtomicMemoryOrderClause (
29732981 &std::get<0 >(atomicRead.t ), &std::get<2 >(atomicRead.t ));
29742982 CheckHintClause<const parser::OmpAtomicClauseList>(
2975- &std::get<0 >(atomicRead.t ), &std::get<2 >(atomicRead.t ));
2983+ &std::get<0 >(atomicRead.t ), &std::get<2 >(atomicRead.t ), " READ " );
29762984 CheckAtomicCaptureStmt (
29772985 std::get<parser::Statement<parser::AssignmentStmt>>(
29782986 atomicRead.t )
@@ -2985,7 +2993,8 @@ void OmpStructureChecker::Enter(const parser::OpenMPAtomicConstruct &x) {
29852993 CheckAtomicMemoryOrderClause (
29862994 &std::get<0 >(atomicWrite.t ), &std::get<2 >(atomicWrite.t ));
29872995 CheckHintClause<const parser::OmpAtomicClauseList>(
2988- &std::get<0 >(atomicWrite.t ), &std::get<2 >(atomicWrite.t ));
2996+ &std::get<0 >(atomicWrite.t ), &std::get<2 >(atomicWrite.t ),
2997+ " WRITE" );
29892998 CheckAtomicWriteStmt (
29902999 std::get<parser::Statement<parser::AssignmentStmt>>(
29913000 atomicWrite.t )
@@ -2998,7 +3007,8 @@ void OmpStructureChecker::Enter(const parser::OpenMPAtomicConstruct &x) {
29983007 CheckAtomicMemoryOrderClause (
29993008 &std::get<0 >(atomicCapture.t ), &std::get<2 >(atomicCapture.t ));
30003009 CheckHintClause<const parser::OmpAtomicClauseList>(
3001- &std::get<0 >(atomicCapture.t ), &std::get<2 >(atomicCapture.t ));
3010+ &std::get<0 >(atomicCapture.t ), &std::get<2 >(atomicCapture.t ),
3011+ " CAPTURE" );
30023012 CheckAtomicCaptureConstruct (atomicCapture);
30033013 },
30043014 [&](const parser::OmpAtomicCompare &atomicCompare) {
@@ -3008,7 +3018,8 @@ void OmpStructureChecker::Enter(const parser::OpenMPAtomicConstruct &x) {
30083018 CheckAtomicMemoryOrderClause (
30093019 &std::get<0 >(atomicCompare.t ), &std::get<2 >(atomicCompare.t ));
30103020 CheckHintClause<const parser::OmpAtomicClauseList>(
3011- &std::get<0 >(atomicCompare.t ), &std::get<2 >(atomicCompare.t ));
3021+ &std::get<0 >(atomicCompare.t ), &std::get<2 >(atomicCompare.t ),
3022+ " CAPTURE" );
30123023 CheckAtomicCompareConstruct (atomicCompare);
30133024 },
30143025 },
0 commit comments