This is an archive of the discontinued LLVM Phabricator instance.

[C++20] [Modules] Support to export declarations in the language linkage
ClosedPublic

Authored by ChuanqiXu on Feb 20 2023, 1:17 AM.

Details

Summary

Close https://github.com/llvm/llvm-project/issues/60405

See the discussion in the above link for the background.

What the patch does:

  • Rename Module::ModuleKind::GlobalModuleFragment to Module::ModuleKind::ExplicitGlobalModuleFragment.
  • Add another module kind ImplicitGlobalModuleFragment to ModuleKind.
  • Create an implicit global module fragment for the language linkage declarations inside a module purview.
    • If the language linkage lives inside the scope of an export decl, the created modules is marked as exported to outer modules.
  • In fact, Sema will only create at most 2 implicit global module fragments to avoid creating a lot of unnecessary modules in the edging case.

Diff Detail

Event Timeline

ChuanqiXu created this revision.Feb 20 2023, 1:17 AM
Herald added a project: Restricted Project. · View Herald TranscriptFeb 20 2023, 1:17 AM
ChuanqiXu requested review of this revision.Feb 20 2023, 1:17 AM
ChuanqiXu added a subscriber: Restricted Project.
ChuanqiXu added inline comments.
clang/include/clang/Sema/Sema.h
2284–2291

This is important otherwise it will be bad if the users write many:

export extern "C++" void f1();
export extern "C++" void f2();
export extern "C++" void f3();
// ...
clang/test/Modules/export-language-linkage.cppm
42–48

We can classify each language linkage into exported/unexported since export is not allowed in unnamed modules.

iains added a comment.Feb 20 2023, 3:48 PM

I am wondering why we need to add another sub-module.

We can identify that the current decl is a language linkage one (and make sure that it is not marked as eligible for elision when that is implemented) - so that we can be sure it is not subject to the elision rules.

If there is already an existing GMF, is it not possible to switch to that when handling the language linkage case? (to avoid creating a second GMF).

(I can understand if "no" is the answer - but just checking).

.. otherwise, mostly nits on comments etc.

clang/include/clang/Basic/Module.h
123–126

This is well-specified, I think we can just refer to that.

130–131

this one is the new thing.

clang/include/clang/Sema/Sema.h
2280–2281

let's just refer to the spec.

2285–2286

why do we need even two?

2288–2289

for there to be content, it must be exported, right? (the implicit case is only used for language linkage AFAIU).

2291

typo?

I am wondering why we need to add another sub-module.

From my minds, because it looks like not a burden to me to add other sub-modules? For example, both the existing GMF and the PMF are the sub-modules. So I feel it looks more straightforward to implement it in this way.

We can identify that the current decl is a language linkage one (and make sure that it is not marked as eligible for elision when that is implemented) - so that we can be sure it is not subject to the elision rules.

If there is already an existing GMF, is it not possible to switch to that when handling the language linkage case? (to avoid creating a second GMF).

(I can understand if "no" is the answer - but just checking).

I don't say "it is impossible". But I want to say it looks odd and ad-hoc. The intention of the patch is to allow us to export the contents in language linkage. But the contents of language linkage belongs to GMF. In the current implementation, all the contents in GMF is not visible to outside. Is it possible for us to insert such codes in the isVisible path?

if ((D belongs to GMF) and (D belongs to language linkage) and (D belongs to export decl))
     return true;

This should be able to work with the 2 issues:

  1. It smells not good to lookup export decl. On the one hand, it seems like we need a lot iterations to look for the parent decl context for D again and again until we meet export decl or the file context. On the other hand, this is not consistency with our current method to handle visibility lookup. We can image that we can refactor all of the current visibility lookup into the style. (Lookup if this declaration lives in an export decl). But it looks inconsistent and not good to me.
  2. In the edge case that the module of D get loaded but not imported, the above code can't work. This is possible if we load a module by -fmodule-file=module but don't import the corresponding module. To handle the case, we need to rewrite the above code into:
