|
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