|
3 | 3 | // any compilation pass, including device. Customers compile their device |
4 | 4 | // code with -fsycl-device-only and expect a clean dependency graph; pulling |
5 | 5 | // the standard iostream machinery breaks that contract by introducing |
6 | | -// host-only globals (std::cin/cout/cerr) and ios_base::Init static |
| 6 | +// globals (std::cin/cout/cerr) and ios_base::Init static |
7 | 7 | // initializers that fail in device JIT/AOT pipelines. |
8 | 8 | // |
9 | 9 | // This test enforces that contract for every KHR header by compiling a |
|
15 | 15 | // offending stream code into the SYCL runtime (sycl/source/...) and keep |
16 | 16 | // the header device-clean. |
17 | 17 | // |
| 18 | +// We enforce the contract with TWO complementary guards, because the -MD |
| 19 | +// dependency list is flat (it records that a header was reached, not who |
| 20 | +// pulled it in): |
| 21 | +// |
| 22 | +// 1. A FileCheck pass over the -MD list that rejects the iostream |
| 23 | +// machinery -- <iostream>, the iostream_proxy shim, and the C-style |
| 24 | +// *.h stream headers. These are never dragged in by <iterator>; their |
| 25 | +// presence means real std::cin/cout/cerr globals and an ios_base::Init |
| 26 | +// static initializer entered the graph. |
| 27 | +// |
| 28 | +// 2. A source-grep guard that rejects any *raw* `#include <ostream>`, |
| 29 | +// <istream>, <iostream> or <sstream> written in a SYCL header that the |
| 30 | +// KHR umbrella actually reaches. This is what catches an author adding a |
| 31 | +// stream include to a KHR-reachable header. |
| 32 | +// |
| 33 | +// Why not simply CHECK-NOT the bare <ostream>/<istream> paths in the -MD list? |
| 34 | +// Because on old libstdc++ (e.g. gcc 8) <iterator> unconditionally pulls in |
| 35 | +// <ostream>/<istream> to define std::ostream_iterator/istream_iterator, and |
| 36 | +// the KHR surface legitimately uses <iterator> (via sycl/multi_ptr.hpp). |
| 37 | +// Newer libstdc++ and libc++ do not. So a bare-path check both false-fails on |
| 38 | +// old toolchains and, being a stdlib artifact, does not actually indicate a |
| 39 | +// SYCL header regression. Guard #2 catches the real regression (a raw include |
| 40 | +// in our own header) regardless of standard-library version. |
| 41 | +// |
18 | 42 | // <sycl/sycl.hpp> and headers under <sycl/ext/...> are intentionally out of |
19 | 43 | // scope -- only the KHR set is required to be device-safe today. The OV team |
20 | 44 | // will interface mainly through the kernel compiler and the KHR headers. As |
|
27 | 51 | // sycl.hpp from this test. |
28 | 52 | // |
29 | 53 | // RUN: %clangxx -fsycl -fsycl-device-only -include %S/Inputs/khr_all.hpp \ |
30 | | -// RUN: -c %s -o %t.o -MD -MF - | FileCheck %s |
| 54 | +// RUN: -c %s -o %t.o -MD -MF %t.d |
| 55 | +// |
| 56 | +// Guard 1: no iostream machinery in the dependency graph. |
| 57 | +// RUN: FileCheck %s < %t.d |
| 58 | +// |
| 59 | +// Guard 2: no raw stream #include in any KHR-reachable SYCL header. Extract the |
| 60 | +// SYCL header paths from the -MD list and grep their sources. `not` wraps the |
| 61 | +// inner grep so the pipeline fails iff a stream include is found; `xargs -r` |
| 62 | +// avoids running grep on an empty header list. |
| 63 | +// RUN: grep -oE '[^ ]*/include/sycl/[^ ]*\.hpp' %t.d \ |
| 64 | +// RUN: | xargs -r not grep -HnE '^[[:space:]]*#[[:space:]]*include[[:space:]]*<(iostream|istream|ostream|sstream)>' |
| 65 | +// |
| 66 | +// REQUIRES: linux |
31 | 67 | // |
32 | 68 | // CHECK-NOT: iostream_proxy.hpp |
33 | 69 | // CHECK-NOT: {{/iostream[ \\]}} |
34 | | -// CHECK-NOT: {{/ostream[ \\]}} |
35 | | -// CHECK-NOT: {{/istream[ \\]}} |
36 | 70 | // CHECK-NOT: {{/iostream\.h}} |
37 | 71 | // CHECK-NOT: {{/ostream\.h}} |
38 | 72 | // CHECK-NOT: {{/istream\.h}} |
0 commit comments