[flang][OpenMP] Gate the allocate clause at OpenMP 5.0 (#213980)
`allocate` is an OpenMP 5.0 clause, but 58 of the 62 directives that
allow it declare it as
bare `VersionedClause<OMPC_Allocate>`. The default in `DirectiveBase.td`
is `min = 1`:
```
class VersionedClause<Clause c, int min = 1, int max = 0x7FFFFFFF> : Versioned<min, max>
```
so those 58 accept the clause at every version. Only four are gated
today: `do`, `taskgroup`
and `parallel do` at 50, and `scope` at 52.
This is reachable in practice because flang defaults to OpenMP 3.1
(`newestFullySupported = 31`, `CompilerInvocation.cpp`). An invocation
with no
`-fopenmp-version=` lands in the ungated range, semantics accepts the
clause, and
`ConstructDecomposition` then correctly refuses to decompose it.
Lowering consumes the empty
result and crashes:
```
$ flang -fc1 -emit-hlfir -fopenmp repro.f90
Segmentation fault
```
In an assertions build it is caught at `Decomposer.cpp:85`:
```
Assertion `!decompose.output.empty() && "Construct decomposition failed"' failed.
```
With the gate, that becomes a diagnostic:
```
error: ALLOCATE clause is not allowed on TARGET TEAMS DISTRIBUTE PARALLEL DO directive
in OpenMP v3.1, try -fopenmp-version=50
```
Reported as #211430.
### Scope
This fixes reachability, not the underlying memory error, and should not
be read as a complete
fix for #211430. Consuming a failed decomposition reads uninitialized
memory, which is why the
crash is intermittent — measured on a release build at a pinned
`-fopenmp-version=31`, 40 trials
each:
| | segfaults |
|---|---|
| ASLR on | 25/40 |
| ASLR off (`setarch -R`) | 0/40 |
Any other clause/directive combination that makes decomposition return
empty will hit the same
path. Making that path diagnose and bail rather than fall through is a
separate change.
I also left the gate uniform at 50 rather than tightening per directive.
`allocators` is a 5.2
construct, so by the precedent `scope` sets its clause could be 52; that
argument applies to
several directives here and depends on each one's introduction version,
so it seemed better kept
out of a mechanical change.
### Tests
Nine tests exercised `allocate` through bare `%openmp_flags` (i.e.
`-fopenmp` with no version) and
so depended on the missing gate. Seven get `-fopenmp-version=50`. The
two `allocators` tests get
52, which is what their own `! OpenMP Version 5.2` header comments
already claim they are testing.
### Verification
| suite | tests | failed |
|---|---|---|
| `check-flang` | 4808 | 0 |
| `mlir/test/Dialect/OpenMP`, `mlir/test/Target/LLVMIR`,
`llvm/test/Frontend` | 425 | 0 |
| `clang/test/OpenMP` | 1594 | 0 |
clang version-checks `allocate` in its own semantic analysis rather than
through this table, but
it shares `OMP.td`, so I ran it to confirm.
---
Parts of this change were written or audited with Claude Code. I have
reviewed all of it and take
full responsibility for the contribution. See
`llvm/docs/AIToolPolicy.md`.