Open
Description
Consider the following set of headers:
// myvector.h
#ifndef MYVECTOR_H
#define MYVECTOR_H
#include <bit_ref.h>
template <class _Allocator>
struct MyVector {
typedef bool value_type;
typedef unsigned long __storage_type;
friend class MyBitIterator<MyVector, false>;
};
#endif
// bit_ref.h
#ifndef BIT_REF_H
#define BIT_REF_H
#include <bit_ref_fwd.h>
#endif
// bit_ref_fwd.h
#ifndef BIT_REF_FWD_H
#define BIT_REF_FWD_H
template <class _Cp, bool _IsConst, typename _Cp::__storage_type = 0>
class MyBitIterator {};
#endif
And the following modulemap:
module mystd {
module myvector {
header "myvector.h"
export mystd.bit_ref
}
module bit_ref_fwd {
header "bit_ref_fwd.h"
}
module bit_ref {
header "bit_ref.h"
export mystd.bit_ref_fwd
}
}
The following fails to compile:
echo '#include <myvector.h>' | clang++ -x c++ - -std=c++17 -fmodules -fcxx-modules -Xclang -fmodules-local-submodule-visibility -fsyntax-only -I $(dirname ${0}) -fmodules-cache-path="$(mktemp -d)"
The error is:
While building module 'mystd' imported from <stdin>:1:
In file included from <module-includes>:1:
./repro-modules/myvector.h:11:16: error: missing '#include "bit_ref_fwd.h"'; 'MyBitIterator' must be declared before it is used
11 | friend class MyBitIterator<MyVector, false>;
| ^
./repro-modules/bit_ref_fwd.h:5:7: note: declaration here is not visible
5 | class MyBitIterator {};
| ^
<stdin>:1:10: fatal error: could not build module 'mystd'
1 | #include <myvector.h>
| ~~~~~~~~^
2 errors generated.
A few things can be observed:
- If we move the definition of
bit_ref_fwd
andbit_ref
before the definition ofmyvector
in the modulemap, the issue goes away. - If we remove
export mystd.bit_ref
from themyvector
module, the issue goes away. - If we add a direct include of
#include <bit_ref_fwd.h>
inmyvector.h
, the issue goes away.
Is this behavior intended? If the order of module definitions in a modulemap matters, there should be a warning that tells us when the compiler encounters something that has not been defined yet in the modulemap. If the order is irrelevant, then there's a bug in Clang.
This was discovered while investigating #127015.