Fixes https://github.com/llvm/llvm-project/issues/173980.
In particular, make step-simple-modifier be compatible (i.e. not
exclusive) for OpenMP spec versions < 52, and update the modifier
validity checks for the construct on which the clause is located.
Follow-up to PR175211.
There are still a few AST nodes that don't have any of the standard
traits (Wrapper/Tuple/etc). Because of that they require special
handling in the parse tree visitor.
Convert a subset of these nodes to the typical format, and remove the
special cases from the parse tree visitor.
The members of these nodes were frequently used, so instead of
extracting them by hand each time use helper member functions to access
them.
Fixes#175688
After #175383 was merged, test failures occurred because removing the
early return exposed additional errors that tests weren't expecting.
This PR comprehensively fixes the issue by:
1. **Removes the early return** in check-omp-loop.cpp (line 767) after
detecting a modifier error on DO/SIMD directives. Previously, when a
modifier error was found, the function would return immediately without
checking other restrictions like the scalar requirement. Now all
applicable errors are reported, improving diagnostics.
2. **Updates linear-clause01.f90** to expect both the modifier error AND
the scalar error for Case 1 and Case 2, where arrays are used
incorrectly in LINEAR clauses.
3. **Updates clause-validity01.f90** to use the new OpenMP 5.2 syntax
(`linear(b: val)` instead of `linear(val(b))`). The old syntax triggers
deprecation warnings, which are now caught because we no longer return
early after the modifier error.
Thanks to @ergawy for identifying the clause-validity01.f90 fix needed.
The changes ensure better error reporting for users - they now see all
issues with their LINEAR clauses instead of just the first error.
Fixes#175688
After #175383 was merged, the test
`Semantics/OpenMP/linear-clause01.f90` was failing because it had an
early return that prevented multiple errors from being reported.
This PR fixes two issues:
1. **Removes the early return** after detecting a modifier error on
DO/SIMD directives. Previously, when a modifier error was found, the
function would return immediately without checking other restrictions
like the scalar requirement. Now all applicable errors are reported.
2. **Updates test expectations** to expect both the modifier error AND
the scalar error for Case 1, where `arg(:)` is an array used with `uval`
modifier on a DO directive.
Thanks to @NimishMishra for catching this during review - arrays should
always be rejected in LINEAR clauses (except for `declare simd` with
`ref` modifier), regardless of whether there are other errors.
Closes#171007
Found this crash while testing OpenMP code - turns out putting an array
in a LINEAR clause on SIMD directives causes the compiler to blow up
with "unknown LLVM dialect type" and hit an UNREACHABLE.
The issue is that LINEAR clauses only accept scalar variables (rank 0),
but we weren't checking for that early enough. The invalid array type
would slip through semantic analysis and then crash during MLIR to LLVM
IR translation when it tried to convert the type.
**What changed:**
- Added a rank check in the LINEAR clause validation to catch arrays up
front
- Made an exception for `declare simd` with the REF modifier since
that's actually allowed per spec
- Added tests covering different array types (1D, multi-dim,
assumed-shape)
- Updated existing tests that now catch the new error
Tested with the original reproducer and it now fails cleanly with a
proper error message instead of crashing.
For an OpenMP loop construct, count how many loops will effectively be
contained in its associated block. For constructs that are loop-nest
associated this number should be 1. Report cases where this number is
different.
Take into account that the block associated with a loop construct can
contain compiler directives.
In a label-DO construct where two or more loops share the same
teminator, an OpenMP construct must enclose all the loops if an
end-directive is present. E.g.
```
do 100 i = 1,10
!$omp do
do 100 j = 1,10
100 continue
!$omp end do ! Error, but ok if this line is removed
```
Fixes https://github.com/llvm/llvm-project/issues/169536.
PR168884 flagged compiler directives (!dir$ ...) inside OpenMP loop
constructs as errors. This caused some customer applications to fail to
compile (issue 169229).
Downgrade the error to a warning, and gracefully ignore compiler
directives when lowering loop constructs to MLIR.
Fixes https://github.com/llvm/llvm-project/issues/169229
Previously, loop constructs were parsed in a piece-wise manner: the
begin directive, the body, and the end directive were parsed separately.
Later on in canonicalization they were all coalesced into a loop
construct. To facilitate that end-loop directives were given a special
treatment, namely they were parsed as OpenMP constructs. As a result
syntax errors caused by misplaced end-loop directives were handled
differently from those cause by misplaced non-loop end directives.
The new loop nest parser constructs the complete loop construct,
removing the need for the canonicalization step. Additionally, it is the
basis for parsing loop-sequence-associated constructs in the future.
It also removes the need for the special treatment of end-loop
directives. While this patch temporarily degrades the error messaging
for misplaced end-loop directives, it enables uniform handling of any
misplaced end-directives in the future.
This patch adds semantics for the `omp fuse` directive in flang, as
specified in OpenMP 6.0. This patch also enables semantic support for
loop sequences which are needed for the fuse directive along with
semantics for the `looprange` clause. These changes are only semantic.
Relevant tests have been added , and previous behavior is retained with
no changes.
---------
Co-authored-by: Ferran Toda <ferran.todacasaban@bsc.es>
Co-authored-by: Krzysztof Parzyszek <Krzysztof.Parzyszek@amd.com>
Instead of storing a variant with specific types, store parser::Block as
the body. Add two access functions to make the traversal of the nest
simpler.
This will allow storing loop-nest sequences in the future.
If there is a call inside a TEAMS construct, and that call contains a
DISTRIBUTE construct, the DISTRIBUTE region is considered to be enclosed
by the TEAMS region (based on the dynamic extent of the construct).
Currently, Flang diagnoses this as an error, which is incorrect.
For eg :
```
subroutine f
!$omp distribute
do i = 1, 100
...
end do
end subroutine
subroutine g
!$omp teams
call f ! this call is ok, distribute enclosed by teams
!$omp end teams
end subroutine
```
This patch adjusts the nesting check for the OpenMP DISTRIBUTE
directive. It retains the error for DISTRIBUTE directives that are
incorrectly nested lexically but downgrades it to a warning for orphaned
directives to allow dynamic nesting, such as when a subroutine with
DISTRIBUTE is called from within a TEAMS region.
Co-authored-by: Chandra Ghale <ghale@pe31.hpc.amslabs.hpecorp.net>
…rective
This makes accessing directive components, such as directive name or the
list of clauses simpler and more uniform across different directives. It
also makes the parser simpler, since it reuses existing parsing
functionality.
The changes are scattered over a number of files, but they all share the
same nature:
- getting the begin/end directive from OpenMPLoopConstruct,
- getting the llvm::omp::Directive enum, and the source location,
- getting the clause list.
OpenMPBlockConstruct, somewhat confusingly, represents most but not all
block-associated constructs. It's derived from OmpBlockConstruct, as are
all the remaining block-associated constructs.
It does not correspond to any well-defined group of constructs. It's the
collection of constructs that don't have their own types (and those that
do have their own types do so for their own reasons).
Using the broader OmpBlockConstruct in type-based visitors won't cause
issues, because the specific overloads (for classes derived from it)
will always be preferred.
The structure is
- OmpBeginDirective (aka OmpDirectiveSpecification)
- Block
- optional<OmpEndDirective> (aka optional<OmpDirectiveSpecification>)
The OmpBeginDirective and OmpEndDirective are effectively different
names for OmpDirectiveSpecification. They exist to allow the semantic
analyses to distinguish between the beginning and the ending of a block
construct without maintaining additional context.
The actual changes are in the parser: parse-tree.h and openmp-parser.cpp
in particular. The rest is simply changing the way the directive/clause
information is accessed (typically for the simpler).
All standalone and block constructs now use OmpDirectiveSpecification to
store the directive/clause information.
Create these new files in flang/lib/Semantics:
openmp-utils.cpp/.h - Common utilities
check-omp-atomic.cpp - Atomic-related checks
check-omp-loop.cpp - Loop constructs/clauses
check-omp-metadirective.cpp - Metadirective-related checks
Update lists of included headers, std in particular.
---------
Co-authored-by: Jack Styles <jack.styles@arm.com>