https://gcc.gnu.org/bugzilla/show_bug.cgi?id=126192
Bug ID: 126192
Summary: Duplicate global-module-fragment entities from two
imported modules fail to merge, causing spurious
ambiguous-conversion errors
Product: gcc
Version: 16.1.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c++
Assignee: unassigned at gcc dot gnu.org
Reporter: avi at scylladb dot com
Target Milestone: ---
When two named modules each pull the same header into their global module
fragment (GMF), the GMF entities are duplicated (one copy per module). If a
translation unit imports both modules and one of them re-exports an
enumerator of an unnamed enum, that enumerator is not unified across the two
modules. Anything that then depends on it breaks with
error: reference to 'max_packed_args' is ambiguous
Two conditions are both necessary (and, together, sufficient):
1. The entity is an enumerator of an unnamed enum. A named enum, an
enum class, or a plain inline constexpr int all merge correctly and do
not reproduce — so the failure is specific to merging the anonymous
enum.
2. A module re-exports that enumerator with a using-declaration. Re-exporting
a sibling (a type, or the dependent alias itself) does not trigger it.
Reproducer:
// base.h
#ifndef BASE_H
#define BASE_H
namespace demo {
enum { max_packed_args = 6 }; // enumerator of an UNNAMED enum
template <bool B, class T, class F> struct cond { using type = F; };
template <class T, class F> struct cond<true, T, F> { using type = T; };
template <class T> struct a_t {};
template <class T> struct b_t {};
template <class Context, int N>
using arg_t = typename cond<(N <= max_packed_args), a_t<Context>,
b_t<Context>>::type;
}
#endif
// fmt.cppm
module;
#include "base.h"
export module fmt;
export namespace demo { using demo::max_packed_args; } // <-- the trigger
// seastar.cppm
module;
#include "base.h"
export module seastar;
export namespace seastar { inline int dummy = 0; }
// main.cc
import seastar;
import fmt;
#include "base.h"
int main() {}
This was first found on clang [1].
Credit for the characterization and minimization: Claude Opus 4.8 (though I did
have to encourage it when the going was tough).
[1] https://github.com/llvm/llvm-project/issues/207581