This is derived from boost's define_if_constexpr header. That (and its sibling undef_if_constexp) are non-idempotent headers that surround conditional use of if constexpr by defining an IF_CONSTEXPR macro. Sadly these #include <boost/config.hpp> to find information about whether if-constexpr is to be used. It's desirable to have config.hpp as a header module (and weirdly I couldn't just make it textual and its includes modules).
// hdr.hh
#include "config.hh"
// cc1 -triple x86_64-linux-gnu -emit-header-module -fmodule-name=testing -std=c++20 -fmodules -fimplicit-module-maps -fno-builtin-module-map -emit-module -fmodules-embed-all-files -fno-implicit-modules -x c++-header -I . -o x module.modulemap
struct F
{
// OK
#include "on.hh"
#include "off.hh"
void Fn () {
// Not OK
#include "on.hh"
if (true) {}
#include "off.hh"
}
};
The redundant include warnings are clueful, but I didn't get them from our build -- I guess disabled? But look at that weird parse error about if (true)! that's really confusing. AFAICT it's because that's in a deferred parse region. The prior on/off includes inside the definition of F are fine.
A somewhat blunter diagnostic about trying to load an importable header not at namespace scope might be more helpful. Yes, I realize the in-struct case works, but seems still like code-smell to me, and of course won't work in C++20 modules land.
(130)devvm5975:47> ../llvm/trunk/build/bin/clang-15 -cc1 -triple x86_64-linux-gnu -emit-header-module -fmodule-name=testing -std=c++20 -fmodules -fimplicit-module-maps -fno-builtin-module-map -emit-module -fmodules-embed-all-files -fno-implicit-modules -x c++-header -I . -o x module.modulemap
While building module 'testing':
In file included from <module-includes>:2:
In file included from ./hdr.hh:8:
./on.hh:1:1: error: redundant #include of module 'testing.bits' appears within 'F' [-Wmodules-import-nested-redundant]
#include "config.hh"
^
./hdr.hh:5:1: note: 'F' begins here
struct F
^
While building module 'testing':
In file included from <module-includes>:2:
In file included from ./hdr.hh:9:
In file included from ./off.hh:2:
./on.hh:1:1: error: redundant #include of module 'testing.bits' appears within 'F' [-Wmodules-import-nested-redundant]
#include "config.hh"
^
./hdr.hh:5:1: note: 'F' begins here
struct F
^
While building module 'testing':
In file included from <module-includes>:2:
In file included from ./hdr.hh:12:
./on.hh:1:1: error: redundant #include of module 'testing.bits' appears within 'F' [-Wmodules-import-nested-redundant]
#include "config.hh"
^
./hdr.hh:5:1: note: 'F' begins here
struct F
^
./hdr.hh:13:5: error: expected member name or ';' after declaration specifiers
if (true) {}
^
While building module 'testing':
In file included from <module-includes>:2:
In file included from ./hdr.hh:14:
In file included from ./off.hh:2:
./on.hh:1:1: error: redundant #include of module 'testing.bits' appears within 'F' [-Wmodules-import-nested-redundant]
#include "config.hh"
^
./hdr.hh:5:1: note: 'F' begins here
struct F
^
./hdr.hh:10:15: error: expected '}'
void Fn () {
^
./hdr.hh:10:14: note: to match this '{'
void Fn () {
^
./hdr.hh:15:4: error: expected ';' after struct
}
^
;
./hdr.hh:16:1: error: extraneous closing brace ('}')
};
^
8 errors generated.
(1)devvm5975:47>
This is derived from boost's
define_if_constexpr
header. That (and its siblingundef_if_constexp
) are non-idempotent headers that surround conditional use ofif constexpr
by defining anIF_CONSTEXPR
macro. Sadly these#include <boost/config.hpp>
to find information about whetherif-constexpr
is to be used. It's desirable to haveconfig.hpp
as a header module (and weirdly I couldn't just make it textual and its includes modules).The redundant include warnings are clueful, but I didn't get them from our build -- I guess disabled? But look at that weird parse error about
if (true)
! that's really confusing. AFAICT it's because that's in a deferred parse region. The prior on/off includes inside the definition of F are fine.A somewhat blunter diagnostic about trying to load an importable header not at namespace scope might be more helpful. Yes, I realize the in-struct case works, but seems still like code-smell to me, and of course won't work in C++20 modules land.