[clang][OpenMP] Keep 'requires' directives read from an AST file (#220058)

An OpenMP `requires` directive is recorded in Sema when the directive is
parsed
(`SemaOpenMP::ActOnOpenMPRequiresDirective`). Nothing repopulated that
list from an AST
file. A translation unit that gets its `requires` directive from a PCH
or a module
therefore behaves as if the directive were absent, and clang rejects
valid code.

`OMPRequiresDecl` is already serialized and eagerly deserialized, so the
declaration is
present in the AST. Only Sema's view of it was missing.

## Reproducer

```c++
// rev.h
#pragma omp requires reverse_offload
void foo();
```

```c++
// use.cpp
void bar(int argc) {
#pragma omp target device(ancestor : argc)
  foo();
}
```

```
$ clang -cc1 -fopenmp -fopenmp-version=51 -fopenmp-targets=x86_64 -triple x86_64 \
        -x c++ -emit-pch -o r.pch rev.h
$ clang -cc1 -fopenmp -fopenmp-version=51 -fopenmp-targets=x86_64 -triple x86_64 \
        -include-pch r.pch -fsyntax-only use.cpp
use.cpp:2:20: error: device clause with ancestor device-modifier used without specifying 'requires reverse_offload'
```

The requirement is specified, so the diagnostic is a false positive. The
same code in a
single file compiles cleanly, because the directive is then parsed in
this TU.

`-fopenmp-targets=` matters. Without an offload target clang defers this
diagnostic and
then drops it, because a host compilation never flushes its deferred
diagnostics. That is
a separate bug, with a fix to follow, and it makes this false positive
reachable in the
default configuration too.

`reverse_offload` is the case with a directly observable diagnostic. The
same state feeds
every `hasRequiresDeclWithClause` query, so `dynamic_allocators` (on a
device compilation)
and `unified_shared_memory` (which changes implicit data-sharing instead
of emitting a
diagnostic) read it as well.

## Fix

Write the `requires` directives into the AST file and register them with
Sema, following
the existing `DeclsWithEffectsToVerify` pattern. This happens in
`ASTReader::UpdateSema`
rather than `ASTReader::InitializeSema` because `UpdateSema` runs after
every AST file is
loaded. A directive can come from a module loaded during the compilation
rather than up
front.

Tests cover both the PCH and the module path.

The contents of this PR is created with help from Claude Code and
ChatGPT.

---------

Co-authored-by: Alexey Bataev <a.bataev@gmx.com>
10 files changed
tree: 09ff5bfdd832eb3b5c0c02ddea9581cfbd2fb6eb
  1. .ci/
  2. .github/
  3. bolt/
  4. clang/
  5. clang-tools-extra/
  6. cmake/
  7. compiler-rt/
  8. cross-project-tests/
  9. flang/
  10. flang-rt/
  11. libc/
  12. libclc/
  13. libcxx/
  14. libcxxabi/
  15. libsycl/
  16. libunwind/
  17. lld/
  18. lldb/
  19. llvm/
  20. llvm-libgcc/
  21. mlir/
  22. offload/
  23. openmp/
  24. orc-rt/
  25. polly/
  26. runtimes/
  27. third-party/
  28. utils/
  29. .clang-format
  30. .clang-format-ignore
  31. .clang-tidy
  32. .git-blame-ignore-revs
  33. .gitattributes
  34. .gitignore
  35. .mailmap
  36. CODE_OF_CONDUCT.md
  37. CONTRIBUTING.md
  38. LICENSE.TXT
  39. pyproject.toml
  40. README.md
  41. SECURITY.md
README.md

The LLVM Compiler Infrastructure

OpenSSF Scorecard OpenSSF Best Practices libc++

Welcome to the LLVM project!

This repository contains the source code for LLVM, a toolkit for the construction of highly optimized compilers, optimizers, and run-time environments.

The LLVM project has multiple components. The core of the project is itself called “LLVM”. This contains all of the tools, libraries, and header files needed to process intermediate representations and convert them into object files. Tools include an assembler, disassembler, bitcode analyzer, and bitcode optimizer.

C-like languages use the Clang frontend. This component compiles C, C++, Objective-C, and Objective-C++ code into LLVM bitcode -- and from there into object files, using LLVM.

Other components include: the libc++ C++ standard library, the LLD linker, and more.

Getting the Source Code and Building LLVM

Consult the Getting Started with LLVM page for information on building and running LLVM.

For information on how to contribute to the LLVM project, please take a look at the Contributing to LLVM guide.

Getting in touch

Join the LLVM Discourse forums, Discord chat, LLVM Office Hours or Regular sync-ups.

The LLVM project has adopted a code of conduct for participants to all modes of communication within the project.