Bug: Missing `<intrin.h>` in `winrt.Windows.Foundation.ixx` in module builds

Aperta Adatta ai principianti
#1,646 7 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
2/5
Tempo stimato
1-3 ore
Idoneità per principianti
72/100
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Attiva
Stack tecnologico
cpp

Direzione di ricerca

Leggi il frammento del modulo globale in winrt.Windows.Foundation.ixx e confronta le inclusioni con l’uso di _InterlockedCompareExchangePointer in Windows.Foundation.h. Aggiungi la dichiarazione dell’intrinseco mancante alla compilazione del modulo e compila il modulo Windows.Foundation con GCC o Clang per confermare che l’errore di ricerca segnalato è risolto.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

Version

3.0.260818.1

Summary

In C++20 module builds (-modules), the global module fragment of winrt.Windows.Foundation.ixx does not include <intrin.h>, even though the coroutine helpers in Windows.Foundation.h (winrt::when_any) directly call _InterlockedCompareExchangePointer.

Because <intrin.h> is only included in the global module fragment of winrt_base.ixx and is not exported across modules, _InterlockedCompareExchangePointer has no visible declaration in winrt.Windows.Foundation.ixx:

  • GCC and Clang (targeting MinGW) reject winrt.Windows.Foundation.ixx during template definition lookup.
  • Clang (targeting MSVC) masks this because -fms-extensions treats the intrinsic as a predeclared compiler builtin.
  • MSVC masks this only because an earlier template instantiation in Windows.Foundation.h happens to pull the global module fragment declaration from winrt_base.ifc into scope before winrt::when_any is parsed.

Here is a minimal reproducible example for the msvc compiler bug:

// hidden.h
inline int hidden(int value)
{
    return value;
}

// mod.ixx
module;
#include "hidden.h"

export module provider;

export template <class T>
auto touch(T value)
{
    return hidden(value);
}

// main.cpp
import provider;

int test()
{
    touch(0);          // Instantiating the template leaks `hidden` into scope
    return hidden(42); // MSVC erroneously allows unqualified lookup to find `hidden`
}
Reproducible example
$out = Join-Path $env:TEMP "cppwinrt_intrin_repro"
Remove-Item -Recurse -Force $out -ErrorAction SilentlyContinue
New-Item -ItemType Directory -Force -Path $out | Out-Null
Push-Location $out

# 1. Generate module projection with cppwinrt 3.0.260818.1
$cppwinrt = "$env:USERPROFILE\.nuget\packages\microsoft.windows.cppwinrt\3.0.260818.1\bin\cppwinrt.exe"
& $cppwinrt -in local -out $out -modules -include Windows.Foundation

# Assume upstream fix for `export extern "C"` in winrt/base.h
# $baseH = Get-Content "winrt/base.h" -Raw
# $idx = $baseH.IndexOf('extern "C"')
# Set-Content "winrt/base.h" ($baseH.Substring(0, $idx) + 'export extern "C"' + $baseH.Substring($idx + 10))

# 2. MSVC
$vsDevCmd = "C:\Program Files\Microsoft Visual Studio\18\Community\Common7\Tools\VsDevCmd.bat"
$stdIxx = Get-ChildItem "C:\Program Files\Microsoft Visual Studio\18\Community\VC\Tools\MSVC\*\modules\std.ixx" |
          Select-Object -Last 1 -ExpandProperty FullName
