Index: flang/lib/Semantics/check-omp-structure.h =================================================================== --- flang/lib/Semantics/check-omp-structure.h +++ flang/lib/Semantics/check-omp-structure.h @@ -191,6 +191,7 @@ } private: + void CheckMultListItems(); bool HasInvalidWorksharingNesting( const parser::CharBlock &, const OmpDirectiveSet &); bool IsCloselyNestedRegion(const OmpDirectiveSet &set); Index: flang/lib/Semantics/check-omp-structure.cpp =================================================================== --- flang/lib/Semantics/check-omp-structure.cpp +++ flang/lib/Semantics/check-omp-structure.cpp @@ -170,6 +170,42 @@ return false; } +void OmpStructureChecker::CheckMultListItems() { + semantics::UnorderedSymbolSet listVars; + auto checkMultipleOcurrence = [&](const std::list &nameList, + const parser::CharBlock &item, + const std::string &clauseName) { + for (auto const &var : nameList) { + if (llvm::is_contained(listVars, *(var.symbol))) { + context_.Say(item, + "List item '%s' present at multiple %s clauses"_err_en_US, + var.ToString(), clauseName); + } + listVars.insert(*(var.symbol)); + } + }; + + // Aligned clause + auto alignedClauses{FindClauses(llvm::omp::Clause::OMPC_aligned)}; + for (auto itr = alignedClauses.first; itr != alignedClauses.second; ++itr) { + const auto &alignedClause{ + std::get(itr->second->u)}; + const auto &alignedNameList{ + std::get>(alignedClause.v.t)}; + checkMultipleOcurrence(alignedNameList, itr->second->source, "ALIGNED"); + } + + // Nontemporal clause + auto nonTemporalClauses{FindClauses(llvm::omp::Clause::OMPC_nontemporal)}; + for (auto itr = nonTemporalClauses.first; itr != nonTemporalClauses.second; + ++itr) { + const auto &nontempClause{ + std::get(itr->second->u)}; + const auto &nontempNameList{nontempClause.v}; + checkMultipleOcurrence(nontempNameList, itr->second->source, "NONTEMPORAL"); + } +} + bool OmpStructureChecker::HasInvalidWorksharingNesting( const parser::CharBlock &source, const OmpDirectiveSet &set) { // set contains all the invalid closely nested directives @@ -1575,24 +1611,9 @@ } } } - // A list-item cannot appear in more than one aligned clause - semantics::UnorderedSymbolSet alignedVars; - auto clauseAll = FindClauses(llvm::omp::Clause::OMPC_aligned); - for (auto itr = clauseAll.first; itr != clauseAll.second; ++itr) { - const auto &alignedClause{ - std::get(itr->second->u)}; - const auto &alignedNameList{ - std::get>(alignedClause.v.t)}; - for (auto const &var : alignedNameList) { - if (alignedVars.count(*(var.symbol)) == 1) { - context_.Say(itr->second->source, - "List item '%s' present at multiple ALIGNED clauses"_err_en_US, - var.ToString()); - break; - } - alignedVars.insert(*(var.symbol)); - } - } + // Sema checks related to presence of multiple list items within the same + // clause + CheckMultListItems(); } // SIMD // 2.7.3 Single Construct Restriction Index: flang/test/Semantics/omp-simd-nontemporal.f90 =================================================================== --- /dev/null +++ flang/test/Semantics/omp-simd-nontemporal.f90 @@ -0,0 +1,63 @@ +! RUN: %python %S/test_errors.py %s %flang -fopenmp + +! OpenMP Version 4.5 +! 2.8.1 simd Construct +! Semantic error for correct test case + +program omp_simd + integer i, j, k + integer, allocatable :: a(:), b(:) + + allocate(a(10)) + allocate(b(10)) + + !ERROR: List item 'a' present at multiple NONTEMPORAL clauses + !$omp simd nontemporal(a, a) + do i = 1, 10 + a(i) = i + end do + !$omp end simd + + !ERROR: List item 'a' present at multiple NONTEMPORAL clauses + !ERROR: List item 'b' present at multiple NONTEMPORAL clauses + !$omp simd nontemporal(a,a) nontemporal(b) nontemporal(b) + do i = 1, 10 + a(i) = i + b(i) = i + end do + !$omp end simd + + !ERROR: List item 'a' present at multiple NONTEMPORAL clauses + !$omp simd nontemporal(a) nontemporal(a) + do i = 1, 10 + a(i) = i + end do + !$omp end simd + + !$omp simd nontemporal(a) nontemporal(b) + do i = 1, 10 + a(i) = i + b(i) = i + end do + !$omp end simd + + !ERROR: List item 'a' present at multiple NONTEMPORAL clauses + !$omp simd nontemporal(a) private(a) nontemporal(a) + do i = 1, 10 + a(i) = i + b(i) = i + end do + !$omp end simd + + !ERROR: List item 'a' present at multiple NONTEMPORAL clauses + !ERROR: List item 'b' present at multiple NONTEMPORAL clauses + !$omp simd nontemporal(a,a,b,b) + do i = 1, 10 + a(i) = i + b(i) = i + end do + !$omp end simd + + print *, a + +end program omp_simd