llvm / llvm/llvm-project

[clang][bytecode] A value made inside a module reads as uninitialised when the importer also includes a standard header textually

Open
#221,415 0 comments 0 reactions 0 assignees View on GitHub
clang:bytecode
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

Clang 22.1.8 (Debian, `22.1.8~++20260714014842+ca7933e47d3a`), target `x86_64-pc-linux-gnu`,
libc++ with its `std` module.

With `-fexperimental-new-constant-interpreter`, a `std::string_view` produced inside a module
that uses `import std;` is read as uninitialised by an importer that also includes
`` textually. Importing alone is fine; including alone is fine; the two together
are not. The default evaluator accepts all three.

### Reproducer

`m9.cppm`:

```cpp
export module m9;
import std;

export template
[[nodiscard]] constexpr auto views_of() {
// A constant of the module, and views into it handed back to the importer.
constexpr std::array storage{'a', 'b', 'c', 'd'};
std::array result{};
std::ranges::transform(result, result.begin(), [&](std::string_view) {
return std::string_view(storage.data(), storage.size());
});
return result;
}
```

`use.cpp`:

```cpp
#include

import m9;

consteval std::size_t evaluate() { return views_of<5>()[4].size(); }
static_assert(evaluate() == 4);
int main() {}
```

```sh
clang++ -std=c++23 -fmodule-file=std=std.pcm --precompile m9.cppm -o m9.pcm
clang++ -std=c++23 -fmodule-file=std=std.pcm -fmodule-file=m9=m9.pcm -fsyntax-only use.cpp
clang++ -std=c++23 -fmodule-file=std=std.pcm -fmodule-file=m9=m9.pcm -fsyntax-only \
-fexperimental-new-constant-interpreter use.cpp
```

The first compilation is accepted. The second reports:

```
use.cpp:6:15: error: static assertion expression is not an integral constant expression
string_view:404:103: note: read of uninitialized object is not allowed in a constant expression
```

### What narrows it down

- Replace `#include ` in the importer with `import std;`: accepted.
- Remove the include and import nothing else: accepted.
- Keep both: rejected.

So it is the two views of the same entity -- one from the `std` module the module unit
imported, one from the header the importer included -- and only the bytecode interpreter
minds.

### Where it was met

A library whose patterns are compiled entirely in constant evaluation, in a translation unit
that imports it and also includes two header-only libraries (a benchmark harness and another
regular expression library). Those headers pull in `` and `` textually,
and every pattern in the file stopped being a constant expression. The same library, in a
translation unit that imports and includes nothing textually, compiles and evaluates.

Contributor guide

Open the contributing guide

Research direction

Start by reproducing the commands with m9.cppm and use.cpp, then compare the default evaluator with -fexperimental-new-constant-interpreter across the three import/include combinations described. Trace the bytecode interpreter's handling of std::string_view values crossing the module boundary; done means the final static_assert is accepted when both import std and textual are present.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.