$msvcCmds = @(
    "`"$vsDevCmd`" -arch=x64 -no_logo"
    "cd /d `"$out`""
    "cl /nologo /std:c++20 /EHsc /MD /c /interface /TP `"$stdIxx`" /ifcOutput std.ifc"
    "cl /nologo /std:c++20 /EHsc /MD /I. /c /interface /TP winrt/winrt_numerics.ixx /ifcOutput winrt_numerics.ifc"
    "cl /nologo /std:c++20 /EHsc /MD /I. /c /interface /TP winrt/winrt_base.ixx /reference std=std.ifc /reference winrt_numerics=winrt_numerics.ifc /ifcOutput winrt_base.ifc"
    "cl /nologo /std:c++20 /EHsc /MD /I. /c /interface /TP winrt/winrt.Windows.Foundation.ixx /reference std=std.ifc /reference winrt_numerics=winrt_numerics.ifc /reference winrt_base=winrt_base.ifc /ifcOutput winrt.Windows.Foundation.ifc"
) -join " && "
cmd /c $msvcCmds

# 3. GCC
(Get-Content "winrt/winrt_numerics.ixx" -Raw) -replace '#include <intrin.h>', "#include <x86intrin.h>`n#include <algorithm>`n#include <cmath>`n#include <intrin.h>" | Set-Content "winrt/winrt_numerics.ixx"
(Get-Content "winrt/winrt_base.ixx" -Raw) -replace '#include <intrin.h>', "#include <x86intrin.h>`n#include <intrin.h>" | Set-Content "winrt/winrt_base.ixx"

$stdCc = Get-ChildItem "C:\Tools\msys64\ucrt64\include\c++\*\bits\std.cc" | Select-Object -First 1 -ExpandProperty FullName
g++ -std=c++23 -fmodules -c "$stdCc" -o std.o
g++ -std=c++23 -fmodules -I. -x c++ -c winrt/winrt_numerics.ixx -o winrt_numerics.o
g++ -std=c++23 -fmodules -I. -x c++ -c winrt/winrt_base.ixx -o winrt_base.o
g++ -std=c++23 -fmodules -I. -x c++ -c winrt/winrt.Windows.Foundation.ixx -o winrt.Windows.Foundation.o

Pop-Location

MSVC output:

std.ixx
winrt_numerics.ixx
winrt_base.ixx
winrt.Windows.Foundation.ixx

GCC output when compiling winrt/winrt.Windows.Foundation.ixx:

In file included from winrt/winrt.Windows.Foundation.ixx:102:
./winrt/Windows.Foundation.h: In member function 'void winrt::when_any(const T&, const Rest& ...)::shared_type::operator()(const T&, winrt::Windows::Foundation::AsyncStatus)':
./winrt/Windows.Foundation.h:4217:32: error: there are no arguments to '_InterlockedCompareExchangePointer' that depend on a template parameter, so a declaration of '_InterlockedCompareExchangePointer' must be available [-Wtemplate-body]
 4217 |                 if (nullptr == _InterlockedCompareExchangePointer(reinterpret_cast<void**>(&result), sender_abi, nullptr))
      |                                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

g++ version:

g++ -v
Using built-in specs.
COLLECT_GCC=C:\Tools\msys64\ucrt64\bin\g++.exe
COLLECT_LTO_WRAPPER=C:/Tools/msys64/ucrt64/bin/../lib/gcc/x86_64-w64-mingw32/16.2.0/lto-wrapper.exe
Target: x86_64-w64-mingw32
Configured with: ../gcc-16.2.0/configure --prefix=/ucrt64 --with-sysroot=/ucrt64 --with-build-sysroot=D:/M/msys64/ucrt64 --with-local-prefix=/local --with-native-system-header-dir=/include --libexecdir=/ucrt64/lib --enable-bootstrap --enable-checking=release --with-arch=nocona --with-tune=generic --enable-mingw-wildcard --enable-languages=c,c++,ada,fortran,lto,objc,obj-c++,jit --enable-shared --enable-static --enable-libatomic --enable-threads=posix --enable-tls --enable-graphite --enable-fully-dynamic-string --enable-libstdcxx-backtrace=yes --enable-libstdcxx-filesystem-ts --enable-libstdcxx-time --disable-libstdcxx-pch --enable-libgomp --disable-libssp --disable-multilib --disable-rpath --disable-win32-registry --disable-nls --disable-werror --disable-symvers --with-libiconv --with-system-zlib --with-gmp=/ucrt64 --with-mpfr=/ucrt64 --with-mpc=/ucrt64 --with-isl=/ucrt64 --with-pkgversion='Rev6, Built by MSYS2 project' --with-bugurl=https://github.com/msys2/MINGW-packages/issues --with-gnu-as --with-gnu-ld --with-libstdcxx-zoneinfo=yes --disable-libstdcxx-debug --enable-lto --enable-plugin --with-boot-ldflags=-static-libstdc++ --with-stage1-ldflags=-static-libstdc++
Thread model: posix
Supported LTO compression algorithms: zlib zstd
gcc version 16.2.0 (Rev6, Built by MSYS2 project)
Additional comments

winrt_numerics.ixx includes <windowsnumerics.impl.h> directly inside its module purview after pre-including only <directxmath.h> in the global module fragment. However, <windowsnumerics.impl.h> transitively includes standard library headers (<stdexcept> and <limits> in the Windows SDK, and <algorithm> and <cmath> in mingw-w64) inside the module purview, which breaks module builds on libstdc++ and libc++. In addition, the DirectX interop functions (XMLoadFloat2, XMStoreFloat2, etc.) defined in <windowsnumerics.impl.h> sit outside _WINDOWS_NUMERICS_BEGIN_NAMESPACE_, leaving them unexported and attached to the winrt_numerics module even on MSVC.

Lingua principale
C++
Stelle
1.9k
Fork
288
Merge medio
18h 15m
PR unite (30g)
2

Preparare l'ambiente

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di microsoft/cppwinrt

Tutte le issue di microsoft/cppwinrt

Issue simili

Altre issue su C++

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.