Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[C++20] [Modules] static function used in template function in C++-20 module not found #78173

Open
ZhalgasFromMSU opened this issue Jan 15, 2024 · 2 comments
Assignees
Labels
clang:modules C++20 modules and Clang Header Modules

Comments

@ZhalgasFromMSU
Copy link

Hi!

NB:
Here is a sample project, depicting the problem: https://godbolt.org/z/neo8M8orM

Imagine, that I have a static inline function foo_header, defined in some header:

// header.hpp
#pragma once

static inline int foo_header(int x) {
    return x;
}

And this function is used in a template function foo_module in some module:

// module.cpp
module;
#include "header.hpp"

export module Mod;

export template<typename T>
T foo_module(T x) {
    return foo_header(x);
}

Now I want to use latter in my main.cpp:

// main.cpp
import Mod;

int main() {
    int x = foo_module(5);
    return 0;
}

However, clang falsely claims, that there is no matching function foo_header:

In file included from /app/main.cpp:1:
module.cpp:9:12: error: no matching function for call to 'foo_header'
    9 |     return foo_header(x);
      |            ^~~~~~~~~~
main.cpp:4:13: note: in instantiation of function template specialization 'foo_module<int>' requested here
    4 |     int x = foo_module(5);
      |             ^
1 error generated.

Here are some observation, based on which, I make an assumption that this is a clang bug:

  1. This code compiles/works properly on trunk of gcc
  2. This code compiles/works properly if I explicitly cast template parameter T to int like this:
// module.cpp
export template<typename T>
T foo_module(T x) {
    return foo_header(static_cast<int>(x));
}
  1. This code compiles/works properly if I remove keyword static from foo_header function declaration

Based on those observations, I could assume that body of foo_module template function gets compiled in different translation unit, from where header was included, and therefore static specifier on foo_header hides this function

@EugeneZelenko EugeneZelenko added clang:modules C++20 modules and Clang Header Modules and removed new issue labels Jan 15, 2024
@llvmbot
Copy link
Collaborator

llvmbot commented Jan 15, 2024

@llvm/issue-subscribers-clang-modules

Author: None (ZhalgasFromMSU)

Hi!

NB:
Here is a sample project, depicting the problem: https://godbolt.org/z/neo8M8orM

Imagine, that I have a static inline function foo_header, defined in some header:

// header.hpp
#pragma once

static inline int foo_header(int x) {
    return x;
}

And this function is used in a template function foo_module in some module:

// module.cpp
module;
#include "header.hpp"

export module Mod;

export template&lt;typename T&gt;
T foo_module(T x) {
    return foo_header(x);
}

Now I want to use latter in my main.cpp:

// main.cpp
import Mod;

int main() {
    int x = foo_module(5);
    return 0;
}

However, clang falsely claims, that there is no matching function foo_header:

In file included from /app/main.cpp:1:
module.cpp:9:12: error: no matching function for call to 'foo_header'
    9 |     return foo_header(x);
      |            ^~~~~~~~~~
main.cpp:4:13: note: in instantiation of function template specialization 'foo_module&lt;int&gt;' requested here
    4 |     int x = foo_module(5);
      |             ^
1 error generated.

Here are some observation, based on which, I make an assumption that this is a clang bug:

  1. This code compiles/works properly on trunk of gcc
  2. This code compiles/works properly if I explicitly cast template parameter T to int like this:
// module.cpp
export template&lt;typename T&gt;
T foo_module(T x) {
    return foo_header(static_cast&lt;int&gt;(x));
}
  1. This code compiles/works properly if I remove keyword static from foo_header function declaration

Based on those observations, I could assume that body of foo_module template function gets compiled in different translation unit, from where header was included, and therefore static specifier on foo_header hides this function

@ChuanqiXu9 ChuanqiXu9 changed the title static function used in template function in C++-20 module not found [C++20] [Modules] static function used in template function in C++-20 module not found Jan 16, 2024
@ChuanqiXu9
Copy link
Member

ChuanqiXu9 commented Jan 16, 2024

In fact, the reproducer here is incorrect. We can find the wording and example in [basic.link/p14] to [basic.link/p19].

Then foo_header is a TU-local entity since it is static. And the implicit declaration of foo_module <int> in main.cpp uses the TU-local entity foo_header. So it is ill formed. We can find the example of g<1> in https://eel.is/c++draft/basic#link-19.

However, this is not supported in clang yet. So the diagnostic is not clear too.

@iains has patch for it. But I just wondered that, we may implement the semantics naturally by not emitting static declarations into the reduced BMI naturally.

@ChuanqiXu9 ChuanqiXu9 self-assigned this Jan 18, 2024
ChuanqiXu9 added a commit that referenced this issue Jan 22, 2024
Changed Things:
- Mentioning we need to specify BMIs for indirectly dependent BMIs too.
- Remove the note for `delayed-template-parsing` since
  #61068 got closed.
- Add a note for #78850 since
  we've seen it for a lot of times.
- Add a note for #78173 since
  we've seen it for a lot of times.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:modules C++20 modules and Clang Header Modules
Projects
None yet
Development

No branches or pull requests

4 participants