Issue 170235
Summary [C++20] [Modules] ADL lookup fails to find friend function defined before the befriending class in a module interface
Labels new issue
Assignees
Reporter someoneinjd
    When a function is defined in a module interface unit before the class that declares it as a friend, ADL fails to find this function in importers. This issue seems sensitive to the declaration order. If the function definition is moved after the class definition, ADL works as expected.

Here is a minimal reproduction case:

```cpp
// lib.cppm
export module lib;
namespace lib {
    struct A;
    // Definition comes BEFORE the class declaration
    int foo(const A &, int) { return 42; }

    struct A {
        // Friend declaration inside the class
        friend int foo(const A &, int);
    };

 export A a{};
}
// main.cpp
import lib;
int main() {
    // Should be found via ADL since lib::a is of type lib::A
    auto res1 = foo(lib::a, 1); 
    return 0;
}
```

compiled with: 

```bash
clang++ lib.cppm -o lib.pcm --precompile -std=c++20
clang++ main.cpp -o main -std=c++20 -fmodule-file=lib=lib.pcm
```

Clang version: https://github.com/llvm/llvm-project/commit/9324dae70f009ceb5c0e93b99e73c51fcaf67911

Clang fails to resolve the function `foo`:

```
main.cpp:4:17: error: use of undeclared identifier 'foo'
    4 |     auto res1 = foo(lib::a, 1); 
 |                 ^~~
1 error generated.
```

This bug critically impacts interoperability with libstdc++ when using C++20 ranges with `import std`.

libstdc++ implements range adaptor closures (like `std::views::reverse`) by defining the `operator|` before the `_RangeAdaptorClosure` class template:

```cpp
template<typename _Self, typename _Range>
constexpr auto operator|(_Range&& __r, _Self&& __self) { ... }

template<typename _Derived>
struct _RangeAdaptorClosure
{
 template<typename _Self, typename _Range>
    friend constexpr auto operator|(_Range&& __r, _Self&& __self);
    // ...
};
```

Consequently, the following code fails to compile with Clang and libstdc++:

```cpp
import std;
int main() {
    int arr[]{1, 2, 3, 4};
    // Fails to find operator| via ADL
    auto v0 = arr | std::views::reverse; 
}
```
_______________________________________________
llvm-bugs mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs

Reply via email to