4

Consider the example

MA.cpp:

export module MA;
import MB;
export int MyFunA()
{
  return 0; 
}

MB.cpp:

export module MB;
export int MyFuncB()
{
   return 0;
}

MA-PA.cpp:

module MA:PA;
import MA;
int x = MyFuncB();  // #1

main.cpp:

import MA;
int main()
{
   return 0;
}

CMakeLists.txt:

project(ModuleTestProject)

cmake_minimum_required(VERSION 3.5)

add_executable(the_executable
    MB.cpp
    MA.cpp
    MA-PA.cpp
    main.cpp)

When compiling the example with GCC(v 12.2): g++ -std=c++20 -fmodules-ts, it reports the error:

MA-PA.cpp:5:9: error: 'MyFuncB' was not declared in this scope
5 | int x = MyFuncB();
  |         ^~~~~~~

When compiling with Visual Studio 2022(v 17.4.1), it reports a similar error:

C3861   'MyFuncB': identifier not found ModuleTestProject

When I deleted #1, both the two compilers could complie successfully.

In the module partion MA:PA, I tried to invoke the function MyFuncB declared in MB. According to the error reported by compiler, it seems that MA:PA doesn't import MB.The result really confused me .After looking for related contents in C++ standard, I found the §10.3/7 said:

Additionally, when a module-import-declaration in a module unit of some module M imports another module unit U of M, it also imports all translation units imported by non-exported module-import-declarations in the module unit purview of U.These rules can in turn lead to the importation of yet more translation units.

I am not able to understand why MA:PA doesn't import MB. According to my understanding, MA:PA shall indirectly import MB. Here are the reasons. On one hand, MA:PA imports MA and MA imports MB. On the other hand, both MA.cpp and MA-PA.cpp are translation units of module MA.

I had found the related question before I asked this question. The related question's answer says a primary module interface unit could import the module imported by its module partion indirectly. This answer is absolutely right because the C++ standard §10.3/7 applies to it. But the behavior of the compiler shows that when a module partion imports it's primary module interface unit,it doesn't also import the module imported by it's primary module interface unit. In my view, §10.3/7 also applies to this situation.So my question is why doesn't a module partion indirectly import the module imported by it's primary module interface unit?

Could you please tell your opinion and point out my mistake about this question? Thank you very much.

English is not my native language so that sometimes I may not be able to express my meanings exactly.Sorry for the inconvenience and thanks for your understanding.

1
  • An interesting note: if you make "MA-PA.cpp" into a pure implementation unit (rather than a partition, so you have to also take out import MA;, as that is implied)... it works. And this is the case in both GCC and VS2022. Commented Dec 3, 2022 at 4:09

1 Answer 1

1

Given that both GCC and VS2022 work just fine if you make your implementation unit a non-partition unit, this is definitely some kind of weird glitch in the compilers. It's clear from this experiment that the result of compiling the primary interface unit does contain all of those imports, even if importing it from outside of the module doesn't let you see them. And through non-partition implementation units, it's clear that importing from within the module is able to reach these things.

It just doesn't work when it happens in an implementation partition unit. There's nothing in the standard to account for this, so it seems like a bug.

But it is weird that both compilers not only have the same bug manifesting in the same way, the bug goes away under the same conditions (using non-partition implementation units).

Not the answer you're looking for? Browse other questions tagged or ask your own question.