[C++20] [Modules] Duplicate-mangled-name codegen error for SSE intrinsics when two module partitions both `#include <emmintrin.h>` in their global module fragment
#195661 opened on May 4, 2026
Description
Compiler
$ clang++-21 --version
Ubuntu clang version 21.1.8 (++20251221032922+2078da43e25a-1~exp1~20251221153059.70)
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/lib/llvm-21/bin
Problem
Got compile error: error: definition with same mangled name '_ZL13_mm_set_epi16ssssssss' as another definition when two C++20 module partitions of the same primary module each #include <emmintrin.h> in their global module fragment and each contain an inline function whose body calls the same SSE intrinsic (e.g. _mm_set_epi16). A consumer TU that imports the primary module fails to compile.
Reproduce
a.cppm:
module;
#include <emmintrin.h>
export module mymod:a;
export inline int a_make() noexcept {
__m128i x = _mm_set_epi16(0, 1, 2, 3, 4, 5, 6, 7);
alignas(16) short out[8];
_mm_store_si128(reinterpret_cast<__m128i*>(out), x);
return out[0];
}
b.cppm:
module;
#include <emmintrin.h>
export module mymod:b;
export inline int b_make() noexcept {
__m128i x = _mm_set_epi16(7, 6, 5, 4, 3, 2, 1, 0);
alignas(16) short out[8];
_mm_store_si128(reinterpret_cast<__m128i*>(out), x);
return out[0];
}
m.cppm:
export module mymod;
export import :a;
export import :b;
main.cpp:
import mymod;
int main() {
return a_make() + b_make();
}
build.sh:
#!/usr/bin/env bash
set -euo pipefail
CXX=clang++-21
FLAGS="-std=c++20 -msse2"
$CXX $FLAGS -x c++-module --precompile -o mymod-a.pcm a.cppm
$CXX $FLAGS -x c++-module --precompile -o mymod-b.pcm b.cppm
$CXX $FLAGS -fmodule-file=mymod:a=mymod-a.pcm -fmodule-file=mymod:b=mymod-b.pcm \
-x c++-module --precompile -o mymod.pcm m.cppm
$CXX $FLAGS -fmodule-file=mymod=mymod.pcm \
-fmodule-file=mymod:a=mymod-a.pcm -fmodule-file=mymod:b=mymod-b.pcm \
-c main.cpp -o main.o
Output
In module 'mymod' imported from main.cpp:1:
In module 'mymod:b' imported from m.cppm:3:
/usr/lib/llvm-21/lib/clang/21/include/emmintrin.h:3605:1: error: definition with same mangled name '_ZL13_mm_set_epi16ssssssss' as another definition
3605 | _mm_set_epi16(short __w7, short __w6, short __w5, short __w4, short __w3,
| ^
/usr/lib/llvm-21/lib/clang/21/include/emmintrin.h:3605:1: note: previous definition is here
3605 | _mm_set_epi16(short __w7, short __w6, short __w5, short __w4, short __w3,
| ^
1 error generated.
In our larger codebase the same pattern produces three errors at once (_mm_set_epi8, _mm_set1_epi8, _mm_add_epi8) — any SSE intrinsic used identically in both partition bodies surfaces.
What is NOT required to trigger
I bisected the trigger by adding/removing flags and structural elements against the minimal four files above. None of these affect the result; the bug fires either way:
-fno-exceptions,-fno-rtti,-pthread-march=native,-O3,-DNDEBUG-std=c++23,-std=c++26,-std=gnu++26--gcc-toolchain=…(libstdc++ from GCC)import std;in the partitions or the consumer- A shared
:detailpartition imported by both partitions - Concept constraints on the inline functions
- Templates instead of plain inline functions
- Whether the intrinsic header is
<emmintrin.h>or<immintrin.h>
What IS required: each partition must contain at least one inline function whose body calls the same intrinsic. Empty partitions (just module; #include <emmintrin.h>; export module mymod:a;) compile cleanly.
Expected behavior
Per [basic.link]p17 and Clang's own documentation, declarations in the global module fragment have internal linkage and should be private to each TU. Two partitions independently including <emmintrin.h> in their GMFs should each have their own internal-linkage copy of the intrinsic definitions; codegen should not reject them as duplicates.
Actual behavior
Codegen emits two definitions of _mm_set_epi16 with the same mangled internal-linkage name and rejects the consumer TU compile.
Workaround we adopted
Restructure so that only one partition #includes the intrinsic header. The other partition's SSE-using helpers are moved into the first partition and exported. This avoids the dual-emission. [[gnu::noinline]] does NOT help — the duplicate fires on the static-inline functions from <emmintrin.h> itself, not on user code.
Related issues
- #98021 / #104701 — fixed a related lookup-time issue (intrinsics not found in modules). Different code path; that fix did not address the codegen-level duplicate-mangling.
- #90259 — anonymous-namespace internal-linkage variables conflicting across partitions. Same general area but a different surface.
- #53232 / Bugzilla #33924 — same error message text, but for lambdas in modules, not intrinsic headers.