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] Don't generate paths implicitly in BMI to their dependent BMI #62707

Closed
ChuanqiXu9 opened this issue May 15, 2023 · 9 comments
Assignees
Labels
clang:modules C++20 modules and Clang Header Modules

Comments

@ChuanqiXu9
Copy link
Member

ChuanqiXu9 commented May 15, 2023

See https://discourse.llvm.org/t/c-20-modules-should-the-bmis-contain-paths-to-their-dependent-bmis/70422 for detail.

Simply, after the issue resolved, the last step of the following example won't compile any more:

// b.cppm
export module b;
export int b() {
    return 43;
}

// a.cppm
export module a;
import b;
export int a() {
    return b() + 43;
}

// user.cpp
import a;
int use() {
    return a();
}
clang++ -std=c++20 b.cppm --precompile -o b.pcm
clang++ -std=c++20 a.cppm --precompile -fmodule-file=b=b.pcm -o a.pcm
clang++ -std=c++20 user.cpp -fmodule-file=a=a.pcm -c -o user.o

We need to specify all the dependency explicitly:

clang++ -std=c++20 user.cpp -fmodule-file=a=a.pcm -fmodule-file=b=b.pcm  -c -o user.o

This should be a breaking change.

@ChuanqiXu9 ChuanqiXu9 added the clang:modules C++20 modules and Clang Header Modules label May 15, 2023
@llvmbot
Copy link
Collaborator

llvmbot commented May 15, 2023

@llvm/issue-subscribers-clang-modules

@ChuanqiXu9
Copy link
Member Author

Given the experience in clang, we should emit warnings for one version (clang17) and emit the hard error in the next version to not break too many things.

ChuanqiXu9 added a commit that referenced this issue May 17, 2023
…it generated path

A step to address #62707.

It is not user friendly enough to drop the implicitly generated path
directly. Let's emit the warning first and drop it in the next version.
@ChuanqiXu9 ChuanqiXu9 self-assigned this May 18, 2023
ChuanqiXu9 added a commit that referenced this issue May 23, 2023
Close #62843.

Previously when we compile .pcm files into .o files, the
`-fmodule-file=<module-name>=<module-path>` option is ignored. This is
conflicted with our consensus in
#62707.
@mathstuf
Copy link
Contributor

Note to self: when this ships, CMake needs to enable the transitive logic done for MSVC in Clang as well.

@iains
Copy link
Contributor

iains commented Jul 5, 2023

hi folks I came across this while making a demo for hidden partition use (somehow i missed the discussion that lead to this change - and I cannot see a paper or change to the std. that allows it)....

After this fix the following code ...

// RUN: rm -rf %t
// RUN: mkdir %t
// RUN: split-file %s %t

// Build the public interface for M
// RUN: %clang_cc1 -std=c++20 %t/M-Part1.cpp -emit-module-interface -o %t/M-Part1.pcm
// RUN: %clang_cc1 -std=c++20 %t/M.cpp -emit-module-interface -o %t/M.pcm -fmodule-file=M:Part1=%t/M-Part1.pcm
// RUN: %clang_cc1 -std=c++20 %t/M.pcm -emit-obj -o %t/M.o

// RUN: %clang_cc1 -std=c++20 %t/M-Part1-impl.cpp -emit-obj -o %t/M-Part1.o -fmodule-file=M:Part1=%t/M-Part1.pcm
// RUN: %clang_cc1 -std=c++20 %t/M-impl.cpp -emit-obj -o %t/M-impl.o -fmodule-file=M=%t/M.pcm

// Build a program using M
// RUN: %clang_cc1 -std=c++20 %t/Use-M.cpp -emit-obj -o %t/Use.o -fmodule-file=M=%t/M.pcm
// RUN: %clang -std=c++20 %t/Use.o %t/M.o %t/M-impl.o %t/M-Part1.o -o %t/Use

// Test that it works.
// RUN: %t/Use

// M and M:Part1 contain the public interfaces for M.
//--- M.cpp
// 
export module M;

export import :Part1;

export int in_module (int);

//--- M-Part1.cpp
//
export module M:Part1;

export int in_part1 (int);
int in_part1_mod (int);

//--- M-Part1-impl.cpp
//
module M:Part1;

int in_part1 (int x) { return 40 + x; }
int in_part1_mod (int x) { return 40 + x; }

//--- M-impl.cpp
// 
module M;

int in_module (int x) { return in_part1 (x) + in_part1_mod (x); }

