Issue
When I put an unexported "using namespace" directive in a C++20 module interface file, it also applies to the separate module implementation file under CLANG, but not under GCC. So, which one is right according to the current standards ?
Note : My version of CLANG is 16.0.6, whereas my version of GCC is 13.2.1.
I know there are many topics dealing with "using" and "modules" available here, however it may be hard to find the details allowing to answer my specific case with precision. This is like if the standard changed since 2020, this would explain a possible difference between the compilers and the difficulty to retrieve convincing information.
Here is the minimal code to reproduce the behaviour : There are three source files, "library.h", "interface.ixx", and "implementation.cxx".
library.h :
#ifndef RAG_DOLL_h
#define RAG_DOLL_h
namespace rag {
class Doll {};
};
#endif
interface.ixx :
export module xd;
import <library.h>;
using namespace rag;
implementation.cxx :
module xd;
import <library.h>;
Doll kore;
This last line "Doll kore;
" is the one GCC dislikes, it triggers the following error :
implementation.cxx:5:1: error: 'Doll' does not name a type
5 | Doll kore;
| ^~~~
Of course, replacing it by "rag::Doll kore;
" fixes the error. CLANG is fine without this fix, so what is going on ? What about the standard ?
Since finding the proper arguments to compile modules may be a little hard, I'm also giving the content of two additional files, one executable script per compiler : "gcc.sh" and "clang.sh".
gcc.sh :
#!/bin/sh
export LANG=C
prg="`realpath "$0"`" && cd "`dirname "$prg"`" || exit $?
ln -sf interface.ixx interface.cxx \
&& g++ -c -fmodules-ts -I. -fmodule-header library.h \
&& g++ -c -fmodules-ts -I. interface.cxx -o interface.o \
&& g++ -c -fmodules-ts -I. implementation.cxx -o implementation.o
rm -rf gcm.cache interface.cxx
clang.sh :
#!/bin/sh
export LANG=C
prg="`realpath "$0"`" && cd "`dirname "$prg"`" || exit $?
ln -sf interface.ixx interface.cxxm \
&& clang++ -std=c++20 -I. -fmodule-header library.h -o library.pcm \
&& clang++ -std=c++20 -I. --precompile interface.cxxm -fmodule-file=library.pcm -o interface.pcm \
&& clang++ -std=c++20 -I. -c implementation.cxx -fmodule-file=library.pcm -fmodule-file=xd=interface.pcm -o implementation.o
rm -f library.pcm interface.cxxm
They require a Unix shell to run, and must be put in the same directory that the one containing the source files.
Thank you for reading, and I hope this is not an implementation-defined feature...
Solution
Clang is correct here: all declarations in one module unit are available in another unit of the same module that imports it. (Non-partition implementation units implicitly import the module’s interface units.) The using-directive being available implies that it affects the importer. (You can export it to affect external importers, although maybe you shouldn’t.)
GCC’s omission may derive from the fact that C++20 as published didn’t really address this question since it phrased the declaration availability in terms of scopes that might or might not extend across translation units.
Answered By - Davis Herring Answer Checked By - Robin (WPSolving Admin)