llvm / llvm/llvm-project

Clang modules does not handle visibility vs. reachability the same way as C++ named modules.

Open
#163,652 6 comments 0 reactions 0 assignees View on GitHub
clang:modules
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

Clang modules allow controlling the visibility of names using `export` in module maps. This long predates standard C++ modules and so has somewhat ad hoc semantics. A major difference is that in C++ 20 modules, `export` only controls the visibility of the name of an entity, while in Clang modules it also (kind of) controls if it is considered reachable.

Some examples:

```
module A {
header "A.h"
}

module B {
header "B.h"
}
```

```cpp
/// A.h
struct A0 {};

/// B.h
#include "A.h"
struct B0 {
A0 a0{};
};

using B1 = A0;

struct B2 : A0 {};

/// test.cpp - clang++ -fmodules -fsyntax-only test.cpp
#include "B.h"
B0 b0{}; // ok, but needs A0
const auto sizeB0 = sizeof(B0); // ok, but needs A0
B1 b1{}; // error: missing '#include "A.h"'; 'A0' must be defined before it is used
B2 b2{}; // error: missing '#include "A.h"'; 'A0' must be defined before it is used
decltype(B0::a0) a0{}; // error: missing '#include "A.h"'; 'A0' must be defined before it is used
```

With C++20 named modules:

```cpp
/// A.cppm
export module A;
export struct A0 {};

/// B.cppm
export module B;
import A;
export struct B0 {
A0 a0{};
};

export using B1 = A0;

export struct B2 : A0 {};

/// test.cpp
import B;
B0 b0{}; // ok
const auto sizeB0 = sizeof(B0); // ok
B1 b1{}; // ok
B2 b2{}; // ok
decltype(B0::a0) a0{}; // ok
```

We should model export in Clang modules the same way as it is in C++ named modules. Clang's current behavior allows a somewhat arbitrary set of things that require the definition of `A0` to be reachable.

We should also allow macros to reference non-exported macros with a similar set of rules to templates. If the expansion chain contains a source location where such a macro is visible then it should be. For example:

```cpp
// same module map as above

/// A.h
#define Anum 5

/// B.h
#include "A.h"
#define B(x) x##num

/// test.cpp
#include "B.h"
int i = B(A);
```

Contributor guide

Open the contributing guide

Research direction

Start by reproducing the module-map examples with clang++ -fmodules -fsyntax-only and compare the behavior with the C++20 named-module examples. Trace the existing Clang modules handling for exported names, reachability, and macro expansion; the work is done when the listed type uses and macro case follow the requested reachability rules and have regression coverage.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
compilers
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.