//--- Use-M.cpp
//

import M;

int main ()
{
  int a = in_module (2) + in_part1 (2);
  return a == 168 ? 0 : 1;
}

produces:

...partition-warning.cpp.tmp/M-impl.cpp:2:1: warning: it is deprecated to read module 'M:Part1' implicitly; it is going to be removed in clang 18; consider to specify the dependencies explicitly [-Wread-modules-implicitly]
    2 | module M;
      | ^
1 warning generated.
....partition-warning.cpp.tmp/Use-M.cpp:3:1: warning: it is deprecated to read module 'M:Part1' implicitly; it is going to be removed in clang 18; consider to specify the dependencies explicitly [-Wread-modules-implicitly]
    3 | import M;
      | ^
1 warning generated.

I do not believe that this is correct per the standard;
https://eel.is/c++draft/module#unit-3

The clarifying note is clear, that the user of a module should not need to know about its partitions; so it is not correct to ask the user to do this...

import M;
import :Part1; // because this is ill-formed 

So .. either we need to explain how we're going to fix the underlying problem or we need to remove this before 17 branches

.... does it also fire for export import B; ?

@ChuanqiXu9
Copy link
Member Author

I think there are in different levels. https://eel.is/c++draft/module#unit-3 talks about the source level and the issue is about the tools (build systems) level. I think the build systems knows every partitions naturally.

@iains
Copy link
Contributor

iains commented Jul 5, 2023

hmm .. I do not follow that logic (yet)
... surely the user must be able to write this code:

import M;

int main ()
{
  int a = in_module (2) + in_part1 (2);
  return a == 168 ? 0 : 1;
}

without knowing that M has some partitions?

@ChuanqiXu9
Copy link
Member Author

Yes. But the build systems knows about the partitions, then the build systems can add these flags. They are on the different abstract levels.

@iains
Copy link
Contributor

iains commented Jul 5, 2023

Hmm, OK so now the meaning of the diagnostic becomes clear - perhaps we might add a hint about how to fix the issue - if it was not obvious to me - then probably someone else will also have troubles.

as an aside:

I must confess IMO it would be very unfortunate to make simple use of modules (like my example above) conditional on having a build system (while it is completely accepted that is required for larger projects, of course), that seems likely to be a barrier to initial adoption.

So, IMO, we need to make this work for the simple kinds of example being discussed in https://discourse.llvm.org/t/rfc-modules-build-daemon-build-system-agnostic-support-for-explicitly-built-modules/71524/47. to allow simple projects to work with just the compiler.

(let's continue the discussion there and not side-track this bug)

@ChuanqiXu9
Copy link
Member Author

In my opinion, such simple use cases can be solved by -fprebuilt-module-path=. And this is what I saw for existing users.

kwrobot pushed a commit to Kitware/CMake that referenced this issue Jul 14, 2023
In the future, Clang plans to require transitive module usage to be
specified on the command line. This is in order to keep BMI files more
reproducible. Handily, MSVC has already required this, so the logic can
be reused for Clang easily.

See: llvm/llvm-project@e22fa1d
See: llvm/llvm-project#62707
See: https://discourse.llvm.org/t/c-20-modules-should-the-bmis-contain-paths-to-their-dependent-bmis/70422
justinfargnoli pushed a commit to justinfargnoli/llvm-project that referenced this issue Jan 28, 2024
Close llvm#62707

As we discussed before, we'll forbid the use of implicit generated path
for C++20 modules. And as I mentioned in
llvm#62707, we've emitted a
warning for clang17 and we'll make it a hard error in clang18. And the
patch addresses the decision.
tru pushed a commit that referenced this issue Feb 26, 2024
Looking at the [release
notes](https://prereleases.llvm.org/18.1.0/rc3/tools/clang/docs/ReleaseNotes.html)
for clang 18.1.0rc, there's some broken links, and many issue numbers
mis-formatted with an extra colon. Aside from being used inconsistently
(with/without colon), I think it should be uncontroversial that `See
(#62707).` is better than `See (#62707:).`

CC @tstellar @AaronBallman

Co-authored-by: Aaron Ballman <aaron@aaronballman.com>
veselypeta pushed a commit to veselypeta/cherillvm that referenced this issue Aug 23, 2024
Close llvm/llvm-project#62843.

Previously when we compile .pcm files into .o files, the
`-fmodule-file=<module-name>=<module-path>` option is ignored. This is
conflicted with our consensus in
llvm/llvm-project#62707.
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