|
23 | 23 | #include "flang/Semantics/openmp-modifiers.h" |
24 | 24 | #include "flang/Semantics/symbol.h" |
25 | 25 | #include "flang/Semantics/tools.h" |
| 26 | +#include "llvm/Frontend/OpenMP/OMP.h.inc" |
26 | 27 | #include "llvm/Support/Debug.h" |
27 | 28 | #include <list> |
28 | 29 | #include <map> |
@@ -740,9 +741,7 @@ class OmpAttributeVisitor : DirectiveAttributeVisitor<llvm::omp::Directive> { |
740 | 741 | } |
741 | 742 |
|
742 | 743 | const parser::OmpClause *associatedClause{nullptr}; |
743 | | - void SetAssociatedClause(const parser::OmpClause &c) { |
744 | | - associatedClause = &c; |
745 | | - } |
| 744 | + void SetAssociatedClause(const parser::OmpClause *c) { associatedClause = c; } |
746 | 745 | const parser::OmpClause *GetAssociatedClause() { return associatedClause; } |
747 | 746 |
|
748 | 747 | private: |
@@ -1919,12 +1918,17 @@ std::int64_t OmpAttributeVisitor::GetAssociatedLoopLevelFromClauses( |
1919 | 1918 | } |
1920 | 1919 |
|
1921 | 1920 | if (orderedLevel && (!collapseLevel || orderedLevel >= collapseLevel)) { |
1922 | | - SetAssociatedClause(*ordClause); |
| 1921 | + SetAssociatedClause(ordClause); |
1923 | 1922 | return orderedLevel; |
1924 | 1923 | } else if (!orderedLevel && collapseLevel) { |
1925 | | - SetAssociatedClause(*collClause); |
| 1924 | + SetAssociatedClause(collClause); |
1926 | 1925 | return collapseLevel; |
1927 | | - } // orderedLevel < collapseLevel is an error handled in structural checks |
| 1926 | + } else { |
| 1927 | + SetAssociatedClause(nullptr); |
| 1928 | + } |
| 1929 | + // orderedLevel < collapseLevel is an error handled in structural |
| 1930 | + // checks |
| 1931 | + |
1928 | 1932 | return 1; // default is outermost loop |
1929 | 1933 | } |
1930 | 1934 |
|
@@ -1952,9 +1956,31 @@ void OmpAttributeVisitor::PrivatizeAssociatedLoopIndexAndCheckLoopLevel( |
1952 | 1956 | ivDSA = Symbol::Flag::OmpLastPrivate; |
1953 | 1957 | } |
1954 | 1958 |
|
| 1959 | + bool isLoopConstruct{ |
| 1960 | + GetContext().directive == llvm::omp::Directive::OMPD_loop}; |
| 1961 | + const parser::OmpClause *clause{GetAssociatedClause()}; |
| 1962 | + bool hasCollapseClause{ |
| 1963 | + clause ? (clause->Id() == llvm::omp::OMPC_collapse) : false}; |
| 1964 | + |
1955 | 1965 | const auto &outer{std::get<std::optional<parser::DoConstruct>>(x.t)}; |
1956 | 1966 | if (outer.has_value()) { |
1957 | 1967 | for (const parser::DoConstruct *loop{&*outer}; loop && level > 0; --level) { |
| 1968 | + if (loop->IsDoConcurrent()) { |
| 1969 | + // DO CONCURRENT is explicitly allowed for the LOOP construct so long as |
| 1970 | + // there isn't a COLLAPSE clause |
| 1971 | + if (isLoopConstruct) { |
| 1972 | + if (hasCollapseClause) { |
| 1973 | + // hasCollapseClause implies clause != nullptr |
| 1974 | + context_.Say(clause->source, |
| 1975 | + "DO CONCURRENT loops cannot be used with the COLLAPSE clause."_err_en_US); |
| 1976 | + } |
| 1977 | + } else { |
| 1978 | + auto &stmt = |
| 1979 | + std::get<parser::Statement<parser::NonLabelDoStmt>>(loop->t); |
| 1980 | + context_.Say(stmt.source, |
| 1981 | + "DO CONCURRENT loops cannot form part of a loop nest."_err_en_US); |
| 1982 | + } |
| 1983 | + } |
1958 | 1984 | // go through all the nested do-loops and resolve index variables |
1959 | 1985 | const parser::Name *iv{GetLoopIndex(*loop)}; |
1960 | 1986 | if (iv) { |
|
0 commit comments