if ((D belongs to GMF) and (D belongs to language linkage) and (D belongs to export decl) and (The top level module of D is imported))
     return true;

which looks odder, doesn't it?

So my idea will be:
(1) On the language side, we can have multiple GMFs in a single module unit.
(2) On the implementation side, currently some modules are divided into visible modules while other modules are classified into invisible modules (like current GMF).
(3) So it makes sense to me to create a new GMF kind which is visible modules.

clang/include/clang/Sema/Sema.h
2285–2286

Currently, it is fine to introduce TheExportedImplicitGlobalModuleFragment only since all the declarations in GMF wouldn't get discarded. But it is helpful when we want to discard declarations in the GMF. I add the 2 modules now since I feel it doesn't add the overhead and the current style is consistent the mental model.

2288–2289

The language linkage can be able to be not exported.

2291

Yes, I will fix it later.

OK - the visibility path is already complex, we do not need to make it more so.
I guess you are intending to rebase/update this?

clang/include/clang/Sema/Sema.h
2285–2286

ah, OK, then it is my misreading of the comment (it seemed to be saying that there could be two implicit global module fragments) - but you mean 1 explicit + 1 implicit, correct?

ChuanqiXu updated this revision to Diff 499069.Feb 21 2023, 1:18 AM
ChuanqiXu marked 5 inline comments as done.

Address comments.

Oh, I forgot to commit the comment.

clang/include/clang/Sema/Sema.h
2285–2286

No, I mean 2 implicit GMFs. One for exported and one for unexported. Although it will work fine from the perspective of functionality if we merge the unexported implicit GMFs into the explicit GMF, the semantics is not consistency. For example:

export module a;
extern "C++" void foo() {}
export extern "C++" void bar() {}

It will be a little bit odd to me if foo belongs to the explicit global module fragment in the compiler since it is not true in the language side. And from the perspective of implementation side, foo() and bar() can't be in the same (sub) module. So we create 2 modules here. One for exported and one for unexported. This may be a little bit overhead but I think it doesn't matter.

@iains ping~ I want to land this one in the next week if no comments come in.

iains added a comment.Feb 27 2023, 7:14 AM

@iains ping~ I want to land this one in the next week if no comments come in.

I will try to review during this week.

One quick question : does the revised module layout work OK with "-module-file-info" which should print the summary of the C++20 content in the first few lines.

Add test for '-module-file-info'

@iains ping~ I want to land this one in the next week if no comments come in.

I will try to review during this week.

One quick question : does the revised module layout work OK with "-module-file-info" which should print the summary of the C++20 content in the first few lines.

Yeah, I've added the test for it.

iains added a comment.Feb 28 2023, 1:03 AM

@iains ping~ I want to land this one in the next week if no comments come in.

I will try to review during this week.

One quick question : does the revised module layout work OK with "-module-file-info" which should print the summary of the C++20 content in the first few lines.

Yeah, I've added the test for it.

Something seems strange, I cannot see that new test in the web page content?

@iains ping~ I want to land this one in the next week if no comments come in.

I will try to review during this week.

One quick question : does the revised module layout work OK with "-module-file-info" which should print the summary of the C++20 content in the first few lines.

Yeah, I've added the test for it.

Something seems strange, I cannot see that new test in the web page content?

See the inline comments.

clang/test/Modules/export-language-linkage.cppm
28–30

I add the test here.

iains accepted this revision.Mar 2 2023, 11:43 AM

OK, I guess one extra sub-module is not too bad.
LGTM.

This revision is now accepted and ready to land.Mar 2 2023, 11:43 AM
This revision was landed with ongoing or failed builds.Mar 2 2023, 6:34 PM
This revision was automatically updated to reflect the committed changes.
Herald added a project: Restricted Project. · View Herald TranscriptMar 2 2023, 6:34 PM
Herald added a subscriber: cfe-commits. · View Herald Transcript