diff --git a/.config/1espt/PipelineAutobaseliningConfig.yml b/.config/1espt/PipelineAutobaseliningConfig.yml new file mode 100644 index 000000000..4b9969c37 --- /dev/null +++ b/.config/1espt/PipelineAutobaseliningConfig.yml @@ -0,0 +1,14 @@ +## DO NOT MODIFY THIS FILE MANUALLY. This is part of auto-baselining from 1ES Pipeline Templates. Go to [https://aka.ms/1espt-autobaselining] for more details. + +pipelines: + 98194: + retail: + source: + credscan: + lastModifiedDate: 2023-12-06 + eslint: + lastModifiedDate: 2023-12-06 + psscriptanalyzer: + lastModifiedDate: 2023-12-06 + armory: + lastModifiedDate: 2023-12-06 diff --git a/.config/tsaoptions.json b/.config/tsaoptions.json new file mode 100644 index 000000000..38fe35171 --- /dev/null +++ b/.config/tsaoptions.json @@ -0,0 +1,8 @@ +{ + "instanceUrl": "https://microsoft.visualstudio.com", + "projectName": "os", + "areaPath": "OS\\Windows Client and Services\\WinPD\\DEEP-Developer Experience, Ecosystem and Partnerships\\AmUse- App Metadata and User Setup Experience\\Projections\\Cppwinrt", + "notificationAliases": [ "cpp4uwpt@microsoft.com" ], + "ignoreBranchName": true, + "codebaseName": "cppwinrt" +} diff --git a/.gdn/.gdnsettings b/.gdn/.gdnsettings new file mode 100644 index 000000000..156408362 --- /dev/null +++ b/.gdn/.gdnsettings @@ -0,0 +1,7 @@ +{ + "files": { }, + "folders": { }, + "overwriteLogs": true, + "telemetryFlushTimeout": 10, + "variables": { } +} \ No newline at end of file diff --git a/.gdn/.gitignore b/.gdn/.gitignore new file mode 100644 index 000000000..decb1055f --- /dev/null +++ b/.gdn/.gitignore @@ -0,0 +1,11 @@ +## Ignore Guardian internal files +.r/ +rc/ +rs/ +i/ +p/ +c/ +o/ + +## Ignore Guardian Local settings +LocalSettings.gdn.json \ No newline at end of file diff --git a/.github/actions/setup-llvm-mingw/action.yml b/.github/actions/setup-llvm-mingw/action.yml index 9926bbe93..d36b48a75 100644 --- a/.github/actions/setup-llvm-mingw/action.yml +++ b/.github/actions/setup-llvm-mingw/action.yml @@ -19,7 +19,7 @@ runs: - name: Cache llvm-mingw (Windows) id: cache-llvm if: runner.os == 'Windows' - uses: actions/cache@v3 + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 with: path: .llvm-mingw key: llvm-mingw-${{ runner.os }}-${{ inputs.llvm-mingw-version }}-${{ inputs.host-arch }} @@ -50,7 +50,7 @@ runs: - name: Cache llvm-mingw (Linux) id: cache-llvm-linux if: runner.os == 'Linux' - uses: actions/cache@v3 + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 with: path: /opt/llvm-mingw key: llvm-mingw-${{ runner.os }}-${{ inputs.llvm-mingw-version }}-${{ inputs.host-arch }} diff --git a/.github/actions/setup-llvm-msvc/action.yml b/.github/actions/setup-llvm-msvc/action.yml index d6a2a5faa..e5a696a9f 100644 --- a/.github/actions/setup-llvm-msvc/action.yml +++ b/.github/actions/setup-llvm-msvc/action.yml @@ -14,7 +14,7 @@ runs: steps: - name: Cache LLVM and tools id: cache-llvm - uses: actions/cache@v3 + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 with: path: | .LLVM diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 000000000..9557baa7a --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,12 @@ +version: 2 +updates: + - package-ecosystem: "cargo" + directory: "/" + schedule: + interval: "daily" + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "daily" + cooldown: + default-days: 7 diff --git a/.github/instructions/cppwinrt.instructions.md b/.github/instructions/cppwinrt.instructions.md new file mode 100644 index 000000000..eae2fc3c6 --- /dev/null +++ b/.github/instructions/cppwinrt.instructions.md @@ -0,0 +1,58 @@ +# C++/WinRT Codebase — Agent Instructions + +## Repository Structure + +- `cppwinrt/` — The cppwinrt.exe code generator (C++ source) + - `main.cpp` — CLI parsing, namespace iteration, SCC detection, .ixx orchestration + - `file_writers.h` — All file generation functions (headers, .ixx modules, component stubs) + - `code_writers.h` — Code-level writing utilities (guards, namespace wrappers, type writers) + - `type_writers.h` — Type formatting (ABI signatures, names, GUIDs) + - `component_writers.h` — Component authoring code generation + - `helpers.h` — Metadata reading helpers + - `settings.h` — Global settings populated from CLI args + - `text_writer.h` — Core text writer infrastructure +- `strings/` — String literal `.h` files embedded by the prebuild step. Changes require: delete prebuild.exe → rebuild solution +- `nuget/` — MSBuild targets, props, and NuGet packaging + - `Microsoft.Windows.CppWinRT.targets` — Main MSBuild integration (projections, module support) +- `test/` — Test projects + - `test/test_cpp20_module/` — Standalone module test (in main solution) + - `test/nuget/` — NuGet integration tests (multi-project module chain) +- `docs/` — Documentation +- `natvis/` — Visual Studio debug visualizer (includes strings/*.h in its pch.h — add new files there too) + +## Build Process + +- Use VS Developer Shell for correct toolset environment +- `cmake --build build --config Release --target cppwinrt` for cppwinrt.exe (or MSBuild: `msbuild cppwinrt\cppwinrt.vcxproj /p:Configuration=Release /p:Platform=x64`) +- NuGet tests: `msbuild test\nuget\NuGetTest.sln /p:Configuration=Release /p:Platform=x64` +- Module test projects require v145 toolset (VS 2026). Directory.Build.Props selects v145 when VisualStudioVersion >= 18.0 (VS 2026) and falls back to v143 otherwise; override `` in the Configuration PropertyGroup to force a specific toolset + +## Key Patterns + +### Prebuild Embedding +The `strings/*.h` files are embedded as string literals by the prebuild step. If you modify any `strings/*.h` file, you must delete `prebuild.exe` and rebuild the entire solution for changes to take effect. + +### Module Guard Macros +- `WINRT_IMPL_BUILD_MODULE` — Defined in .ixx global fragment. Makes `WINRT_EXPORT` expand to `export extern "C++"` and suppresses `#include` of dependencies +- `WINRT_IMPORT_MODULE` — Defined by consumers who import modules. Makes namespace headers and base.h no-op (types come from module import) +- `WINRT_EXPORT` — Empty in header mode, `export extern "C++"` in module mode. Defined in `winrt/base_macros.h` +- `WINRT_IMPL_STD_EXPORT` — Empty in header mode, `extern "C++"` (without export) in module mode. Used for `namespace std` specializations + +### Generated Header Structure +Each namespace produces four header files: +- `impl/.0.h` — Forward declarations, ABIs, GUIDs, categories +- `impl/.1.h` — Interface definitions +- `impl/.2.h` — Delegates, structs, class implementations +- `.h` — Public API surface (consume definitions, class wrappers, operators) + +### Dependency Collection +When generating headers with `-modules`, writer.depends is inspected after each header to build a namespace dependency graph. This graph drives SCC detection and module import lists. + +## Common Gotchas + +- Module IFCs are NOT compatible across toolset versions — always clean rebuild when switching +- PCH and modules can coexist but PCH should NOT include winrt headers when using modules +- `/ifcSearchDir` works for the module dependency scanner to find IFCs, but cross-component modules may need explicit `/reference "name=path.ifc"` flags +- `import std;` requires `BuildStlModules=true` +- `strings/base_macros.h` is the single source of truth for shared macros (generated as `winrt/base_macros.h`). New macros go in `base_macros.h` only +- When adding, removing, or heavily refactoring `strings/*.h` files, always rebuild the natvis project (`natvis/cppwinrtvisualizer.sln`) to verify — it includes strings/*.h directly in its pch.h diff --git a/.github/instructions/modules.instructions.md b/.github/instructions/modules.instructions.md new file mode 100644 index 000000000..3deee2955 --- /dev/null +++ b/.github/instructions/modules.instructions.md @@ -0,0 +1,40 @@ +# C++/WinRT Modules — Agent Instructions + +## Module Architecture (v2 — Per-Namespace) + +Each WinRT namespace gets its own C++20 named module (`winrt.`). Base infrastructure is in `winrt_base` and `winrt_numerics`. + +### Code Generator Flow + +1. `-modules` flag enables .ixx generation in cppwinrt.exe +2. `-module_include`/`-module_exclude` filter which namespaces get modules +3. Headers are generated with dependency tracking (deps_ptr parameter) +4. Tarjan's SCC algorithm detects cyclic namespace groups +5. Standalone namespaces get individual .ixx; cyclic groups get consolidated SCC owner + re-export stubs + +### MSBuild Flow + +1. `CppWinRTBuildModule=true` adds `-modules` to cppwinrt.exe invocations +2. `CppWinRTAddModuleInterfaces` discovers `$(GeneratedFilesDir)winrt\*.ixx` and adds to ClCompile +3. `CppWinRTConsumeModule` metadata on ProjectReference controls per-reference IFC sharing +4. `CppWinRTResolveModuleReferences` calls `CppWinRTGetModuleOutputs` on tagged references +5. Platform projection suppresses `-modules` when consuming pre-built IFCs + +### Critical Invariants + +- Module guards are unconditional in codegen — `-modules` controls .ixx generation and component codegen (module.g.cpp, stub .cpp) +- SCC owner is alphabetically first namespace in the cycle +- All .ixx filenames use `winrt` prefix: `winrt.Windows.Foundation.ixx`, `winrt_base.ixx` +- Shared macros live in `strings/base_module.h` → generates `winrt/macros.h`. `base_macros.h` includes it via `#include "winrt/macros.h"` + +### Testing Changes + +After modifying cppwinrt.exe code: +1. Rebuild cppwinrt.exe: `msbuild cppwinrt\cppwinrt.vcxproj /p:Configuration=Release /p:Platform=x64` +2. Run standalone test: build `test_cpp20_module` in main solution +3. Run NuGet tests: `msbuild test\nuget\NuGetTest.sln /p:Configuration=Release /p:Platform=x64` + +After modifying targets: +1. Clean NuGet test obj dirs +2. Build with `/v:normal` and check "Module providers:" diagnostic messages +3. Inspect `.rsp` files in `obj/` to verify correct `-modules` flag placement diff --git a/.github/workflows/check-line-endings.yml b/.github/workflows/check-line-endings.yml new file mode 100644 index 000000000..3891aec09 --- /dev/null +++ b/.github/workflows/check-line-endings.yml @@ -0,0 +1,32 @@ +name: Check Line Endings + +on: + pull_request: + push: + branches: + - master + +jobs: + check-line-endings: + name: Enforce .gitattributes line endings + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + + - name: Check for line ending violations + run: | + # Re-normalize all files according to .gitattributes + git add --renormalize . + + # Check if renormalization changed anything + if git diff --cached --name-only | grep -q .; then + echo "::error::The following files have line endings that don't match .gitattributes settings:" + git diff --cached --name-only + echo "" + echo "To fix, run:" + echo " git add --renormalize ." + echo " git commit -m 'Normalize line endings'" + exit 1 + fi + + echo "All files have correct line endings." diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2d37aa360..5e2677fed 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,12 +8,15 @@ on: jobs: test-msvc-cppwinrt-build: - name: '${{ matrix.compiler }}: Build (${{ matrix.arch }}, ${{ matrix.config }})' + name: '${{ matrix.compiler }}: Build (${{ matrix.arch }}, ${{ matrix.config }}, ${{ matrix.toolchain.platform_toolset }})' strategy: matrix: compiler: [MSVC, clang-cl] arch: [x86, x64, arm64] config: [Debug, Release] + toolchain: + - image: windows-2025-vs2026 + platform_toolset: v145 exclude: - arch: arm64 config: Debug @@ -21,14 +24,9 @@ jobs: arch: arm64 - compiler: clang-cl config: Release - runs-on: windows-latest + runs-on: ${{ matrix.toolchain.image }} steps: - - uses: actions/checkout@v3 - - - id: setup-llvm - name: Set up LLVM (MSVC) - uses: ./.github/actions/setup-llvm-msvc - if: matrix.compiler == 'clang-cl' + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Download nuget run: | @@ -46,10 +44,12 @@ jobs: run: | $target_configuration = "${{ matrix.config }}" $target_platform = "${{ matrix.arch }}" - $target_version = "1.2.3.4" + $target_version = "999.999.999.999" $props = "Configuration=$target_configuration,Platform=$target_platform,CppWinRTBuildVersion=$target_version" if ("${{ matrix.compiler }}" -eq "clang-cl") { - $props += ",Clang=1,PlatformToolset=LLVM_v143,LLVMInstallDir=${{ steps.setup-llvm.outputs.llvm-path }}" + $props += ",Clang=1,PlatformToolset=ClangCl" + } else { + $props += ",PlatformToolset=${{ matrix.toolchain.platform_toolset }}" } Add-Content $env:GITHUB_ENV "msbuild_config_props=/p:$props" @@ -71,9 +71,9 @@ jobs: cmd /c "$env:VSDevCmd" "&" msbuild /m /clp:ForceConsoleColor "$env:msbuild_config_props" cppwinrt.sln /t:cppwinrt - name: Upload built executables - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: - name: msvc-build-${{ matrix.arch }}-${{ matrix.config }}-bin + name: msvc-build-${{ matrix.compiler}}-${{ matrix.arch }}-${{ matrix.config }}-${{ matrix.toolchain.platform_toolset }}-bin path: | _build/${{ matrix.arch }}/${{ matrix.config }}/*.exe _build/${{ matrix.arch }}/${{ matrix.config }}/*.dll @@ -89,7 +89,7 @@ jobs: & "_build\$target_platform\$target_configuration\cppwinrt.exe" -in local -out _build\$target_platform\$target_configuration -verbose test-msvc-cppwinrt-test: - name: '${{ matrix.compiler }}: Test [${{ matrix.test_exe }}] (${{ matrix.arch }}, ${{ matrix.config }})' + name: '${{ matrix.compiler }}: Test [${{ matrix.test_exe }}] (${{ matrix.arch }}, ${{ matrix.config }}, ${{ matrix.toolchain.platform_toolset }})' needs: test-msvc-cppwinrt-build strategy: fail-fast: false @@ -97,7 +97,10 @@ jobs: compiler: [MSVC, clang-cl] arch: [x86, x64, arm64] config: [Debug, Release] - test_exe: [test, test_cpp20, test_cpp20_no_sourcelocation, test_fast, test_slow, test_old, test_module_lock_custom, test_module_lock_none] + test_exe: [test, test_nocoro, test_cpp20, test_cpp20_no_sourcelocation, test_cpp20_module, test_fast, test_slow, test_old, test_module_lock_custom, test_module_lock_none] + toolchain: + - image: windows-2025-vs2026 + platform_toolset: v145 exclude: - arch: arm64 config: Debug @@ -105,27 +108,25 @@ jobs: arch: arm64 - compiler: clang-cl config: Release - runs-on: windows-latest + # C++20 named modules require the MSVC v145 toolset; clang-cl is not supported. + - compiler: clang-cl + test_exe: test_cpp20_module + runs-on: ${{ matrix.toolchain.image }} steps: - - uses: actions/checkout@v3 - - - id: setup-llvm - name: Set up LLVM (MSVC) - uses: ./.github/actions/setup-llvm-msvc - if: matrix.compiler == 'clang-cl' + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Fetch cppwinrt executables if: matrix.arch != 'arm64' - uses: actions/download-artifact@v3 + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: - name: msvc-build-${{ matrix.arch }}-${{ matrix.config }}-bin + name: msvc-build-${{ matrix.compiler}}-${{ matrix.arch }}-${{ matrix.config }}-${{ matrix.toolchain.platform_toolset }}-bin path: _build/${{ matrix.arch }}/${{ matrix.config }}/ - name: Fetch x86 cppwinrt executables (arm64 only) if: matrix.arch == 'arm64' - uses: actions/download-artifact@v3 + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: - name: msvc-build-x86-Release-bin + name: msvc-build-${{ matrix.compiler}}-x86-Release-${{ matrix.toolchain.platform_toolset }}-bin path: _build/x86/Release/ - name: Download nuget @@ -144,10 +145,12 @@ jobs: run: | $target_configuration = "${{ matrix.config }}" $target_platform = "${{ matrix.arch }}" - $target_version = "1.2.3.4" + $target_version = "999.999.999.999" $props = "Configuration=$target_configuration,Platform=$target_platform,CppWinRTBuildVersion=$target_version" if ("${{ matrix.compiler }}" -eq "clang-cl") { - $props += ",Clang=1,PlatformToolset=LLVM_v143,LLVMInstallDir=${{ steps.setup-llvm.outputs.llvm-path }}" + $props += ",Clang=1,PlatformToolset=ClangCl" + } else { + $props += ",PlatformToolset=${{ matrix.toolchain.platform_toolset }}" } Add-Content $env:GITHUB_ENV "msbuild_config_props=/p:$props" @@ -240,9 +243,9 @@ jobs: - name: Upload arm64 test executables if: matrix.arch == 'arm64' - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: - name: msvc-tests-${{ matrix.arch }}-${{ matrix.config }}-bin + name: msvc-tests-${{ matrix.test_exe }}-${{ matrix.compiler }}-${{ matrix.arch }}-${{ matrix.config }}-${{ matrix.toolchain.platform_toolset }}-bin path: | _build/${{ matrix.arch }}/${{ matrix.config }}/*.exe _build/${{ matrix.arch }}/${{ matrix.config }}/*.dll @@ -260,7 +263,7 @@ jobs: CMAKE_COLOR_DIAGNOSTICS: 1 CLICOLOR_FORCE: 1 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Install cross compiler run: | @@ -279,7 +282,7 @@ jobs: cmake --build build/cross_x64/ --target install -j2 - name: Upload cppwinrt.exe - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: cross-build-${{ matrix.arch }}-bin path: install/bin/cppwinrt.exe @@ -291,9 +294,9 @@ jobs: arch: [x86, x64, arm64] config: [Release] Deployment: [Component, Standalone] - runs-on: windows-latest + runs-on: windows-2025-vs2026 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Download nuget run: | @@ -311,8 +314,8 @@ jobs: run: | $target_configuration = "${{ matrix.config }}" $target_platform = "${{ matrix.arch }}" - $target_version = "1.2.3.4" - Add-Content $env:GITHUB_ENV "msbuild_config_props=/p:Configuration=$target_configuration,Platform=$target_platform,CppWinRTBuildVersion=$target_version" + $target_version = "999.999.999.999" + Add-Content $env:GITHUB_ENV "msbuild_config_props=/p:Configuration=$target_configuration,Platform=$target_platform,CppWinRTBuildVersion=$target_version,PlatformToolset=v145" - name: Restore nuget packages run: | @@ -323,20 +326,25 @@ jobs: cmd /c "$env:VSDevCmd" "&" msbuild /m /clp:ForceConsoleColor "$env:msbuild_config_props" /p:Deployment=${{ matrix.Deployment }} natvis\cppwinrtvisualizer.sln build-msvc-nuget-test: - name: 'Build nuget test' + name: 'Build nuget test (${{ matrix.arch }}, ${{ matrix.toolchain.platform_toolset }})' needs: test-msvc-cppwinrt-build strategy: matrix: + compiler: + - MSVC arch: [x86, x64] config: [Release] - runs-on: windows-latest + toolchain: + - image: windows-2025-vs2026 + platform_toolset: v145 + runs-on: ${{ matrix.toolchain.image }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Fetch cppwinrt executables - uses: actions/download-artifact@v3 + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: - name: msvc-build-${{ matrix.arch }}-${{ matrix.config }}-bin + name: msvc-build-${{ matrix.compiler}}-${{ matrix.arch }}-${{ matrix.config }}-${{ matrix.toolchain.platform_toolset }}-bin path: _build/${{ matrix.arch }}/${{ matrix.config }}/ - name: Download nuget @@ -355,8 +363,8 @@ jobs: run: | $target_configuration = "${{ matrix.config }}" $target_platform = "${{ matrix.arch }}" - $target_version = "1.2.3.4" - Add-Content $env:GITHUB_ENV "msbuild_config_props=/p:Configuration=$target_configuration,Platform=$target_platform,CppWinRTBuildVersion=$target_version" + $target_version = "999.999.999.999" + Add-Content $env:GITHUB_ENV "msbuild_config_props=/p:Configuration=$target_configuration,Platform=$target_platform,CppWinRTBuildVersion=$target_version,PlatformToolset=${{ matrix.toolchain.platform_toolset }}" - name: Restore nuget packages run: | @@ -367,21 +375,16 @@ jobs: $target_configuration = "${{ matrix.config }}" $target_platform = "${{ matrix.arch }}" & "_build\$target_platform\$target_configuration\cppwinrt.exe" -in local -out _build\$target_platform\$target_configuration -verbose - + - name: Run nuget test run: | cmd /c "$env:VSDevCmd" "&" msbuild /m /clp:ForceConsoleColor "$env:msbuild_config_props" test\nuget\NugetTest.sln - if ($LastExitCode -ne 0) { - echo "::warning::nuget test failed" - } - # FIXME: This build was failing from the start - exit 0 build-nuget: name: Build nuget package with MSVC - runs-on: windows-latest + runs-on: windows-2025-vs2026 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Package run: | @@ -396,7 +399,7 @@ jobs: } - name: Upload nuget package artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: package path: "*.nupkg" diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml deleted file mode 100644 index 20bf8f2a4..000000000 --- a/.github/workflows/stale.yml +++ /dev/null @@ -1,24 +0,0 @@ -name: Mark stale issues and pull requests - -on: - schedule: - - cron: '0 0 * * *' - -jobs: - stale: - - runs-on: ubuntu-latest - permissions: - issues: write - pull-requests: write - - steps: - - uses: actions/stale@v6 - with: - repo-token: ${{ secrets.GITHUB_TOKEN }} - days-before-stale: 10 - days-before-close: 5 - stale-issue-message: 'This issue is stale because it has been open 10 days with no activity. Remove stale label or comment or this will be closed in 5 days.' - stale-pr-message: 'This pull request is stale because it has been open 10 days with no activity. Remove stale label or comment or this will be closed in 5 days.' - stale-issue-label: 'no-issue-activity' - stale-pr-label: 'no-pr-activity' diff --git a/.pipelines/OneBranch.Official.yml b/.pipelines/OneBranch.Official.yml index def1114a8..158d3bf4e 100644 --- a/.pipelines/OneBranch.Official.yml +++ b/.pipelines/OneBranch.Official.yml @@ -6,11 +6,13 @@ parameters: # parameters are shown up in ADO UI in a build queue time variables: - template: variables/version.yml + parameters: + OfficialBuild: true - template: variables/OneBranchVariables.yml parameters: debug: ${{ parameters.debug }} -name: 2.0.$(date:yyMMdd)$(rev:.r) +name: 3.0.$(date:yyMMdd)$(rev:.r) trigger: none @@ -27,23 +29,27 @@ extends: platform: name: 'windows_undocked' product: 'build_tools' + + featureFlags: + WindowsHostVersion: + Version: 2022 cloudvault: enabled: false globalSdl: + isNativeCode: true + asyncSdl: + enabled: true tsa: - enabled: false - - nugetPublishing: - feeds: - name: CppWinRT + enabled: true + codeql: + compiled: + enabled: true + tsaEnabled: true stages: - stage: build - pool: - type: windows - jobs: - template: .pipelines/jobs/OneBranchBuild.yml@self parameters: @@ -59,7 +65,6 @@ extends: type: windows variables: ob_outputDirectory: '$(Build.SourcesDirectory)\out' - ob_createvpack_enabled: true ob_createvpack_packagename: CppWinRT.Compiler ob_createvpack_owneralias: cpp4uwpt @@ -72,48 +77,6 @@ extends: ob_createvpack_metadata: $(Build.SourceBranchName).x86.$(Build.BuildNumber).$(Build.SourceVersion) ob_createvpack_target: $(OSBuildToolsRoot)\cppwinrt - steps: - - task: UseDotNet@2 - continueOnError: true - inputs: - packageType: 'runtime' - version: '6.x' - performMultiLevelLookup: true - - - task: DownloadPipelineArtifact@2 - displayName: 'Download x86 artifacts' - inputs: - artifactName: 'drop_build_x86' - targetPath: '$(Build.SourcesDirectory)/x86' - - - task: CopyFiles@2 - displayName: 'Stage compiler vpack contents' - inputs: - SourceFolder: $(Build.SourcesDirectory)/x86 - Contents: | - cppwinrt/cppwinrt.exe - cppwinrt/cppwinrt.pdb - TargetFolder: $(ob_outputDirectory) - - - job: MSBuild_vpack - pool: - type: windows - variables: - ob_outputDirectory: '$(Build.SourcesDirectory)\out' - - ob_createvpack_enabled: true - ob_createvpack_packagename: CppWinRT.MSBuild - ob_createvpack_owneralias: cpp4uwpt - ob_createvpack_description: C++/WinRT MSBuild - ob_createvpack_provData: true - ob_createvpack_versionAs: parts - ob_createvpack_majorVer: $(MajorVersion) - ob_createvpack_minorVer: $(MinorVersion) - ob_createvpack_patchVer: $(PatchVersion) - ob_createvpack_metadata: $(Build.SourceBranchName).$(Build.BuildNumber).$(Build.SourceVersion) - ob_createvpack_verbose: true - ob_createvpack_target: $(OSBuildToolsRoot)\cppwinrt - steps: - task: UseDotNet@2 continueOnError: true @@ -134,25 +97,26 @@ extends: artifactName: 'drop_build_x64' targetPath: '$(Build.SourcesDirectory)/x64' - - task: DownloadPipelineArtifact@2 - displayName: 'Download arm artifacts' - inputs: - artifactName: 'drop_build_arm' - targetPath: '$(Build.SourcesDirectory)/arm' - - task: DownloadPipelineArtifact@2 displayName: 'Download arm64 artifacts' inputs: artifactName: 'drop_build_arm64' targetPath: '$(Build.SourcesDirectory)/arm64' + + - task: CopyFiles@2 + displayName: 'Stage compiler vpack contents' + inputs: + SourceFolder: $(Build.SourcesDirectory)/x86/cppwinrt + Contents: | + cppwinrt.exe + cppwinrt.pdb + TargetFolder: $(ob_outputDirectory) - task: CmdLine@2 displayName: 'Stage MSBuild vpack contents' inputs: script: | set TargetDir=$(ob_outputDirectory) - rd /s /q %TargetDir% >nul 2>&1 - md %TargetDir% cd %TargetDir% copy $(Build.SourcesDirectory)\vsix\Microsoft.Cpp.CppWinRT.props @@ -163,16 +127,15 @@ extends: echo d | xcopy $(Build.SourcesDirectory)\x86\cppwinrt_fast_forwarder.lib build\native\lib\Win32 echo d | xcopy $(Build.SourcesDirectory)\x64\cppwinrt_fast_forwarder.lib build\native\lib\amd64 echo d | xcopy $(Build.SourcesDirectory)\x64\cppwinrt_fast_forwarder.lib build\native\lib\x64 - echo d | xcopy $(Build.SourcesDirectory)\arm\cppwinrt_fast_forwarder.lib build\native\lib\arm echo d | xcopy $(Build.SourcesDirectory)\arm64\cppwinrt_fast_forwarder.lib build\native\lib\arm64 - + - stage: NuGet dependsOn: build jobs: - template: .pipelines/jobs/OneBranchNuGet.yml@self parameters: BuildConfiguration: $(BuildConfiguration) - BuildVersion: $(BuildVersion) + NugetPackageVersion: $(NugetPackageVersion) OfficialBuild: true - stage: Test @@ -190,4 +153,5 @@ extends: parameters: BuildConfiguration: $(BuildConfiguration) BuildVersion: $(BuildVersion) + NugetPackageVersion: $(NugetPackageVersion) OfficialBuild: true diff --git a/.pipelines/OneBranch.PullRequest.yml b/.pipelines/OneBranch.PullRequest.yml index 2ee26d1ad..d92dccaa2 100644 --- a/.pipelines/OneBranch.PullRequest.yml +++ b/.pipelines/OneBranch.PullRequest.yml @@ -10,7 +10,7 @@ variables: parameters: debug: ${{ parameters.debug }} -name: PullRequest_2.0.$(date:yyMMdd)$(rev:.r) +name: PullRequest_3.0.$(date:yyMMdd)$(rev:.r) trigger: none @@ -31,7 +31,12 @@ extends: name: 'windows_undocked' product: 'build_tools' + featureFlags: + WindowsHostVersion: + Version: 2022 + globalSdl: + isNativeCode: true tsa: enabled: false sbom: @@ -51,7 +56,7 @@ extends: - template: .pipelines/jobs/OneBranchNuGet.yml@self parameters: BuildConfiguration: $(BuildConfiguration) - BuildVersion: $(BuildVersion) + NugetPackageVersion: $(NugetPackageVersion) - stage: Test dependsOn: build @@ -68,3 +73,4 @@ extends: parameters: BuildConfiguration: $(BuildConfiguration) BuildVersion: $(BuildVersion) + NugetPackageVersion: $(NugetPackageVersion) diff --git a/.pipelines/build.yml b/.pipelines/build.yml index 8a7ee5568..ebe8ad041 100644 --- a/.pipelines/build.yml +++ b/.pipelines/build.yml @@ -31,8 +31,6 @@ jobs: buildPlatform: 'x86' x64: buildPlatform: 'x64' - arm: - buildPlatform: 'arm' arm64: buildPlatform: 'arm64' @@ -49,6 +47,10 @@ jobs: - task: NuGetCommand@2 displayName: NuGet restore + inputs: + command: 'restore' + feedsToUse: config + nugetConfigPath: NuGet.config - task: CmdLine@2 displayName: Build Tools @@ -165,12 +167,6 @@ jobs: artifactName: $(BuildConfiguration)_x64 downloadPath: $(Build.SourcesDirectory)\x64 - - task: DownloadPipelineArtifact@1 - displayName: Download arm Artifacts - inputs: - artifactName: $(BuildConfiguration)_arm - downloadPath: $(Build.SourcesDirectory)\arm - - task: DownloadPipelineArtifact@1 displayName: Download arm64 Artifacts inputs: @@ -258,7 +254,7 @@ jobs: - task: CmdLine@2 displayName: Stage MSBuild vpack inputs: - script: "set TargetDir=$(Build.SourcesDirectory)\\msbuild\nrd /s /q %TargetDir% >nul 2>&1\nmd %TargetDir%\ncd %TargetDir%\n\ncopy $(Build.SourcesDirectory)\\vsix\\Microsoft.Cpp.CppWinRT.props\ncopy $(Build.SourcesDirectory)\\nuget\\Microsoft.Windows.CppWinRT.props Microsoft.Cpp.CppWinRTEnabled.props \ncopy $(Build.SourcesDirectory)\\nuget\\Microsoft.Windows.CppWinRT.targets Microsoft.Cpp.CppWinRTEnabled.targets\ncopy $(Build.SourcesDirectory)\\nuget\\CppWinrtRules.Project.xml CppWinrtRules.Project.xml\necho d | xcopy $(Build.SourcesDirectory)\\x86\\cppwinrt_fast_forwarder.lib build\\native\\lib\\i386\necho d | xcopy $(Build.SourcesDirectory)\\x86\\cppwinrt_fast_forwarder.lib build\\native\\lib\\Win32\necho d | xcopy $(Build.SourcesDirectory)\\x64\\cppwinrt_fast_forwarder.lib build\\native\\lib\\amd64\necho d | xcopy $(Build.SourcesDirectory)\\x64\\cppwinrt_fast_forwarder.lib build\\native\\lib\\x64\necho d | xcopy $(Build.SourcesDirectory)\\arm\\cppwinrt_fast_forwarder.lib build\\native\\lib\\arm\necho d | xcopy $(Build.SourcesDirectory)\\arm64\\cppwinrt_fast_forwarder.lib build\\native\\lib\\arm64\n" + script: "set TargetDir=$(Build.SourcesDirectory)\\msbuild\nrd /s /q %TargetDir% >nul 2>&1\nmd %TargetDir%\ncd %TargetDir%\n\ncopy $(Build.SourcesDirectory)\\vsix\\Microsoft.Cpp.CppWinRT.props\ncopy $(Build.SourcesDirectory)\\nuget\\Microsoft.Windows.CppWinRT.props Microsoft.Cpp.CppWinRTEnabled.props \ncopy $(Build.SourcesDirectory)\\nuget\\Microsoft.Windows.CppWinRT.targets Microsoft.Cpp.CppWinRTEnabled.targets\ncopy $(Build.SourcesDirectory)\\nuget\\CppWinrtRules.Project.xml CppWinrtRules.Project.xml\necho d | xcopy $(Build.SourcesDirectory)\\x86\\cppwinrt_fast_forwarder.lib build\\native\\lib\\i386\necho d | xcopy $(Build.SourcesDirectory)\\x86\\cppwinrt_fast_forwarder.lib build\\native\\lib\\Win32\necho d | xcopy $(Build.SourcesDirectory)\\x64\\cppwinrt_fast_forwarder.lib build\\native\\lib\\amd64\necho d | xcopy $(Build.SourcesDirectory)\\x64\\cppwinrt_fast_forwarder.lib build\\native\\lib\\x64\necho d | xcopy $(Build.SourcesDirectory)\\arm64\\cppwinrt_fast_forwarder.lib build\\native\\lib\\arm64\n" failOnStderr: true - task: PkgESVPack@12 @@ -322,6 +318,10 @@ jobs: - task: NuGetCommand@2 displayName: NuGet restore + inputs: + command: 'restore' + feedsToUse: config + nugetConfigPath: NuGet.config - task: DownloadPipelineArtifact@1 displayName: Download x86 Artifacts @@ -335,12 +335,6 @@ jobs: artifactName: $(BuildConfiguration)_x64 downloadPath: $(Build.SourcesDirectory)\x64 - - task: DownloadPipelineArtifact@1 - displayName: Download arm Artifacts - inputs: - artifactName: $(BuildConfiguration)_arm - downloadPath: $(Build.SourcesDirectory)\arm - - task: DownloadPipelineArtifact@1 displayName: Download arm64 Artifacts inputs: @@ -422,7 +416,7 @@ jobs: command: pack searchPatternPack: nuget/Microsoft.Windows.CppWinRT.nuspec versioningScheme: byBuildNumber - buildProperties: 'target_version=$(Build.BuildNumber);cppwinrt_exe=$(Build.ArtifactStagingDirectory)\x86\cppwinrt.exe;cppwinrt_fast_fwd_x86=$(Build.SourcesDirectory)\x86\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_x64=$(Build.SourcesDirectory)\x64\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_arm=$(Build.SourcesDirectory)\arm\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_arm64=$(Build.SourcesDirectory)\arm64\cppwinrt_fast_forwarder.lib ' + buildProperties: 'target_version=$(Build.BuildNumber);cppwinrt_exe=$(Build.ArtifactStagingDirectory)\x86\cppwinrt.exe;cppwinrt_fast_fwd_x86=$(Build.SourcesDirectory)\x86\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_x64=$(Build.SourcesDirectory)\x64\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_arm64=$(Build.SourcesDirectory)\arm64\cppwinrt_fast_forwarder.lib ' - task: ComponentGovernanceComponentDetection@0 displayName: Component Detection diff --git a/.pipelines/jobs/OneBranchBuild.yml b/.pipelines/jobs/OneBranchBuild.yml index 984530eba..dfee85edf 100644 --- a/.pipelines/jobs/OneBranchBuild.yml +++ b/.pipelines/jobs/OneBranchBuild.yml @@ -20,8 +20,6 @@ jobs: BuildPlatform: 'x86' x64: BuildPlatform: 'x64' - arm: - BuildPlatform: 'arm' arm64: BuildPlatform: 'arm64' @@ -33,6 +31,10 @@ jobs: ${{ if eq(parameters.OfficialBuild, 'false') }}: ob_sdl_codeSignValidation_excludes: '-|**\*.exe;-|**\*.dll' + ob_sdl_prefast_enabled: true + ob_sdl_prefast_runDuring: "Guardian" + ob_sdl_checkCompliantCompilerWarnings: true + ob_symbolsPublishing_enabled: ${{ parameters.OfficialBuild }} ob_symbolsPublishing_symbolsFolder: '$(ob_outputDirectory)' ob_symbolsPublishing_searchPattern: '**\*.pdb' @@ -51,6 +53,8 @@ jobs: inputs: command: 'restore' restoreSolution: '$(Build.SourcesDirectory)\cppwinrt.sln' + feedsToUse: config + nugetConfigPath: NuGet.config - task: VSBuild@1 displayName: Build fast_fwd @@ -72,6 +76,8 @@ jobs: inputs: command: 'restore' restoreSolution: '$(Build.SourcesDirectory)\natvis\cppwinrtvisualizer.sln' + feedsToUse: config + nugetConfigPath: NuGet.config - task: VSBuild@1 displayName: Build Component visualizer diff --git a/.pipelines/jobs/OneBranchNuGet.yml b/.pipelines/jobs/OneBranchNuGet.yml index 803e6f9f7..36ec3144b 100644 --- a/.pipelines/jobs/OneBranchNuGet.yml +++ b/.pipelines/jobs/OneBranchNuGet.yml @@ -2,7 +2,7 @@ parameters: - name: BuildConfiguration type: string - - name: BuildVersion + - name: NugetPackageVersion type: string - name: OfficialBuild type: boolean @@ -15,8 +15,11 @@ jobs: variables: ob_outputDirectory: '$(Build.SourcesDirectory)\out' - ob_nugetPublishing_enabled: ${{ parameters.OfficialBuild }} - PackageVersion: ${{ parameters.BuildVersion }} + PackageVersion: ${{ parameters.NugetPackageVersion }} + + ob_sdl_prefast_enabled: true + ob_sdl_prefast_runDuring: 'Guardian' + ob_sdl_checkCompliantCompilerWarnings: true steps: - task: UseDotNet@2 @@ -44,12 +47,6 @@ jobs: artifactName: 'drop_build_x64' targetPath: '$(Build.SourcesDirectory)/x64' - - task: DownloadPipelineArtifact@1 - displayName: 'Download arm artifacts' - inputs: - artifactName: 'drop_build_arm' - targetPath: '$(Build.SourcesDirectory)/arm' - - task: DownloadPipelineArtifact@1 displayName: 'Download arm64 artifacts' inputs: @@ -59,12 +56,8 @@ jobs: - task: NuGetCommand@2 displayName: 'Build NuGet package' inputs: - command: 'pack' - packagesToPack: 'nuget/Microsoft.Windows.CppWinRT.nuspec' - versioningScheme: byEnvVar - versionEnvVar: 'PackageVersion' - buildProperties: 'cppwinrt_exe=$(Build.SourcesDirectory)\x86\cppwinrt\cppwinrt.exe;cppwinrt_fast_fwd_x86=$(Build.SourcesDirectory)\x86\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_x64=$(Build.SourcesDirectory)\x64\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_arm=$(Build.SourcesDirectory)\arm\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_arm64=$(Build.SourcesDirectory)\arm64\cppwinrt_fast_forwarder.lib' - packDestination: $(ob_outputDirectory)\packages + command: 'custom' + arguments: 'pack nuget/Microsoft.Windows.CppWinRT.nuspec -NonInteractive -OutputDirectory $(ob_outputDirectory)\packages -Properties Configuration=release;cppwinrt_exe=$(Build.SourcesDirectory)\x86\cppwinrt\cppwinrt.exe;cppwinrt_fast_fwd_x86=$(Build.SourcesDirectory)\x86\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_x64=$(Build.SourcesDirectory)\x64\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_arm64=$(Build.SourcesDirectory)\arm64\cppwinrt_fast_forwarder.lib;target_version=$(PackageVersion) -Version $(PackageVersion) -Verbosity Detailed' - task: onebranch.pipeline.signing@1 displayName: '🔒 Onebranch Signing for NuGet package' @@ -74,3 +67,9 @@ jobs: signing_profile: external_distribution files_to_sign: 'Microsoft.Windows.CppWinRT.*.nupkg' search_root: $(ob_outputDirectory)\packages + + - task: NuGetCommand@2 + displayName: 'Publish NuGet package' + inputs: + command: 'custom' + arguments: 'push $(ob_outputDirectory)\packages\Microsoft.Windows.CppWinRT.$(PackageVersion).nupkg -NonInteractive -Source https://microsoft.pkgs.visualstudio.com/_packaging/CppWinRT/nuget/v3/index.json -ApiKey VSTS' diff --git a/.pipelines/jobs/OneBranchTest.yml b/.pipelines/jobs/OneBranchTest.yml index d9634ff1e..2fb3a4bd1 100644 --- a/.pipelines/jobs/OneBranchTest.yml +++ b/.pipelines/jobs/OneBranchTest.yml @@ -8,12 +8,19 @@ jobs: - job: pool: type: windows + isCustom: true + name: 'Azure Pipelines' + vmImage: 'windows-2022' # (or 2019) strategy: matrix: test.x86: TestExe: 'test' TestProject: 'test' BuildPlatform: 'x86' + test_nocoro.x86: + TestExe: 'test_nocoro' + TestProject: 'test_nocoro' + BuildPlatform: 'x86' test_cpp20.x86: TestExe: 'test_cpp20' TestProject: 'test_cpp20' @@ -48,6 +55,10 @@ jobs: ob_artifactSuffix: $(TestExe).$(BuildPlatform) ob_sdl_codeSignValidation_excludes: '-|**\*.exe;-|**\*.dll' + ob_sdl_prefast_enabled: true + ob_sdl_prefast_runDuring: 'Build' + ob_sdl_checkCompliantCompilerWarnings: true + BuildPath: '$(Build.SourcesDirectory)/_build/$(BuildPlatform)/${{ parameters.BuildConfiguration }}' steps: @@ -77,6 +88,8 @@ jobs: inputs: command: 'restore' restoreSolution: '$(Build.SourcesDirectory)\cppwinrt.sln' + feedsToUse: config + nugetConfigPath: NuGet.config - task: PowerShell@2 displayName: Remove cppwinrt dependency from test projects diff --git a/.pipelines/jobs/OneBranchVsix.yml b/.pipelines/jobs/OneBranchVsix.yml index 2efa5b29c..696b7e292 100644 --- a/.pipelines/jobs/OneBranchVsix.yml +++ b/.pipelines/jobs/OneBranchVsix.yml @@ -3,6 +3,8 @@ parameters: type: string - name: BuildVersion type: string + - name: NugetPackageVersion + type: string - name: OfficialBuild type: boolean default: false @@ -36,6 +38,10 @@ jobs: ob_symbolsPublishing_symbolsFolder: '$(ob_outputDirectory)' ob_symbolsPublishing_searchPattern: '**\*.pdb' ob_symbolsPublishing_indexSources: true + + ob_sdl_prefast_enabled: true + ob_sdl_prefast_runDuring: 'Build' + ob_sdl_checkCompliantCompilerWarnings: true steps: - task: UseDotNet@2 @@ -56,6 +62,8 @@ jobs: inputs: command: 'restore' restoreSolution: '$(Build.SourcesDirectory)\vsix\vsix.sln' + feedsToUse: config + nugetConfigPath: NuGet.config - task: DownloadPipelineArtifact@2 displayName: 'Download x86 binaries' @@ -69,12 +77,6 @@ jobs: artifactName: 'drop_build_x64' targetPath: '$(Build.SourcesDirectory)\x64' - - task: DownloadPipelineArtifact@2 - displayName: 'Download arm binaries' - inputs: - artifactName: 'drop_build_arm' - targetPath: '$(Build.SourcesDirectory)\arm' - - task: DownloadPipelineArtifact@2 displayName: 'Download arm64 binaries' inputs: @@ -91,7 +93,7 @@ jobs: displayName: Build VSIX inputs: solution: $(Build.SourcesDirectory)\vsix\vsix.sln - msbuildArgs: /t:vsix_$(VsVersion) /m /p:CppWinRTVersion=${{ parameters.BuildVersion }},clean_intermediate_files=true,Deployment=$(Deployment),NatvisDirx86=$(Build.SourcesDirectory)\x86\$(Deployment)\,NatvisDirx64=$(Build.SourcesDirectory)\x64\$(Deployment)\,NatvisDirarm64=$(Build.SourcesDirectory)\arm64\$(Deployment)\,NupkgDir=$(Pipeline.Workspace)\nuget\packages /bl:$(ob_outputDirectory)\output.binlog + msbuildArgs: /t:vsix_$(VsVersion) /m /p:CppWinRTVersion=${{ parameters.BuildVersion }},NugetPackageVersion=${{ parameters.NugetPackageVersion }},clean_intermediate_files=true,Deployment=$(Deployment),NatvisDirx86=$(Build.SourcesDirectory)\x86\$(Deployment)\,NatvisDirx64=$(Build.SourcesDirectory)\x64\$(Deployment)\,NatvisDirarm64=$(Build.SourcesDirectory)\arm64\$(Deployment)\,NupkgDir=$(Pipeline.Workspace)\nuget\packages /bl:$(ob_outputDirectory)\output.binlog platform: 'Any CPU' configuration: ${{ parameters.BuildConfiguration }} @@ -108,7 +110,7 @@ jobs: inputs: command: sign signing_profile: external_distribution - files_to_sign: '**/Microsoft.Windows.CppWinRT.*.dll' + files_to_sign: '**\*.dll' search_root: '$(Agent.TempDirectory)\$(VsixFilename)' - task: ArchiveFiles@2 diff --git a/.pipelines/variables/OneBranchVariables.yml b/.pipelines/variables/OneBranchVariables.yml index 8e6ad8af0..ff7a98adb 100644 --- a/.pipelines/variables/OneBranchVariables.yml +++ b/.pipelines/variables/OneBranchVariables.yml @@ -10,7 +10,7 @@ variables: NUGET_XMLDOC_MODE: none # Docker image which is used to build the project https://aka.ms/obpipelines/containers - WindowsContainerImage: 'onebranch.azurecr.io/windows/ltsc2019/vse2022:latest' + WindowsContainerImage: 'onebranch.azurecr.io/windows/ltsc2022/vse2022:latest' Codeql.Enabled: true # CodeQL once every 3 days on the default branch for all languages its applicable to in that pipeline. GDN_USE_DOTNET: true \ No newline at end of file diff --git a/.pipelines/variables/version.yml b/.pipelines/variables/version.yml index 576d896eb..46a535ee0 100644 --- a/.pipelines/variables/version.yml +++ b/.pipelines/variables/version.yml @@ -1,7 +1,17 @@ +parameters: + - name: OfficialBuild + type: boolean + default: false + variables: - MajorVersion: "2" + MajorVersion: "3" MinorVersion: "0" VersionDate: $[format('{0:yyMMdd}', pipeline.startTime)] VersionCounter: $[counter(variables['VersionDate'], 1)] BuildVersion: $(MajorVersion).$(MinorVersion).$(VersionDate).$(VersionCounter) - PatchVersion: $(VersionDate)$(VersionCounter) \ No newline at end of file + PatchVersion: $(VersionDate)$(VersionCounter) + + ${{ if eq(parameters.OfficialBuild, true) }}: + NugetPackageVersion: $(BuildVersion) + ${{ else }}: + NugetPackageVersion: $(BuildVersion)-unofficial diff --git a/.runsettings b/.runsettings new file mode 100644 index 000000000..5f10e44f8 --- /dev/null +++ b/.runsettings @@ -0,0 +1,24 @@ + + + + .\TestResults + 60000 + true + + + + + + + Single + (?i:Test) + true + on + true + Verbose + AdditionalInfo + ShortInfo + , + 20000 + + \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 139da8379..b0089e7ad 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,8 +13,8 @@ project(cppwinrt LANGUAGES CXX) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED True) -set(CPPWINRT_BUILD_VERSION "2.3.4.5" CACHE STRING "The version string used for cppwinrt.") -if(CPPWINRT_BUILD_VERSION STREQUAL "2.3.4.5" OR CPPWINRT_BUILD_VERSION STREQUAL "0.0.0.0") +set(CPPWINRT_BUILD_VERSION "999.999.999.999" CACHE STRING "The version string used for cppwinrt.") +if(CPPWINRT_BUILD_VERSION STREQUAL "999.999.999.999" OR CPPWINRT_BUILD_VERSION STREQUAL "0.0.0.0") message(WARNING "CPPWINRT_BUILD_VERSION has been set to a dummy version string. Do not use in production!") endif() message(STATUS "Using version string: ${CPPWINRT_BUILD_VERSION}") diff --git a/Directory.Build.Props b/Directory.Build.Props index 95286d288..5972803c0 100644 --- a/Directory.Build.Props +++ b/Directory.Build.Props @@ -3,7 +3,10 @@ + v143 + v145 10.0 10.0.18362.0 @@ -30,24 +33,26 @@ ClangCL - + 20 false - 2.3.4.5 + 999.999.999.999 $(Platform) x86 $(SolutionDir)_build\$(CppWinRTPlatform)\$(Configuration)\ + $(SolutionDir)_build\$(CppWinRTPlatform)\$(Configuration)\temp\$(MSBuildProjectName)\ $(OutDir) - $(SolutionDir)_build\x86\$(Configuration)\ + $(SolutionDir)_build\x86\$(Configuration)\ Level4 + true true true stdcpp17 @@ -58,7 +63,7 @@ CATCH_CONFIG_COLOUR_ANSI;%(PreprocessorDefinitions) true /bigobj - /await %(AdditionalOptions) + /await:strict %(AdditionalOptions) -Wno-unused-command-line-argument -fno-delayed-template-parsing -mcx16 diff --git a/Directory.Build.Targets b/Directory.Build.Targets deleted file mode 100644 index 98abcdd3f..000000000 --- a/Directory.Build.Targets +++ /dev/null @@ -1,7 +0,0 @@ - - - - $(OutDir)temp\$(ProjectName)\ - - - diff --git a/Directory.Packages.props b/Directory.Packages.props new file mode 100644 index 000000000..1d77adffd --- /dev/null +++ b/Directory.Packages.props @@ -0,0 +1,12 @@ + + + true + + + + + + + + + \ No newline at end of file diff --git a/README.md b/README.md index 691809d31..19e1493dc 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ If you really want to build it yourself, the simplest way to do so is to run the * Open the `cppwinrt.sln` solution. * Choose a configuration (x64, x86, Release, Debug) and build projects as needed. -If you are working on an ARM64 or ARM specific issue from an x64 or x86 host, you will need to instead: +If you are working on an ARM64 specific issue from an x64 or x86 host, you will need to instead: * Open the `cppwinrt.sln` solution * Build the x86 version of the "cppwinrt" project first @@ -34,3 +34,8 @@ a dev command prompt at the root of the repo _after_ following the above build i * Run `build_prior_projection.cmd` in the dev command prompt as well * Run `prepare_versionless_diffs.cmd` which removes version stamps on both current and prior projection * Use a directory-level differencing tool to compare `_build\$(arch)\$(flavor)\winrt` and `_reference\$(arch)\$(flavor)\winrt` + +## Testing +This repository uses the [Catch2](https://github.com/catchorg/Catch2) testing framework. +- From a Visual Studio command line, you should run `build_tests_all.cmd` to build and run the tests. To Debug the tests, you can debug the associated `_build\$(arch)\$(flavor)\.exe` under the debugger of your choice. +- Optionally, you can install the [Catch2Adapter](https://marketplace.visualstudio.com/items?itemName=JohnnyHendriks.ext01) to run the tests from Visual Studio. \ No newline at end of file diff --git a/build_nuget.cmd b/build_nuget.cmd index cb950a625..99e193311 100644 --- a/build_nuget.cmd +++ b/build_nuget.cmd @@ -1,13 +1,12 @@ rem @echo off set target_version=%1 -if "%target_version%"=="" set target_version=3.0.0.0 +if "%target_version%"=="" set target_version=999.999.999.999 call msbuild /m /p:Configuration=Release,Platform=x86,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:fast_fwd call msbuild /m /p:Configuration=Release,Platform=x64,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:fast_fwd -call msbuild /m /p:Configuration=Release,Platform=arm,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:fast_fwd call msbuild /m /p:Configuration=Release,Platform=arm64,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:fast_fwd call msbuild /m /p:Configuration=Release,Platform=x86,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:cppwinrt -nuget pack nuget\Microsoft.Windows.CppWinRT.nuspec -Properties target_version=%target_version%;cppwinrt_exe=%cd%\_build\x86\Release\cppwinrt.exe;cppwinrt_fast_fwd_x86=%cd%\_build\x86\Release\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_x64=%cd%\_build\x64\Release\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_arm=%cd%\_build\arm\Release\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_arm64=%cd%\_build\arm64\Release\cppwinrt_fast_forwarder.lib +nuget pack nuget\Microsoft.Windows.CppWinRT.nuspec -Properties target_version=%target_version%;cppwinrt_exe=%cd%\_build\x86\Release\cppwinrt.exe;cppwinrt_fast_fwd_x86=%cd%\_build\x86\Release\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_x64=%cd%\_build\x64\Release\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_arm64=%cd%\_build\arm64\Release\cppwinrt_fast_forwarder.lib diff --git a/build_prior_projection.cmd b/build_prior_projection.cmd index c7bdf2f64..9d10f3eaa 100644 --- a/build_prior_projection.cmd +++ b/build_prior_projection.cmd @@ -12,7 +12,6 @@ if /I "%target_platform%" equ "all" ( ) call %0 x86 !target_configuration! call %0 x64 !target_configuration! - call %0 arm !target_configuration! call %0 arm64 !target_configuration! goto :eof ) diff --git a/build_projection.cmd b/build_projection.cmd index 778fa7aca..140e6c7f8 100644 --- a/build_projection.cmd +++ b/build_projection.cmd @@ -12,7 +12,6 @@ if /I "%target_platform%" equ "all" ( ) call %0 x86 !target_configuration! call %0 x64 !target_configuration! - call %0 arm !target_configuration! call %0 arm64 !target_configuration! goto :eof ) diff --git a/build_test_all.cmd b/build_test_all.cmd index 89967a04b..c9beb852c 100644 --- a/build_test_all.cmd +++ b/build_test_all.cmd @@ -7,7 +7,7 @@ set clean_intermediate_files=%4 if "%target_platform%"=="" set target_platform=x64 if "%target_configuration%"=="" set target_configuration=Release -if "%target_version%"=="" set target_version=1.2.3.4 +if "%target_version%"=="" set target_version=999.999.999.999 if not exist ".\.nuget" mkdir ".\.nuget" if not exist ".\.nuget\nuget.exe" powershell -Command "$ProgressPreference = 'SilentlyContinue' ; Invoke-WebRequest https://dist.nuget.org/win-x86-commandline/latest/nuget.exe -OutFile .\.nuget\nuget.exe" @@ -18,8 +18,6 @@ call .nuget\nuget.exe restore test\nuget\NugetTest.sln call msbuild /m /p:Configuration=%target_configuration%,Platform=%target_platform%,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:fast_fwd -if "%target_platform%"=="arm" goto :eof - call msbuild /p:Configuration=%target_configuration%,Platform=%target_platform%,Deployment=Component;CppWinRTBuildVersion=%target_version% natvis\cppwinrtvisualizer.sln call msbuild /p:Configuration=%target_configuration%,Platform=%target_platform%,Deployment=Standalone;CppWinRTBuildVersion=%target_version% natvis\cppwinrtvisualizer.sln @@ -30,6 +28,7 @@ call msbuild /m /p:Configuration=%target_configuration%,Platform=%target_platfor call msbuild /p:Configuration=%target_configuration%,Platform=%target_platform%,CppWinRTBuildVersion=%target_version% test\nuget\NugetTest.sln call msbuild /m /p:Configuration=%target_configuration%,Platform=%target_platform%,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:test\test +call msbuild /m /p:Configuration=%target_configuration%,Platform=%target_platform%,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:test\test_nocoro call msbuild /m /p:Configuration=%target_configuration%,Platform=%target_platform%,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:test\test_cpp20 call msbuild /m /p:Configuration=%target_configuration%,Platform=%target_platform%,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:test\test_cpp20_no_sourcelocation call msbuild /m /p:Configuration=%target_configuration%,Platform=%target_platform%,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:test\test_fast diff --git a/build_vsix.cmd b/build_vsix.cmd index 111527a48..0a47f6bd6 100644 --- a/build_vsix.cmd +++ b/build_vsix.cmd @@ -6,7 +6,7 @@ set target_version=%2 set target_deployment=%3 if "%target_configuration%"=="" set target_configuration=Release -if "%target_version%"=="" set target_version=1.2.3.4 +if "%target_version%"=="" set target_version=999.999.999.999 if "%target_deployment%"=="" set target_deployment=Standalone if not exist ".\.nuget" mkdir ".\.nuget" @@ -19,7 +19,6 @@ call .nuget\nuget.exe restore test\nuget\NugetTest.sln rem Build fast forwarder libs or all arches call msbuild /m /p:Configuration=%target_configuration%,Platform=x86,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:fast_fwd call msbuild /m /p:Configuration=%target_configuration%,Platform=x64,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:fast_fwd -call msbuild /m /p:Configuration=%target_configuration%,Platform=arm,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:fast_fwd call msbuild /m /p:Configuration=%target_configuration%,Platform=arm64,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:fast_fwd rem Build cppwinrt.exe for x86 only @@ -31,7 +30,7 @@ call msbuild /p:Configuration=%target_configuration%,Platform=x86,Deployment=%ta call msbuild /p:Configuration=%target_configuration%,Platform=arm64,Deployment=%target_deployment%,CppWinRTBuildVersion=%target_version% natvis\cppwinrtvisualizer.sln rem Build nuget -.nuget\nuget.exe pack nuget\Microsoft.Windows.CppWinRT.nuspec -NonInteractive -OutputDirectory %this_dir%_build -Properties Configuration=%target_configuration%;cppwinrt_exe=%this_dir%_build\x86\%target_configuration%\cppwinrt.exe;cppwinrt_fast_fwd_x86=%this_dir%_build\x86\%target_configuration%\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_x64=%this_dir%_build\x64\%target_configuration%\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_arm=%this_dir%_build\arm\%target_configuration%\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_arm64=%this_dir%_build\arm64\%target_configuration%\cppwinrt_fast_forwarder.lib -version %target_version% -Verbosity Detailed +.nuget\nuget.exe pack nuget\Microsoft.Windows.CppWinRT.nuspec -NonInteractive -OutputDirectory %this_dir%_build -Properties Configuration=%target_configuration%;cppwinrt_exe=%this_dir%_build\x86\%target_configuration%\cppwinrt.exe;cppwinrt_fast_fwd_x86=%this_dir%_build\x86\%target_configuration%\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_x64=%this_dir%_build\x64\%target_configuration%\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_arm64=%this_dir%_build\arm64\%target_configuration%\cppwinrt_fast_forwarder.lib;target_version=%target_version% -version %target_version% -Verbosity Detailed rem Build vsix -call msbuild /restore /p:Configuration=%target_configuration%,Platform="Any CPU",Deployment=%target_deployment%,CppWinRTVersion=%target_version%,NatvisDirx86=%this_dir%natvis\x86\%target_configuration%\%target_deployment%,NatvisDirx64=%this_dir%natvis\x64\%target_configuration%\%target_deployment%,NatvisDirarm64=%this_dir%natvis\arm64\%target_configuration%\%target_deployment%,NupkgDir=%this_dir%_build vsix\vsix.sln +call msbuild /restore /p:Configuration=%target_configuration%,Platform="Any CPU",Deployment=%target_deployment%,CppWinRTVersion=%target_version%,NugetPackageVersion=%target_version%,NatvisDirx86=%this_dir%natvis\x86\%target_configuration%\%target_deployment%,NatvisDirx64=%this_dir%natvis\x64\%target_configuration%\%target_deployment%,NatvisDirarm64=%this_dir%natvis\arm64\%target_configuration%\%target_deployment%,NupkgDir=%this_dir%_build vsix\vsix.sln diff --git a/cppwinrt.sln b/cppwinrt.sln index 43e96ffab..700e9f5ea 100644 --- a/cppwinrt.sln +++ b/cppwinrt.sln @@ -88,6 +88,9 @@ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fast_fwd", "fast_fwd\fast_fwd.vcxproj", "{A63B3AD1-AB7B-461E-9FFF-2447F5BCD459}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "scratch", "scratch\scratch.vcxproj", "{E893622C-47DE-4F83-B422-0A26711590A4}" + ProjectSection(ProjectDependencies) = postProject + {D613FB39-5035-4043-91E2-BAB323908AF4} = {D613FB39-5035-4043-91E2-BAB323908AF4} + EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_module_lock_none", "test\test_module_lock_none\test_module_lock_none.vcxproj", "{D48A96C2-8512-4CC3-B6E4-7CFF07ED8ED3}" ProjectSection(ProjectDependencies) = postProject @@ -116,6 +119,16 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_cpp20_no_sourcelocatio {D613FB39-5035-4043-91E2-BAB323908AF4} = {D613FB39-5035-4043-91E2-BAB323908AF4} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_nocoro", "test\test_nocoro\test_nocoro.vcxproj", "{9E392830-805A-4AAF-932D-C493143EFACA}" + ProjectSection(ProjectDependencies) = postProject + {D613FB39-5035-4043-91E2-BAB323908AF4} = {D613FB39-5035-4043-91E2-BAB323908AF4} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_cpp20_module", "test\test_cpp20_module\test_cpp20_module.vcxproj", "{B8E3A5CE-4E91-4F27-9B02-E0CAF7E10D72}" + ProjectSection(ProjectDependencies) = postProject + {D613FB39-5035-4043-91E2-BAB323908AF4} = {D613FB39-5035-4043-91E2-BAB323908AF4} + EndProjectSection +EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{D15C8430-A7CD-4616-BD84-243B26A9F1C2}" ProjectSection(SolutionItems) = preProject build_nuget.cmd = build_nuget.cmd @@ -131,352 +144,290 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|ARM = Debug|ARM Debug|ARM64 = Debug|ARM64 Debug|x64 = Debug|x64 Debug|x86 = Debug|x86 - Release|ARM = Release|ARM Release|ARM64 = Release|ARM64 Release|x64 = Release|x64 Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {D613FB39-5035-4043-91E2-BAB323908AF4}.Debug|ARM.ActiveCfg = Debug|ARM - {D613FB39-5035-4043-91E2-BAB323908AF4}.Debug|ARM.Build.0 = Debug|ARM {D613FB39-5035-4043-91E2-BAB323908AF4}.Debug|ARM64.ActiveCfg = Debug|ARM64 {D613FB39-5035-4043-91E2-BAB323908AF4}.Debug|ARM64.Build.0 = Debug|ARM64 {D613FB39-5035-4043-91E2-BAB323908AF4}.Debug|x64.ActiveCfg = Debug|x64 {D613FB39-5035-4043-91E2-BAB323908AF4}.Debug|x64.Build.0 = Debug|x64 {D613FB39-5035-4043-91E2-BAB323908AF4}.Debug|x86.ActiveCfg = Debug|Win32 {D613FB39-5035-4043-91E2-BAB323908AF4}.Debug|x86.Build.0 = Debug|Win32 - {D613FB39-5035-4043-91E2-BAB323908AF4}.Release|ARM.ActiveCfg = Release|ARM - {D613FB39-5035-4043-91E2-BAB323908AF4}.Release|ARM.Build.0 = Release|ARM {D613FB39-5035-4043-91E2-BAB323908AF4}.Release|ARM64.ActiveCfg = Release|ARM64 {D613FB39-5035-4043-91E2-BAB323908AF4}.Release|ARM64.Build.0 = Release|ARM64 {D613FB39-5035-4043-91E2-BAB323908AF4}.Release|x64.ActiveCfg = Release|x64 {D613FB39-5035-4043-91E2-BAB323908AF4}.Release|x64.Build.0 = Release|x64 {D613FB39-5035-4043-91E2-BAB323908AF4}.Release|x86.ActiveCfg = Release|Win32 {D613FB39-5035-4043-91E2-BAB323908AF4}.Release|x86.Build.0 = Release|Win32 - {FB239623-7D19-4025-BCEA-B43298D4A315}.Debug|ARM.ActiveCfg = Debug|ARM - {FB239623-7D19-4025-BCEA-B43298D4A315}.Debug|ARM.Build.0 = Debug|ARM {FB239623-7D19-4025-BCEA-B43298D4A315}.Debug|ARM64.ActiveCfg = Debug|ARM64 {FB239623-7D19-4025-BCEA-B43298D4A315}.Debug|ARM64.Build.0 = Debug|ARM64 {FB239623-7D19-4025-BCEA-B43298D4A315}.Debug|x64.ActiveCfg = Debug|x64 {FB239623-7D19-4025-BCEA-B43298D4A315}.Debug|x64.Build.0 = Debug|x64 {FB239623-7D19-4025-BCEA-B43298D4A315}.Debug|x86.ActiveCfg = Debug|Win32 {FB239623-7D19-4025-BCEA-B43298D4A315}.Debug|x86.Build.0 = Debug|Win32 - {FB239623-7D19-4025-BCEA-B43298D4A315}.Release|ARM.ActiveCfg = Release|ARM - {FB239623-7D19-4025-BCEA-B43298D4A315}.Release|ARM.Build.0 = Release|ARM {FB239623-7D19-4025-BCEA-B43298D4A315}.Release|ARM64.ActiveCfg = Release|ARM64 {FB239623-7D19-4025-BCEA-B43298D4A315}.Release|ARM64.Build.0 = Release|ARM64 {FB239623-7D19-4025-BCEA-B43298D4A315}.Release|x64.ActiveCfg = Release|x64 {FB239623-7D19-4025-BCEA-B43298D4A315}.Release|x64.Build.0 = Release|x64 {FB239623-7D19-4025-BCEA-B43298D4A315}.Release|x86.ActiveCfg = Release|Win32 {FB239623-7D19-4025-BCEA-B43298D4A315}.Release|x86.Build.0 = Release|Win32 - {C8B95FCB-9B0B-4E9F-B7D5-643883C192C9}.Debug|ARM.ActiveCfg = Debug|ARM - {C8B95FCB-9B0B-4E9F-B7D5-643883C192C9}.Debug|ARM.Build.0 = Debug|ARM {C8B95FCB-9B0B-4E9F-B7D5-643883C192C9}.Debug|ARM64.ActiveCfg = Debug|ARM64 {C8B95FCB-9B0B-4E9F-B7D5-643883C192C9}.Debug|ARM64.Build.0 = Debug|ARM64 {C8B95FCB-9B0B-4E9F-B7D5-643883C192C9}.Debug|x64.ActiveCfg = Debug|x64 {C8B95FCB-9B0B-4E9F-B7D5-643883C192C9}.Debug|x64.Build.0 = Debug|x64 {C8B95FCB-9B0B-4E9F-B7D5-643883C192C9}.Debug|x86.ActiveCfg = Debug|Win32 {C8B95FCB-9B0B-4E9F-B7D5-643883C192C9}.Debug|x86.Build.0 = Debug|Win32 - {C8B95FCB-9B0B-4E9F-B7D5-643883C192C9}.Release|ARM.ActiveCfg = Release|ARM - {C8B95FCB-9B0B-4E9F-B7D5-643883C192C9}.Release|ARM.Build.0 = Release|ARM {C8B95FCB-9B0B-4E9F-B7D5-643883C192C9}.Release|ARM64.ActiveCfg = Release|ARM64 {C8B95FCB-9B0B-4E9F-B7D5-643883C192C9}.Release|ARM64.Build.0 = Release|ARM64 {C8B95FCB-9B0B-4E9F-B7D5-643883C192C9}.Release|x64.ActiveCfg = Release|x64 {C8B95FCB-9B0B-4E9F-B7D5-643883C192C9}.Release|x64.Build.0 = Release|x64 {C8B95FCB-9B0B-4E9F-B7D5-643883C192C9}.Release|x86.ActiveCfg = Release|Win32 {C8B95FCB-9B0B-4E9F-B7D5-643883C192C9}.Release|x86.Build.0 = Release|Win32 - {559A7CF4-DC5F-4D62-BA6B-0C2B025593F8}.Debug|ARM.ActiveCfg = Debug|ARM - {559A7CF4-DC5F-4D62-BA6B-0C2B025593F8}.Debug|ARM.Build.0 = Debug|ARM {559A7CF4-DC5F-4D62-BA6B-0C2B025593F8}.Debug|ARM64.ActiveCfg = Debug|ARM64 {559A7CF4-DC5F-4D62-BA6B-0C2B025593F8}.Debug|ARM64.Build.0 = Debug|ARM64 {559A7CF4-DC5F-4D62-BA6B-0C2B025593F8}.Debug|x64.ActiveCfg = Debug|x64 {559A7CF4-DC5F-4D62-BA6B-0C2B025593F8}.Debug|x64.Build.0 = Debug|x64 {559A7CF4-DC5F-4D62-BA6B-0C2B025593F8}.Debug|x86.ActiveCfg = Debug|Win32 {559A7CF4-DC5F-4D62-BA6B-0C2B025593F8}.Debug|x86.Build.0 = Debug|Win32 - {559A7CF4-DC5F-4D62-BA6B-0C2B025593F8}.Release|ARM.ActiveCfg = Release|ARM - {559A7CF4-DC5F-4D62-BA6B-0C2B025593F8}.Release|ARM.Build.0 = Release|ARM {559A7CF4-DC5F-4D62-BA6B-0C2B025593F8}.Release|ARM64.ActiveCfg = Release|ARM64 {559A7CF4-DC5F-4D62-BA6B-0C2B025593F8}.Release|ARM64.Build.0 = Release|ARM64 {559A7CF4-DC5F-4D62-BA6B-0C2B025593F8}.Release|x64.ActiveCfg = Release|x64 {559A7CF4-DC5F-4D62-BA6B-0C2B025593F8}.Release|x64.Build.0 = Release|x64 {559A7CF4-DC5F-4D62-BA6B-0C2B025593F8}.Release|x86.ActiveCfg = Release|Win32 {559A7CF4-DC5F-4D62-BA6B-0C2B025593F8}.Release|x86.Build.0 = Release|Win32 - {152E4C6E-9A9D-4D5A-B38D-4905D173649A}.Debug|ARM.ActiveCfg = Debug|ARM - {152E4C6E-9A9D-4D5A-B38D-4905D173649A}.Debug|ARM.Build.0 = Debug|ARM {152E4C6E-9A9D-4D5A-B38D-4905D173649A}.Debug|ARM64.ActiveCfg = Debug|ARM64 {152E4C6E-9A9D-4D5A-B38D-4905D173649A}.Debug|ARM64.Build.0 = Debug|ARM64 {152E4C6E-9A9D-4D5A-B38D-4905D173649A}.Debug|x64.ActiveCfg = Debug|x64 {152E4C6E-9A9D-4D5A-B38D-4905D173649A}.Debug|x64.Build.0 = Debug|x64 {152E4C6E-9A9D-4D5A-B38D-4905D173649A}.Debug|x86.ActiveCfg = Debug|Win32 {152E4C6E-9A9D-4D5A-B38D-4905D173649A}.Debug|x86.Build.0 = Debug|Win32 - {152E4C6E-9A9D-4D5A-B38D-4905D173649A}.Release|ARM.ActiveCfg = Release|ARM - {152E4C6E-9A9D-4D5A-B38D-4905D173649A}.Release|ARM.Build.0 = Release|ARM {152E4C6E-9A9D-4D5A-B38D-4905D173649A}.Release|ARM64.ActiveCfg = Release|ARM64 {152E4C6E-9A9D-4D5A-B38D-4905D173649A}.Release|ARM64.Build.0 = Release|ARM64 {152E4C6E-9A9D-4D5A-B38D-4905D173649A}.Release|x64.ActiveCfg = Release|x64 {152E4C6E-9A9D-4D5A-B38D-4905D173649A}.Release|x64.Build.0 = Release|x64 {152E4C6E-9A9D-4D5A-B38D-4905D173649A}.Release|x86.ActiveCfg = Release|Win32 {152E4C6E-9A9D-4D5A-B38D-4905D173649A}.Release|x86.Build.0 = Release|Win32 - {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270}.Debug|ARM.ActiveCfg = Debug|ARM - {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270}.Debug|ARM.Build.0 = Debug|ARM {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270}.Debug|ARM64.ActiveCfg = Debug|ARM64 {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270}.Debug|ARM64.Build.0 = Debug|ARM64 {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270}.Debug|x64.ActiveCfg = Debug|x64 {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270}.Debug|x64.Build.0 = Debug|x64 {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270}.Debug|x86.ActiveCfg = Debug|Win32 {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270}.Debug|x86.Build.0 = Debug|Win32 - {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270}.Release|ARM.ActiveCfg = Release|ARM - {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270}.Release|ARM.Build.0 = Release|ARM {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270}.Release|ARM64.ActiveCfg = Release|ARM64 {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270}.Release|ARM64.Build.0 = Release|ARM64 {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270}.Release|x64.ActiveCfg = Release|x64 {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270}.Release|x64.Build.0 = Release|x64 {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270}.Release|x86.ActiveCfg = Release|Win32 {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270}.Release|x86.Build.0 = Release|Win32 - {D2961EA1-A8CA-4A62-B760-948403DC8494}.Debug|ARM.ActiveCfg = Debug|ARM - {D2961EA1-A8CA-4A62-B760-948403DC8494}.Debug|ARM.Build.0 = Debug|ARM {D2961EA1-A8CA-4A62-B760-948403DC8494}.Debug|ARM64.ActiveCfg = Debug|ARM64 {D2961EA1-A8CA-4A62-B760-948403DC8494}.Debug|ARM64.Build.0 = Debug|ARM64 {D2961EA1-A8CA-4A62-B760-948403DC8494}.Debug|x64.ActiveCfg = Debug|x64 {D2961EA1-A8CA-4A62-B760-948403DC8494}.Debug|x64.Build.0 = Debug|x64 {D2961EA1-A8CA-4A62-B760-948403DC8494}.Debug|x86.ActiveCfg = Debug|Win32 {D2961EA1-A8CA-4A62-B760-948403DC8494}.Debug|x86.Build.0 = Debug|Win32 - {D2961EA1-A8CA-4A62-B760-948403DC8494}.Release|ARM.ActiveCfg = Release|ARM - {D2961EA1-A8CA-4A62-B760-948403DC8494}.Release|ARM.Build.0 = Release|ARM {D2961EA1-A8CA-4A62-B760-948403DC8494}.Release|ARM64.ActiveCfg = Release|ARM64 {D2961EA1-A8CA-4A62-B760-948403DC8494}.Release|ARM64.Build.0 = Release|ARM64 {D2961EA1-A8CA-4A62-B760-948403DC8494}.Release|x64.ActiveCfg = Release|x64 {D2961EA1-A8CA-4A62-B760-948403DC8494}.Release|x64.Build.0 = Release|x64 {D2961EA1-A8CA-4A62-B760-948403DC8494}.Release|x86.ActiveCfg = Release|Win32 {D2961EA1-A8CA-4A62-B760-948403DC8494}.Release|x86.Build.0 = Release|Win32 - {85695954-3800-4558-9857-966E69E9F9EC}.Debug|ARM.ActiveCfg = Debug|ARM - {85695954-3800-4558-9857-966E69E9F9EC}.Debug|ARM.Build.0 = Debug|ARM {85695954-3800-4558-9857-966E69E9F9EC}.Debug|ARM64.ActiveCfg = Debug|ARM64 {85695954-3800-4558-9857-966E69E9F9EC}.Debug|ARM64.Build.0 = Debug|ARM64 {85695954-3800-4558-9857-966E69E9F9EC}.Debug|x64.ActiveCfg = Debug|x64 {85695954-3800-4558-9857-966E69E9F9EC}.Debug|x64.Build.0 = Debug|x64 {85695954-3800-4558-9857-966E69E9F9EC}.Debug|x86.ActiveCfg = Debug|Win32 {85695954-3800-4558-9857-966E69E9F9EC}.Debug|x86.Build.0 = Debug|Win32 - {85695954-3800-4558-9857-966E69E9F9EC}.Release|ARM.ActiveCfg = Release|ARM - {85695954-3800-4558-9857-966E69E9F9EC}.Release|ARM.Build.0 = Release|ARM {85695954-3800-4558-9857-966E69E9F9EC}.Release|ARM64.ActiveCfg = Release|ARM64 {85695954-3800-4558-9857-966E69E9F9EC}.Release|ARM64.Build.0 = Release|ARM64 {85695954-3800-4558-9857-966E69E9F9EC}.Release|x64.ActiveCfg = Release|x64 {85695954-3800-4558-9857-966E69E9F9EC}.Release|x64.Build.0 = Release|x64 {85695954-3800-4558-9857-966E69E9F9EC}.Release|x86.ActiveCfg = Release|Win32 {85695954-3800-4558-9857-966E69E9F9EC}.Release|x86.Build.0 = Release|Win32 - {F1C915B3-2C64-4992-AFB7-7F035B1A7607}.Debug|ARM.ActiveCfg = Debug|ARM - {F1C915B3-2C64-4992-AFB7-7F035B1A7607}.Debug|ARM.Build.0 = Debug|ARM {F1C915B3-2C64-4992-AFB7-7F035B1A7607}.Debug|ARM64.ActiveCfg = Debug|ARM64 {F1C915B3-2C64-4992-AFB7-7F035B1A7607}.Debug|ARM64.Build.0 = Debug|ARM64 {F1C915B3-2C64-4992-AFB7-7F035B1A7607}.Debug|x64.ActiveCfg = Debug|x64 {F1C915B3-2C64-4992-AFB7-7F035B1A7607}.Debug|x64.Build.0 = Debug|x64 {F1C915B3-2C64-4992-AFB7-7F035B1A7607}.Debug|x86.ActiveCfg = Debug|Win32 {F1C915B3-2C64-4992-AFB7-7F035B1A7607}.Debug|x86.Build.0 = Debug|Win32 - {F1C915B3-2C64-4992-AFB7-7F035B1A7607}.Release|ARM.ActiveCfg = Release|ARM - {F1C915B3-2C64-4992-AFB7-7F035B1A7607}.Release|ARM.Build.0 = Release|ARM {F1C915B3-2C64-4992-AFB7-7F035B1A7607}.Release|ARM64.ActiveCfg = Release|ARM64 {F1C915B3-2C64-4992-AFB7-7F035B1A7607}.Release|ARM64.Build.0 = Release|ARM64 {F1C915B3-2C64-4992-AFB7-7F035B1A7607}.Release|x64.ActiveCfg = Release|x64 {F1C915B3-2C64-4992-AFB7-7F035B1A7607}.Release|x64.Build.0 = Release|x64 {F1C915B3-2C64-4992-AFB7-7F035B1A7607}.Release|x86.ActiveCfg = Release|Win32 {F1C915B3-2C64-4992-AFB7-7F035B1A7607}.Release|x86.Build.0 = Release|Win32 - {13333A6F-6A4A-48CD-865C-0F65135EB018}.Debug|ARM.ActiveCfg = Debug|ARM - {13333A6F-6A4A-48CD-865C-0F65135EB018}.Debug|ARM.Build.0 = Debug|ARM {13333A6F-6A4A-48CD-865C-0F65135EB018}.Debug|ARM64.ActiveCfg = Debug|ARM64 {13333A6F-6A4A-48CD-865C-0F65135EB018}.Debug|ARM64.Build.0 = Debug|ARM64 {13333A6F-6A4A-48CD-865C-0F65135EB018}.Debug|x64.ActiveCfg = Debug|x64 {13333A6F-6A4A-48CD-865C-0F65135EB018}.Debug|x64.Build.0 = Debug|x64 {13333A6F-6A4A-48CD-865C-0F65135EB018}.Debug|x86.ActiveCfg = Debug|Win32 {13333A6F-6A4A-48CD-865C-0F65135EB018}.Debug|x86.Build.0 = Debug|Win32 - {13333A6F-6A4A-48CD-865C-0F65135EB018}.Release|ARM.ActiveCfg = Release|ARM - {13333A6F-6A4A-48CD-865C-0F65135EB018}.Release|ARM.Build.0 = Release|ARM {13333A6F-6A4A-48CD-865C-0F65135EB018}.Release|ARM64.ActiveCfg = Release|ARM64 {13333A6F-6A4A-48CD-865C-0F65135EB018}.Release|ARM64.Build.0 = Release|ARM64 {13333A6F-6A4A-48CD-865C-0F65135EB018}.Release|x64.ActiveCfg = Release|x64 {13333A6F-6A4A-48CD-865C-0F65135EB018}.Release|x64.Build.0 = Release|x64 {13333A6F-6A4A-48CD-865C-0F65135EB018}.Release|x86.ActiveCfg = Release|Win32 {13333A6F-6A4A-48CD-865C-0F65135EB018}.Release|x86.Build.0 = Release|Win32 - {0080F6D1-AEC3-4F89-ADE1-3D22A7EBF99E}.Debug|ARM.ActiveCfg = Debug|ARM - {0080F6D1-AEC3-4F89-ADE1-3D22A7EBF99E}.Debug|ARM.Build.0 = Debug|ARM {0080F6D1-AEC3-4F89-ADE1-3D22A7EBF99E}.Debug|ARM64.ActiveCfg = Debug|ARM64 {0080F6D1-AEC3-4F89-ADE1-3D22A7EBF99E}.Debug|ARM64.Build.0 = Debug|ARM64 {0080F6D1-AEC3-4F89-ADE1-3D22A7EBF99E}.Debug|x64.ActiveCfg = Debug|x64 {0080F6D1-AEC3-4F89-ADE1-3D22A7EBF99E}.Debug|x64.Build.0 = Debug|x64 {0080F6D1-AEC3-4F89-ADE1-3D22A7EBF99E}.Debug|x86.ActiveCfg = Debug|Win32 {0080F6D1-AEC3-4F89-ADE1-3D22A7EBF99E}.Debug|x86.Build.0 = Debug|Win32 - {0080F6D1-AEC3-4F89-ADE1-3D22A7EBF99E}.Release|ARM.ActiveCfg = Release|ARM - {0080F6D1-AEC3-4F89-ADE1-3D22A7EBF99E}.Release|ARM.Build.0 = Release|ARM {0080F6D1-AEC3-4F89-ADE1-3D22A7EBF99E}.Release|ARM64.ActiveCfg = Release|ARM64 {0080F6D1-AEC3-4F89-ADE1-3D22A7EBF99E}.Release|ARM64.Build.0 = Release|ARM64 {0080F6D1-AEC3-4F89-ADE1-3D22A7EBF99E}.Release|x64.ActiveCfg = Release|x64 {0080F6D1-AEC3-4F89-ADE1-3D22A7EBF99E}.Release|x64.Build.0 = Release|x64 {0080F6D1-AEC3-4F89-ADE1-3D22A7EBF99E}.Release|x86.ActiveCfg = Release|Win32 {0080F6D1-AEC3-4F89-ADE1-3D22A7EBF99E}.Release|x86.Build.0 = Release|Win32 - {0E0ACA62-A92F-44CF-BD41-AEB541946DF8}.Debug|ARM.ActiveCfg = Debug|ARM - {0E0ACA62-A92F-44CF-BD41-AEB541946DF8}.Debug|ARM.Build.0 = Debug|ARM {0E0ACA62-A92F-44CF-BD41-AEB541946DF8}.Debug|ARM64.ActiveCfg = Debug|ARM64 {0E0ACA62-A92F-44CF-BD41-AEB541946DF8}.Debug|ARM64.Build.0 = Debug|ARM64 {0E0ACA62-A92F-44CF-BD41-AEB541946DF8}.Debug|x64.ActiveCfg = Debug|x64 {0E0ACA62-A92F-44CF-BD41-AEB541946DF8}.Debug|x64.Build.0 = Debug|x64 {0E0ACA62-A92F-44CF-BD41-AEB541946DF8}.Debug|x86.ActiveCfg = Debug|Win32 {0E0ACA62-A92F-44CF-BD41-AEB541946DF8}.Debug|x86.Build.0 = Debug|Win32 - {0E0ACA62-A92F-44CF-BD41-AEB541946DF8}.Release|ARM.ActiveCfg = Release|ARM - {0E0ACA62-A92F-44CF-BD41-AEB541946DF8}.Release|ARM.Build.0 = Release|ARM {0E0ACA62-A92F-44CF-BD41-AEB541946DF8}.Release|ARM64.ActiveCfg = Release|ARM64 {0E0ACA62-A92F-44CF-BD41-AEB541946DF8}.Release|ARM64.Build.0 = Release|ARM64 {0E0ACA62-A92F-44CF-BD41-AEB541946DF8}.Release|x64.ActiveCfg = Release|x64 {0E0ACA62-A92F-44CF-BD41-AEB541946DF8}.Release|x64.Build.0 = Release|x64 {0E0ACA62-A92F-44CF-BD41-AEB541946DF8}.Release|x86.ActiveCfg = Release|Win32 {0E0ACA62-A92F-44CF-BD41-AEB541946DF8}.Release|x86.Build.0 = Release|Win32 - {F8A1FE5A-DC8A-49DF-B882-DEF76E38E484}.Debug|ARM.ActiveCfg = Debug|ARM - {F8A1FE5A-DC8A-49DF-B882-DEF76E38E484}.Debug|ARM.Build.0 = Debug|ARM {F8A1FE5A-DC8A-49DF-B882-DEF76E38E484}.Debug|ARM64.ActiveCfg = Debug|ARM64 {F8A1FE5A-DC8A-49DF-B882-DEF76E38E484}.Debug|ARM64.Build.0 = Debug|ARM64 {F8A1FE5A-DC8A-49DF-B882-DEF76E38E484}.Debug|x64.ActiveCfg = Debug|x64 {F8A1FE5A-DC8A-49DF-B882-DEF76E38E484}.Debug|x64.Build.0 = Debug|x64 {F8A1FE5A-DC8A-49DF-B882-DEF76E38E484}.Debug|x86.ActiveCfg = Debug|Win32 {F8A1FE5A-DC8A-49DF-B882-DEF76E38E484}.Debug|x86.Build.0 = Debug|Win32 - {F8A1FE5A-DC8A-49DF-B882-DEF76E38E484}.Release|ARM.ActiveCfg = Release|ARM - {F8A1FE5A-DC8A-49DF-B882-DEF76E38E484}.Release|ARM.Build.0 = Release|ARM {F8A1FE5A-DC8A-49DF-B882-DEF76E38E484}.Release|ARM64.ActiveCfg = Release|ARM64 {F8A1FE5A-DC8A-49DF-B882-DEF76E38E484}.Release|ARM64.Build.0 = Release|ARM64 {F8A1FE5A-DC8A-49DF-B882-DEF76E38E484}.Release|x64.ActiveCfg = Release|x64 {F8A1FE5A-DC8A-49DF-B882-DEF76E38E484}.Release|x64.Build.0 = Release|x64 {F8A1FE5A-DC8A-49DF-B882-DEF76E38E484}.Release|x86.ActiveCfg = Release|Win32 {F8A1FE5A-DC8A-49DF-B882-DEF76E38E484}.Release|x86.Build.0 = Release|Win32 - {B68C61C6-4699-41E6-A158-EA1BE029E7A0}.Debug|ARM.ActiveCfg = Debug|ARM - {B68C61C6-4699-41E6-A158-EA1BE029E7A0}.Debug|ARM.Build.0 = Debug|ARM {B68C61C6-4699-41E6-A158-EA1BE029E7A0}.Debug|ARM64.ActiveCfg = Debug|ARM64 {B68C61C6-4699-41E6-A158-EA1BE029E7A0}.Debug|ARM64.Build.0 = Debug|ARM64 {B68C61C6-4699-41E6-A158-EA1BE029E7A0}.Debug|x64.ActiveCfg = Debug|x64 {B68C61C6-4699-41E6-A158-EA1BE029E7A0}.Debug|x64.Build.0 = Debug|x64 {B68C61C6-4699-41E6-A158-EA1BE029E7A0}.Debug|x86.ActiveCfg = Debug|Win32 {B68C61C6-4699-41E6-A158-EA1BE029E7A0}.Debug|x86.Build.0 = Debug|Win32 - {B68C61C6-4699-41E6-A158-EA1BE029E7A0}.Release|ARM.ActiveCfg = Release|ARM - {B68C61C6-4699-41E6-A158-EA1BE029E7A0}.Release|ARM.Build.0 = Release|ARM {B68C61C6-4699-41E6-A158-EA1BE029E7A0}.Release|ARM64.ActiveCfg = Release|ARM64 {B68C61C6-4699-41E6-A158-EA1BE029E7A0}.Release|ARM64.Build.0 = Release|ARM64 {B68C61C6-4699-41E6-A158-EA1BE029E7A0}.Release|x64.ActiveCfg = Release|x64 {B68C61C6-4699-41E6-A158-EA1BE029E7A0}.Release|x64.Build.0 = Release|x64 {B68C61C6-4699-41E6-A158-EA1BE029E7A0}.Release|x86.ActiveCfg = Release|Win32 {B68C61C6-4699-41E6-A158-EA1BE029E7A0}.Release|x86.Build.0 = Release|Win32 - {303CC0FE-7D66-4F9F-B7A1-0AF7F9359074}.Debug|ARM.ActiveCfg = Debug|ARM - {303CC0FE-7D66-4F9F-B7A1-0AF7F9359074}.Debug|ARM.Build.0 = Debug|ARM {303CC0FE-7D66-4F9F-B7A1-0AF7F9359074}.Debug|ARM64.ActiveCfg = Debug|ARM64 {303CC0FE-7D66-4F9F-B7A1-0AF7F9359074}.Debug|ARM64.Build.0 = Debug|ARM64 {303CC0FE-7D66-4F9F-B7A1-0AF7F9359074}.Debug|x64.ActiveCfg = Debug|x64 {303CC0FE-7D66-4F9F-B7A1-0AF7F9359074}.Debug|x64.Build.0 = Debug|x64 {303CC0FE-7D66-4F9F-B7A1-0AF7F9359074}.Debug|x86.ActiveCfg = Debug|Win32 {303CC0FE-7D66-4F9F-B7A1-0AF7F9359074}.Debug|x86.Build.0 = Debug|Win32 - {303CC0FE-7D66-4F9F-B7A1-0AF7F9359074}.Release|ARM.ActiveCfg = Release|ARM - {303CC0FE-7D66-4F9F-B7A1-0AF7F9359074}.Release|ARM.Build.0 = Release|ARM {303CC0FE-7D66-4F9F-B7A1-0AF7F9359074}.Release|ARM64.ActiveCfg = Release|ARM64 {303CC0FE-7D66-4F9F-B7A1-0AF7F9359074}.Release|ARM64.Build.0 = Release|ARM64 {303CC0FE-7D66-4F9F-B7A1-0AF7F9359074}.Release|x64.ActiveCfg = Release|x64 {303CC0FE-7D66-4F9F-B7A1-0AF7F9359074}.Release|x64.Build.0 = Release|x64 {303CC0FE-7D66-4F9F-B7A1-0AF7F9359074}.Release|x86.ActiveCfg = Release|Win32 {303CC0FE-7D66-4F9F-B7A1-0AF7F9359074}.Release|x86.Build.0 = Release|Win32 - {A63B3AD1-AB7B-461E-9FFF-2447F5BCD459}.Debug|ARM.ActiveCfg = Debug|ARM - {A63B3AD1-AB7B-461E-9FFF-2447F5BCD459}.Debug|ARM.Build.0 = Debug|ARM {A63B3AD1-AB7B-461E-9FFF-2447F5BCD459}.Debug|ARM64.ActiveCfg = Debug|ARM64 {A63B3AD1-AB7B-461E-9FFF-2447F5BCD459}.Debug|ARM64.Build.0 = Debug|ARM64 {A63B3AD1-AB7B-461E-9FFF-2447F5BCD459}.Debug|x64.ActiveCfg = Debug|x64 {A63B3AD1-AB7B-461E-9FFF-2447F5BCD459}.Debug|x64.Build.0 = Debug|x64 {A63B3AD1-AB7B-461E-9FFF-2447F5BCD459}.Debug|x86.ActiveCfg = Debug|Win32 {A63B3AD1-AB7B-461E-9FFF-2447F5BCD459}.Debug|x86.Build.0 = Debug|Win32 - {A63B3AD1-AB7B-461E-9FFF-2447F5BCD459}.Release|ARM.ActiveCfg = Release|ARM - {A63B3AD1-AB7B-461E-9FFF-2447F5BCD459}.Release|ARM.Build.0 = Release|ARM {A63B3AD1-AB7B-461E-9FFF-2447F5BCD459}.Release|ARM64.ActiveCfg = Release|ARM64 {A63B3AD1-AB7B-461E-9FFF-2447F5BCD459}.Release|ARM64.Build.0 = Release|ARM64 {A63B3AD1-AB7B-461E-9FFF-2447F5BCD459}.Release|x64.ActiveCfg = Release|x64 {A63B3AD1-AB7B-461E-9FFF-2447F5BCD459}.Release|x64.Build.0 = Release|x64 {A63B3AD1-AB7B-461E-9FFF-2447F5BCD459}.Release|x86.ActiveCfg = Release|Win32 {A63B3AD1-AB7B-461E-9FFF-2447F5BCD459}.Release|x86.Build.0 = Release|Win32 - {E893622C-47DE-4F83-B422-0A26711590A4}.Debug|ARM.ActiveCfg = Debug|ARM - {E893622C-47DE-4F83-B422-0A26711590A4}.Debug|ARM.Build.0 = Debug|ARM {E893622C-47DE-4F83-B422-0A26711590A4}.Debug|ARM64.ActiveCfg = Debug|ARM64 {E893622C-47DE-4F83-B422-0A26711590A4}.Debug|ARM64.Build.0 = Debug|ARM64 {E893622C-47DE-4F83-B422-0A26711590A4}.Debug|x64.ActiveCfg = Debug|x64 {E893622C-47DE-4F83-B422-0A26711590A4}.Debug|x64.Build.0 = Debug|x64 {E893622C-47DE-4F83-B422-0A26711590A4}.Debug|x86.ActiveCfg = Debug|Win32 {E893622C-47DE-4F83-B422-0A26711590A4}.Debug|x86.Build.0 = Debug|Win32 - {E893622C-47DE-4F83-B422-0A26711590A4}.Release|ARM.ActiveCfg = Release|ARM - {E893622C-47DE-4F83-B422-0A26711590A4}.Release|ARM.Build.0 = Release|ARM {E893622C-47DE-4F83-B422-0A26711590A4}.Release|ARM64.ActiveCfg = Release|ARM64 {E893622C-47DE-4F83-B422-0A26711590A4}.Release|ARM64.Build.0 = Release|ARM64 {E893622C-47DE-4F83-B422-0A26711590A4}.Release|x64.ActiveCfg = Release|x64 {E893622C-47DE-4F83-B422-0A26711590A4}.Release|x64.Build.0 = Release|x64 {E893622C-47DE-4F83-B422-0A26711590A4}.Release|x86.ActiveCfg = Release|Win32 {E893622C-47DE-4F83-B422-0A26711590A4}.Release|x86.Build.0 = Release|Win32 - {D48A96C2-8512-4CC3-B6E4-7CFF07ED8ED3}.Debug|ARM.ActiveCfg = Debug|ARM - {D48A96C2-8512-4CC3-B6E4-7CFF07ED8ED3}.Debug|ARM.Build.0 = Debug|ARM {D48A96C2-8512-4CC3-B6E4-7CFF07ED8ED3}.Debug|ARM64.ActiveCfg = Debug|ARM64 {D48A96C2-8512-4CC3-B6E4-7CFF07ED8ED3}.Debug|ARM64.Build.0 = Debug|ARM64 {D48A96C2-8512-4CC3-B6E4-7CFF07ED8ED3}.Debug|x64.ActiveCfg = Debug|x64 {D48A96C2-8512-4CC3-B6E4-7CFF07ED8ED3}.Debug|x64.Build.0 = Debug|x64 {D48A96C2-8512-4CC3-B6E4-7CFF07ED8ED3}.Debug|x86.ActiveCfg = Debug|Win32 {D48A96C2-8512-4CC3-B6E4-7CFF07ED8ED3}.Debug|x86.Build.0 = Debug|Win32 - {D48A96C2-8512-4CC3-B6E4-7CFF07ED8ED3}.Release|ARM.ActiveCfg = Release|ARM - {D48A96C2-8512-4CC3-B6E4-7CFF07ED8ED3}.Release|ARM.Build.0 = Release|ARM {D48A96C2-8512-4CC3-B6E4-7CFF07ED8ED3}.Release|ARM64.ActiveCfg = Release|ARM64 {D48A96C2-8512-4CC3-B6E4-7CFF07ED8ED3}.Release|ARM64.Build.0 = Release|ARM64 {D48A96C2-8512-4CC3-B6E4-7CFF07ED8ED3}.Release|x64.ActiveCfg = Release|x64 {D48A96C2-8512-4CC3-B6E4-7CFF07ED8ED3}.Release|x64.Build.0 = Release|x64 {D48A96C2-8512-4CC3-B6E4-7CFF07ED8ED3}.Release|x86.ActiveCfg = Release|Win32 {D48A96C2-8512-4CC3-B6E4-7CFF07ED8ED3}.Release|x86.Build.0 = Release|Win32 - {08C40663-B6A3-481E-8755-AE32BAD99501}.Debug|ARM.ActiveCfg = Debug|ARM - {08C40663-B6A3-481E-8755-AE32BAD99501}.Debug|ARM.Build.0 = Debug|ARM {08C40663-B6A3-481E-8755-AE32BAD99501}.Debug|ARM64.ActiveCfg = Debug|ARM64 {08C40663-B6A3-481E-8755-AE32BAD99501}.Debug|ARM64.Build.0 = Debug|ARM64 {08C40663-B6A3-481E-8755-AE32BAD99501}.Debug|x64.ActiveCfg = Debug|x64 {08C40663-B6A3-481E-8755-AE32BAD99501}.Debug|x64.Build.0 = Debug|x64 {08C40663-B6A3-481E-8755-AE32BAD99501}.Debug|x86.ActiveCfg = Debug|Win32 {08C40663-B6A3-481E-8755-AE32BAD99501}.Debug|x86.Build.0 = Debug|Win32 - {08C40663-B6A3-481E-8755-AE32BAD99501}.Release|ARM.ActiveCfg = Release|ARM - {08C40663-B6A3-481E-8755-AE32BAD99501}.Release|ARM.Build.0 = Release|ARM {08C40663-B6A3-481E-8755-AE32BAD99501}.Release|ARM64.ActiveCfg = Release|ARM64 {08C40663-B6A3-481E-8755-AE32BAD99501}.Release|ARM64.Build.0 = Release|ARM64 {08C40663-B6A3-481E-8755-AE32BAD99501}.Release|x64.ActiveCfg = Release|x64 {08C40663-B6A3-481E-8755-AE32BAD99501}.Release|x64.Build.0 = Release|x64 {08C40663-B6A3-481E-8755-AE32BAD99501}.Release|x86.ActiveCfg = Release|Win32 {08C40663-B6A3-481E-8755-AE32BAD99501}.Release|x86.Build.0 = Release|Win32 - {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Debug|ARM.ActiveCfg = Debug|ARM - {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Debug|ARM.Build.0 = Debug|ARM {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Debug|ARM64.ActiveCfg = Debug|ARM64 {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Debug|ARM64.Build.0 = Debug|ARM64 {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Debug|x64.ActiveCfg = Debug|x64 {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Debug|x64.Build.0 = Debug|x64 {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Debug|x86.ActiveCfg = Debug|Win32 {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Debug|x86.Build.0 = Debug|Win32 - {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Release|ARM.ActiveCfg = Release|ARM - {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Release|ARM.Build.0 = Release|ARM {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Release|ARM64.ActiveCfg = Release|ARM64 {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Release|ARM64.Build.0 = Release|ARM64 {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Release|x64.ActiveCfg = Release|x64 {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Release|x64.Build.0 = Release|x64 {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Release|x86.ActiveCfg = Release|Win32 {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Release|x86.Build.0 = Release|Win32 - {D4C8F881-84D5-4A7B-8BDE-AB4E34A05374}.Debug|ARM.ActiveCfg = Debug|ARM - {D4C8F881-84D5-4A7B-8BDE-AB4E34A05374}.Debug|ARM.Build.0 = Debug|ARM {D4C8F881-84D5-4A7B-8BDE-AB4E34A05374}.Debug|ARM64.ActiveCfg = Debug|ARM64 {D4C8F881-84D5-4A7B-8BDE-AB4E34A05374}.Debug|ARM64.Build.0 = Debug|ARM64 {D4C8F881-84D5-4A7B-8BDE-AB4E34A05374}.Debug|x64.ActiveCfg = Debug|x64 {D4C8F881-84D5-4A7B-8BDE-AB4E34A05374}.Debug|x64.Build.0 = Debug|x64 {D4C8F881-84D5-4A7B-8BDE-AB4E34A05374}.Debug|x86.ActiveCfg = Debug|Win32 {D4C8F881-84D5-4A7B-8BDE-AB4E34A05374}.Debug|x86.Build.0 = Debug|Win32 - {D4C8F881-84D5-4A7B-8BDE-AB4E34A05374}.Release|ARM.ActiveCfg = Release|ARM - {D4C8F881-84D5-4A7B-8BDE-AB4E34A05374}.Release|ARM.Build.0 = Release|ARM {D4C8F881-84D5-4A7B-8BDE-AB4E34A05374}.Release|ARM64.ActiveCfg = Release|ARM64 {D4C8F881-84D5-4A7B-8BDE-AB4E34A05374}.Release|ARM64.Build.0 = Release|ARM64 {D4C8F881-84D5-4A7B-8BDE-AB4E34A05374}.Release|x64.ActiveCfg = Release|x64 {D4C8F881-84D5-4A7B-8BDE-AB4E34A05374}.Release|x64.Build.0 = Release|x64 {D4C8F881-84D5-4A7B-8BDE-AB4E34A05374}.Release|x86.ActiveCfg = Release|Win32 {D4C8F881-84D5-4A7B-8BDE-AB4E34A05374}.Release|x86.Build.0 = Release|Win32 + {9E392830-805A-4AAF-932D-C493143EFACA}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {9E392830-805A-4AAF-932D-C493143EFACA}.Debug|ARM64.Build.0 = Debug|ARM64 + {9E392830-805A-4AAF-932D-C493143EFACA}.Debug|x64.ActiveCfg = Debug|x64 + {9E392830-805A-4AAF-932D-C493143EFACA}.Debug|x64.Build.0 = Debug|x64 + {9E392830-805A-4AAF-932D-C493143EFACA}.Debug|x86.ActiveCfg = Debug|Win32 + {9E392830-805A-4AAF-932D-C493143EFACA}.Debug|x86.Build.0 = Debug|Win32 + {9E392830-805A-4AAF-932D-C493143EFACA}.Release|ARM64.ActiveCfg = Release|ARM64 + {9E392830-805A-4AAF-932D-C493143EFACA}.Release|ARM64.Build.0 = Release|ARM64 + {9E392830-805A-4AAF-932D-C493143EFACA}.Release|x64.ActiveCfg = Release|x64 + {9E392830-805A-4AAF-932D-C493143EFACA}.Release|x64.Build.0 = Release|x64 + {9E392830-805A-4AAF-932D-C493143EFACA}.Release|x86.ActiveCfg = Release|Win32 + {9E392830-805A-4AAF-932D-C493143EFACA}.Release|x86.Build.0 = Release|Win32 + {B8E3A5CE-4E91-4F27-9B02-E0CAF7E10D72}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {B8E3A5CE-4E91-4F27-9B02-E0CAF7E10D72}.Debug|ARM64.Build.0 = Debug|ARM64 + {B8E3A5CE-4E91-4F27-9B02-E0CAF7E10D72}.Debug|x64.ActiveCfg = Debug|x64 + {B8E3A5CE-4E91-4F27-9B02-E0CAF7E10D72}.Debug|x64.Build.0 = Debug|x64 + {B8E3A5CE-4E91-4F27-9B02-E0CAF7E10D72}.Debug|x86.ActiveCfg = Debug|Win32 + {B8E3A5CE-4E91-4F27-9B02-E0CAF7E10D72}.Debug|x86.Build.0 = Debug|Win32 + {B8E3A5CE-4E91-4F27-9B02-E0CAF7E10D72}.Release|ARM64.ActiveCfg = Release|ARM64 + {B8E3A5CE-4E91-4F27-9B02-E0CAF7E10D72}.Release|ARM64.Build.0 = Release|ARM64 + {B8E3A5CE-4E91-4F27-9B02-E0CAF7E10D72}.Release|x64.ActiveCfg = Release|x64 + {B8E3A5CE-4E91-4F27-9B02-E0CAF7E10D72}.Release|x64.Build.0 = Release|x64 + {B8E3A5CE-4E91-4F27-9B02-E0CAF7E10D72}.Release|x86.ActiveCfg = Release|Win32 + {B8E3A5CE-4E91-4F27-9B02-E0CAF7E10D72}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -500,6 +451,8 @@ Global {08C40663-B6A3-481E-8755-AE32BAD99501} = {3C7EA5F8-6E8C-4376-B499-2CAF596384B0} {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA} = {3C7EA5F8-6E8C-4376-B499-2CAF596384B0} {D4C8F881-84D5-4A7B-8BDE-AB4E34A05374} = {3C7EA5F8-6E8C-4376-B499-2CAF596384B0} + {9E392830-805A-4AAF-932D-C493143EFACA} = {3C7EA5F8-6E8C-4376-B499-2CAF596384B0} + {B8E3A5CE-4E91-4F27-9B02-E0CAF7E10D72} = {3C7EA5F8-6E8C-4376-B499-2CAF596384B0} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {2783B8FD-EA3B-4D6B-9F81-662D289E02AA} diff --git a/cppwinrt/cmd_reader.h b/cppwinrt/cmd_reader.h index 7faf49e4f..e2787b7d4 100644 --- a/cppwinrt/cmd_reader.h +++ b/cppwinrt/cmd_reader.h @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -203,7 +204,7 @@ namespace cppwinrt while (true) { - DWORD actual_size = GetModuleFileNameA(nullptr, path.data(), 1 + static_cast(path.size())); + DWORD actual_size = GetModuleFileNameA(nullptr, path.data(), 1 + static_cast(path.size())); if (actual_size < 1 + path.size()) { @@ -237,12 +238,12 @@ namespace cppwinrt } auto key = open_sdk(); - uint32_t index{}; + std::uint32_t index{}; std::array subkey; std::array version_parts{}; std::string result; - while (0 == RegEnumKeyA(key.handle, index++, subkey.data(), static_cast(subkey.size()))) + while (0 == RegEnumKeyA(key.handle, index++, subkey.data(), static_cast(subkey.size()))) { if (!std::regex_match(subkey.data(), match, rx)) { @@ -258,7 +259,7 @@ namespace cppwinrt char* next_part = subkey.data(); bool force_newer = false; - for (size_t i = 0; ; ++i) + for (std::size_t i = 0; ; ++i) { auto version_part = strtoul(next_part, &next_part, 10); @@ -312,19 +313,19 @@ namespace cppwinrt struct option { - static constexpr uint32_t no_min = 0; - static constexpr uint32_t no_max = UINT_MAX; + static constexpr std::uint32_t no_min = 0; + static constexpr std::uint32_t no_max = (std::numeric_limits::max)(); std::string_view name; - uint32_t min{ no_min }; - uint32_t max{ no_max }; + std::uint32_t min{ no_min }; + std::uint32_t max{ no_max }; std::string_view arg{}; std::string_view desc{}; }; struct reader { - template + template reader(C const argc, V const argv, const option(& options)[numOptions]) { #ifdef _DEBUG @@ -449,9 +450,9 @@ namespace cppwinrt #if defined(_WIN32) || defined(_WIN64) std::array local{}; #ifdef _WIN64 - ExpandEnvironmentStringsA("%windir%\\System32\\WinMetadata", local.data(), static_cast(local.size())); + ExpandEnvironmentStringsA("%windir%\\System32\\WinMetadata", local.data(), static_cast(local.size())); #else - ExpandEnvironmentStringsA("%windir%\\SysNative\\WinMetadata", local.data(), static_cast(local.size())); + ExpandEnvironmentStringsA("%windir%\\SysNative\\WinMetadata", local.data(), static_cast(local.size())); #endif add_directory(local.data()); #else /* defined(_WIN32) || defined(_WIN64) */ @@ -586,7 +587,7 @@ namespace cppwinrt std::filesystem::path response_path{ std::string{ arg } }; std::string extension = response_path.extension().generic_string(); std::transform(extension.begin(), extension.end(), extension.begin(), - [](auto c) { return static_cast(::tolower(c)); }); + [](auto c) { return static_cast(std::tolower(c)); }); // Check if misuse of @ prefix, so if directory or metadata file instead of response file. if (is_directory(response_path) || extension == ".winmd") @@ -597,12 +598,12 @@ namespace cppwinrt std::ifstream response_file(absolute(response_path)); while (getline(response_file, line_buf)) { - size_t argc = 0; + std::size_t argc = 0; std::vector argv; parse_command_line(line_buf.data(), argv, &argc); - for (size_t i = 0; i < argc; i++) + for (std::size_t i = 0; i < argc; i++) { extract_option(argv[i], options, last); } @@ -610,7 +611,7 @@ namespace cppwinrt } template - static void parse_command_line(Character* cmdstart, std::vector& argv, size_t* argument_count) + static void parse_command_line(Character* cmdstart, std::vector& argv, std::size_t* argument_count) { std::string arg; diff --git a/cppwinrt/code_writers.h b/cppwinrt/code_writers.h index 3c77269cd..a9aa5bc78 100644 --- a/cppwinrt/code_writers.h +++ b/cppwinrt/code_writers.h @@ -5,9 +5,9 @@ namespace cppwinrt struct finish_with { writer& w; - void (*finisher)(writer&); + std::function finisher; - finish_with(writer& w, void (*finisher)(writer&)) : w(w), finisher(finisher) {} + finish_with(writer& w, std::function finisher) : w(w), finisher(std::move(finisher)) {} finish_with(finish_with const&)= delete; void operator=(finish_with const&) = delete; @@ -35,6 +35,35 @@ namespace cppwinrt } } + static void write_endif(writer& w, std::string_view macro = {}) + { + if (macro.empty()) + { + w.write("#endif\n"); + } + else + { + w.write("#endif // %\n", macro); + } + } + + // When modules are enabled, wraps a block of #include directives in + // #ifndef WINRT_IMPL_BUILD_MODULE ... #endif so that in module builds (where + // WINRT_IMPL_BUILD_MODULE is defined in the global module fragment), textual + // includes are suppressed — dependencies come via import instead. + [[nodiscard]] static finish_with wrap_module_aware_includes_guard(writer& w, bool modules_enabled) + { + if (modules_enabled) + { + w.write("#ifndef WINRT_IMPL_BUILD_MODULE\n"); + return { w, [](writer& w) { write_endif(w, "WINRT_IMPL_BUILD_MODULE"); } }; + } + else + { + return { w, write_nothing }; + } + } + static void write_version_assert(writer& w) { w.write_root_include("base"); @@ -52,14 +81,6 @@ namespace cppwinrt w.write(format); } - static void write_endif(writer& w) - { - auto format = R"(#endif -)"; - - w.write(format); - } - static void write_close_file_guard(writer& w) { write_endif(w); @@ -105,7 +126,7 @@ namespace cppwinrt w.write(format); - return { w, write_endif }; + return { w, [](writer& w) { write_endif(w, "WINRT_LEAN_AND_MEAN"); } }; } else { @@ -120,7 +141,17 @@ namespace cppwinrt w.write(format, macro); - return { w, write_endif }; + return { w, [macro = std::string(macro)](writer& w) { write_endif(w, macro); } }; + } + + [[nodiscard]] static finish_with wrap_ifndef(writer& w, std::string_view macro) + { + auto format = R"(#ifndef % +)"; + + w.write(format, macro); + + return { w, [macro = std::string(macro)](writer& w) { write_endif(w, macro); } }; } static void write_parent_depends(writer& w, cache const& c, std::string_view const& type_namespace) @@ -166,7 +197,7 @@ namespace cppwinrt [[nodiscard]] static finish_with wrap_impl_namespace(writer& w) { - auto format = R"(namespace winrt::impl + auto format = R"(WINRT_EXPORT namespace winrt::impl { )"; @@ -195,6 +226,17 @@ namespace cppwinrt return { w, write_close_namespace }; } + [[nodiscard]] static finish_with wrap_type_namespace_without_export(writer& w, std::string_view const& ns) + { + auto format = R"(namespace winrt::@ +{ +)"; + + w.write(format, ns); + + return { w, write_close_namespace }; + } + static void write_enum_field(writer& w, Field const& field) { auto format = R"( % = %, @@ -359,17 +401,17 @@ namespace cppwinrt using std::get; w.write_printf("0x%08X,0x%04X,0x%04X,{ 0x%02X,0x%02X,0x%02X,0x%02X,0x%02X,0x%02X,0x%02X,0x%02X }", - get(get(args[0].value).value), - get(get(args[1].value).value), - get(get(args[2].value).value), - get(get(args[3].value).value), - get(get(args[4].value).value), - get(get(args[5].value).value), - get(get(args[6].value).value), - get(get(args[7].value).value), - get(get(args[8].value).value), - get(get(args[9].value).value), - get(get(args[10].value).value)); + get(get(args[0].value).value), + get(get(args[1].value).value), + get(get(args[2].value).value), + get(get(args[3].value).value), + get(get(args[4].value).value), + get(get(args[5].value).value), + get(get(args[6].value).value), + get(get(args[7].value).value), + get(get(args[8].value).value), + get(get(args[9].value).value), + get(get(args[10].value).value)); } static void write_guid_comment(writer& w, std::vector const& args) @@ -377,17 +419,17 @@ namespace cppwinrt using std::get; w.write_printf("%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X", - get(get(args[0].value).value), - get(get(args[1].value).value), - get(get(args[2].value).value), - get(get(args[3].value).value), - get(get(args[4].value).value), - get(get(args[5].value).value), - get(get(args[6].value).value), - get(get(args[7].value).value), - get(get(args[8].value).value), - get(get(args[9].value).value), - get(get(args[10].value).value)); + get(get(args[0].value).value), + get(get(args[1].value).value), + get(get(args[2].value).value), + get(get(args[3].value).value), + get(get(args[4].value).value), + get(get(args[5].value).value), + get(get(args[6].value).value), + get(get(args[7].value).value), + get(get(args[8].value).value), + get(get(args[9].value).value), + get(get(args[10].value).value)); } static void write_category(writer& w, TypeDef const& type, std::string_view const& category) @@ -561,15 +603,15 @@ namespace cppwinrt if (param.Flags().In()) { - format = "uint32_t%, %"; + format = "std::uint32_t%, %"; } else if (param_signature->ByRef()) { - format = "uint32_t*%, %*"; + format = "std::uint32_t*%, %*"; } else { - format = "uint32_t%, %"; + format = "std::uint32_t%, %"; } w.write(format, bind(param), bind(param_signature->Type())); @@ -605,7 +647,7 @@ namespace cppwinrt if (type.is_szarray()) { - w.write("uint32_t* __%Size, %**", method_signature.return_param_name(), type); + w.write("std::uint32_t* __%Size, %**", method_signature.return_param_name(), type); } else { @@ -619,10 +661,15 @@ namespace cppwinrt } } - static void write_abi_args(writer& w, method_signature const& method_signature) + static void write_abi_args(writer& w, method_signature const& method_signature, bool start_comma) { separator s{ w }; + if (start_comma) + { + s(); + } + for (auto&& [param, param_signature] : method_signature.params()) { s(); @@ -743,7 +790,7 @@ namespace cppwinrt break; } - auto format = R"( virtual int32_t __stdcall %(%) noexcept = 0; + auto format = R"( virtual std::int32_t __stdcall %(%) noexcept = 0; )"; for (auto&& method : info.type.MethodList()) @@ -763,7 +810,7 @@ namespace cppwinrt { auto format = R"( template <> struct abi<%> { - struct WINRT_IMPL_NOVTABLE type : inspectable_abi + struct WINRT_IMPL_ABI_DECL type : inspectable_abi { )"; @@ -773,7 +820,7 @@ namespace cppwinrt { auto format = R"( template <%> struct abi<%> { - struct WINRT_IMPL_NOVTABLE type : inspectable_abi + struct WINRT_IMPL_ABI_DECL type : inspectable_abi { )"; @@ -783,7 +830,7 @@ namespace cppwinrt } - auto format = R"( virtual int32_t __stdcall %(%) noexcept = 0; + auto format = R"( virtual std::int32_t __stdcall %(%) noexcept = 0; )"; auto abi_guard = w.push_abi_types(true); @@ -814,9 +861,9 @@ namespace cppwinrt { auto format = R"( template <%> struct abi<%> { - struct WINRT_IMPL_NOVTABLE type : unknown_abi + struct WINRT_IMPL_ABI_DECL type : unknown_abi { - virtual int32_t __stdcall Invoke(%) noexcept = 0; + virtual std::int32_t __stdcall Invoke(%) noexcept = 0; }; }; )"; @@ -1049,7 +1096,7 @@ namespace cppwinrt if (category == param_category::array_type) { auto format = R"( - uint32_t %_impl_size{}; + std::uint32_t %_impl_size{}; %* %{};)"; auto abi_guard = w.push_abi_types(true); @@ -1129,9 +1176,13 @@ namespace cppwinrt if (is_remove_overload(method)) { // we intentionally ignore errors when unregistering event handlers to be consistent with event_revoker + // + // The `noexcept` versions will crash if check_hresult throws but that is no different than previous + // behavior where it would not check the cast result and nullptr crash. At least the exception will terminate + // immediately while preserving the error code and local variables. format = R"( template auto consume_%::%(%) const noexcept {% - WINRT_IMPL_SHIM(%)->%(%);% + consume_noexcept_remove_overload<%, D>(static_cast(this), &abi_t<%>::%%);% } )"; } @@ -1139,7 +1190,7 @@ namespace cppwinrt { format = R"( template auto consume_%::%(%) const noexcept {% - WINRT_VERIFY_(0, WINRT_IMPL_SHIM(%)->%(%));% + consume_noexcept<%, D>(static_cast(this), &abi_t<%>::%%);% } )"; } @@ -1148,7 +1199,7 @@ namespace cppwinrt { format = R"( template auto consume_%::%(%) const {% - check_hresult(WINRT_IMPL_SHIM(%)->%(%));% + consume_general<%, D>(static_cast(this), &abi_t<%>::%%);% } )"; } @@ -1161,8 +1212,9 @@ namespace cppwinrt bind(signature), bind(signature, false), type, + type, get_abi_name(method), - bind(signature), + bind(signature, true), bind(signature)); if (is_add_overload(method)) @@ -1307,7 +1359,7 @@ namespace cppwinrt w.write(R"( auto data() const { - uint8_t* data{}; + std::uint8_t* data{}; static_cast(*this).template as()->Buffer(&data); return data; } @@ -1318,8 +1370,8 @@ namespace cppwinrt w.write(R"( auto data() const { - uint8_t* data{}; - uint32_t capacity{}; + std::uint8_t* data{}; + std::uint32_t capacity{}; check_hresult(static_cast(*this).template as()->GetBuffer(&data, &capacity)); return data; } @@ -1423,24 +1475,36 @@ namespace cppwinrt else if (type_name == "Windows.Foundation.IAsyncAction") { w.write(R"( auto get() const; + // Synchronously waits without asserting that the calling thread is not an STA. + // Use only when the STA is not presenting UI and blocking is known to be safe. + auto get_unchecked() const; auto wait_for(Windows::Foundation::TimeSpan const& timeout) const; )"); } else if (type_name == "Windows.Foundation.IAsyncOperation`1") { w.write(R"( auto get() const; + // Synchronously waits without asserting that the calling thread is not an STA. + // Use only when the STA is not presenting UI and blocking is known to be safe. + auto get_unchecked() const; auto wait_for(Windows::Foundation::TimeSpan const& timeout) const; )"); } else if (type_name == "Windows.Foundation.IAsyncActionWithProgress`1") { w.write(R"( auto get() const; + // Synchronously waits without asserting that the calling thread is not an STA. + // Use only when the STA is not presenting UI and blocking is known to be safe. + auto get_unchecked() const; auto wait_for(Windows::Foundation::TimeSpan const& timeout) const; )"); } else if (type_name == "Windows.Foundation.IAsyncOperationWithProgress`2") { w.write(R"( auto get() const; + // Synchronously waits without asserting that the calling thread is not an STA. + // Use only when the STA is not presenting UI and blocking is known to be safe. + auto get_unchecked() const; auto wait_for(Windows::Foundation::TimeSpan const& timeout) const; )"); } @@ -1470,7 +1534,7 @@ namespace cppwinrt using iterator_concept = std::input_iterator_tag; using iterator_category = std::input_iterator_tag; using value_type = T; - using difference_type = ptrdiff_t; + using difference_type = std::ptrdiff_t; using pointer = void; using reference = T; )"); @@ -1481,7 +1545,7 @@ namespace cppwinrt using iterator_concept = std::input_iterator_tag; using iterator_category = std::input_iterator_tag; using value_type = Windows::Foundation::IInspectable; - using difference_type = ptrdiff_t; + using difference_type = std::ptrdiff_t; using pointer = void; using reference = Windows::Foundation::IInspectable; )"); @@ -1823,18 +1887,48 @@ namespace cppwinrt { auto param_name = param.Name(); - w.write("\n if (%) *% = detach_abi(winrt_impl_%);", param_name, param_name, param_name); + w.write("\n if (%) *% = detach_abi(winrt_impl_%);", param_name, param_name, param_name); + } + } + } + + static void write_produce_upcall_TryLookup(writer& w, std::string_view const& upcall, method_signature const& method_signature) + { + auto name = method_signature.return_param_name(); + + w.write("auto out_param_val = %(%, trylookup_from_abi);", + upcall, + bind(method_signature)); + w.write(R"( + if (out_param_val.has_value()) + { + *% = detach_from<%>(std::move(*out_param_val)); + } + else + { + return impl::error_out_of_bounds; + } +)", + name, method_signature.return_signature()); + + for (auto&& [param, param_signature] : method_signature.params()) + { + if (param.Flags().Out() && !param_signature->Type().is_szarray() && is_object(param_signature->Type())) + { + auto param_name = param.Name(); + + w.write("\n if (%) *% = detach_abi(winrt_impl_%);", param_name, param_name, param_name); } } } - static void write_produce_method(writer& w, MethodDef const& method) + static void write_produce_method(writer& w, MethodDef const& method, TypeDef const& type) { std::string_view format; if (is_noexcept(method)) { - format = R"( int32_t __stdcall %(%) noexcept final + format = R"( std::int32_t __stdcall %(%) noexcept final { % typename D::abi_guard guard(this->shim()); % @@ -1844,7 +1938,7 @@ namespace cppwinrt } else { - format = R"( int32_t __stdcall %(%) noexcept final try + format = R"( std::int32_t __stdcall %(%) noexcept final try { % typename D::abi_guard guard(this->shim()); % @@ -1857,13 +1951,45 @@ namespace cppwinrt method_signature signature{ method }; auto async_types_guard = w.push_async_types(signature.is_async()); std::string upcall = "this->shim()."; - upcall += get_name(method); + auto name = get_name(method); + upcall += name; - w.write(format, - get_abi_name(method), - bind(signature), - bind(signature), - bind(upcall, signature)); + auto typeName = type.TypeName(); + if (((typeName == "IMapView`2") || (typeName == "IMap`2")) + && (name == "Lookup")) + { + // Special-case IMap*::Lookup to look for a TryLookup here, to avoid extranous throw/originates + std::string tryLookupUpCall = "this->shim().TryLookup"; + format = R"( std::int32_t __stdcall %(%) noexcept final try + { +% typename D::abi_guard guard(this->shim()); + if constexpr (has_TryLookup_v) + { + % + } + else + { + % + } + return 0; + } + catch (...) { return to_hresult(); } +)"; + w.write(format, + get_abi_name(method), + bind(signature), + bind(signature), // clear_abi + bind(tryLookupUpCall, signature), + bind(upcall, signature)); + } + else + { + w.write(format, + get_abi_name(method), + bind(signature), + bind(signature), + bind(upcall, signature)); + } } static void write_fast_produce_methods(writer& w, TypeDef const& default_interface) @@ -1906,7 +2032,7 @@ namespace cppwinrt break; } - w.write_each(info.type.MethodList()); + w.write_each(info.type.MethodList(), info.type); } } @@ -1928,7 +2054,7 @@ namespace cppwinrt bind(generics), type, type, - bind_each(type.MethodList()), + bind_each(type.MethodList(), type), bind(type)); } @@ -2108,6 +2234,10 @@ struct WINRT_IMPL_EMPTY_BASES produce_dispatch_to_overridable w.write("\n friend impl::consume_t;", name); w.write("\n friend impl::require_one;", name); } + else if (info.overridable) + { + w.write("\n friend impl::produce;", name); + } } } @@ -2233,13 +2363,13 @@ struct WINRT_IMPL_EMPTY_BASES produce_dispatch_to_overridable static void write_class_override_usings(writer& w, get_interfaces_t const& required_interfaces) { - std::map> method_usage; + std::map> method_usage; - for (auto&& [interface_name, info] : required_interfaces) + for (auto&& interface_desc : required_interfaces) { - for (auto&& method : info.type.MethodList()) + for (auto&& method : interface_desc.second.type.MethodList()) { - method_usage[get_name(method)].insert(interface_name); + method_usage[get_name(method)].insert(interface_desc); } } @@ -2250,9 +2380,11 @@ struct WINRT_IMPL_EMPTY_BASES produce_dispatch_to_overridable continue; } - for (auto&& interface_name : interfaces) + for (auto&& [interface_name, info] : interfaces) { - w.write(" using impl::consume_t::%;\n", + w.write(info.overridable + ? " using %T::%;\n" + : " using impl::consume_t::%;\n", interface_name, method_name); } @@ -2518,7 +2650,7 @@ struct WINRT_IMPL_EMPTY_BASES produce_dispatch_to_overridable { delegate(H&& handler) : implements_delegate<%, H>(std::forward(handler)) {} - int32_t __stdcall Invoke(%) noexcept final try + std::int32_t __stdcall Invoke(%) noexcept final try { % % return 0; @@ -2637,7 +2769,7 @@ struct WINRT_IMPL_EMPTY_BASES produce_dispatch_to_overridable bind(signature, true), type_name, bind_list(", ", generics), - bind(signature), + bind(signature, false), bind(signature)); } else @@ -2709,21 +2841,21 @@ struct WINRT_IMPL_EMPTY_BASES produce_dispatch_to_overridable bind(signature), bind(signature, true), type_name, - bind(signature), + bind(signature, false), bind(signature)); } } static void write_struct_field(writer& w, std::pair const& field) { - w.write(" @ %;\n", + w.write(" @ % {};\n", field.second, field.first); } static void write_struct_equality(writer& w, std::vector> const& fields) { - for (size_t i = 0; i != fields.size(); ++i) + for (std::size_t i = 0; i != fields.size(); ++i) { w.write(" left.% == right.%", fields[i].first, fields[i].first); @@ -2799,9 +2931,9 @@ struct WINRT_IMPL_EMPTY_BASES produce_dispatch_to_overridable return false; }; - for (size_t left = 0; left < structs.size(); ++left) + for (std::size_t left = 0; left < structs.size(); ++left) { - for (size_t right = left + 1; right < structs.size(); ++right) + for (std::size_t right = left + 1; right < structs.size(); ++right) { if (depends(w, structs[left], structs[right])) { @@ -2838,7 +2970,7 @@ struct WINRT_IMPL_EMPTY_BASES produce_dispatch_to_overridable for (auto&& field : type.fields) { - if (field.second.find(':') == std::string::npos) + if (field.second.find(':') == std::string::npos || starts_with(field.second, "std::")) { continue; } @@ -3364,10 +3496,6 @@ struct WINRT_IMPL_EMPTY_BASES produce_dispatch_to_overridable { w.write(strings::base_coroutine_system); } - else if (namespace_name == "Microsoft.System") - { - w.write(strings::base_coroutine_system_winui); - } else if (namespace_name == "Windows.UI.Core") { w.write(strings::base_coroutine_ui_core); diff --git a/cppwinrt/component_writers.h b/cppwinrt/component_writers.h index 4a2cce556..94e20e53e 100644 --- a/cppwinrt/component_writers.h +++ b/cppwinrt/component_writers.h @@ -136,7 +136,10 @@ namespace cppwinrt static void write_module_g_cpp(writer& w, std::vector const& classes) { - w.write_root_include("base"); + if (!settings.modules) + { + w.write_root_include("base"); + } auto format = R"(% bool __stdcall %_can_unload_now() noexcept { @@ -172,9 +175,12 @@ void* __stdcall %_get_activation_factory([[maybe_unused]] std::wstring_view cons } format = R"( -int32_t __stdcall WINRT_CanUnloadNow() noexcept +std::int32_t __stdcall WINRT_CanUnloadNow() noexcept { #ifdef _WRL_MODULE_H_ +#ifdef _MSC_VER +#pragma warning(suppress: 4324) // structure was padded due to alignment specifier +#endif if (!::Microsoft::WRL::Module<::Microsoft::WRL::InProc>::GetModule().Terminate()) { return 1; @@ -184,7 +190,7 @@ int32_t __stdcall WINRT_CanUnloadNow() noexcept return %_can_unload_now() ? 0 : 1; } -int32_t __stdcall WINRT_GetActivationFactory(void* classId, void** factory) noexcept try +std::int32_t __stdcall WINRT_GetActivationFactory(void* classId, void** factory) noexcept try { std::wstring_view const name{ *reinterpret_cast(&classId) }; *factory = %_get_activation_factory(name); @@ -195,6 +201,7 @@ int32_t __stdcall WINRT_GetActivationFactory(void* classId, void** factory) noex } #ifdef _WRL_MODULE_H_ +#pragma warning(suppress: 4324) // structure was padded due to alignment specifier return ::Microsoft::WRL::Module<::Microsoft::WRL::InProc>::GetModule().GetActivationFactory(static_cast(classId), reinterpret_cast<::IActivationFactory**>(factory)); #else return winrt::hresult_class_not_available(name).to_abi(); @@ -393,7 +400,7 @@ catch (...) { return winrt::to_hresult(); } return; } - auto wrap_type = wrap_type_namespace(w, type_namespace); + auto wrap_type = wrap_type_namespace_without_export(w, type_namespace); for (auto&&[factory_name, factory] : get_factories(w, type)) { @@ -636,7 +643,7 @@ catch (...) { return winrt::to_hresult(); } } )"; - size_t offset = get_bases(type).size(); + std::size_t offset = get_bases(type).size(); auto interfaces = get_interfaces(w, type); for (auto&& [name, info] : interfaces) @@ -681,7 +688,7 @@ catch (...) { return winrt::to_hresult(); } if (has_base) { auto format = R"( - int32_t query_interface_tearoff(guid const& id, void** result) const noexcept override + std::int32_t query_interface_tearoff(guid const& id, void** result) const noexcept override {% return B::query_interface_tearoff(id, result); } @@ -697,7 +704,7 @@ catch (...) { return winrt::to_hresult(); } } auto format = R"( - int32_t query_interface_tearoff(guid const& id, void** result) const noexcept override + std::int32_t query_interface_tearoff(guid const& id, void** result) const noexcept override {% return impl::error_no_interface; } @@ -750,7 +757,7 @@ catch (...) { return winrt::to_hresult(); } using implements_type = typename %_base::implements_type; using implements_type::implements_type; %% - hstring GetRuntimeClassName() const + hstring GetRuntimeClassName() const override { return L"%.%"; } @@ -775,8 +782,8 @@ catch (...) { return winrt::to_hresult(); } { composable_base_name = w.write_temp("using composable_base = %;", base_type); auto base_interfaces = get_interfaces(w, base_type); - uint32_t base_interfaces_count{}; - uint32_t protected_base_interfaces_count{}; + std::uint32_t base_interfaces_count{}; + std::uint32_t protected_base_interfaces_count{}; external_requires = ",\n impl::require(::toupper(c)); }); + std::transform(upper.begin(), upper.end(), upper.begin(), [](char c) {return static_cast(std::toupper(c)); }); auto include_path = get_generated_component_filename(type); @@ -1236,7 +1243,7 @@ namespace winrt::@::implementation static void write_component_fast_abi_thunk(writer& w) { - for (uint32_t slot = 6; slot < 1024; ++slot) + for (std::uint32_t slot = 6; slot < 1024; ++slot) { auto format = R"( extern "C" void __stdcall winrt_ff_thunk%(); )"; @@ -1247,7 +1254,7 @@ namespace winrt::@::implementation static void write_component_fast_abi_vtable(writer& w) { - for (uint32_t slot = 6; slot < 1024; ++slot) + for (std::uint32_t slot = 6; slot < 1024; ++slot) { auto format = R"( #if WINRT_FAST_ABI_SIZE > % diff --git a/cppwinrt/cppwinrt.vcxproj b/cppwinrt/cppwinrt.vcxproj index 46b5836e7..b8beed890 100644 --- a/cppwinrt/cppwinrt.vcxproj +++ b/cppwinrt/cppwinrt.vcxproj @@ -2,10 +2,6 @@ - - Debug - ARM - Debug ARM64 @@ -14,10 +10,6 @@ Debug Win32 - - Release - ARM - Release ARM64 @@ -132,10 +124,6 @@ Application true - - Application - true - Application true @@ -145,11 +133,6 @@ false true - - Application - false - true - Application false @@ -172,18 +155,12 @@ - - - - - - @@ -199,23 +176,8 @@ Disabled ..\inc;$(OutputPath);$(WinMDPackageDir); MultiThreadedDebug - - - Console - - - $(OutputPath)prebuild.exe ..\strings $(OutputPath) - - - - - - - - - Disabled - ..\inc;$(OutputPath);$(WinMDPackageDir); - MultiThreadedDebug + Level4 + true Console @@ -233,6 +195,8 @@ Disabled ..\inc;$(OutputPath);$(WinMDPackageDir); MultiThreadedDebug + Level4 + true Console @@ -250,6 +214,8 @@ Disabled ..\inc;$(OutputPath);$(WinMDPackageDir); MultiThreadedDebug + Level4 + true Console @@ -270,29 +236,8 @@ ..\inc;$(OutputPath);$(WinMDPackageDir); MultiThreaded Guard - - - Console - true - true - /DEBUGTYPE:CV,FIXUP %(AdditionalOptions) - - - $(OutputPath)prebuild.exe ..\strings $(OutputPath) - - - - - - - - - MaxSpeed - true - true - ..\inc;$(OutputPath);$(WinMDPackageDir); - MultiThreaded - Guard + Level4 + true Console @@ -316,6 +261,8 @@ ..\inc;$(OutputPath);$(WinMDPackageDir); MultiThreaded Guard + Level4 + true Console @@ -339,6 +286,8 @@ ..\inc;$(OutputPath);$(WinMDPackageDir); MultiThreaded Guard + Level4 + true Console diff --git a/cppwinrt/file_writers.h b/cppwinrt/file_writers.h index ed9386b4e..fd9833cb1 100644 --- a/cppwinrt/file_writers.h +++ b/cppwinrt/file_writers.h @@ -9,9 +9,16 @@ namespace cppwinrt w.write(strings::base_version_odr, CPPWINRT_VERSION_STRING); { auto wrap_file_guard = wrap_open_file_guard(w, "BASE"); + auto wrap_import = wrap_ifndef(w, "WINRT_IMPORT_MODULE"); - w.write(strings::base_includes); - w.write(strings::base_macros); + { + auto wrap_includes = wrap_module_aware_includes_guard(w, true); + w.write(strings::base_includes); + w.write(strings::base_detect_numerics); + w.write(strings::base_include_numerics); + } + w.write_root_include("base_macros"); + w.write(strings::base_source_location); w.write(strings::base_types); w.write(strings::base_extern); w.write(strings::base_meta); @@ -65,7 +72,15 @@ namespace cppwinrt w.flush_to_file(settings.output_folder + "winrt/fast_forward.h"); } - static void write_namespace_0_h(std::string_view const& ns, cache::namespace_members const& members) + static void collect_writer_deps(writer const& w, std::set& out) + { + for (auto&& [dep_ns, _] : w.depends) + { + out.insert(std::string(dep_ns)); + } + } + + static void write_namespace_0_h(std::string_view const& ns, cache::namespace_members const& members, std::set* out_deps = nullptr) { writer w; w.type_namespace = ns; @@ -118,10 +133,11 @@ namespace cppwinrt w.write_each(depends.second); } + if (out_deps) collect_writer_deps(w, *out_deps); w.save_header('0'); } - static void write_namespace_1_h(std::string_view const& ns, cache::namespace_members const& members) + static void write_namespace_1_h(std::string_view const& ns, cache::namespace_members const& members, std::set* out_deps = nullptr) { writer w; w.type_namespace = ns; @@ -137,16 +153,20 @@ namespace cppwinrt write_preamble(w); write_open_file_guard(w, ns, '1'); - for (auto&& depends : w.depends) { - w.write_depends(depends.first, '0'); - } + auto wrap_includes = wrap_module_aware_includes_guard(w, true); + for (auto&& depends : w.depends) + { + w.write_depends(depends.first, '0'); + } - w.write_depends(w.type_namespace, '0'); + w.write_depends(w.type_namespace, '0'); + } + if (out_deps) collect_writer_deps(w, *out_deps); w.save_header('1'); } - static void write_namespace_2_h(std::string_view const& ns, cache::namespace_members const& members) + static void write_namespace_2_h(std::string_view const& ns, cache::namespace_members const& members, std::set* out_deps = nullptr) { writer w; w.type_namespace = ns; @@ -167,16 +187,20 @@ namespace cppwinrt char const impl = promote ? '2' : '1'; - for (auto&& depends : w.depends) { - w.write_depends(depends.first, impl); - } + auto wrap_includes = wrap_module_aware_includes_guard(w, true); + for (auto&& depends : w.depends) + { + w.write_depends(depends.first, impl); + } - w.write_depends(w.type_namespace, '1'); + w.write_depends(w.type_namespace, '1'); + } + if (out_deps) collect_writer_deps(w, *out_deps); w.save_header('2'); } - static void write_namespace_h(cache const& c, std::string_view const& ns, cache::namespace_members const& members) + static void write_namespace_h(cache const& c, std::string_view const& ns, cache::namespace_members const& members, std::set* out_deps = nullptr) { writer w; w.type_namespace = ns; @@ -216,18 +240,28 @@ namespace cppwinrt write_namespace_special(w, ns); write_close_file_guard(w); + // The #ifndef WINRT_IMPORT_MODULE / #endif pair spans across w.swap(). + // The body is written first (above), then swap() prepends the header prefix (below). + // In the final output, #ifndef opens before the includes and #endif closes after + // the file guard, mirroring the write_open_file_guard / write_close_file_guard pair. + w.write("#endif // WINRT_IMPORT_MODULE\n"); w.swap(); write_preamble(w); write_open_file_guard(w, ns); - write_version_assert(w); - write_parent_depends(w, c, ns); - - for (auto&& depends : w.depends) + w.write("#ifndef WINRT_IMPORT_MODULE\n\n"); { - w.write_depends(depends.first, '2'); - } + auto wrap_includes = wrap_module_aware_includes_guard(w, true); + write_version_assert(w); + write_parent_depends(w, c, ns); - w.write_depends(w.type_namespace, '2'); + for (auto&& depends : w.depends) + { + w.write_depends(depends.first, '2'); + } + + w.write_depends(w.type_namespace, '2'); + } + if (out_deps) collect_writer_deps(w, *out_deps); w.save_header(); } @@ -236,6 +270,28 @@ namespace cppwinrt writer w; write_preamble(w); write_pch(w); + + if (settings.modules) + { + // In module builds, import std and winrt_base instead of #include "winrt/base.h". + // std is needed for std::wstring_view, std::equal, std::int32_t used in + // the activation factory lookup code. + w.write("\nimport std;\n"); + w.write("import winrt_base;\n"); + + // Collect all unique namespaces from the component classes + std::set namespaces; + for (auto&& type : classes) + { + namespaces.insert(std::string(type.TypeNamespace())); + } + for (auto&& ns : namespaces) + { + w.write("import winrt.%;\n", ns); + } + w.write("\n"); + } + write_module_g_cpp(w, classes); w.flush_to_file(settings.output_folder + "module.g.cpp"); } @@ -250,9 +306,19 @@ namespace cppwinrt write_preamble(w); write_include_guard(w); - for (auto&& depends : w.depends) { - w.write_depends(depends.first); + auto wrap = wrap_ifdef(w, "WINRT_IMPORT_MODULE"); + w.write_root_include("base_macros"); + for (auto&& depends : w.depends) + { + w.write("import winrt.%;\n", depends.first); + } + w.write("#else // WINRT_IMPORT_MODULE\n"); + + for (auto&& depends : w.depends) + { + w.write_depends(depends.first); + } } auto filename = settings.output_folder + get_generated_component_filename(type) + ".g.h"; @@ -316,7 +382,269 @@ namespace cppwinrt writer w; write_pch(w); + + if (settings.modules) + { + // The .g.h handles its own imports, but the implementation .h + // needs the types available in scope, so we import them here. + writer dep_scanner; + dep_scanner.add_depends(type); + write_component_g_h(dep_scanner, type); + + w.write("\n#define WINRT_IMPORT_MODULE\n"); + for (auto&& depends : dep_scanner.depends) + { + w.write("import winrt.%;\n", depends.first); + } + w.write("\n"); + } + write_component_cpp(w, type); w.flush_to_file(path); } + + // --- Per-namespace C++20 module interface unit (.ixx) writers --- + + // Emits the common global module fragment used by all generated .ixx files. + // Defines WINRT_IMPL_BUILD_MODULE so generated headers switch WINRT_EXPORT + // to 'export extern "C++"' and suppress textual #includes of dependencies + // (dependencies arrive via module imports instead). + // Includes minimal headers needed for macros, intrinsics, and debug assertions. + static void write_module_preamble(writer& w) + { + write_preamble(w); + w.write(strings::base_module_ixx_preamble); + w.write_root_include("base_macros"); + } + + // Emits $(out)/winrt/base_macros.h + // This header provides the core macros shared between header and module builds. + // In header builds, base.h includes base_macros.h inline (via the prebuild-embedded string). + // In module builds, each .ixx file includes this in its global module fragment. + static void write_macros_h() + { + writer w; + write_preamble(w); + w.write(strings::base_macros, CPPWINRT_VERSION_STRING); + w.flush_to_file(settings.output_folder + "winrt/base_macros.h"); + } + + static void write_base_ixx() + { + writer w; + write_module_preamble(w); + w.write(strings::base_module_base_ixx); + w.write(strings::base_detect_numerics); + w.write("\n"); + w.write_root_include("base"); + w.flush_to_file(settings.output_folder + "winrt/winrt_base.ixx"); + } + + static void write_numerics_ixx() + { + writer w; + write_module_preamble(w); + // GMF: detect numerics and pre-include directxmath so it's not pulled + // into the module purview by windowsnumerics.impl.h + w.write(strings::base_detect_numerics); + { + auto wrap = wrap_ifdef(w, "WINRT_IMPL_NUMERICS"); + w.write("#include \n"); + } + w.write(strings::base_module_numerics_ixx); + // Module declaration + w.write("\nexport module winrt_numerics;\n"); + // Include windowsnumerics.impl.h in the module purview (exports the types). + // directxmath.h is already included in the GMF above, so the #include inside + // base_include_numerics is a no-op (header guard). + { + auto wrap = wrap_ifdef(w, "_MSC_VER"); + w.write("#pragma warning(push)\n"); + w.write("#pragma warning(disable : 5244)\n"); + } + w.write(strings::base_include_numerics); + { + auto wrap = wrap_ifdef(w, "_MSC_VER"); + w.write("#pragma warning(pop)\n"); + } + w.flush_to_file(settings.output_folder + "winrt/winrt_numerics.ixx"); + } + + // Emits a per-namespace module interface unit for namespaces that are NOT + // part of a dependency cycle (standalone module). + // Output: $(out)/winrt/winrt..ixx (export module winrt.;) + // + // The generated .ixx: + // 1. Starts with the global module fragment (WINRT_IMPL_BUILD_MODULE, minimal includes) + // 2. Declares 'export module winrt.;' + // 3. Imports std and re-exports winrt_base + // 4. Imports each dependent namespace module (computed from type references in headers) + // 5. Includes the impl headers (*.0.h, *.1.h, *.2.h) and public header (.h) + // in the module purview, where WINRT_EXPORT causes declarations to be exported + static void write_namespace_ixx( + std::string_view const& ns, + std::set const& deps) + { + writer w; + write_module_preamble(w); + + // Module declaration + w.write("export module winrt.%;\n\n", ns); + + // Document dependencies + w.write("// Module dependencies:\n"); + w.write("// - std\n"); + w.write("// - winrt_base (re-exported)\n"); + if (deps.empty()) + { + w.write("// - (no additional namespace imports)\n"); + } + else + { + for (auto& dep : deps) + { + w.write("// - winrt.%\n", dep); + } + } + w.write("\n"); + + // Import std and base + w.write("import std;\n"); + w.write("export import winrt_base;\n"); + + // Import dependency namespace modules + for (auto& dep : deps) + { + w.write("import winrt.%;\n", dep); + } + + // Version mismatch check: ensure this namespace module was generated by the + // same version of cppwinrt.exe as the winrt_base module it imports. + // winrt::cppwinrt_version is exported from winrt_base; CPPWINRT_VERSION is + // the macro from this module's own base_macros.h in the global module fragment. + w.write("\nstatic_assert(winrt::check_version(winrt::cppwinrt_version, CPPWINRT_VERSION), \"Mismatched C++/WinRT headers.\");\n\n"); + + // Include namespace headers in module purview + w.write_depends(ns, '0'); + w.write_depends(ns, '1'); + w.write_depends(ns, '2'); + w.write_root_include(ns); + + w.flush_to_file(settings.output_folder + "winrt/winrt." + std::string(ns) + ".ixx"); + } + + // Emits the SCC (Strongly Connected Component) owner module interface unit. + // When multiple namespaces form a dependency cycle, they cannot each have their + // own independent module (circular imports are illegal in C++20 modules). + // Instead, one namespace is chosen as the "owner" (alphabetically first in the SCC), + // and ALL cyclic namespaces' declarations are consolidated into this single module. + // The other namespaces in the SCC get thin re-export stubs (see write_namespace_reexport_ixx). + // + // Output: $(out)/winrt/winrt..ixx (export module winrt.;) + // + // The owner module: + // 1. Imports external dependencies (deps outside the SCC) + // 2. Forward-declares all projected types for ALL SCC namespaces before any + // impl headers — this breaks the type reference cycles + // 3. Includes impl headers in stable phase order: all *.0.h, then all *.1.h, + // then all *.2.h, then all public headers — preserving the original header + // layering while keeping SCC compilation deterministic + static void write_namespace_scc_owner_ixx( + cache const& c, + std::string_view const& owner, + std::vector const& scc_members, + std::set const& external_deps) + { + writer w; + write_module_preamble(w); + + // Module declaration (owner namespace) + w.write("// This module is an SCC owner (cycle breaker). The following namespaces\n"); + w.write("// form a dependency cycle and are consolidated into this single module:\n"); + for (auto& ns : scc_members) + { + w.write("// - %\n", ns); + } + w.write("// Other SCC namespaces are emitted as re-export stubs.\n\n"); + w.write("export module winrt.%;\n\n", owner); + + // Import std and base + w.write("import std;\n"); + w.write("export import winrt_base;\n"); + + // Import external dependency modules (outside the SCC) + for (auto& dep : external_deps) + { + w.write("import winrt.%;\n", dep); + } + + // Version mismatch check: ensure this namespace module was generated by the + // same version of cppwinrt.exe as the winrt_base module it imports. + // winrt::cppwinrt_version is exported from winrt_base; CPPWINRT_VERSION is + // the macro from this module's own base_macros.h in the global module fragment. + w.write("\nstatic_assert(winrt::check_version(winrt::cppwinrt_version, CPPWINRT_VERSION), \"Mismatched C++/WinRT headers.\");\n"); + + // Forward declarations for all projected types in this SCC. + // This is required because SCC members have cyclic type references, + // and generated headers suppress dependent #includes when WINRT_IMPL_BUILD_MODULE + // is defined. Forward declarations provide the names needed before definitions. + for (auto& ns : scc_members) + { + auto found = c.namespaces().find(ns); + if (found == c.namespaces().end()) + { + continue; + } + auto& members = found->second; + + auto wrap_type = wrap_type_namespace(w, ns); + w.write_each(members.enums); + w.write_each(members.interfaces); + w.write_each(members.classes); + w.write_each(members.structs); + w.write_each(members.delegates); + w.write_each(members.contracts); + } + + // Include all SCC members' headers in stable phase order. + // All *.0.h (forward decls + ABIs), then all *.1.h (interfaces), + // then all *.2.h (delegates/structs/classes), then all public headers. + // This preserves the original header layering while keeping compilation deterministic. + for (auto& ns : scc_members) + { + w.write_depends(ns, '0'); + } + for (auto& ns : scc_members) + { + w.write_depends(ns, '1'); + } + for (auto& ns : scc_members) + { + w.write_depends(ns, '2'); + } + for (auto& ns : scc_members) + { + w.write_root_include(ns); + } + + w.flush_to_file(settings.output_folder + "winrt/winrt." + std::string(owner) + ".ixx"); + } + + // Emits a thin re-export stub module for SCC non-owner namespaces. + // This allows 'import winrt.;' to work even though the actual declarations + // live in the SCC owner module. The stub simply re-exports the owner. + // Output: $(out)/winrt/winrt..ixx (export module winrt.; export import winrt.;) + static void write_namespace_reexport_ixx( + std::string_view const& ns, + std::string_view const& owner) + { + writer w; + write_preamble(w); + w.write("\n// NOTE: This module does not define declarations of its own.\n"); + w.write("// It re-exports all declarations from the 'winrt.%' module. This is used to break cycles in the\n", owner); + w.write("// WinRT namespace module dependency graph (SCC owner consolidation).\n\n"); + w.write("export module winrt.%;\n", ns); + w.write("export import winrt.%;\n", owner); + w.flush_to_file(settings.output_folder + "winrt/winrt." + std::string(ns) + ".ixx"); + } } diff --git a/cppwinrt/helpers.h b/cppwinrt/helpers.h index 522d0bcd1..2dc152a74 100644 --- a/cppwinrt/helpers.h +++ b/cppwinrt/helpers.h @@ -31,7 +31,7 @@ namespace cppwinrt ++params.first; } - for (uint32_t i{}; i != size(m_signature.Params()); ++i) + for (std::uint32_t i{}; i != size(m_signature.Params()); ++i) { m_params.emplace_back(params.first + i, &m_signature.Params().first[i]); } @@ -193,7 +193,7 @@ namespace cppwinrt } template - auto get_attribute_value(CustomAttribute const& attribute, uint32_t const arg) + auto get_attribute_value(CustomAttribute const& attribute, std::uint32_t const arg) { return get_attribute_value(attribute.Value().FixedArgs()[arg]); } @@ -330,15 +330,15 @@ namespace cppwinrt struct contract_version { std::string_view name; - uint32_t version; + std::uint32_t version; }; struct previous_contract { std::string_view contract_from; std::string_view contract_to; - uint32_t version_low; - uint32_t version_high; + std::uint32_t version_low; + std::uint32_t version_high; }; struct contract_history @@ -359,7 +359,7 @@ namespace cppwinrt assert(args.size() == 2); contract_version result{}; - result.version = get_integer_attribute(args[1]); + result.version = get_integer_attribute(args[1]); call(std::get(args[0].value).value, [&](ElemSig::SystemType t) { @@ -388,8 +388,8 @@ namespace cppwinrt previous_contract result{}; result.contract_from = get_attribute_value(args[0]); - result.version_low = get_integer_attribute(args[1]); - result.version_high = get_integer_attribute(args[2]); + result.version_low = get_integer_attribute(args[1]); + result.version_high = get_integer_attribute(args[2]); if (args.size() == 4) { result.contract_to = get_attribute_value(args[3]); @@ -452,7 +452,7 @@ namespace cppwinrt // is not a contract version if (current_contract.name.empty()) { - current_contract.version = get_attribute_value(attribute, 0); + current_contract.version = get_attribute_value(attribute, 0); } } } @@ -509,7 +509,7 @@ namespace cppwinrt } assert(result.previous_contracts.back().contract_to == result.current_contract.name); - for (size_t size = result.previous_contracts.size() - 1; size; --size) + for (std::size_t size = result.previous_contracts.size() - 1; size; --size) { auto& last = result.previous_contracts[size]; auto itr = std::find_if(result.previous_contracts.begin(), result.previous_contracts.begin() + size, [&](auto const& prev) @@ -537,7 +537,7 @@ namespace cppwinrt // in relative to the contract history of the class. E.g. if a class goes from contract 'A' to 'B' to 'C', // 'relativeContract' would be '0' for an interface introduced in contract 'A', '1' for an interface introduced // in contract 'B', etc. This is only set/valid for 'fastabi' interfaces - std::pair relative_version{}; + std::pair relative_version{}; std::vector> generic_param_stack{}; }; @@ -660,7 +660,7 @@ namespace cppwinrt } auto history = get_contract_history(type); - size_t count = 0; + std::size_t count = 0; for (auto& pair : result) { if (pair.second.exclusive && !pair.second.base && !pair.second.overridable) @@ -676,12 +676,12 @@ namespace cppwinrt }); if (itr != history.previous_contracts.end()) { - pair.second.relative_version.first = static_cast(itr - history.previous_contracts.begin()); + pair.second.relative_version.first = static_cast(itr - history.previous_contracts.begin()); } else { assert(history.current_contract.name == introduced.name); - pair.second.relative_version.first = static_cast(history.previous_contracts.size()); + pair.second.relative_version.first = static_cast(history.previous_contracts.size()); } } } @@ -863,7 +863,7 @@ namespace cppwinrt { if (auto visibility = std::get_if(&std::get(arg.value).value)) { - info.visible = std::get(visibility->value) == 2; + info.visible = std::get(visibility->value) == 2; break; } } diff --git a/cppwinrt/main.cpp b/cppwinrt/main.cpp index 70a55b076..33bb9248e 100644 --- a/cppwinrt/main.cpp +++ b/cppwinrt/main.cpp @@ -1,5 +1,6 @@ #include "pch.h" #include +#include #include "strings.h" #include "settings.h" #include "type_writers.h" @@ -39,6 +40,9 @@ namespace cppwinrt { "fastabi", 0, 0 }, // Enable support for the Fast ABI { "ignore_velocity", 0, 0 }, // Ignore feature staging metadata and always include implementations { "synchronous", 0, 0 }, // Instructs cppwinrt to run on a single thread to avoid file system issues in batch builds + { "modules", 0, 0, {}, "Generate per-namespace C++20 module interface units (.ixx)" }, + { "module_include", 0, option::no_max, "", "Filter which namespaces are included in module .ixx generation" }, + { "module_exclude", 0, option::no_max, "", "Filter which namespaces are excluded from module .ixx generation" }, }; static void print_usage(writer& w) @@ -85,6 +89,7 @@ R"( local Local ^%WinDir^%\System32\WinMetadata folder { settings.verbose = args.exists("verbose"); settings.fastabi = args.exists("fastabi"); + settings.modules = args.exists("modules"); settings.input = args.files("input", database::is_database); settings.reference = args.files("reference", database::is_database); @@ -92,6 +97,15 @@ R"( local Local ^%WinDir^%\System32\WinMetadata folder settings.component = args.exists("component"); settings.base = args.exists("base"); + for (auto&& ns : args.values("module_include")) + { + settings.module_include.insert(ns); + } + for (auto&& ns : args.values("module_exclude")) + { + settings.module_exclude.insert(ns); + } + settings.license = args.exists("license"); settings.brackets = args.exists("brackets"); @@ -199,6 +213,13 @@ R"( local Local ^%WinDir^%\System32\WinMetadata folder static void build_filters(cache const& c) { + // Build module_filter from -module_include / -module_exclude args. + // This controls which namespaces get .ixx files without affecting header generation. + if (!settings.module_include.empty() || !settings.module_exclude.empty()) + { + settings.module_filter = { settings.module_include, settings.module_exclude }; + } + if (settings.reference.empty()) { return; @@ -281,6 +302,79 @@ R"( local Local ^%WinDir^%\System32\WinMetadata folder c.remove_type("Windows.Foundation.Numerics", "Vector4"); } + // Tarjan's algorithm for finding strongly connected components in the + // namespace dependency graph. Namespaces in an SCC have cyclic deps and + // must be combined into a single module. + static std::vector> find_sccs( + std::map, std::less<>> const& graph) + { + struct context + { + std::map index_of; + std::map lowlink; + std::map on_stack; + std::vector stack; + int next_index = 0; + std::vector> result; + + void strongconnect(std::string const& v, + std::map, std::less<>> const& g) + { + index_of[v] = next_index; + lowlink[v] = next_index; + next_index++; + stack.push_back(v); + on_stack[v] = true; + + auto it = g.find(v); + if (it != g.end()) + { + for (auto& w : it->second) + { + if (g.find(w) == g.end()) + { + continue; // dep not in graph (not a projected namespace) + } + + if (index_of.find(w) == index_of.end()) + { + strongconnect(w, g); + lowlink[v] = (std::min)(lowlink[v], lowlink[w]); + } + else if (on_stack[w]) + { + lowlink[v] = (std::min)(lowlink[v], index_of[w]); + } + } + } + + if (lowlink[v] == index_of[v]) + { + std::vector scc; + std::string w; + do + { + w = stack.back(); + stack.pop_back(); + on_stack[w] = false; + scc.push_back(std::move(w)); + } while (scc.back() != v); + result.push_back(std::move(scc)); + } + } + }; + + context ctx; + for (auto& [node, _] : graph) + { + if (ctx.index_of.find(node) == ctx.index_of.end()) + { + ctx.strongconnect(node, graph); + } + } + return std::move(ctx.result); + } + static int run(int const argc, char** argv) { int result{}; @@ -342,11 +436,30 @@ R"( local Local ^%WinDir^%\System32\WinMetadata folder w.flush_to_console(); task_group group; group.synchronous(args.exists("synchronous")); - writer ixx; - write_preamble(ixx); - ixx.write("module;\n"); - ixx.write(strings::base_includes); - ixx.write("\nexport module winrt;\n#define WINRT_EXPORT export\n\n"); + + // Dependency collection for per-namespace modules (v2) + std::map, std::less<>> ns_deps_map; + std::set projected_namespaces; + std::mutex ns_deps_mutex; + + // First pass: determine which namespaces will be in the module. + // This includes namespaces from this invocation AND those from other invocations + // (e.g., platform namespaces when building a component). The module_filter + // tells us which namespaces have modules across all invocations. + if (settings.modules) + { + for (auto&& [ns, members] : c.namespaces()) + { + if (!has_projected_types(members)) + { + continue; + } + if (settings.module_filter.empty() || settings.module_filter.includes(members)) + { + projected_namespaces.insert(std::string(ns)); + } + } + } for (auto&&[ns, members] : c.namespaces()) { @@ -355,21 +468,29 @@ R"( local Local ^%WinDir^%\System32\WinMetadata folder continue; } - ixx.write("#include \"winrt/%.h\"\n", ns); - group.add([&, &ns = ns, &members = members] { - write_namespace_0_h(ns, members); - write_namespace_1_h(ns, members); - write_namespace_2_h(ns, members); - write_namespace_h(c, ns, members); + bool in_module = projected_namespaces.count(std::string(ns)) > 0; + std::set ns_deps; + auto* deps_ptr = (settings.modules && in_module) ? &ns_deps : nullptr; + + write_namespace_0_h(ns, members, deps_ptr); + write_namespace_1_h(ns, members, deps_ptr); + write_namespace_2_h(ns, members, deps_ptr); + write_namespace_h(c, ns, members, deps_ptr); + + if (settings.modules && in_module) + { + std::lock_guard lock(ns_deps_mutex); + ns_deps_map[std::string(ns)] = std::move(ns_deps); + } }); } if (settings.base) { write_base_h(); - ixx.flush_to_file(settings.output_folder + "winrt/winrt.ixx"); + write_macros_h(); } if (settings.component) @@ -404,6 +525,64 @@ R"( local Local ^%WinDir^%\System32\WinMetadata folder group.get(); + // Generate per-namespace module interface files (.ixx) + // + // Each projected namespace gets its own C++20 named module (winrt.). + // Namespaces that form dependency cycles are detected using Tarjan's SCC algorithm + // and consolidated: one namespace "owns" the SCC module (containing all declarations), + // while others get thin re-export stubs so 'import winrt.;' always works. + // + // Base infrastructure modules (winrt_base, winrt_numerics) are only generated + // for platform projection builds (-base flag). + if (settings.modules) + { + if (settings.base) + { + write_numerics_ixx(); + write_base_ixx(); + } + + // Tarjan's SCC algorithm for cyclic namespace dependencies + auto sccs = find_sccs(ns_deps_map); + + for (auto& scc : sccs) + { + if (scc.size() == 1) + { + // Standalone namespace module + auto& ns = scc[0]; + write_namespace_ixx(ns, ns_deps_map[ns]); + } + else + { + // SCC: choose owner (alphabetically first), others re-export + std::sort(scc.begin(), scc.end()); + auto& owner = scc[0]; + + // External deps = union of all SCC members' deps, minus SCC members themselves + std::set external_deps; + std::set scc_set(scc.begin(), scc.end()); + for (auto& ns : scc) + { + for (auto& dep : ns_deps_map[ns]) + { + if (!scc_set.count(dep)) + { + external_deps.insert(dep); + } + } + } + + write_namespace_scc_owner_ixx(c, owner, scc, external_deps); + + for (size_t i = 1; i < scc.size(); ++i) + { + write_namespace_reexport_ixx(scc[i], owner); + } + } + } + } + if (settings.verbose) { w.write(" time: %ms\n", get_elapsed_time(start)); diff --git a/cppwinrt/settings.h b/cppwinrt/settings.h index e07df4ea2..110e64917 100644 --- a/cppwinrt/settings.h +++ b/cppwinrt/settings.h @@ -31,6 +31,12 @@ namespace cppwinrt bool fastabi{}; std::map fastabi_cache; + + bool modules{}; // Generate per-namespace C++20 module interface units (.ixx) + + std::set module_include; + std::set module_exclude; + winmd::reader::filter module_filter; }; extern settings_type settings; diff --git a/cppwinrt/text_writer.h b/cppwinrt/text_writer.h index 0b7c07a4e..c6fc380b3 100644 --- a/cppwinrt/text_writer.h +++ b/cppwinrt/text_writer.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include #include @@ -12,8 +13,26 @@ namespace cppwinrt { inline std::string file_to_string(std::string const& filename) { - std::ifstream file(filename, std::ios::binary); - return static_cast(std::stringstream() << file.rdbuf()).str(); + std::ifstream file(filename, std::ios::binary | std::ios::ate); + if (!file) { return{}; } + + const auto stream_size = file.tellg(); + if (stream_size == std::ifstream::pos_type(-1)) + { + return {}; + } + + file.seekg(0); + + auto size = static_cast(stream_size); + std::string result(size, '\0'); + file.read(result.data(), size); + if (!file) + { + result.resize(static_cast(file.gcount())); + } + + return result; } template @@ -66,7 +85,7 @@ namespace cppwinrt #if defined(_DEBUG) if (debug_trace) { - ::printf("%.*s", static_cast(value.size()), value.data()); + std::printf("%.*s", static_cast(value.size()), value.data()); } #endif } @@ -78,7 +97,7 @@ namespace cppwinrt #if defined(_DEBUG) if (debug_trace) { - ::printf("%c", value); + std::printf("%c", value); } #endif } @@ -139,12 +158,12 @@ namespace cppwinrt { char buffer[128]; #if defined(_WIN32) || defined(_WIN64) - size_t const size = sprintf_s(buffer, format, args...); + std::size_t const size = sprintf_s(buffer, format, args...); #else - size_t size = snprintf(buffer, sizeof(buffer), format, args...); + std::size_t size = std::snprintf(buffer, sizeof(buffer), format, args...); if (size > sizeof(buffer) - 1) { - fprintf(stderr, "\n*** WARNING: writer_base::write_printf -- buffer too small\n"); + std::fprintf(stderr, "\n*** WARNING: writer_base::write_printf -- buffer too small\n"); size = sizeof(buffer) - 1; } #endif @@ -167,8 +186,8 @@ namespace cppwinrt void flush_to_console(bool to_stdout = true) noexcept { - fprintf(to_stdout ? stdout : stderr, "%.*s", static_cast(m_first.size()), m_first.data()); - fprintf(to_stdout ? stdout : stderr, "%.*s", static_cast(m_second.size()), m_second.data()); + std::fprintf(to_stdout ? stdout : stderr, "%.*s", static_cast(m_first.size()), m_first.data()); + std::fprintf(to_stdout ? stdout : stderr, "%.*s", static_cast(m_second.size()), m_second.data()); m_first.clear(); m_second.clear(); } @@ -217,18 +236,15 @@ namespace cppwinrt bool file_equal(std::string const& filename) const { - if (!std::filesystem::exists(filename)) + // Non-throwing file_size returns uintmax_t(-1) on errors, which shouldn't ever be the size of m_first or m_second + std::error_code ec; + if (std::filesystem::file_size(filename, ec) != m_first.size() + m_second.size()) { return false; } auto file = file_to_string(filename); - if (file.size() != m_first.size() + m_second.size()) - { - return false; - } - if (!std::equal(m_first.begin(), m_first.end(), file.begin(), file.begin() + m_first.size())) { return false; @@ -243,9 +259,9 @@ namespace cppwinrt private: - static constexpr uint32_t count_placeholders(std::string_view const& format) noexcept + static constexpr std::uint32_t count_placeholders(std::string_view const& format) noexcept { - uint32_t count{}; + std::uint32_t count{}; bool escape{}; for (auto c : format) @@ -332,7 +348,7 @@ namespace cppwinrt { struct indent_guard { - indent_guard(indented_writer_base& w, int32_t offset = 1) noexcept : m_writer(w), m_offset(offset) + indent_guard(indented_writer_base& w, std::int32_t offset = 1) noexcept : m_writer(w), m_offset(offset) { m_writer.m_indent += m_offset; } @@ -344,13 +360,13 @@ namespace cppwinrt private: indented_writer_base& m_writer; - int32_t m_offset{}; + std::int32_t m_offset{}; }; void write_indent() { - for (int32_t i = 0; i < m_indent; i++) + for (std::int32_t i = 0; i < m_indent; i++) { writer_base::write_impl(" "); } @@ -418,7 +434,7 @@ namespace cppwinrt return result; } - int32_t m_indent{}; + std::int32_t m_indent{}; }; diff --git a/cppwinrt/type_writers.h b/cppwinrt/type_writers.h index 0fa3e5f8d..df17450f1 100644 --- a/cppwinrt/type_writers.h +++ b/cppwinrt/type_writers.h @@ -232,12 +232,12 @@ namespace cppwinrt return member_value_guard(this, &writer::delegate_types, value); } - void write_value(int32_t value) + void write_value(std::int32_t value) { write_printf("%d", value); } - void write_value(uint32_t value) + void write_value(std::uint32_t value) { write_printf("%#0x", value); } @@ -309,7 +309,7 @@ namespace cppwinrt { if ((name == "DateTime" || name == "TimeSpan") && ns == "Windows.Foundation") { - write("int64_t"); + write("std::int64_t"); } else if ((name == "Point" || name == "Size" || name == "Rect") && ns == "Windows.Foundation") { @@ -473,14 +473,14 @@ namespace cppwinrt { if (type == ElementType::Boolean) { write("bool"); } else if (type == ElementType::Char) { write("char16_t"); } - else if (type == ElementType::I1) { write("int8_t"); } - else if (type == ElementType::U1) { write("uint8_t"); } - else if (type == ElementType::I2) { write("int16_t"); } - else if (type == ElementType::U2) { write("uint16_t"); } - else if (type == ElementType::I4) { write("int32_t"); } - else if (type == ElementType::U4) { write("uint32_t"); } - else if (type == ElementType::I8) { write("int64_t"); } - else if (type == ElementType::U8) { write("uint64_t"); } + else if (type == ElementType::I1) { write("std::int8_t"); } + else if (type == ElementType::U1) { write("std::uint8_t"); } + else if (type == ElementType::I2) { write("std::int16_t"); } + else if (type == ElementType::U2) { write("std::uint16_t"); } + else if (type == ElementType::I4) { write("std::int32_t"); } + else if (type == ElementType::U4) { write("std::uint32_t"); } + else if (type == ElementType::I8) { write("std::int64_t"); } + else if (type == ElementType::U8) { write("std::uint64_t"); } else if (type == ElementType::R4) { write("float"); } else if (type == ElementType::R8) { write("double"); } else if (type == ElementType::String) diff --git a/cross-mingw-toolchain.cmake b/cross-mingw-toolchain.cmake index d58bb278d..23156e11b 100644 --- a/cross-mingw-toolchain.cmake +++ b/cross-mingw-toolchain.cmake @@ -1,5 +1,5 @@ # This is a cmake-toolchain(5) file that can be used to cross-build -# cppwinrt.exe fron Linux or other operating systems using a mingw-w64 cross +# cppwinrt.exe from Linux or other operating systems using a mingw-w64 cross # toolchain. This should work with both GCC-based and llvm-mingw toolchains. # # Example usage with external toolchain: diff --git a/docs/modules-design.md b/docs/modules-design.md new file mode 100644 index 000000000..8327231a7 --- /dev/null +++ b/docs/modules-design.md @@ -0,0 +1,190 @@ +# C++/WinRT Per-Namespace Modules: Design & Internals + +This document describes the design and implementation of per-namespace C++20 module support in C++/WinRT. It is intended for cppwinrt maintainers and contributors. + +## Architecture Overview + +The module system generates one C++20 named module per WinRT namespace. Each module encapsulates the same content as the traditional header files but exports declarations via `WINRT_EXPORT` in module purview. + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ winrt_numerics.ixx ── export module winrt_numerics; │ +│ winrt_base.ixx ── export module winrt_base; │ +│ export import winrt_numerics; │ +│ winrt.Windows.Foundation.ixx │ +│ ── export module winrt.Windows.Foundation; │ +│ import std; export import winrt_base; │ +│ import winrt.Windows.Foundation.Collections; │ +│ #include "winrt/impl/Windows.Foundation.0.h" │ +│ ... │ +│ #include "winrt/Windows.Foundation.h" │ +└─────────────────────────────────────────────────────────────────┘ +``` + +## Key Design Decisions + +### Unconditional Guards + +Module guards (`WINRT_IMPL_BUILD_MODULE`, `WINRT_IMPORT_MODULE`) are emitted unconditionally in generated projection headers — they are always present regardless of whether `-modules` was passed to cppwinrt.exe. The `-modules` flag controls `.ixx` generation and whether generated component files (`module.g.cpp`, stub `.cpp`) use module imports. This means: + +- Projection headers generated without `-modules` still work correctly when later compiled inside a module interface unit +- No regeneration of projection headers needed when switching between header and module consumption + +### WINRT_EXPORT Macro + +`WINRT_EXPORT` is defined in `base_macros.h` (generated as `winrt/base_macros.h`): +- When `WINRT_IMPL_BUILD_MODULE` is defined (inside `.ixx` compilation): `export extern "C++"` +- Otherwise (header mode): empty + +All `namespace winrt::impl` and `namespace std` blocks use `WINRT_EXPORT` so they export correctly from modules. The `extern "C++"` wrapping enables include-before-import compatibility (same technique as MSVC STL). + +### Per-Namespace vs Monolithic + +Unlike the v1 approach (single `import winrt;`), v2 generates one module per namespace. This provides: + +- **Finer granularity**: Import only what you need +- **Better parallelism**: Independent modules compile in parallel +- **Component module support**: Component namespaces get their own modules + +The trade-off is handling dependency cycles between namespaces (see SCC below). + +This is enforced via the MSBuild `CppWinRTConsumeModule` metadata on ProjectReference — it only points at the platform module builder, not at component projects. + +## Code Generator Pipeline + +### Entry Point: `main.cpp` + +1. **Namespace enumeration**: First pass determines which namespaces are module-eligible using `module_filter` (from `-module_include`/`-module_exclude`) + +2. **Header generation**: Standard header generation with optional dependency collection. When `-modules` is active and a namespace is in the module, `write_namespace_*_h()` functions populate `ns_deps` sets via the `deps_ptr` parameter + +3. **Dependency graph construction**: After all headers are generated, `ns_deps_map` contains the full namespace dependency graph + +4. **SCC detection**: Tarjan's algorithm (`find_sccs()`) identifies strongly-connected components + +5. **Module generation**: For each SCC: + - Size 1: `write_namespace_ixx()` — standalone module + - Size > 1: `write_namespace_scc_owner_ixx()` for the owner (alphabetically first) + `write_namespace_reexport_ixx()` for others + +### CLI Options + +| Flag | Description | +|-|-| +| `-modules` | Enable `.ixx` generation | +| `-module_include ...` | Only generate modules for these namespace prefixes | +| `-module_exclude ...` | Skip these namespace prefixes | + +The `module_filter` is populated from these flags and checked against ALL cache namespaces (not just the projection filter). This is important for component builds where the platform namespaces are not being projected but their modules exist from a prior builder invocation. + +### Generated Files + +| File | When Generated | Purpose | +|-|-|-| +| `winrt/base_macros.h` | Always with `-base` | Macros for module builds (WINRT_EXPORT, etc.) | +| `winrt/winrt_base.ixx` | `-modules -base` | Core types module | +| `winrt/winrt_numerics.ixx` | `-modules -base` | Numerics module | +| `winrt/winrt..ixx` | `-modules` | Per-namespace module | + +## SCC (Strongly Connected Components) + +### The Problem + +WinRT namespaces have cyclic dependencies. For example: +- `Windows.Foundation` depends on `Windows.Foundation.Collections` (via `IVector`, `IMap`, etc.) +- `Windows.Foundation.Collections` depends on `Windows.Foundation` (via `IAsyncOperation`, `Uri`, etc.) + +C++20 modules cannot have circular imports. If module A imports module B, then module B cannot import module A. + +### The Solution: SCC Consolidation + +Tarjan's algorithm identifies groups of namespaces that form dependency cycles. These groups (SCCs) are consolidated: + +1. **Owner selection**: The alphabetically first namespace in the SCC becomes the "owner" +2. **Owner module**: Contains ALL declarations from ALL SCC namespaces. Forward-declares all types first, then includes headers in phase order (all `*.0.h`, then `*.1.h`, then `*.2.h`, then public headers) +3. **Re-export stubs**: Other SCC members get thin `.ixx` files that just re-export the owner module + +This means `import winrt.Windows.Foundation;` and `import winrt.Windows.Foundation.Collections;` both work — they resolve to the same underlying module. + +### Example Generated Files + +**Owner** (`winrt.Windows.Foundation.ixx`): +```cpp +module; +#define WINRT_IMPL_BUILD_MODULE +#include "winrt/base_macros.h" +// ... + +// This module is an SCC owner (cycle breaker). The following namespaces +// form a dependency cycle and are consolidated into this single module: +// - Windows.Foundation +// - Windows.Foundation.Collections +// Other SCC namespaces are emitted as re-export stubs. + +export module winrt.Windows.Foundation; + +import std; +export import winrt_base; + +// Forward declarations for all SCC namespaces... +// #include all impl headers in phase order... +``` + +**Re-export stub** (`winrt.Windows.Foundation.Collections.ixx`): +```cpp +// NOTE: This module does not define declarations of its own. +// It re-exports all declarations from the 'winrt.Windows.Foundation' module. +export module winrt.Windows.Foundation.Collections; +export import winrt.Windows.Foundation; +``` + +## MSBuild Integration + +### Targets Flow + +``` +CppWinRTResolveModuleReferences (resolves IFC paths from ProjectReference metadata) + ↓ +CppWinRTMakePlatformProjection (generates headers + .ixx for platform types) +CppWinRTMakeReferenceProjection (generates headers + .ixx for referenced WinMDs) +CppWinRTMakeComponentProjection (generates headers + .ixx for component types) + ↓ +CppWinRTAddModuleInterfaces (discovers .ixx files, adds to ClCompile items) + ↓ +FixupCLCompileOptions (MSVC module dependency scanner processes .ixx) + ↓ +ClCompile (compiles .ixx → .ifc + .obj) +``` + +### Key Properties + +- `CppWinRTBuildModule`: Enables `-modules` for all three projections (platform, reference, component), causing `.ixx` generation and compilation. +- `CppWinRTConsumeModule` (ProjectReference metadata): Per-reference opt-in for IFC consumption. When set, suppresses `-modules` on the platform projection so the consumer uses pre-built IFCs from the referenced project instead of generating its own. +- `_CppWinRTConsumesPlatformModules`: Internal property set by `CppWinRTResolveModuleReferences` when any ProjectReference has `CppWinRTConsumeModule=true`. Controls whether the platform projection receives `-modules`. + +### Cross-Project IFC Resolution + +MSVC's module dependency scanner uses `/ifcSearchDir` for within-project module resolution. For cross-project modules, the scanner generates explicit `/reference "module.name=path.ifc"` entries based on the dependency scan results. The `/ifcSearchDir` pointing to the builder's `$(IntDir)` allows the scanner to find the pre-built IFCs. + +## Dependency Collection + +During header generation, when `-modules` is active, each `write_namespace_*_h()` function receives a `deps_ptr` parameter. The writer's `w.depends` map is inspected to find referenced namespaces. Only namespaces that: +1. Exist in the cache +2. Have projected types +3. Are in the module namespace set (or set is empty) + +are added to the dependency set. Self-references are excluded. The union of dependencies from all four header files (`*.0.h`, `*.1.h`, `*.2.h`, `.h`) gives the complete dependency set for a namespace module. + +## Testing + +### test/test_cpp20_module/ (in-repo) + +Standalone test built by the main solution. Uses a PreBuildEvent to run cppwinrt.exe with `-modules -base -module_include "Windows.Foundation"`. Tests URI, events, collections, and coroutines. + +### test/nuget/ (NuGet integration) + +Multi-project solution: +- **TestModuleBuilder**: Static library that pre-builds platform modules +- **TestModuleComponent1**: Component DLL (Greeter class), consumes builder's modules +- **TestModuleComponent2**: Component DLL (GreeterGroup), depends on Component1 +- **TestModuleConsumerApp**: Console app, consumes builder + both components +- **TestModuleApp**: Single-project that builds and consumes its own modules diff --git a/fast_fwd/arm/thunks.asm b/fast_fwd/arm/thunks.asm deleted file mode 100644 index 9010908b6..000000000 --- a/fast_fwd/arm/thunks.asm +++ /dev/null @@ -1,58 +0,0 @@ -; ARM fast forwarder thunk implementations -; Calling convention: https://docs.microsoft.com/en-us/cpp/build/overview-of-arm-abi-conventions - -#include "ksarm.h" - - IMPORT __guard_check_icall_fptr - - TEXTAREA - - CFG_ALIGN - NESTED_ENTRY InvokeForwarder - - ; Save enregistered args and return address - PROLOG_PUSH {r0-r4, lr} - - ; Replace forwarder abi with owner abi - ldr r1, [r0, #4] - str r1, [sp] - - ; Add offset and index (on stack) - ldr r2, [sp, #24] - ldr r3, [r0, #8] - add r2, r2, r3 - - ; Get method address from owner abi vtable - ldr r0, [r1] - ldr r4, [r0, r2, lsl #2] - mov r0, r4 - - ; Verify indirect call target - mov32 r12, __guard_check_icall_fptr - ldr r12, [r12] - blx r12 - - ; Restore method address, return address, and args - mov r12, r4 - EPILOG_POP {r0-r4, lr} - EPILOG_NOP add sp, #4 - - ; Jump to method - EPILOG_NOP bx r12 - - NESTED_END InvokeForwarder - - ; Define thunks - MACRO - WINRT_FF_THUNK $i - LEAF_ENTRY winrt_ff_thunk$i - ; Note: no scratch registers available (r12/IP is used by CFG), must use stack - mov r12, $i - push r12 - ldr pc, =InvokeForwarder - LEAF_END winrt_ff_thunk$i - MEND - -#include "thunks.inc" - - END \ No newline at end of file diff --git a/fast_fwd/fast_fwd.vcxproj b/fast_fwd/fast_fwd.vcxproj index 6d7a42d77..b9452d149 100644 --- a/fast_fwd/fast_fwd.vcxproj +++ b/fast_fwd/fast_fwd.vcxproj @@ -17,14 +17,6 @@ Release x64 - - Debug - ARM - - - Release - ARM - Debug ARM64 @@ -79,16 +71,10 @@ - true + true false !$(Platform_Arm) - - cppwinrt_fast_forwarder - - - cppwinrt_fast_forwarder - cppwinrt_fast_forwarder diff --git a/natvis/cppwinrt_visualizer.cpp b/natvis/cppwinrt_visualizer.cpp index f6affd566..4b0a0c370 100644 --- a/natvis/cppwinrt_visualizer.cpp +++ b/natvis/cppwinrt_visualizer.cpp @@ -11,8 +11,39 @@ using namespace std::filesystem; using namespace winrt; using namespace winmd::reader; -std::vector db_files; -std::unique_ptr db; +namespace +{ + std::vector db_files; + std::unique_ptr db_cache; + coded_index guid_TypeRef{}; +} + +coded_index FindGuidType() +{ + if (!guid_TypeRef) + { + // There is no definitive TypeDef for System.Guid. But there are a variety of TypeRefs scattered about + // This one should be relatively quick to find + auto pv = db_cache->find("Windows.Foundation", "IPropertyValue"); + for (auto&& method : pv.MethodList()) + { + if (method.Name() == "GetGuid") + { + auto const& sig = method.Signature(); + auto const& type = sig.ReturnType().Type().Type(); + XLANG_ASSERT(std::holds_alternative>(type)); + if (std::holds_alternative>(type)) + { + guid_TypeRef = std::get>(type); + XLANG_ASSERT(guid_TypeRef.type() == TypeDefOrRef::TypeRef); + XLANG_ASSERT(guid_TypeRef.TypeRef().TypeNamespace() == "System"); + XLANG_ASSERT(guid_TypeRef.TypeRef().TypeName() == "Guid"); + } + } + } + } + return guid_TypeRef; +} void MetadataDiagnostic(DkmProcess* process, std::wstring const& status, std::filesystem::path const& path) { @@ -105,7 +136,7 @@ void LoadMetadata(DkmProcess* process, WCHAR const* processPath, std::string_vie if (std::find(db_files.begin(), db_files.end(), path_string) == db_files.end()) { - db->add_database(path_string, [](TypeDef const& type) { return type.Flags().WindowsRuntime(); }); + db_cache->add_database(path_string, [](TypeDef const& type) { return type.Flags().WindowsRuntime(); }); db_files.push_back(path_string); } } @@ -118,14 +149,15 @@ void LoadMetadata(DkmProcess* process, WCHAR const* processPath, std::string_vie } } -TypeDef FindType(DkmProcess* process, std::string_view const& typeName) +TypeDef FindSimpleType(DkmProcess* process, std::string_view const& typeName) { - auto type = db->find(typeName); + XLANG_ASSERT(typeName.find('<') == std::string_view::npos); + auto type = db_cache->find(typeName); if (!type) { auto processPath = process->Path()->Value(); LoadMetadata(process, processPath, typeName); - type = db->find(typeName); + type = db_cache->find(typeName); if (!type) { NatvisDiagnostic(process, @@ -135,19 +167,104 @@ TypeDef FindType(DkmProcess* process, std::string_view const& typeName) return type; } -TypeDef FindType(DkmProcess* process, std::string_view const& typeNamespace, std::string_view const& typeName) +TypeDef FindSimpleType(DkmProcess* process, std::string_view const& typeNamespace, std::string_view const& typeName) { - auto type = db->find(typeNamespace, typeName); + XLANG_ASSERT(typeName.find('<') == std::string_view::npos); + auto type = db_cache->find(typeNamespace, typeName); if (!type) { std::string fullName(typeNamespace); fullName.append("."); fullName.append(typeName); - FindType(process, fullName); + FindSimpleType(process, fullName); } return type; } +std::vector ParseTypeName(std::string_view name) +{ + DWORD count; + HSTRING* parts; + auto wide_name = winrt::to_hstring(name); + winrt::check_hresult(::RoParseTypeName(static_cast(get_abi(wide_name)), &count, &parts)); + + winrt::com_array wide_parts{ parts, count, winrt::take_ownership_from_abi }; + std::vector result; + for (auto&& part : wide_parts) + { + result.push_back(winrt::to_string(part)); + } + return result; +} + +template sent> +TypeSig ResolveGenericTypePart(DkmProcess* process, iter& it, sent const& end) +{ + constexpr std::pair elementNames[] = { + {"Boolean", ElementType::Boolean}, + {"Int8", ElementType::I1}, + {"Int16", ElementType::I2}, + {"Int32", ElementType::I4}, + {"Int64", ElementType::I8}, + {"UInt8", ElementType::U1}, + {"UInt16", ElementType::U2}, + {"UInt32", ElementType::U4}, + {"UInt64", ElementType::U8}, + {"Single", ElementType::R4}, + {"Double", ElementType::R8}, + {"String", ElementType::String}, + {"Char16", ElementType::Char}, + {"Object", ElementType::Object} + }; + std::string_view partName = *it; + auto basic_type_pos = std::find_if(std::begin(elementNames), std::end(elementNames), [&partName](auto&& elem) { return elem.first == partName; }); + if (basic_type_pos != std::end(elementNames)) + { + return TypeSig{ basic_type_pos->second }; + } + + if (partName == "Guid") + { + return TypeSig{ FindGuidType() }; + } + + TypeDef type = FindSimpleType(process, partName); + auto tickPos = partName.rfind('`'); + if (tickPos == partName.npos) + { + return TypeSig{ type.coded_index() }; + } + + int paramCount = 0; + std::from_chars(partName.data() + tickPos + 1, partName.data() + partName.size(), paramCount); + std::vector genericArgs; + for (int i = 0; i < paramCount; ++i) + { + genericArgs.push_back(ResolveGenericTypePart(process, ++it, end)); + } + return TypeSig{ GenericTypeInstSig{ type.coded_index(), std::move(genericArgs) } }; +} + +TypeSig ResolveGenericType(DkmProcess* process, std::string_view genericName) +{ + auto parts = ParseTypeName(genericName); + auto begin = parts.begin(); + return ResolveGenericTypePart(process, begin, parts.end()); +} + +TypeSig FindType(DkmProcess* process, std::string_view const& typeName) +{ + auto paramIndex = typeName.find('<'); + if (paramIndex == std::string_view::npos) + { + return TypeSig{ FindSimpleType(process, typeName).coded_index() }; + } + else + { + return ResolveGenericType(process, typeName); + } +} + cppwinrt_visualizer::cppwinrt_visualizer() { try @@ -165,7 +282,7 @@ cppwinrt_visualizer::cppwinrt_visualizer() db_files.push_back(file.path().string()); } } - db.reset(new cache(db_files, [](TypeDef const& type) { return type.Flags().WindowsRuntime(); })); + db_cache.reset(new cache(db_files, [](TypeDef const& type) { return type.Flags().WindowsRuntime(); })); } catch (...) { @@ -187,13 +304,14 @@ cppwinrt_visualizer::cppwinrt_visualizer() cppwinrt_visualizer::~cppwinrt_visualizer() { ClearTypeResolver(); + guid_TypeRef = {}; db_files.clear(); - db.reset(); + db_cache.reset(); } HRESULT cppwinrt_visualizer::EvaluateVisualizedExpression( _In_ DkmVisualizedExpression* pVisualizedExpression, - _Deref_out_ DkmEvaluationResult** ppResultObject + _COM_Outptr_result_maybenull_ DkmEvaluationResult** ppResultObject ) { try @@ -233,6 +351,7 @@ HRESULT cppwinrt_visualizer::EvaluateVisualizedExpression( // unrecognized type NatvisDiagnostic(pVisualizedExpression, std::wstring(L"Unrecognized type: ") + (LPWSTR)bstrTypeName, NatvisDiagnosticLevel::Error); + *ppResultObject = nullptr; return S_OK; } diff --git a/natvis/cppwinrt_visualizer.h b/natvis/cppwinrt_visualizer.h index 5f12ec39a..924dc3cbc 100644 --- a/natvis/cppwinrt_visualizer.h +++ b/natvis/cppwinrt_visualizer.h @@ -8,7 +8,7 @@ struct cppwinrt_visualizer : winrt::implements - + Debug @@ -103,8 +103,8 @@ Use Level4 + true Disabled - false VSDEBUGENG_USE_CPP11_SCOPED_ENUMS;WIN32;_DEBUG;VISUALIZER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) $(IntDir);..\cppwinrt;..\strings;$(DIASDKInc);%(AdditionalIncludeDirectories) stdcpp20 @@ -128,8 +128,8 @@ Use Level4 + true Disabled - false VSDEBUGENG_USE_CPP11_SCOPED_ENUMS;_DEBUG;VISUALIZER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) $(IntDir);..\cppwinrt;..\strings;$(DIASDKInc);%(AdditionalIncludeDirectories) stdcpp20 @@ -152,8 +152,8 @@ Use Level4 + true Disabled - false VSDEBUGENG_USE_CPP11_SCOPED_ENUMS;_DEBUG;VISUALIZER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) $(IntDir);..\cppwinrt;..\strings;$(DIASDKInc);%(AdditionalIncludeDirectories) stdcpp20 @@ -176,10 +176,10 @@ Use Level4 + true MaxSpeed true true - false VSDEBUGENG_USE_CPP11_SCOPED_ENUMS;WIN32;NDEBUG;VISUALIZER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) $(IntDir);..\cppwinrt;..\strings;$(DIASDKInc);%(AdditionalIncludeDirectories) stdcpp20 @@ -206,10 +206,10 @@ Use Level4 + true MaxSpeed true true - false VSDEBUGENG_USE_CPP11_SCOPED_ENUMS;NDEBUG;VISUALIZER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) $(IntDir);..\cppwinrt;..\strings;$(DIASDKInc);%(AdditionalIncludeDirectories) stdcpp20 @@ -236,10 +236,10 @@ Use Level4 + true MaxSpeed true true - false VSDEBUGENG_USE_CPP11_SCOPED_ENUMS;NDEBUG;VISUALIZER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) $(IntDir);..\cppwinrt;..\strings;$(DIASDKInc);%(AdditionalIncludeDirectories) stdcpp20 @@ -321,6 +321,6 @@ - + \ No newline at end of file diff --git a/natvis/object_visualizer.cpp b/natvis/object_visualizer.cpp index 5308c33fc..d953a1c03 100644 --- a/natvis/object_visualizer.cpp +++ b/natvis/object_visualizer.cpp @@ -110,7 +110,7 @@ static HRESULT EvaluatePropertyExpression( wchar_t wszEvalText[500]; std::wstring propCast; PCWSTR propField; - if (prop.category < PropertyCategory::Value) + if (IsBuiltIn(prop.category)) { propField = g_categoryData[(int)prop.category].propField; } @@ -278,7 +278,7 @@ static HRESULT CreateChildVisualizedExpression( IF_FAIL_RET(DkmString::Create(prop.displayName.c_str(), pDisplayName.put())); PCWSTR displayType; - if (prop.category < PropertyCategory::Value) + if (IsBuiltIn(prop.category)) { displayType = g_categoryData[(int)prop.category].displayType; } @@ -340,19 +340,291 @@ static HRESULT CreateChildVisualizedExpression( return S_OK; } -struct property_type +std::optional GetPropertyCategory( + Microsoft::VisualStudio::Debugger::DkmProcess* process, + TypeSig const& owningType, + TypeSig const& propertyType +) +{ + std::optional propCategory; + if (auto pElementType = std::get_if(&propertyType.Type())) + { + if ((ElementType::Boolean <= *pElementType) && (*pElementType <= ElementType::String)) + { + propCategory = (PropertyCategory)(static_cast::type>(*pElementType) - + static_cast::type>(ElementType::Boolean)); + } + else if (*pElementType == ElementType::Object) + { + // result = PropertyCategory::Class; + } + } + else if (auto pIndex = std::get_if>(&propertyType.Type())) + { + auto type = ResolveType(process, *pIndex); + if (type) + { + if (get_category(type) == category::class_type || get_category(type) == category::interface_type) + { + propCategory = PropertyCategory::Class; + } + else + { + propCategory = PropertyCategory::Value; + } + } + else if (pIndex->type() == TypeDefOrRef::TypeRef) + { + auto typeRef = pIndex->TypeRef(); + if (typeRef.TypeNamespace() == "System" && typeRef.TypeName() == "Guid") + { + propCategory = PropertyCategory::Guid; + } + } + } + else if (auto pGenericInst = std::get_if(&propertyType.Type())) + { + XLANG_ASSERT(get_category(ResolveType(process, pGenericInst->GenericType())) == category::interface_type); + propCategory = PropertyCategory::Class; + } + else if (auto pGenericIndex = std::get_if(&propertyType.Type())) + { + if (auto pOwner = std::get_if(&owningType.Type())) + { + auto const& index = pGenericIndex->index; + auto const& genericArgs = pOwner->GenericArgs(); + propCategory = GetPropertyCategory(process, owningType, genericArgs.first[index]); + } + else + { + NatvisDiagnostic(process, L"Can't resolve GenericTypeIndex property on non-generic Type", NatvisDiagnosticLevel::Warning); + } + } + else + { + NatvisDiagnostic(process, L"Unsupported TypeSig encountered", NatvisDiagnosticLevel::Warning); + } + return propCategory; +} + +struct writer { - MethodDef get; - MethodDef set; + std::vector generic_params; + + std::string result; + + void write(char c) + { + result.push_back(c); + } + + void write(std::string_view const& str) + { + for (auto c : str) + { + if (c == '.') + { + write(':'); + write(':'); + } + else if (c != '`') + { + write(c); + } + else + { + return; + } + } + } + + void write(ElementType type) + { + switch (type) + { + case ElementType::Boolean: + write("bool"); + break; + case ElementType::Char: + write("wchar_t"); + break; + case ElementType::I1: + write("int8_t"); + break; + case ElementType::U1: + write("uint8_t"); + break; + case ElementType::I2: + write("int16_t"); + break; + case ElementType::U2: + write("uint16_t"); + break; + case ElementType::I4: + write("int32_t"); + break; + case ElementType::U4: + write("uint32_t"); + break; + case ElementType::I8: + write("int64_t"); + break; + case ElementType::U8: + write("uint64_t"); + break; + case ElementType::R4: + write("float"); + break; + case ElementType::R8: + write("double"); + break; + case ElementType::String: + write("winrt::hstring"); + break; + case ElementType::Object: + write("winrt::Windows::Foundation::IInspectable"); + break; + default: + XLANG_ASSERT(false); + break; + }; + } + + void write_namespace_and_type(std::string_view ns, std::string_view name) + { + if (ns == "System") + { + if (name == "Guid") + { + ns = ""; + name = "guid"; + } + } + else if (ns == "Windows.Foundation") + { + if (name == "EventRegistrationToken") + { + ns = ""; + name = "event_token"; + } + else if (name == "HResult") + { + ns = ""; + name = "hresult"; + } + } + else if (ns == "Windows.Foundation.Numerics") + { + if (name == "Matrix3x2") { name = "float3x2"; } + else if (name == "Matrix4x4") { name = "float4x4"; } + else if (name == "Plane") { name = "plane"; } + else if (name == "Quaternion") { name = "quarternion"; } + else if (name == "Vector2") { name = "float2"; } + else if (name == "Vector3") { name = "float3"; } + else if (name == "Vector4") { name = "float4"; } + } + + write("winrt::"); + if (!ns.empty()) + { + write(ns); + write("::"); + } + write(name); + } + + void write(TypeRef const& type) + { + write_namespace_and_type(type.TypeNamespace(), type.TypeName()); + } + + void write(TypeDef const& type) + { + write_namespace_and_type(type.TypeNamespace(), type.TypeName()); + } + + void write(TypeSpec const& type) + { + write(type.Signature().GenericTypeInst()); + } + + void write(coded_index type) + { + switch (type.type()) + { + case TypeDefOrRef::TypeDef: + write(type.TypeDef()); + break; + case TypeDefOrRef::TypeRef: + write(type.TypeRef()); + break; + case TypeDefOrRef::TypeSpec: + write(type.TypeSpec()); + break; + } + } + + void write(GenericTypeInstSig const& type) + { + write(type.GenericType()); + bool first = true; + write("<"); + for (auto&& elem : type.GenericArgs()) + { + if (first) + { + first = false; + } + else + { + write(", "); + } + write(elem); + } + write(">"); + } + + void write(GenericTypeIndex const& var) + { + write(generic_params[var.index]); + } + + void write(GenericMethodTypeIndex const&) + { + // Nothing + } + + void write(TypeSig const& type) + { + std::visit([this](auto&& arg) + { + write(arg); + }, type.Type()); + } }; +std::wstring string_to_wstring(std::string_view const& str) +{ + int const size = MultiByteToWideChar(CP_UTF8, 0, str.data(), static_cast(str.size()), nullptr, 0); + if (size == 0) + { + return {}; + } + + std::wstring result(size, L'?'); + [[maybe_unused]] auto size_result = MultiByteToWideChar(CP_UTF8, 0, str.data(), static_cast(str.size()), result.data(), size); + XLANG_ASSERT(size == size_result); + return result; +} + void GetInterfaceData( Microsoft::VisualStudio::Debugger::DkmProcess* process, - coded_index index, + TypeSig const& typeSig, _Inout_ std::vector& propertyData, _Out_ bool& isStringable ){ - auto [type, propIid] = ResolveTypeInterface(process, index); + auto [type, propIid] = ResolveTypeInterface(process, typeSig); + if (!type) { return; @@ -375,106 +647,34 @@ void GetInterfaceData( continue; } - std::optional propCategory; - std::wstring propAbiType; - std::wstring propDisplayType; - - auto retType = method.Signature().ReturnType(); - std::visit(overloaded{ - [&](ElementType type) - { - if ((ElementType::Boolean <= type) && (type <= ElementType::String)) - { - propCategory = (PropertyCategory)(static_cast::type>(type) - - static_cast::type>(ElementType::Boolean)); - } - else if (type == ElementType::Object) - { - //propDisplayType = L"winrt::Windows::Foundation::IInspectable"; - //propCategory = PropertyCategory::Class; - //propAbiType = L"winrt::impl::inspectable_abi*"; - } - }, - [&](coded_index const& index) + std::optional propCategory = GetPropertyCategory(process, typeSig, method.Signature().ReturnType().Type()); + if (propCategory) + { + std::wstring propAbiType; + std::wstring propDisplayType; + if (!IsBuiltIn(*propCategory)) { - auto type = ResolveType(process, index); - if (!type) + writer writer; + if (auto pGenericTypeInst = std::get_if(&typeSig.Type())) { - return; + auto const& genericArgs = pGenericTypeInst->GenericArgs(); + writer.generic_params.assign(genericArgs.first, genericArgs.second); } - - auto typeName = type.TypeName(); - if (typeName == "GUID"sv) + writer.write(method.Signature().ReturnType().Type()); + propDisplayType = string_to_wstring(writer.result); + + if (*propCategory == PropertyCategory::Class) { - propCategory = PropertyCategory::Guid; + propAbiType = L"winrt::impl::inspectable_abi*"; } else { - auto ns = std::string(type.TypeNamespace()); - auto name = std::string(type.TypeName()); - - // Map numeric type names - if (ns == "Windows.Foundation.Numerics") - { - if (name == "Matrix3x2") { name = "float3x2"; } - else if (name == "Matrix4x4") { name = "float4x4"; } - else if (name == "Plane") { name = "plane"; } - else if (name == "Quaternion") { name = "quaternion"; } - else if (name == "Vector2") { name = "float2"; } - else if (name == "Vector3") { name = "float3"; } - else if (name == "Vector4") { name = "float4"; } - } - - // Types come back from winmd files with '.', need to be '::' - // Ex. Windows.Foundation.Uri needs to be Windows::Foundation::Uri - auto fullTypeName = ns + "::" + name; - wchar_t cppTypename[500]; - size_t i, j; - for (i = 0, j = 0; i < (fullTypeName.length() + 1); i++, j++) - { - if (fullTypeName[i] == L'.') - { - cppTypename[j++] = L':'; - cppTypename[j] = L':'; - } - else - { - cppTypename[j] = fullTypeName[i]; - } - } - - propDisplayType = std::wstring(L"winrt::") + cppTypename; - if(get_category(type) == category::class_type) - { - propCategory = PropertyCategory::Class; - propAbiType = L"winrt::impl::inspectable_abi*"; - } - else - { - propCategory = PropertyCategory::Value; - propAbiType = propDisplayType; - } + propAbiType = propDisplayType; } - }, - [&](GenericTypeIndex /*var*/) - { - NatvisDiagnostic(process, L"Generics not yet supported", NatvisDiagnosticLevel::Warning); - }, - [&](GenericMethodTypeIndex /*var*/) - { - NatvisDiagnostic(process, L"Generics not yet supported", NatvisDiagnosticLevel::Warning); - }, - [&](GenericTypeInstSig const& /*type*/) - { - NatvisDiagnostic(process, L"Generics not yet supported", NatvisDiagnosticLevel::Warning); } - }, retType.Type().Type()); - if (propCategory) - { auto propName = method.Name().substr(4); - std::wstring propDisplayName(propName.cbegin(), propName.cend()); - propertyData.push_back({ propIid, propIndex, *propCategory, propAbiType, propDisplayType, propDisplayName }); + propertyData.emplace_back(propIid, propIndex, *propCategory, std::move(propAbiType), std::move(propDisplayType), string_to_wstring(propName)); } } } @@ -493,10 +693,55 @@ void object_visualizer::GetPropertyData() GetTypeProperties(process, std::string_view{ rc.data() + 2, rc.length() - 3 }); } +GenericTypeInstSig ReplaceGenericIndices(GenericTypeInstSig const& sig, std::vector const& genericArgs) +{ + std::vector replacementArgs; + for (auto&& arg : sig.GenericArgs()) + { + if (auto pGenericSig = std::get_if(&arg.Type())) + { + replacementArgs.emplace_back(ReplaceGenericIndices(*pGenericSig, genericArgs)); + } + else if (auto pGenericIndex = std::get_if(&arg.Type())) + { + replacementArgs.push_back(genericArgs[pGenericIndex->index]); + } + else + { + replacementArgs.push_back(arg); + } + } + return GenericTypeInstSig{ sig.GenericType(), std::move(replacementArgs) }; +} + +TypeSig ExpandInterfaceImplForType(coded_index impl, TypeSig const& type) +{ + if (auto pGenericInst = std::get_if(&type.Type())) + { + if (impl.type() == TypeDefOrRef::TypeSpec) + { + auto const& genericArgs = pGenericInst->GenericArgs(); + auto newSig = ReplaceGenericIndices(impl.TypeSpec().Signature().GenericTypeInst(), std::vector{ genericArgs.first, genericArgs.second }); + return TypeSig{ newSig }; + } + } + return TypeSig{ impl }; +} + void object_visualizer::GetTypeProperties(Microsoft::VisualStudio::Debugger::DkmProcess* process, std::string_view const& type_name) { // TODO: add support for direct generic interface implementations (e.g., key_value_pair) - auto type = FindType(process, type_name); + auto typeSig = FindType(process, type_name); + TypeDef type{}; + if (auto const* index = std::get_if>(&typeSig.Type())) + { + type = ResolveType(process, *index); + } + else if (auto const* genericInst = std::get_if(&typeSig.Type())) + { + type = ResolveType(process, genericInst->GenericType()); + } + if (!type) { return; @@ -516,7 +761,7 @@ void object_visualizer::GetTypeProperties(Microsoft::VisualStudio::Debugger::Dkm auto impls = type.InterfaceImpl(); for (auto&& impl : impls) { - GetInterfaceData(process, impl.Interface(), m_propertyData, m_isStringable); + GetInterfaceData(process, ExpandInterfaceImplForType(impl.Interface(), typeSig), m_propertyData, m_isStringable); } } else if (get_category(type) == category::interface_type) @@ -524,9 +769,9 @@ void object_visualizer::GetTypeProperties(Microsoft::VisualStudio::Debugger::Dkm auto impls = type.InterfaceImpl(); for (auto&& impl : impls) { - GetInterfaceData(process, impl.Interface(), m_propertyData, m_isStringable); + GetInterfaceData(process, ExpandInterfaceImplForType(impl.Interface(), typeSig), m_propertyData, m_isStringable); } - GetInterfaceData(process, type.coded_index(), m_propertyData, m_isStringable); + GetInterfaceData(process, typeSig, m_propertyData, m_isStringable); } } @@ -671,7 +916,7 @@ HRESULT object_visualizer::GetItems( auto pParent = pVisualizedExpression; auto childCount = std::min(m_propertyData.size() - StartIndex, (size_t)Count); - for(auto i = 0; i < childCount; ++i) + for(size_t i = 0; i < childCount; ++i) { auto& prop = m_propertyData[i + (size_t)StartIndex]; com_ptr pPropertyVisualized; diff --git a/natvis/object_visualizer.h b/natvis/object_visualizer.h index 08cc40f72..6d1a0f00c 100644 --- a/natvis/object_visualizer.h +++ b/natvis/object_visualizer.h @@ -20,13 +20,18 @@ enum class PropertyCategory Class, }; +inline constexpr bool IsBuiltIn(PropertyCategory value) noexcept +{ + return PropertyCategory::Bool <= value && value < PropertyCategory::Value; +} + enum class ObjectType { Abi, Projection, }; -// Metatdata for resolving a runtime class property value +// Metadata for resolving a runtime class property value struct PropertyData { std::wstring iid; diff --git a/natvis/packages.config b/natvis/packages.config index 356e82f7f..7907cba44 100644 --- a/natvis/packages.config +++ b/natvis/packages.config @@ -2,5 +2,5 @@ - + \ No newline at end of file diff --git a/natvis/pch.h b/natvis/pch.h index c687b1f09..3de6807b3 100644 --- a/natvis/pch.h +++ b/natvis/pch.h @@ -4,11 +4,15 @@ #define NOMINMAX #include +#pragma warning(push) +#pragma warning(disable : 4471) #include +#pragma warning(pop) #include #include #include "base_includes.h" #include "base_macros.h" +#include "base_source_location.h" #include "base_types.h" #include "base_extern.h" #include "base_meta.h" @@ -40,6 +44,7 @@ #include #include #include +#include #ifndef IF_FAIL_RET #define IF_FAIL_RET(expr) { HRESULT _hr = (expr); if(FAILED(_hr)) { return(_hr); } } @@ -88,8 +93,9 @@ inline bool starts_with(std::string_view const& value, std::string_view const& m return 0 == value.compare(0, match.size(), match); } -winmd::reader::TypeDef FindType(Microsoft::VisualStudio::Debugger::DkmProcess* process, std::string_view const& typeName); -winmd::reader::TypeDef FindType(Microsoft::VisualStudio::Debugger::DkmProcess* process, std::string_view const& typeNamespace, std::string_view const& typeName); +winmd::reader::TypeDef FindSimpleType(Microsoft::VisualStudio::Debugger::DkmProcess* process, std::string_view const& typeName); +winmd::reader::TypeDef FindSimpleType(Microsoft::VisualStudio::Debugger::DkmProcess* process, std::string_view const& typeNamespace, std::string_view const& typeName); +winmd::reader::TypeSig FindType(Microsoft::VisualStudio::Debugger::DkmProcess* process, std::string_view const& typeName); inline winmd::reader::TypeDef ResolveType(Microsoft::VisualStudio::Debugger::DkmProcess* process, winmd::reader::coded_index index) noexcept { @@ -98,13 +104,13 @@ inline winmd::reader::TypeDef ResolveType(Microsoft::VisualStudio::Debugger::Dkm case winmd::reader::TypeDefOrRef::TypeDef: return index.TypeDef(); case winmd::reader::TypeDefOrRef::TypeRef: - return FindType(process, index.TypeRef().TypeNamespace(), index.TypeRef().TypeName()); + return FindSimpleType(process, index.TypeRef().TypeNamespace(), index.TypeRef().TypeName()); default: //case TypeDefOrRef::TypeSpec: return winmd::reader::find_required(index.TypeSpec().Signature(). GenericTypeInst().GenericType().TypeRef()); } } -std::pair ResolveTypeInterface(Microsoft::VisualStudio::Debugger::DkmProcess* process, winmd::reader::coded_index index); +std::pair ResolveTypeInterface(Microsoft::VisualStudio::Debugger::DkmProcess* process, winmd::reader::TypeSig const& typeSig); void ClearTypeResolver(); diff --git a/natvis/type_resolver.cpp b/natvis/type_resolver.cpp index 17999997f..de8af71f4 100644 --- a/natvis/type_resolver.cpp +++ b/natvis/type_resolver.cpp @@ -98,6 +98,18 @@ struct signature_generator } } + static std::string get_signature(GenericTypeInstSig const& type) + { + std::string sig = "pinterface(" + get_guid_signature(type.GenericType()); + for (auto&& arg : type.GenericArgs()) + { + sig += ";"; + sig += get_signature(arg); + } + sig += ")"; + return sig; + } + private: static std::string get_class_signature(TypeDef const& type) { @@ -152,20 +164,8 @@ struct signature_generator case TypeDefOrRef::TypeRef: return get_guid_signature(find_required(type.TypeRef())); default: //case TypeDefOrRef::TypeSpec: - return get_guid_signature(type.TypeSpec().Signature().GenericTypeInst().GenericType()); - } - } - - static std::string get_signature(GenericTypeInstSig const& type) - { - std::string sig = "pinterface(" + get_guid_signature(type.GenericType()); - for (auto&& arg : type.GenericArgs()) - { - sig += ";"; - sig += get_signature(arg); + return get_signature(type.TypeSpec().Signature().GenericTypeInst()); } - sig += ")"; - return sig; } static std::string get_signature(TypeSig::value_type const& type) @@ -266,7 +266,7 @@ static auto calculate_sha1(std::vector const& input) return get_result(intermediate_hash); } -static guid generate_guid(coded_index const& type) +static guid generate_guid(GenericTypeInstSig const& type) { constexpr guid namespace_guid = { 0xd57af411, 0x737b, 0xc042,{ 0xab, 0xae, 0x87, 0x8b, 0x1e, 0x16, 0xad, 0xee } }; constexpr auto namespace_bytes = winrt::impl::to_array(namespace_guid); @@ -278,25 +278,38 @@ static guid generate_guid(coded_index const& type) return set_named_guid_fields(endian_swap(to_guid(calculate_sha1(buffer)))); } -std::pair ResolveTypeInterface(DkmProcess* process, coded_index index) +std::pair ResolveTypeInterface(DkmProcess* process, winmd::reader::TypeSig const& typeSig) { - if (auto found = _cache.find(index); found != _cache.end()) + coded_index index; + if (auto ptrIndex = std::get_if>(&typeSig.Type())) { - return found->second; - } + index = *ptrIndex; + // TODO: Cache on the whole TypeSig, not just the generic index + if (auto found = _cache.find(index); found != _cache.end()) + { + return found->second; + } - TypeDef type = ResolveType(process, index); - if (!type) - { - return {}; - } + TypeDef type = ResolveType(process, index); + if (!type) + { + return {}; + } - auto guid = index.type() == TypeDefOrRef::TypeSpec ? - format_guid(generate_guid(index)) : format_guid(get_guid(type)); + auto guid = index.type() == TypeDefOrRef::TypeSpec ? + format_guid(generate_guid(index.TypeSpec().Signature().GenericTypeInst())) : format_guid(get_guid(type)); - auto type_guid = std::pair{ type, guid }; - _cache[index] = type_guid; - return type_guid; + auto type_guid = std::pair{ type, guid }; + _cache[index] = type_guid; + return type_guid; + } + else if (auto* ptrGeneric = std::get_if(&typeSig.Type())) + { + index = ptrGeneric->GenericType(); + auto guid = format_guid(generate_guid(*ptrGeneric)); + return { ResolveType(process, index), guid }; + } + return {}; }; void ClearTypeResolver() diff --git a/nuget.config b/nuget.config new file mode 100644 index 000000000..a7584f8d9 --- /dev/null +++ b/nuget.config @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/nuget/CppWinrtRules.Project.xml b/nuget/CppWinrtRules.Project.xml index 7f69fcd74..43a712d21 100644 --- a/nuget/CppWinrtRules.Project.xml +++ b/nuget/CppWinrtRules.Project.xml @@ -3,6 +3,7 @@ + @@ -81,9 +82,29 @@ Description="Enables or disables the default for copying binaries to the output folder to be false" Category="General" /> - + + + + + + + + diff --git a/nuget/Microsoft.Windows.CppWinRT.nuspec b/nuget/Microsoft.Windows.CppWinRT.nuspec index 882931734..52151fc08 100644 --- a/nuget/Microsoft.Windows.CppWinRT.nuspec +++ b/nuget/Microsoft.Windows.CppWinRT.nuspec @@ -12,6 +12,7 @@ native C++ WinRT nativepackage © Microsoft Corporation. All rights reserved. LICENSE + readme.md https://github.com/Microsoft/cppwinrt https://aka.ms/cppwinrt.ico @@ -20,11 +21,12 @@ - + + diff --git a/nuget/Microsoft.Windows.CppWinRT.targets b/nuget/Microsoft.Windows.CppWinRT.targets index f5606caec..a297258f3 100644 --- a/nuget/Microsoft.Windows.CppWinRT.targets +++ b/nuget/Microsoft.Windows.CppWinRT.targets @@ -26,9 +26,13 @@ Copyright (C) Microsoft Corporation. All rights reserved. $([System.IO.Path]::GetFullPath($(MSBuildThisFileDirectory)))..\..\ $([System.IO.Path]::GetFullPath($(MSBuildThisFileDirectory))) $(CppWinRTParameters) -fastabi + + -modules + -module_include $(CppWinRTModuleInclude.Replace(';', ' ')) + $(CppWinRTCommandModuleFilter) -module_exclude $(CppWinRTModuleExclude.Replace(';', ' ')) "$(CppWinRTPackageDir)bin\" "$(CppWinRTPackageDir)" - + true C++ @@ -651,6 +655,9 @@ $(XamlMetaDataProviderPch) <_CppwinrtParameters>$(CppWinRTCommandVerbosity) $(CppWinRTParameters) + + <_CppwinrtParameters Condition="'$(_CppWinRTConsumesPlatformModules)'!='true'">$(_CppwinrtParameters) $(CppWinRTCommandModules) $(CppWinRTCommandModuleFilter) <_CppwinrtParameters>$(_CppwinrtParameters) @(_CppwinrtInputs->'-in "%(WinMDPath)"', ' ') <_CppwinrtParameters>$(_CppwinrtParameters) -out "$(GeneratedFilesDir)." @@ -729,7 +736,7 @@ $(XamlMetaDataProviderPch) <_CppwinrtRefRefs Include="@(CppWinRTPlatformWinMDReferences)"/> - <_CppwinrtParameters>$(CppWinRTCommandVerbosity) $(CppWinRTParameters) + <_CppwinrtParameters>$(CppWinRTCommandVerbosity) $(CppWinRTParameters) $(CppWinRTCommandModules) $(CppWinRTCommandModuleFilter) <_CppwinrtParameters>$(_CppwinrtParameters) @(_CppwinrtRefInputs->'-in "%(WinMDPath)"', ' ') <_CppwinrtParameters>$(_CppwinrtParameters) @(_CppwinrtRefRefs->'-ref "%(WinMDPath)"', ' ') <_CppwinrtParameters>$(_CppwinrtParameters) -out "$(GeneratedFilesDir)." @@ -835,7 +842,7 @@ $(XamlMetaDataProviderPch) <_CppwinrtCompRefs Include="@(CppWinRTPlatformWinMDReferences)"/> - <_CppwinrtParameters>$(CppWinRTCommandVerbosity) $(CppWinRTParameters) -overwrite -name $(RootNamespace) $(CppWinRTCommandPrecompiledHeader) $(CppWinRTCommandUsePrefixes) -comp "$(GeneratedFilesDir)sources" + <_CppwinrtParameters>$(CppWinRTCommandVerbosity) $(CppWinRTParameters) $(CppWinRTCommandModules) $(CppWinRTCommandModuleFilter) -overwrite -name $(RootNamespace) $(CppWinRTCommandPrecompiledHeader) $(CppWinRTCommandUsePrefixes) -comp "$(GeneratedFilesDir)sources" <_CppwinrtParameters Condition="'$(CppWinRTOptimized)'=='true'">$(_CppwinrtParameters) -opt <_CppwinrtParameters>$(_CppwinrtParameters) @(_CppwinrtCompInputs->'-in "%(WinMDPath)"', ' ') <_CppwinrtParameters>$(_CppwinrtParameters) @(_CppwinrtCompRefs->'-ref "%(WinMDPath)"', ' ') @@ -861,7 +868,9 @@ $(XamlMetaDataProviderPch) Condition="'@(Page)@(ApplicationDefinition)' != '' and '$(XamlLanguage)' == 'CppWinRT'" DependsOnTargets="$(CppWinRTAddXamlReferencesDependsOn);CppWinRTGetResolvedWinMD;GetCppWinRTProjectWinMDReferences"> - + + + @@ -880,7 +889,7 @@ $(XamlMetaDataProviderPch) %(AdditionalOptions) /bigobj - %(AdditionalOptions) /await + %(AdditionalOptions) /await:strict %(AdditionalIncludeDirectories);$(GeneratedFilesDir) @@ -893,4 +902,88 @@ $(XamlMetaDataProviderPch) + + + + + CompileAsCppModule + true + NotUsing + + + + + + + + + $(GeneratedFilesDir) + $(IntDir) + $(OutDir) + + + + + + + + + <_CppWinRTModuleProviders Remove="@(_CppWinRTModuleProviders)" /> + <_CppWinRTModuleProviders Include="@(ProjectReference)" + Condition="'%(ProjectReference.CppWinRTConsumeModule)' == 'true'" /> + + + + + <_CppWinRTConsumesPlatformModules>true + + + + + + + + + + + + + <_CppWinRTModuleIfcSearchDirs>@(_CppWinRTResolvedModuleRefs->'%(CppWinRTModuleIfcDir)') + + + + $(_CppWinRTModuleIfcSearchDirs);%(ClCompile.AdditionalBMIDirectories) + + + + diff --git a/nuget/modules.md b/nuget/modules.md new file mode 100644 index 000000000..4f0eebb95 --- /dev/null +++ b/nuget/modules.md @@ -0,0 +1,524 @@ +# C++/WinRT C++20 Modules Guide + +## Overview + +C++/WinRT can generate per-namespace C++20 named modules (`.ixx` files) alongside the traditional projection headers. This allows you to write: + +```cpp +import winrt.Windows.Foundation; +``` + +instead of: + +```cpp +#include +``` + +Benefits include: + +- **Smaller intermediate artifacts.** The IFC representation of a C++/WinRT projection is significantly smaller than the equivalent precompiled header (PCH). +- **Shared compilation across projects.** PCHs eliminate redundant parsing *within* a project, but each project rebuilds its own PCH. Module IFCs can be built once in a shared module builder project and consumed by all dependent projects, eliminating redundant work across the entire solution. +- **Better isolation.** Module imports don't leak macros into the importing translation unit. + +> **Real-world experience:** The guidance in this document was hardened against a prototype conversion of the Windows Terminal codebase (~250 files across 15+ projects) from textual `#include`s to module imports. + +## Prerequisites + +- **MSVC v145 toolset** (Visual Studio 2026) or later with C++20 module support +- **C++/WinRT 3.x** NuGet package with `CppWinRTBuildModule` support +- `/std:c++20` or later (`/std:c++latest` recommended for `import std;`) +- `BuildStlModules=true` for `import std;` support + +## Three Fundamental Constraints + +These three rules drive almost every pattern in this guide. Understanding them up front makes the rest of the document much easier to follow: + +1. **`import` in a PCH breaks the compiler.** MSVC cannot handle module `import` declarations inside a precompiled header — it produces internal compiler errors (ICE). All module imports must live outside the PCH. + +2. **Include-then-import is safe, but has a cost.** MSVC handles the case where you `#include` a header and then `import` the same content. For STL headers this is a reasonable workaround (the compilation cost is modest), but C++/WinRT projection headers can be extremely expensive to parse textually. Include-then-import with winrt headers defeats the build-cost improvements of adopting modules, so it should be avoided where possible. + +3. **Import-then-include is not supported.** When a module has already been imported, `#include`-ing a header that declares the same types causes errors — the compiler sees conflicting declarations. C++/WinRT provides a workaround: defining `WINRT_IMPORT_MODULE` before including a winrt header causes the header to be (mostly) a no-op, defining only its include-guard macro. This makes it safe to include winrt headers *after* importing modules, which is essential for lighting up header-guard-based features in libraries like WIL, and for interoperating with external code that includes winrt headers out of your control (e.g. the XAML compiler). STL headers do not have an equivalent workaround, but can fall back on the "generally safe" include-then-import pattern. + +The patterns throughout this guide are direct consequences of these constraints: + +- The PCH is stripped of all winrt content. +- A separate "module preamble" header centralizes imports. +- Wrapper headers define `WINRT_IMPORT_MODULE` before including winrt headers. +- STL headers are sometimes pre-included in the PCH, but only as a workaround. + +## Quick Start — Single Project + +For a small project that builds and consumes its own modules: + +1. Set `CppWinRTBuildModule` to `true` in your project: + ```xml + + true + + ``` + +2. Optionally limit which namespaces get modules: + ```xml + + Windows.Foundation;Windows.Storage + + ``` + + By default, C++/WinRT generates and builds `.ixx` files for **every** namespace reachable from your WinMD inputs — for a typical Windows SDK projection, that's hundreds of namespaces and can add upwards of a minute to your build. If build speed matters, prune the set with `CppWinRTModuleInclude` (or `CppWinRTModuleExclude`) so that only the namespaces you actually `import` are produced. See [Understanding the Include and Exclude Filters](#understanding-the-include-and-exclude-filters) for the full discussion. + +3. Enable `BuildStlModules` for `import std;` support: + ```xml + + true + + ``` + +4. In your `.cpp` files: + ```cpp + import winrt.Windows.Foundation; + + int main() { + winrt::init_apartment(); + winrt::Windows::Foundation::Uri uri(L"https://example.com"); + } + ``` + +For a single vcxproj — or a handful of projects that don't share many namespaces — this is all you need. A dedicated module builder is only worth the overhead when multiple projects need the same platform and third-party WinRT modules. + +## Architecture — Module Builder (Recommended for Multi-Project Solutions) + +For solutions with multiple projects, the recommended approach is a dedicated **module builder** project that builds the shared IFC files once, consumed by all other projects. This avoids each project redundantly compiling the same module interfaces. + +### The Module Builder Project + +Create a dedicated static library project whose sole purpose is to build the shared platform module IFC files. This project has no source files of its own — the C++/WinRT NuGet targets generate `.ixx` files automatically. + +```xml + + StaticLibrary + true + true + +``` + +Key configuration: + +- **`CppWinRTBuildModule=true`** generates per-namespace `.ixx` module interface files. +- **`BuildStlModules=true`** is required because the generated `.ixx` files use `import std;`. +- **`WINRT_ENABLE_LEGACY_COM`** — define this preprocessor macro if your project uses classic COM interfaces (`IUnknown`, `IInspectable`). It causes `` and `` to be included within the `winrt_base` module. +- **PCH**: don't bother. The module builder can use a PCH, but there is little benefit — its content is almost entirely C++/WinRT headers, and most non-C++/WinRT headers are only used once in `winrt_base`. + +### Consumer Project Configuration + +Each project that uses modules needs: + +```xml + + true + MyCompany.MyComponent + Microsoft.UI;Microsoft.Web + + + + true + + +``` + +- **`CppWinRTBuildModule=true`** is required on consumers too. It enables the C++/WinRT targets to generate `.ixx` module interface files for the project's own component namespaces (filtered by `CppWinRTModuleInclude` / `CppWinRTModuleExclude`) and wires up module consumption from referenced projects. +- **`CppWinRTConsumeModule=true`** on the `ProjectReference` tells the build system to use the builder's pre-built platform IFCs instead of compiling platform `.ixx` files again, and skip generating platform `.ixx` files in the consumer's own projection. + +### Adding Third-Party WinMDs to the Module Builder + +If your project uses third-party WinRT components (e.g., WinUI/MUX, WebView2), build their modules in the shared builder by adding their WinMDs as platform inputs: + +```xml + + + + + + +``` + +**Important:** Add these WinMDs as `CppWinRTPlatformWinMDReferences`, **not** as NuGet `` items. In practice, adding third-party WinMDs via NuGet `` items on the module builder has been observed to cause empty path errors in the reference projection step. Adding them directly as `CppWinRTPlatformWinMDReferences` feeds them into the platform projection, which is the correct pipeline for a module builder project. + +### Component DLLs + +WinRT component projects can also use modules. Set `CppWinRTBuildModule=true` and all three projections (platform, reference, component) will generate `.ixx` files. + +```xml + + true + MyComponent + + + + true + + +``` + +If project A references a component DLL from project B, project A builds its own reference projection modules from B's `.winmd`: + +```cpp +// These modules are built locally from the component's .winmd +import winrt.MyComponent; + +auto obj = winrt::MyComponent::MyClass(); +``` + +## MSBuild Properties + +| Property | Default | Description | +|-|-|-| +| `CppWinRTBuildModule` | `false` | Generate `.ixx` module interface units from projections | +| `CppWinRTModuleInclude` | (all) | Semicolon-delimited namespace prefixes to include in module generation | +| `CppWinRTModuleExclude` | (none) | Semicolon-delimited namespace prefixes to exclude from module generation | + +| `ProjectReference` Metadata | Default | Description | +|-|-|-| +| `CppWinRTConsumeModule` | `false` | Consume pre-built platform module IFCs from this project reference | + +### Understanding the Include and Exclude Filters + +These filters control which C++/WinRT module `.ixx` files are generated from WinMD inputs. They only affect modules produced by the C++/WinRT NuGet targets from `.winmd` files — hand-authored modules or modules unrelated to WinRT are not affected. + +- **`CppWinRTModuleInclude`** — semicolon-separated namespace prefixes. Only matching namespaces will have `.ixx` files generated. Without this, *all* namespaces from the project's WinMD inputs are candidates. +- **`CppWinRTModuleExclude`** — semicolon-separated namespace prefixes to suppress `.ixx` generation for. **Import statements are still generated** in the modules that remain; only the `.ixx` file creation is suppressed. + +#### Why Filter at All? + +There are three distinct reasons to set these filters. Most non-trivial projects will hit more than one: + +1. **Build performance.** By default, enabling `CppWinRTBuildModule=true` generates and compiles `.ixx` files for *every* namespace reachable from your WinMD inputs. For a typical Windows SDK projection that's hundreds of namespaces, and the IFC compilation step can easily add upwards of a minute to a clean build. Use `CppWinRTModuleInclude` to narrow generation to namespaces you (or your consumers) actually `import`, or `CppWinRTModuleExclude` to drop large subtrees you don't use (e.g., `Windows.Devices`, `Windows.Media`). For a dedicated module builder project that other projects consume, this is typically the dominant reason to filter. + +2. **Avoiding ambiguous IFC errors (C7684).** An IFC is ambiguous when the same module name resolves to two different `.ifc` files — typically one built locally and one from a referenced project. See [When to Set an Exclude for Ambiguity](#when-to-set-an-exclude-for-ambiguity) below. + +3. **Avoiding modules with unsatisfied dependencies.** Filtering to a subset of namespaces does *not* prune the `import` statements those modules emit for their dependencies — so a generated module whose dependencies fall outside your filter will fail to compile. See [Module Filtering and Transitive Dependencies](#module-filtering-and-transitive-dependencies) below. + +#### When to Set an Exclude for Ambiguity + +Exclude a namespace when its IFC is already provided by a project you reference: + +| Scenario | Action | +|----------|--------| +| You reference a **static library** with `CppWinRTBuildModule=true` | Exclude namespaces that static lib produces (its IFCs propagate via `AdditionalBMIDirectories`) | +| You reference a **DLL** with `CppWinRTBuildModule=true` | **No exclude needed** — DLL IFCs don't propagate by default | +| The **module builder** produces a namespace (e.g., `Microsoft.UI`) | Exclude it — the module builder's IFCs propagate via `CppWinRTConsumeModule` | + +Example — a project that references both the module builder (which provides `Microsoft.UI.*`) and a `TerminalCore` static library (which provides `Microsoft.Terminal.Core`): + +```xml +Microsoft.Terminal +Microsoft.Terminal.Core;Microsoft.UI;Microsoft.Web +``` + +### Module Filtering and Transitive Dependencies + +`CppWinRTModuleInclude` and `CppWinRTModuleExclude` control which namespace `.ixx` files are **generated**, but they do not suppress `import` statements for dependencies. If namespace A is included in the filter and depends on namespace B, the generated `winrt.A.ixx` will contain `import winrt.B;` even if B is excluded from the filter. This is by design — the module for B must exist *somewhere* (either from the same project or from a referenced project). + +Implications: + +- **Transitive closure must be satisfied.** If you filter to a subset of namespaces, any dependencies that fall outside the filter must be available from another source (e.g., a module builder project referenced via `CppWinRTConsumeModule`, or MSBuild's automatic `ReferencedModuleBMIs` from a static library reference). Otherwise, compilation will fail with "could not find module" errors. + +- **Use `CppWinRTModuleExclude` to avoid generating modules that have unsatisfied dependencies.** For example, `Windows.Foundation.Diagnostics` depends on `Windows.Storage`. If you filter to `CppWinRTModuleInclude=Windows.Foundation`, the Diagnostics `.ixx` will be generated (it matches the prefix) but will fail to compile because `winrt.Windows.Storage` doesn't exist. Add `CppWinRTModuleExclude=Windows.Foundation.Diagnostics` to prevent this. + +- **In multi-project scenarios with static libraries, use `CppWinRTModuleExclude` to avoid duplicate modules.** MSBuild automatically propagates all module IFCs from static library references to consuming projects (via the `AllProjectBMIsArePublic` property, which defaults to `true` for static libraries). If project A is a static library that builds modules for namespace X, and project B references A, then B already has A's IFCs available. If B also has `CppWinRTBuildModule=true`, its reference projection will generate a second `winrt.X.ixx`, causing an ambiguous module error. Set `CppWinRTModuleExclude=X` on project B to prevent this. B's own `.ixx` files will still emit `import winrt.X;`, which resolves to A's IFC via MSBuild's automatic propagation. Note: this issue does not affect DLL references — MSBuild does not propagate module IFCs from DLLs by default. + +## Module Names + +| Module | Contents | +|-|-| +| `winrt_base` | Core C++/WinRT types (`hstring`, `com_ptr`, `IUnknown`, etc.) — re-exported by all namespace modules | +| `winrt_numerics` | `Windows::Foundation::Numerics` types — re-exported by `winrt_base` | +| `winrt.` | Per-namespace projection (e.g., `winrt.Windows.Foundation`) | + +## Converting an Existing Project: Step by Step + +### 1. Strip winrt from the PCH + +Module `import` declarations inside a precompiled header cause compiler ICEs. All C++/WinRT content must be moved out of the PCH and into the module preamble header (see next step). + +Remove the following from your PCH: + +- `#include ` — all winrt projection headers +- `#include ` and `` +- Any header that depends on C++/WinRT types, **including headers that conditionally enable behavior based on C++/WinRT header guards.** For example, `wil/cppwinrt_helpers.h` checks for `WINRT_Windows_UI_Core_H` and uses types from `Windows.UI.Core` when defined — this header must move out of the PCH. + +**Keep** in the PCH: + +- Platform SDK headers (``, ``, etc.) +- Non-winrt third-party headers + +**STL headers and `import std;`** — STL headers are safe to include *before* `import std;` (include-then-import works). Problems arise when STL headers are included *after* `import std;`, which can cause redefinition warnings (C4348, C5028). In most cases it is preferable to use `import std;` instead of putting STL headers in the PCH. However, if you depend on libraries that internally `#include` STL headers *after* modules have been imported, you may need to pre-include the offending STL headers in the PCH to make the later inclusion inert: + +```cpp +// Pre-include STL headers that other libraries include after import std; +#include +#include +``` + +Ideally, the offending library code would also adopt `import std;`, but that's not always immediately practical. + +### 2. Create a Module Preamble Header + +A module preamble header centralizes the module imports and library setup that are shared across a project's source files. It is not strictly required — you could add imports directly to each `.cpp` file — but it speeds up migration significantly and becomes necessary if you need to deal with generated files outside your control (see [XAML Projects](#xaml-projects)). + +Create a preamble header in each project that contains the module imports commonly used across that project: + +```cpp +// ModulePreamble.h (or whatever name you prefer) +#pragma once + +#define WINRT_IMPORT_MODULE + +// Import the C++/WinRT namespaces used across this project +import winrt.Windows.Foundation; +import winrt.Windows.Foundation.Collections; +import winrt.Windows.System; +// ... other namespaces your project needs + +// Component modules +import winrt.MyCompany.MyComponent; +``` + +Importing modules is cheap, so don't hesitate to list every namespace the project uses. You can add library wrapper headers and other setup to this file as needed (see next section). + +Include the preamble in each `.cpp` file after the PCH: + +```cpp +#include "pch.h" +#include "ModulePreamble.h" +// ... rest of the file +``` + +### 3. Wrap Library Headers That Depend on C++/WinRT Types + +Libraries like WIL use `#ifdef WINRT_Windows_Foundation_H` guards to conditionally enable winrt-dependent features. With modules, those header guards are never defined because the winrt headers are never textually included. To light up this behavior, define the appropriate header guards before including the library header — or, equivalently, include the now-inert winrt headers under `WINRT_IMPORT_MODULE`, which defines the guards as a side effect. + +You can do this directly in the module preamble: + +```cpp +// In your module preamble header +import winrt.Windows.Foundation; +#define WINRT_IMPORT_MODULE +#define WINRT_Windows_Foundation_H // Lights up WIL's Foundation support +#include +``` + +If you include the library from many places, you can author a **wrapper header** that bundles the imports, guard definitions, and library include together: + +```cpp +// wil_cppwinrt_module.h +#pragma once + +import winrt_base; +import winrt.Windows.Foundation; +import winrt.Windows.Foundation.Collections; + +#define WINRT_IMPORT_MODULE +// Define header guards to light up WIL's conditional winrt features. +// You can either define the guards directly, or include the now-inert +// winrt headers (which define the guards as a side effect): +#include +#include + +#include +#include +``` + +Include this wrapper in your module preamble as needed. Re-importing modules and re-defining header guards is harmless, so there's no issue with including the wrapper from multiple places. + +This pattern applies to any library that conditionally uses winrt types based on header include guards. + +### 4. Update the vcxproj + +```xml + +true +MyCompany.MyComponent +Microsoft.UI;Microsoft.Web + + + + true + +``` + +### 5. Add Solution Build Dependency + +If using `.slnx` or `.sln`, add a build dependency to ensure the module builder, if using, compiles first: + +```xml + +``` + +## Special Cases + +### XAML Projects + +XAML projects have a two-pass compilation model that complicates module adoption. The XAML compiler generates source files (`XamlTypeInfo.g.cpp`, `XamlTypeInfo.Impl.g.cpp`, `XamlMetaDataProvider.cpp`) that use winrt types but don't know about modules. + +The solution is to inject `ModulePreamble.h` via the `/FI` (forced include) compiler flag on these generated files, using MSBuild targets: + +```xml + + + + + NotUsing + $(MSBuildProjectDirectory)\ModulePreamble.h + + + +``` + +For static library projects, the XAML build system has a second compilation pass (`CompileXamlGeneratedFiles`) that runs after `ClCompile` but before `Lib`. For DLLs and EXEs, the same targets run after the build compile phase. In either case, you need a second target to ensure the `/FI` metadata is applied before `CompileXamlGeneratedFiles`: + +```xml + + + + NotUsing + $(MSBuildProjectDirectory)\ModulePreamble.h + + + +``` + +**Critical MSBuild detail:** Use ``, not just ``. Without `Update`, MSBuild adds new items instead of modifying metadata on existing ones. + +**Why the preamble header needs `#include "pch.h"` for XAML:** When used as `/FI`, the preamble header is processed *before* the generated file's own `#include "pch.h"`. Adding `#include "pch.h"` at the top of the preamble ensures platform headers are available. For regular `.cpp` files that already include pch.h before the preamble, it's a `#pragma once` no-op. If your project doesn't use the `/FI` approach for XAML, you don't need pch.h in the preamble. + +#### Understanding the XAML Build Order + +The XAML build targets schedule `MarkupCompilePass2` and `CompileXamlGeneratedFiles` differently depending on project type: + +- **Static libraries** (`AfterClCompileTargets`): Pass2 runs after `ClCompile`, before `Lib` +- **DLLs/EXEs** (`AfterBuildCompileTargets`): Pass2 runs after the build compile phase, before `Link` + +In both cases, the order is: + +1. **MarkupCompilePass1** (before `ClCompile`): Generates `.xaml.g.h` declarations +2. **ClCompile**: Compiles your source files +3. **MarkupCompilePass2**: Generates `.xaml.g.hpp` implementations +4. **CompileXamlGeneratedFiles**: Compiles `XamlTypeInfo.g.cpp` (which `#include`s the `.xaml.g.hpp` files) + +The XAML-generated items (`XamlTypeInfo.g.cpp`, etc.) are added to `ClCompile` by the `ComputeXamlGeneratedCompileInputs` target, which is why the `/FI` target uses `AfterTargets="ComputeXamlGeneratedCompileInputs"`. + +### Headers with Conditional winrt Conversions + +If you have utility types (like a `color` struct) with conversion operators gated behind winrt header guards: + +```cpp +#ifdef WINRT_Windows_UI_H + operator winrt::Windows::UI::Color() const { ... } +#endif +``` + +These guards must be defined **before** the header is first included (`#pragma once` means it won't be processed again). Create a dedicated wrapper that imports the module, sets the guard, then re-includes the header: + +```cpp +// color_module.h +#pragma once +import winrt.Windows.UI; +#define WINRT_IMPORT_MODULE +#include // Sets WINRT_Windows_UI_H +#include // Now sees the guard, enables converters +``` + +Include this wrapper in your `ModulePreamble.h` **before** any other header that might include the guarded file. + +### Win32 Macro Conflicts + +Some Win32 macros (e.g., `GetObject` from `wingdi.h`) conflict with WinRT method names. With headers, the macro was applied to both the projection types and the call site. With modules, the WinRT types don't have the macro applied (they were compiled in the module without the macro), but your source file still has the macro defined. Use: + +```cpp +#pragma push_macro("GetObject") +#undef GetObject +// ... code using winrt types with GetObject method +#pragma pop_macro("GetObject") +``` + +## Caution: Module Reuse Across Projects + +Pre-built IFCs (via `CppWinRTConsumeModule`) should only be shared when the builder and consumer use the same compilation context. In particular: + +- **Component modules are project-private.** A component projection built with `CppWinRTOptimized=true` generates modules that bypass activation factories for in-component type instantiation (`-opt`). If a consuming project accidentally imports these modules instead of building its own reference projection, the consumer will attempt direct instantiation across DLL boundaries, resulting in linker errors or incorrect behavior. Each project should build its own modules from the component's `.winmd` — do not tag component `ProjectReference`s with `CppWinRTConsumeModule`. + +- **`CppWinRTConsumeModule` is intended for platform module builders only.** The builder project is a dedicated static library whose sole purpose is compiling platform SDK modules. Its compilation flags (no `-opt`, no `-comp`) produce modules safe for any consumer. Only tag this builder's `ProjectReference` with `CppWinRTConsumeModule=true`. + +- **Module filter scope matters.** `CppWinRTModuleInclude` / `CppWinRTModuleExclude` applies to all three projections (platform, reference, component). If you set `CppWinRTModuleInclude=MyComponent`, only `MyComponent` namespaces will get `.ixx` files — platform and reference namespace modules will not be generated. Make sure your filter includes all namespaces you intend to import as modules, or use `CppWinRTConsumeModule` to get platform modules from a builder that was configured with the appropriate filter. + +- **Compilation settings must be compatible between builder and consumer.** Module IFCs encode assumptions about the compilation environment. While the compiler may not always diagnose mismatches, the following differences between the module builder and consumer may cause subtle or hard-to-diagnose issues: + - **Debug vs Release** — mixing Debug and Release configurations can produce mismatched code generation, iterator debugging levels, and runtime library selections. + - **Preprocessor definitions** — definitions that affect type layout, conditional compilation, or feature flags should match between builder and consumer. + - **Struct alignment / packing** — different `/Zp` settings between projects can change struct layout, causing silent ABI mismatches. + - **Language standard** — while C++20 and later are generally compatible, mixing `/std:c++20` and `/std:c++23` and/or `/std:c++latest` can affect type definitions if language features differ. + + As a general rule, the module builder project should try to use the same configuration, preprocessor definitions, and compiler options as its consumers. + +## Limitations + +- Module IFCs are not compatible across toolset versions. All projects must use the same toolset. +- Cyclic namespace dependencies (e.g., `Windows.Foundation` ↔ `Windows.Foundation.Collections`) are handled automatically via SCC consolidation, but the resulting module name is chosen alphabetically. Adding new APIs could change SCC groupings. + +## Common Errors and Solutions + +| Error | Cause | Solution | +|-------|-------|----------| +| **C2230**: could not find module `winrt.X` | Missing import or the module IFC wasn't built | Add the import; verify the module builder or consumer produces it; check `CppWinRTModuleInclude` | +| **C7684**: ambiguous resolution to IFC | Same module built by multiple projects visible to the consumer | Add the namespace to `CppWinRTModuleExclude` | +| **C4348**: redefinition of default parameter | STL header included after `import std;` | Pre-include the STL header in the PCH (e.g., `#include `) | +| **C5028**: alignment specified in prior declaration | Same root cause as C4348 | Pre-include the STL header (e.g., `#include `) | +| **C4430 / C2039**: missing type / not a member | Type not visible because module not imported | Add the missing `import winrt.Namespace;` to ModulePreamble | +| **LNK2019**: unresolved external for `InitializeComponent` | XAML-generated code compiled without module imports | Ensure the `/FI` targets are present and use `Update="@(ClCompile)"` | +| **LNK2005**: symbol already defined | XAML-generated file compiled both directly and via a wrapper | Use the `/FI` injection approach instead of wrapper `.cpp` files | +| Redefinition errors when mixing `#include` and `import` | Same namespace included textually after being imported | Define `WINRT_IMPORT_MODULE` before the winrt header, or remove the `#include` | +| **"could not find module 'winrt.X'"** in cross-project consumer | Builder's `IntDir` not visible to consumer | Verify `ProjectReference` to the builder has `CppWinRTConsumeModule=true` | +| Linker errors for component constructors | Importing a component's internal module instead of building your own reference projection | Remove explicit `/reference` flags for component IFCs and ensure your project has `CppWinRTBuildModule=true` so it builds reference projection modules from the component's `.winmd` | + +## Tips + +- **Clean build after configuration changes.** Stale IFC files from previous builds cause confusing ambiguity errors. Clean the intermediate directory when changing module include/exclude filters. +- **Start from leaf projects.** Convert projects with no WinRT component dependencies first (e.g., utility libraries), then work up the dependency graph. +- **One project at a time.** Each conversion may surface new missing imports or exclude requirements. Building incrementally makes errors easier to diagnose. +- **Watch for transitive IFC propagation.** Static library IFCs become visible to all consumers in the reference chain. This is correct behavior but requires `CppWinRTModuleExclude` entries in consumers. +- **`CppWinRTModuleInclude` is usually needed.** Without it, projects with `CppWinRTModuleExclude` may not generate any `.ixx` files at all. Specify the namespace prefix for your component (e.g., `Microsoft.Terminal`). +- **DLL wrapper projects typically need no changes.** If you have a pattern of "static lib + thin DLL wrapper", the DLL wrapper usually just links the lib and doesn't need module conversion. + +## Approaches Tried and Abandoned + +For posterity, these patterns were attempted during the Terminal prototype but proved problematic. Avoid them. + +### Wrapper `.module.cpp` files for XAML-generated code + +The idea was to create wrapper `.cpp` files that would `#include` the XAML-generated files after setting up module imports, then remove the original generated items from `ClCompile` and replace them with the wrappers. + +**Why it failed:** The XAML build system generates files across two compilation passes. `XamlTypeInfo.g.cpp` `#include`s `.xaml.g.hpp` files that don't exist until Pass2, but the wrapper needed to compile during the first `ClCompile` pass. `__has_include` guards to make wrappers compile empty initially and recompile later proved unreliable — `CompileXamlGeneratedFiles` is a separate compilation step, and the wrapper items weren't correctly routed through it. + +**The `/FI` approach works** because it modifies the compiler flags on the *existing* generated items rather than replacing them, working with the XAML build system's two-pass compilation. + +### `AllProjectBMIsArePublic=false` on static libraries + +The idea was to prevent IFC propagation from static libraries by setting `AllProjectBMIsArePublic=false`, hiding the static lib's IFCs from consumers. + +**Why we moved away:** This fights against the intended VC++ build model. If a project consumes a static library, it should also consume that library's IFC files. Using different IFCs for the same types risks ODR violations. The `CppWinRTModuleExclude` approach is better — the consumer avoids building duplicate IFCs while still consuming the producer's IFCs. + +### Moving wrapper items into MSBuild targets + +The idea was to add wrapper `.cpp` `ClCompile` items inside a `` (dynamically) instead of a static ``, so they'd only enter `ClCompile` after generated files existed. + +**Why it failed:** Items added inside targets don't get the same metadata processing (module dependency scanning, IFC reference resolution) as items in static `ItemGroup`s. The compiler couldn't find any modules. diff --git a/nuget/readme.md b/nuget/readme.md index 991fd2768..16eb5d2bb 100644 --- a/nuget/readme.md +++ b/nuget/readme.md @@ -41,7 +41,7 @@ It sets the following project properties and item metadata: | Link.AdditionalDependencies | WindowsApp.lib | Umbrella library for Windows Runtime imports | | Midl.AdditionalOptions | /reference ... | Enables faster compilation with winmd references (versus idl imports) | | Midl.EnableWindowsRuntime | true | Enables Windows Runtime semantics | -| Midl.MetadataFileName | Unmerged\%(Filename).winmd | Generates unmerged metadata in a tempoary location | +| Midl.MetadataFileName | Unmerged\%(Filename).winmd | Generates unmerged metadata in a temporary location | | Midl.GenerateClientFiles, GenerateServerFiles, GenerateStublessProxies, GenerateTypeLibrary, HeaderFileName, DllDataFileName, InterfaceIdentifierFileName, ProxyFileName, TypeLibraryName | *nul, *None, *false | Disable unnecessary output | \*If not already set @@ -70,6 +70,9 @@ C++/WinRT behavior can be customized with these project properties: | CppWinRTOptimized | true \| *false | Enables component projection [optimization features](https://kennykerr.ca/2019/06/07/cppwinrt-optimizing-components/) | | CppWinRTGenerateWindowsMetadata | true \| *false | Indicates whether this project produces Windows Metadata | | CppWinRTEnableDefaultPrivateFalse | true \| *false | Indicates whether this project uses C++/WinRT optimized default for copying binaries to the output directory | +| CppWinRTBuildModule | true \| *false | Generates per-namespace C++20 module interface units (.ixx) alongside projection headers | +| CppWinRTModuleInclude | namespace list | Semicolon-delimited namespaces to include in module generation (default: all) | +| CppWinRTModuleExclude | namespace list | Semicolon-delimited namespaces to exclude from module generation | \*Default value To customize common C++/WinRT project properties: @@ -114,7 +117,7 @@ void MyComponent::InitializeComponent() ***[Windows|Microsoft]::UI::Xaml::Markup::ComponentConnectorT*** -A consequence of calling InitializeComponent outside construction is that Xaml runtime callbacks to IComponentConnector::Connect and IComponentConnector2::GetBindingConnector are now dispatched to the most derived implementations. Previously, these calls were dispatched directly to the class under construction, as the vtable had yet to be initialized. For objects with markup that derive from composable base classes with markup, this is a breaking change. Derived classes must now implement IComponentConnector::Connect and IComponentConnector2::GetBindingConnector by explicitly calling into the base class. The ComponentConnectorT template provides a correct implemenation for these interfaces: +A consequence of calling InitializeComponent outside construction is that Xaml runtime callbacks to IComponentConnector::Connect and IComponentConnector2::GetBindingConnector are now dispatched to the most derived implementations. Previously, these calls were dispatched directly to the class under construction, as the vtable had yet to be initialized. For objects with markup that derive from composable base classes with markup, this is a breaking change. Derived classes must now implement IComponentConnector::Connect and IComponentConnector2::GetBindingConnector by explicitly calling into the base class. The ComponentConnectorT template provides a correct implementation for these interfaces: ```cpp struct DerivedPage : winrt::Windows::UI::Xaml::Markup::ComponentConnectorT> @@ -132,6 +135,17 @@ void DerivedPage::InitializeComponent() } ``` +## C++20 Modules + +C++/WinRT supports C++20 named modules as an alternative to `#include`-based consumption. Instead of `#include `, you can write `import winrt.Windows.Foundation;`. + +See the [C++/WinRT C++20 Modules Guide](https://github.com/microsoft/cppwinrt/blob/master/nuget/modules.md) for the full guide (also shipped alongside this file as `modules.md`). + +| ProjectReference metadata | Description | +|-|-| +| CppWinRTConsumeModule | true \| *false | When set on a ProjectReference, consumes pre-built platform module IFCs from the referenced project | +\*Default value + ## Troubleshooting The msbuild verbosity level maps to msbuild message importance as follows: @@ -147,7 +161,7 @@ For example, if the verbosity is set to minimal, then only messages with high im The default importance of C++/WinRT build messages is 'normal', but this can be overridden with the CppWinRTVerbosity property to enable throttling of C++/WinRT messages independent of the overall verbosity level. Example: -> msbuild project.vcxproj /vebosity:minimal /property:CppWinRTVerbosity=high ... +> msbuild project.vcxproj /verbosity:minimal /property:CppWinRTVerbosity=high ... For more complex analysis of build errors, the [MSBuild Binary and Structured Log Viewer](http://msbuildlog.com/) is highly recommended. diff --git a/nuget/readme.txt b/nuget/readme.txt index 049ab13b8..8d2681b6b 100644 --- a/nuget/readme.txt +++ b/nuget/readme.txt @@ -19,4 +19,7 @@ In addition, C++/WinRT generates templates and skeleton implementations for each ======================================================================== For more information, visit: https://github.com/Microsoft/cppwinrt/tree/master/nuget + +The full documentation is also included in this package as readme.md, and +the C++20 modules guide as modules.md. ======================================================================== diff --git a/prebuild/main.cpp b/prebuild/main.cpp index 3e427d32b..1295f8f69 100644 --- a/prebuild/main.cpp +++ b/prebuild/main.cpp @@ -77,12 +77,19 @@ namespace cppwinrt::strings { writer version_rc; + // Extract major.minor substrings from CPPWINRT_VERSION_STRING (e.g. "3.0.250316.1") + std::string_view const full_version{ CPPWINRT_VERSION_STRING }; + auto const first_dot = full_version.find('.'); + auto const second_dot = full_version.find('.', first_dot + 1); + auto const ver_major = full_version.substr(0, first_dot); + auto const ver_minor = full_version.substr(first_dot + 1, second_dot - first_dot - 1); + version_rc.write(R"( #include "winres.h" VS_VERSION_INFO VERSIONINFO - FILEVERSION 2,0,0,0 - PRODUCTVERSION 2,0,0,0 + FILEVERSION %,%,0,0 + PRODUCTVERSION %,%,0,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -99,7 +106,7 @@ BEGIN BEGIN VALUE "CompanyName", "Microsoft Corporation" VALUE "FileDescription", "C++/WinRT" - VALUE "FileVersion", "2.0.0.0" + VALUE "FileVersion", "%.%.0.0" VALUE "LegalCopyright", "Microsoft Corporation. All rights reserved." VALUE "OriginalFilename", "cppwinrt.exe" VALUE "ProductName", "C++/WinRT" @@ -112,7 +119,10 @@ BEGIN END END )", - CPPWINRT_VERSION_STRING); + ver_major, ver_minor, // FILEVERSION + ver_major, ver_minor, // PRODUCTVERSION + ver_major, ver_minor, // FileVersion string + CPPWINRT_VERSION_STRING); // ProductVersion string std::filesystem::create_directories(argv[2]); auto const output = std::filesystem::canonical(argv[2]); diff --git a/prebuild/prebuild.vcxproj b/prebuild/prebuild.vcxproj index 8308ae560..9fad91fd8 100644 --- a/prebuild/prebuild.vcxproj +++ b/prebuild/prebuild.vcxproj @@ -1,10 +1,6 @@ - - Debug - ARM - Debug ARM64 @@ -13,10 +9,6 @@ Debug Win32 - - Release - ARM - Release ARM64 @@ -44,10 +36,6 @@ Application true - - Application - true - Application true @@ -57,11 +45,6 @@ false true - - Application - false - true - Application false @@ -84,18 +67,12 @@ - - - - - - @@ -111,16 +88,8 @@ Disabled ..\cppwinrt MultiThreadedDebug - - - Console - - - - - Disabled - ..\cppwinrt - MultiThreadedDebug + Level4 + true Console @@ -131,6 +100,8 @@ Disabled ..\cppwinrt MultiThreadedDebug + Level4 + true Console @@ -141,6 +112,8 @@ Disabled ..\cppwinrt MultiThreadedDebug + Level4 + true Console @@ -153,20 +126,9 @@ true ..\cppwinrt MultiThreaded - - - Console - true - true - - - - - MaxSpeed - true - true - ..\cppwinrt - MultiThreaded + Guard + Level4 + true Console @@ -181,6 +143,9 @@ true ..\cppwinrt MultiThreaded + Guard + Level4 + true Console @@ -195,6 +160,9 @@ true ..\cppwinrt MultiThreaded + Guard + Level4 + true Console diff --git a/prepare_versionless_diffs.cmd b/prepare_versionless_diffs.cmd index 468645657..05cb6dd0b 100644 --- a/prepare_versionless_diffs.cmd +++ b/prepare_versionless_diffs.cmd @@ -12,7 +12,6 @@ if /I "%target_platform%" equ "all" ( ) call %0 x86 !target_configuration! call %0 x64 !target_configuration! - call %0 arm !target_configuration! call %0 arm64 !target_configuration! goto :eof ) diff --git a/run_tests.cmd b/run_tests.cmd index 77d883642..58e3c5524 100644 --- a/run_tests.cmd +++ b/run_tests.cmd @@ -9,6 +9,7 @@ if "%target_platform%"=="" set target_platform=x64 if "%target_configuration%"=="" set target_configuration=Debug call :run_test test +call :run_test test_nocoro call :run_test test_cpp20 call :run_test test_cpp20_no_sourcelocation call :run_test test_fast diff --git a/scratch/scratch.vcxproj b/scratch/scratch.vcxproj index 4a26617b4..84f6ce3d8 100644 --- a/scratch/scratch.vcxproj +++ b/scratch/scratch.vcxproj @@ -1,10 +1,7 @@ + - - Debug - ARM - Debug ARM64 @@ -13,10 +10,6 @@ Debug Win32 - - Release - ARM - Release ARM64 @@ -35,277 +28,69 @@ + true + true + true + true 16.0 {E893622C-47DE-4F83-B422-0A26711590A4} scratch scratch - - - - Application - true - - - Application - true - - - Application - true - - - Application - false - true - - - Application - false - true - - Application - false - true + + ..\_build\$(Platform)\$(Configuration) + false - - Application + + true - - Application + false true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - MaxSpeed - true - true - $(OutputPath);Generated Files;..\..\..\library - NOMINMAX;_MBCS;%(PreprocessorDefinitions) - %(AdditionalOptions) - MultiThreaded - - - Console - true - true - - - - - - - - - - - - - Disabled - $(OutputPath);Generated Files;..\..\..\library - _MBCS;%(PreprocessorDefinitions) - %(AdditionalOptions) - MultiThreadedDebug - - - Console - - - - - - - - - - - - - Disabled - $(OutputPath);Generated Files;..\..\..\library - _MBCS;%(PreprocessorDefinitions) - %(AdditionalOptions) - MultiThreadedDebug - - - Console - - - - - - - - - - - + - Disabled - $(OutputPath);Generated Files;..\..\..\library - _MBCS;%(PreprocessorDefinitions) - %(AdditionalOptions) - MultiThreadedDebug - - - Console - - - - - - - - - - - - - Disabled - $(OutputPath);Generated Files;..\..\..\library - _MBCS;%(PreprocessorDefinitions) - %(AdditionalOptions) - MultiThreadedDebug + $(OutputPath);Generated Files; + Level4 + true Console - - - - - - - - - + MaxSpeed true true - $(OutputPath);Generated Files;..\..\..\library NOMINMAX;_MBCS;%(PreprocessorDefinitions) - %(AdditionalOptions) MultiThreaded - Console true true - - - - - - - - - + - MaxSpeed - true - true - $(OutputPath);Generated Files;..\..\..\library - NOMINMAX;_MBCS;%(PreprocessorDefinitions) - %(AdditionalOptions) - MultiThreaded - - - Console - true - true - - - - - - - - - - - - - MaxSpeed - true - true - $(OutputPath);Generated Files;..\..\..\library - NOMINMAX;_MBCS;%(PreprocessorDefinitions) - %(AdditionalOptions) - MultiThreaded + Disabled + _MBCS;%(PreprocessorDefinitions) + MultiThreadedDebug - - Console - true - true - - - - - - - - - - NotUsing - Use - Use - Use - Use - Use - Use - Use - Use + Use - Create - Create - Create - Create - Create - Create - Create - Create + Create + + + diff --git a/strings/base_abi.h b/strings/base_abi.h index d1eab2950..4b7b8f77f 100644 --- a/strings/base_abi.h +++ b/strings/base_abi.h @@ -1,13 +1,13 @@ -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template <> struct abi { - struct WINRT_IMPL_NOVTABLE type + struct WINRT_IMPL_ABI_DECL type { - virtual int32_t __stdcall QueryInterface(guid const& id, void** object) noexcept = 0; - virtual uint32_t __stdcall AddRef() noexcept = 0; - virtual uint32_t __stdcall Release() noexcept = 0; + virtual std::int32_t __stdcall QueryInterface(guid const& id, void** object) noexcept = 0; + virtual std::uint32_t __stdcall AddRef() noexcept = 0; + virtual std::uint32_t __stdcall Release() noexcept = 0; }; }; @@ -15,11 +15,11 @@ namespace winrt::impl template <> struct abi { - struct WINRT_IMPL_NOVTABLE type : unknown_abi + struct WINRT_IMPL_ABI_DECL type : unknown_abi { - virtual int32_t __stdcall GetIids(uint32_t* count, guid** ids) noexcept = 0; - virtual int32_t __stdcall GetRuntimeClassName(void** name) noexcept = 0; - virtual int32_t __stdcall GetTrustLevel(Windows::Foundation::TrustLevel* level) noexcept = 0; + virtual std::int32_t __stdcall GetIids(std::uint32_t* count, guid** ids) noexcept = 0; + virtual std::int32_t __stdcall GetRuntimeClassName(void** name) noexcept = 0; + virtual std::int32_t __stdcall GetTrustLevel(Windows::Foundation::TrustLevel* level) noexcept = 0; }; }; @@ -27,119 +27,119 @@ namespace winrt::impl template <> struct abi { - struct WINRT_IMPL_NOVTABLE type : inspectable_abi + struct WINRT_IMPL_ABI_DECL type : inspectable_abi { - virtual int32_t __stdcall ActivateInstance(void** instance) noexcept = 0; + virtual std::int32_t __stdcall ActivateInstance(void** instance) noexcept = 0; }; }; - struct WINRT_IMPL_NOVTABLE IAgileObject : unknown_abi {}; + struct WINRT_IMPL_ABI_DECL IAgileObject : unknown_abi {}; - struct WINRT_IMPL_NOVTABLE IAgileReference : unknown_abi + struct WINRT_IMPL_ABI_DECL IAgileReference : unknown_abi { - virtual int32_t __stdcall Resolve(guid const& id, void** object) noexcept = 0; + virtual std::int32_t __stdcall Resolve(guid const& id, void** object) noexcept = 0; }; - struct WINRT_IMPL_NOVTABLE IMarshal : unknown_abi + struct WINRT_IMPL_ABI_DECL IMarshal : unknown_abi { - virtual int32_t __stdcall GetUnmarshalClass(guid const& riid, void* pv, uint32_t dwDestContext, void* pvDestContext, uint32_t mshlflags, guid* pCid) noexcept = 0; - virtual int32_t __stdcall GetMarshalSizeMax(guid const& riid, void* pv, uint32_t dwDestContext, void* pvDestContext, uint32_t mshlflags, uint32_t* pSize) noexcept = 0; - virtual int32_t __stdcall MarshalInterface(void* pStm, guid const& riid, void* pv, uint32_t dwDestContext, void* pvDestContext, uint32_t mshlflags) noexcept = 0; - virtual int32_t __stdcall UnmarshalInterface(void* pStm, guid const& riid, void** ppv) noexcept = 0; - virtual int32_t __stdcall ReleaseMarshalData(void* pStm) noexcept = 0; - virtual int32_t __stdcall DisconnectObject(uint32_t dwReserved) noexcept = 0; + virtual std::int32_t __stdcall GetUnmarshalClass(guid const& riid, void* pv, std::uint32_t dwDestContext, void* pvDestContext, std::uint32_t mshlflags, guid* pCid) noexcept = 0; + virtual std::int32_t __stdcall GetMarshalSizeMax(guid const& riid, void* pv, std::uint32_t dwDestContext, void* pvDestContext, std::uint32_t mshlflags, std::uint32_t* pSize) noexcept = 0; + virtual std::int32_t __stdcall MarshalInterface(void* pStm, guid const& riid, void* pv, std::uint32_t dwDestContext, void* pvDestContext, std::uint32_t mshlflags) noexcept = 0; + virtual std::int32_t __stdcall UnmarshalInterface(void* pStm, guid const& riid, void** ppv) noexcept = 0; + virtual std::int32_t __stdcall ReleaseMarshalData(void* pStm) noexcept = 0; + virtual std::int32_t __stdcall DisconnectObject(std::uint32_t dwReserved) noexcept = 0; }; - struct WINRT_IMPL_NOVTABLE IGlobalInterfaceTable : unknown_abi + struct WINRT_IMPL_ABI_DECL IGlobalInterfaceTable : unknown_abi { - virtual int32_t __stdcall RegisterInterfaceInGlobal(void* object, guid const& iid, uint32_t* cookie) noexcept = 0; - virtual int32_t __stdcall RevokeInterfaceFromGlobal(uint32_t cookie) noexcept = 0; - virtual int32_t __stdcall GetInterfaceFromGlobal(uint32_t cookie, guid const& iid, void** object) noexcept = 0; + virtual std::int32_t __stdcall RegisterInterfaceInGlobal(void* object, guid const& iid, std::uint32_t* cookie) noexcept = 0; + virtual std::int32_t __stdcall RevokeInterfaceFromGlobal(std::uint32_t cookie) noexcept = 0; + virtual std::int32_t __stdcall GetInterfaceFromGlobal(std::uint32_t cookie, guid const& iid, void** object) noexcept = 0; }; - struct WINRT_IMPL_NOVTABLE IStaticLifetime : inspectable_abi + struct WINRT_IMPL_ABI_DECL IStaticLifetime : inspectable_abi { - virtual int32_t __stdcall unused() noexcept = 0; - virtual int32_t __stdcall GetCollection(void** value) noexcept = 0; + virtual std::int32_t __stdcall unused() noexcept = 0; + virtual std::int32_t __stdcall GetCollection(void** value) noexcept = 0; }; - struct WINRT_IMPL_NOVTABLE IStaticLifetimeCollection : inspectable_abi + struct WINRT_IMPL_ABI_DECL IStaticLifetimeCollection : inspectable_abi { - virtual int32_t __stdcall Lookup(void*, void**) noexcept = 0; - virtual int32_t __stdcall unused() noexcept = 0; - virtual int32_t __stdcall unused2() noexcept = 0; - virtual int32_t __stdcall unused3() noexcept = 0; - virtual int32_t __stdcall Insert(void*, void*, bool*) noexcept = 0; - virtual int32_t __stdcall Remove(void*) noexcept = 0; - virtual int32_t __stdcall unused4() noexcept = 0; + virtual std::int32_t __stdcall Lookup(void*, void**) noexcept = 0; + virtual std::int32_t __stdcall unused() noexcept = 0; + virtual std::int32_t __stdcall unused2() noexcept = 0; + virtual std::int32_t __stdcall unused3() noexcept = 0; + virtual std::int32_t __stdcall Insert(void*, void*, bool*) noexcept = 0; + virtual std::int32_t __stdcall Remove(void*) noexcept = 0; + virtual std::int32_t __stdcall unused4() noexcept = 0; }; - struct WINRT_IMPL_NOVTABLE IWeakReference : unknown_abi + struct WINRT_IMPL_ABI_DECL IWeakReference : unknown_abi { - virtual int32_t __stdcall Resolve(guid const& iid, void** objectReference) noexcept = 0; + virtual std::int32_t __stdcall Resolve(guid const& iid, void** objectReference) noexcept = 0; }; - struct WINRT_IMPL_NOVTABLE IWeakReferenceSource : unknown_abi + struct WINRT_IMPL_ABI_DECL IWeakReferenceSource : unknown_abi { - virtual int32_t __stdcall GetWeakReference(IWeakReference** weakReference) noexcept = 0; + virtual std::int32_t __stdcall GetWeakReference(IWeakReference** weakReference) noexcept = 0; }; - struct WINRT_IMPL_NOVTABLE IRestrictedErrorInfo : unknown_abi + struct WINRT_IMPL_ABI_DECL IRestrictedErrorInfo : unknown_abi { - virtual int32_t __stdcall GetErrorDetails(bstr* description, int32_t* error, bstr* restrictedDescription, bstr* capabilitySid) noexcept = 0; - virtual int32_t __stdcall GetReference(bstr* reference) noexcept = 0; + virtual std::int32_t __stdcall GetErrorDetails(bstr* description, std::int32_t* error, bstr* restrictedDescription, bstr* capabilitySid) noexcept = 0; + virtual std::int32_t __stdcall GetReference(bstr* reference) noexcept = 0; }; - struct WINRT_IMPL_NOVTABLE IErrorInfo : unknown_abi + struct WINRT_IMPL_ABI_DECL IErrorInfo : unknown_abi { - virtual int32_t __stdcall GetGUID(guid* value) noexcept = 0; - virtual int32_t __stdcall GetSource(bstr* value) noexcept = 0; - virtual int32_t __stdcall GetDescription(bstr* value) noexcept = 0; - virtual int32_t __stdcall GetHelpFile(bstr* value) noexcept = 0; - virtual int32_t __stdcall GetHelpContext(uint32_t* value) noexcept = 0; + virtual std::int32_t __stdcall GetGUID(guid* value) noexcept = 0; + virtual std::int32_t __stdcall GetSource(bstr* value) noexcept = 0; + virtual std::int32_t __stdcall GetDescription(bstr* value) noexcept = 0; + virtual std::int32_t __stdcall GetHelpFile(bstr* value) noexcept = 0; + virtual std::int32_t __stdcall GetHelpContext(std::uint32_t* value) noexcept = 0; }; - struct WINRT_IMPL_NOVTABLE ILanguageExceptionErrorInfo2 : unknown_abi + struct WINRT_IMPL_ABI_DECL ILanguageExceptionErrorInfo2 : unknown_abi { - virtual int32_t __stdcall GetLanguageException(void** exception) noexcept = 0; - virtual int32_t __stdcall GetPreviousLanguageExceptionErrorInfo(ILanguageExceptionErrorInfo2** previous) noexcept = 0; - virtual int32_t __stdcall CapturePropagationContext(void* exception) noexcept = 0; - virtual int32_t __stdcall GetPropagationContextHead(ILanguageExceptionErrorInfo2** head) noexcept = 0; + virtual std::int32_t __stdcall GetLanguageException(void** exception) noexcept = 0; + virtual std::int32_t __stdcall GetPreviousLanguageExceptionErrorInfo(ILanguageExceptionErrorInfo2** previous) noexcept = 0; + virtual std::int32_t __stdcall CapturePropagationContext(void* exception) noexcept = 0; + virtual std::int32_t __stdcall GetPropagationContextHead(ILanguageExceptionErrorInfo2** head) noexcept = 0; }; struct ICallbackWithNoReentrancyToApplicationSTA; - struct WINRT_IMPL_NOVTABLE IContextCallback : unknown_abi + struct WINRT_IMPL_ABI_DECL IContextCallback : unknown_abi { - virtual int32_t __stdcall ContextCallback(int32_t(__stdcall* callback)(com_callback_args*), com_callback_args* args, guid const& iid, int method, void* reserved) noexcept = 0; + virtual std::int32_t __stdcall ContextCallback(std::int32_t(__stdcall* callback)(com_callback_args*), com_callback_args* args, guid const& iid, int method, void* reserved) noexcept = 0; }; - struct WINRT_IMPL_NOVTABLE IServerSecurity : unknown_abi + struct WINRT_IMPL_ABI_DECL IServerSecurity : unknown_abi { - virtual int32_t __stdcall QueryBlanket(uint32_t*, uint32_t*, wchar_t**, uint32_t*, uint32_t*, void**, uint32_t*) noexcept = 0; - virtual int32_t __stdcall ImpersonateClient() noexcept = 0; - virtual int32_t __stdcall RevertToSelf() noexcept = 0; - virtual int32_t __stdcall IsImpersonating() noexcept = 0; + virtual std::int32_t __stdcall QueryBlanket(std::uint32_t*, std::uint32_t*, wchar_t**, std::uint32_t*, std::uint32_t*, void**, std::uint32_t*) noexcept = 0; + virtual std::int32_t __stdcall ImpersonateClient() noexcept = 0; + virtual std::int32_t __stdcall RevertToSelf() noexcept = 0; + virtual std::int32_t __stdcall IsImpersonating() noexcept = 0; }; - struct WINRT_IMPL_NOVTABLE IBufferByteAccess : unknown_abi + struct WINRT_IMPL_ABI_DECL IBufferByteAccess : unknown_abi { - virtual int32_t __stdcall Buffer(uint8_t** value) noexcept = 0; + virtual std::int32_t __stdcall Buffer(std::uint8_t** value) noexcept = 0; }; - struct WINRT_IMPL_NOVTABLE IMemoryBufferByteAccess : unknown_abi + struct WINRT_IMPL_ABI_DECL IMemoryBufferByteAccess : unknown_abi { - virtual int32_t __stdcall GetBuffer(uint8_t** value, uint32_t* capacity) noexcept = 0; + virtual std::int32_t __stdcall GetBuffer(std::uint8_t** value, std::uint32_t* capacity) noexcept = 0; }; template <> struct abi { - using type = int64_t; + using type = std::int64_t; }; template <> struct abi { - using type = int64_t; + using type = std::int64_t; }; template <> inline constexpr guid guid_v{ 0x00000000, 0x0000, 0x0000, { 0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46 } }; diff --git a/strings/base_activation.h b/strings/base_activation.h index bb6be5ca1..c657c692d 100644 --- a/strings/base_activation.h +++ b/strings/base_activation.h @@ -1,5 +1,5 @@ -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { struct library_traits { @@ -30,7 +30,7 @@ namespace winrt::impl if (hr == impl::error_not_initialized) { - auto usage = reinterpret_cast(WINRT_IMPL_GetProcAddress(load_library(L"combase.dll"), "CoIncrementMTAUsage")); + auto usage = reinterpret_cast(WINRT_IMPL_GetProcAddress(load_library(L"combase.dll"), "CoIncrementMTAUsage")); if (!usage) { @@ -65,7 +65,7 @@ namespace winrt::impl continue; } - auto library_call = reinterpret_cast(WINRT_IMPL_GetProcAddress(library.get(), "DllGetActivationFactory")); + auto library_call = reinterpret_cast(WINRT_IMPL_GetProcAddress(library.get(), "DllGetActivationFactory")); if (!library_call) { @@ -119,27 +119,25 @@ WINRT_EXPORT namespace winrt #pragma clang diagnostic ignored "-Wdeprecated-declarations" #endif -#if defined(__GNUC__) && (defined(__arm__) || defined(__aarch64__)) +#if defined(__GNUC__) && defined(__aarch64__) #define WINRT_IMPL_INTERLOCKED_READ_MEMORY_BARRIER __asm__ __volatile__ ("dmb ish"); -#elif defined _M_ARM -#define WINRT_IMPL_INTERLOCKED_READ_MEMORY_BARRIER (__dmb(_ARM_BARRIER_ISH)); #elif defined _M_ARM64 #define WINRT_IMPL_INTERLOCKED_READ_MEMORY_BARRIER (__dmb(_ARM64_BARRIER_ISH)); #endif -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { - inline int32_t interlocked_read_32(int32_t const volatile* target) noexcept + inline std::int32_t interlocked_read_32(std::int32_t const volatile* target) noexcept { #if defined _M_IX86 || defined _M_X64 - int32_t const result = *target; + std::int32_t const result = *target; _ReadWriteBarrier(); return result; -#elif defined _M_ARM || defined _M_ARM64 +#elif defined _M_ARM64 #if defined(__GNUC__) - int32_t const result = *target; + std::int32_t const result = *target; #else - int32_t const result = __iso_volatile_load32(reinterpret_cast(target)); + std::int32_t const result = __iso_volatile_load32(reinterpret_cast(target)); #endif WINRT_IMPL_INTERLOCKED_READ_MEMORY_BARRIER return result; @@ -149,17 +147,17 @@ namespace winrt::impl } #if defined _WIN64 - inline int64_t interlocked_read_64(int64_t const volatile* target) noexcept + inline std::int64_t interlocked_read_64(std::int64_t const volatile* target) noexcept { #if defined _M_X64 - int64_t const result = *target; + std::int64_t const result = *target; _ReadWriteBarrier(); return result; #elif defined _M_ARM64 #if defined(__GNUC__) - int64_t const result = *target; + std::int64_t const result = *target; #else - int64_t const result = __iso_volatile_load64(target); + std::int64_t const result = __iso_volatile_load64(target); #endif WINRT_IMPL_INTERLOCKED_READ_MEMORY_BARRIER return result; @@ -179,14 +177,14 @@ namespace winrt::impl T* interlocked_read_pointer(T* const volatile* target) noexcept { #ifdef _WIN64 - return (T*)interlocked_read_64((int64_t*)target); + return (T*)interlocked_read_64((std::int64_t*)target); #else - return (T*)interlocked_read_32((int32_t*)target); + return (T*)interlocked_read_32((std::int32_t*)target); #endif } #ifdef _WIN64 - inline constexpr uint32_t memory_allocation_alignment{ 16 }; + inline constexpr std::uint32_t memory_allocation_alignment{ 16 }; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable:4324) // structure was padded due to alignment specifier @@ -199,34 +197,34 @@ namespace winrt::impl { struct { - uint64_t reserved1; - uint64_t reserved2; + std::uint64_t reserved1; + std::uint64_t reserved2; } reserved1; struct { - uint64_t reserved1 : 16; - uint64_t reserved2 : 48; - uint64_t reserved3 : 4; - uint64_t reserved4 : 60; + std::uint64_t reserved1 : 16; + std::uint64_t reserved2 : 48; + std::uint64_t reserved3 : 4; + std::uint64_t reserved4 : 60; } reserved2; }; #ifdef _MSC_VER #pragma warning(pop) #endif #else - inline constexpr uint32_t memory_allocation_alignment{ 8 }; + inline constexpr std::uint32_t memory_allocation_alignment{ 8 }; struct slist_entry { slist_entry* next; }; union slist_header { - uint64_t reserved1; + std::uint64_t reserved1; struct { slist_entry reserved1; - uint16_t reserved2; - uint16_t reserved3; + std::uint16_t reserved2; + std::uint16_t reserved3; } reserved2; }; #endif @@ -236,11 +234,11 @@ namespace winrt::impl factory_count_guard(factory_count_guard const&) = delete; factory_count_guard& operator=(factory_count_guard const&) = delete; - explicit factory_count_guard(size_t& count) noexcept : m_count(count) + explicit factory_count_guard(std::size_t& count) noexcept : m_count(count) { #ifndef WINRT_NO_MODULE_LOCK #ifdef _WIN64 - _InterlockedIncrement64((int64_t*)&m_count); + _InterlockedIncrement64((std::int64_t*)&m_count); #else _InterlockedIncrement((long*)&m_count); #endif @@ -251,7 +249,7 @@ namespace winrt::impl { #ifndef WINRT_NO_MODULE_LOCK #ifdef _WIN64 - _InterlockedDecrement64((int64_t*)&m_count); + _InterlockedDecrement64((std::int64_t*)&m_count); #else _InterlockedDecrement((long*)&m_count); #endif @@ -259,8 +257,7 @@ namespace winrt::impl } private: - - size_t& m_count; + [[maybe_unused]] std::size_t& m_count; // Field is unused when WINRT_NO_MODULE_LOCK is defined. }; struct factory_cache_entry_base @@ -268,7 +265,7 @@ namespace winrt::impl struct alignas(sizeof(void*) * 2) object_and_count { unknown_abi* object; - size_t count; + std::size_t count; }; object_and_count m_value; @@ -289,16 +286,16 @@ namespace winrt::impl #if defined(__GNUC__) bool exchanged = __sync_bool_compare_and_swap((__int128*)this, *(__int128*)¤t_value, (__int128)0); #else - bool exchanged = 1 == _InterlockedCompareExchange128((int64_t*)this, 0, 0, (int64_t*)¤t_value); + bool exchanged = 1 == _InterlockedCompareExchange128((std::int64_t*)this, 0, 0, (std::int64_t*)¤t_value); #endif if (exchanged) { pointer_value->Release(); } #else - int64_t const result = _InterlockedCompareExchange64((int64_t*)this, 0, *(int64_t*)¤t_value); + std::int64_t const result = _InterlockedCompareExchange64((std::int64_t*)this, 0, *(std::int64_t*)¤t_value); - if (result == *(int64_t*)¤t_value) + if (result == *(std::int64_t*)¤t_value) { pointer_value->Release(); } @@ -308,7 +305,7 @@ namespace winrt::impl static_assert(std::is_standard_layout_v); -#if !defined _M_IX86 && !defined _M_X64 && !defined _M_ARM && !defined _M_ARM64 +#if !defined _M_IX86 && !defined _M_X64 && !defined _M_ARM64 #error Unsupported architecture: verify that zero-initialization of SLIST_HEADER is still safe #endif @@ -333,7 +330,7 @@ namespace winrt::impl // entry->next must be read before entry->clear() is called since the InterlockedCompareExchange // inside clear() will allow another thread to add the entry back to the cache. slist_entry* next = entry->next; - reinterpret_cast(reinterpret_cast(entry) - offsetof(factory_cache_entry_base, m_next))->clear(); + reinterpret_cast(reinterpret_cast(entry) - offsetof(factory_cache_entry_base, m_next))->clear(); entry = next; } } @@ -446,7 +443,7 @@ namespace winrt::impl template struct produce : produce_base { - int32_t __stdcall ActivateInstance(void** instance) noexcept final try + std::int32_t __stdcall ActivateInstance(void** instance) noexcept final try { *instance = nullptr; typename D::abi_guard guard(this->shim()); @@ -459,7 +456,7 @@ namespace winrt::impl WINRT_EXPORT namespace winrt { - enum class apartment_type : int32_t + enum class apartment_type : std::int32_t { multi_threaded = 0, single_threaded = 2, @@ -467,7 +464,7 @@ WINRT_EXPORT namespace winrt inline void init_apartment(apartment_type const type = apartment_type::multi_threaded) { - hresult const result = WINRT_IMPL_CoInitializeEx(nullptr, static_cast(type)); + hresult const result = WINRT_IMPL_CoInitializeEx(nullptr, static_cast(type)); if (result < 0) { @@ -522,13 +519,13 @@ WINRT_EXPORT namespace winrt } template - auto try_create_instance(guid const& clsid, uint32_t context = 0x1 /*CLSCTX_INPROC_SERVER*/, void* outer = nullptr) + auto try_create_instance(guid const& clsid, std::uint32_t context = 0x1 /*CLSCTX_INPROC_SERVER*/, void* outer = nullptr) { return try_capture(WINRT_IMPL_CoCreateInstance, clsid, outer, context); } template - auto create_instance(guid const& clsid, uint32_t context = 0x1 /*CLSCTX_INPROC_SERVER*/, void* outer = nullptr) + auto create_instance(guid const& clsid, std::uint32_t context = 0x1 /*CLSCTX_INPROC_SERVER*/, void* outer = nullptr) { return capture(WINRT_IMPL_CoCreateInstance, clsid, outer, context); } @@ -551,7 +548,7 @@ WINRT_EXPORT namespace winrt } } -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template T fast_activate(Windows::Foundation::IActivationFactory const& factory) diff --git a/strings/base_agile_ref.h b/strings/base_agile_ref.h index b85cb7e61..14447706a 100644 --- a/strings/base_agile_ref.h +++ b/strings/base_agile_ref.h @@ -10,12 +10,12 @@ WINRT_EXPORT namespace winrt { struct lock { - constexpr uint32_t operator++() noexcept + constexpr std::uint32_t operator++() noexcept { return 1; } - constexpr uint32_t operator--() noexcept + constexpr std::uint32_t operator--() noexcept { return 0; } @@ -47,7 +47,7 @@ WINRT_EXPORT namespace winrt #endif } -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template struct module_lock_updater; diff --git a/strings/base_array.h b/strings/base_array.h index a4f570614..d29bee883 100644 --- a/strings/base_array.h +++ b/strings/base_array.h @@ -5,7 +5,7 @@ WINRT_EXPORT namespace winrt struct array_view { using value_type = T; - using size_type = uint32_t; + using size_type = std::uint32_t; using reference = value_type&; using const_reference = value_type const&; using pointer = value_type*; @@ -32,11 +32,11 @@ WINRT_EXPORT namespace winrt {} #ifdef __cpp_lib_span - template + template array_view(std::span span) noexcept : array_view(span.data(), static_cast(span.size())) { - WINRT_ASSERT(span.size() <= UINT_MAX); + WINRT_ASSERT(span.size() <= (std::numeric_limits::max)()); } operator std::span() const noexcept @@ -62,12 +62,12 @@ WINRT_EXPORT namespace winrt { } - template + template array_view(std::array& value) noexcept : array_view(value.data(), static_cast(value.size())) {} - template + template array_view(std::array const& value) noexcept : array_view(value.data(), static_cast(value.size())) {} @@ -231,15 +231,15 @@ WINRT_EXPORT namespace winrt } }; - template array_view(C(&value)[N]) -> array_view; + template array_view(C(&value)[N]) -> array_view; template array_view(std::vector& value) -> array_view; template array_view(std::vector const& value) -> array_view; - template array_view(std::array& value) -> array_view; - template array_view(std::array const& value) -> array_view; + template array_view(std::array& value) -> array_view; + template array_view(std::array const& value) -> array_view; #ifdef __cpp_lib_span - template array_view(std::span& value) -> array_view; - template array_view(std::span const& value) -> array_view; + template array_view(std::span& value) -> array_view; + template array_view(std::span const& value) -> array_view; #endif template @@ -265,7 +265,7 @@ WINRT_EXPORT namespace winrt com_array(count, value_type()) {} - com_array(void* ptr, uint32_t const count, take_ownership_from_abi_t) noexcept : + com_array(void* ptr, std::uint32_t const count, take_ownership_from_abi_t) noexcept : array_view(static_cast(ptr), static_cast(ptr) + count) { } @@ -288,21 +288,21 @@ WINRT_EXPORT namespace winrt com_array(value.begin(), value.end()) {} - template + template explicit com_array(std::array const& value) : com_array(value.begin(), value.end()) {} #ifdef __cpp_lib_span - template + template explicit com_array(std::span span) noexcept : com_array(span.data(), span.data() + span.size()) { - WINRT_ASSERT(span.size() <= UINT_MAX); + WINRT_ASSERT(span.size() <= (std::numeric_limits::max)()); } #endif - template + template explicit com_array(U const(&value)[N]) : com_array(value, value + N) {} @@ -374,17 +374,17 @@ WINRT_EXPORT namespace winrt } } - std::pair> detach_abi() noexcept + std::pair> detach_abi() noexcept { -#ifdef _MSC_VER +#if defined(_MSC_VER) && !defined(__clang__) // https://github.com/microsoft/cppwinrt/pull/1165 - std::pair> result; - memset(&result, 0, sizeof(result)); + std::pair> result; + std::memset(&result, 0, sizeof(result)); result.first = this->size(); result.second = *reinterpret_cast*>(this); - memset(this, 0, sizeof(com_array)); + std::memset(this, 0, sizeof(com_array)); #else - std::pair> result(this->size(), *reinterpret_cast*>(this)); + std::pair> result(this->size(), *reinterpret_cast*>(this)); this->m_data = nullptr; this->m_size = 0; #endif @@ -392,19 +392,19 @@ WINRT_EXPORT namespace winrt } template - friend std::pair> detach_abi(com_array& object) noexcept; + friend std::pair> detach_abi(com_array& object) noexcept; }; - template com_array(uint32_t, C const&) -> com_array>; + template com_array(std::uint32_t, C const&) -> com_array>; template ::difference_type>> com_array(InIt, InIt) -> com_array::value_type>>; template com_array(std::vector const&) -> com_array>; - template com_array(std::array const&) -> com_array>; - template com_array(C const(&)[N]) -> com_array>; + template com_array(std::array const&) -> com_array>; + template com_array(C const(&)[N]) -> com_array>; template com_array(std::initializer_list) -> com_array>; #ifdef __cpp_lib_span - template com_array(std::span const& value) -> com_array>; + template com_array(std::span const& value) -> com_array>; #endif @@ -471,7 +471,7 @@ WINRT_EXPORT namespace winrt } template - std::pair> detach_abi(com_array& object) noexcept + std::pair> detach_abi(com_array& object) noexcept { return object.detach_abi(); } @@ -483,7 +483,7 @@ WINRT_EXPORT namespace winrt } } -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template struct array_size_proxy @@ -496,10 +496,10 @@ namespace winrt::impl ~array_size_proxy() noexcept { WINRT_ASSERT(m_value.data() || (!m_value.data() && m_size == 0)); - *reinterpret_cast(reinterpret_cast(&m_value) + 1) = m_size; + *reinterpret_cast(reinterpret_cast(&m_value) + 1) = m_size; } - operator uint32_t*() noexcept + operator std::uint32_t*() noexcept { return &m_size; } @@ -512,7 +512,7 @@ namespace winrt::impl private: com_array& m_value; - uint32_t m_size{ 0 }; + std::uint32_t m_size{ 0 }; }; template @@ -524,7 +524,7 @@ namespace winrt::impl template struct com_array_proxy { - com_array_proxy(uint32_t* size, winrt::impl::arg_out* value) noexcept : m_size(size), m_value(value) + com_array_proxy(std::uint32_t* size, winrt::impl::arg_out* value) noexcept : m_size(size), m_value(value) {} ~com_array_proxy() noexcept @@ -545,7 +545,7 @@ namespace winrt::impl private: - uint32_t* m_size; + std::uint32_t* m_size; arg_out* m_value; com_array m_temp; }; @@ -554,7 +554,7 @@ namespace winrt::impl WINRT_EXPORT namespace winrt { template - auto detach_abi(uint32_t* __valueSize, impl::arg_out* value) noexcept + auto detach_abi(std::uint32_t* __valueSize, impl::arg_out* value) noexcept { return impl::com_array_proxy(__valueSize, value); } diff --git a/strings/base_chrono.h b/strings/base_chrono.h index d48cd703b..7934ac5b2 100644 --- a/strings/base_chrono.h +++ b/strings/base_chrono.h @@ -3,17 +3,17 @@ WINRT_EXPORT namespace winrt { struct file_time { - uint64_t value{}; + std::uint64_t value{}; file_time() noexcept = default; - constexpr explicit file_time(uint64_t const value) noexcept : value(value) + constexpr explicit file_time(std::uint64_t const value) noexcept : value(value) { } #ifdef _FILETIME_ constexpr file_time(FILETIME const& value) noexcept - : value(value.dwLowDateTime | (static_cast(value.dwHighDateTime) << 32)) + : value(value.dwLowDateTime | (static_cast(value.dwHighDateTime) << 32)) { } @@ -26,7 +26,7 @@ WINRT_EXPORT namespace winrt struct clock { - using rep = int64_t; + using rep = std::int64_t; using period = impl::filetime_period; using duration = Windows::Foundation::TimeSpan; using time_point = Windows::Foundation::DateTime; @@ -52,7 +52,7 @@ WINRT_EXPORT namespace winrt static file_time to_file_time(time_point const& time) noexcept { - return file_time{ static_cast(time.time_since_epoch().count()) }; + return file_time{ static_cast(time.time_since_epoch().count()) }; } static time_point from_file_time(file_time const& time) noexcept diff --git a/strings/base_collections.h b/strings/base_collections.h index cba0864b3..7d8dc2e77 100644 --- a/strings/base_collections.h +++ b/strings/base_collections.h @@ -1,5 +1,5 @@ -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { namespace wfc = Windows::Foundation::Collections; @@ -101,10 +101,10 @@ namespace winrt::impl private: - uint32_t const m_snapshot; + std::uint32_t const m_snapshot; }; - uint32_t get_version() const noexcept + std::uint32_t get_version() const noexcept { return m_version; } @@ -116,7 +116,7 @@ namespace winrt::impl private: - std::atomic m_version{}; + std::atomic m_version{}; }; template diff --git a/strings/base_collections_base.h b/strings/base_collections_base.h index b2d58f602..d299cc0c8 100644 --- a/strings/base_collections_base.h +++ b/strings/base_collections_base.h @@ -1,4 +1,4 @@ -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { struct nop_lock_guard {}; @@ -108,7 +108,7 @@ WINRT_EXPORT namespace winrt auto First() { // NOTE: iterator's constructor requires shared access - auto guard = static_cast(*this).acquire_shared(); + [[maybe_unused]] auto guard = static_cast(*this).acquire_shared(); return make(static_cast(this)); } @@ -161,7 +161,7 @@ WINRT_EXPORT namespace winrt T Current() const { - auto guard = m_owner->acquire_shared(); + [[maybe_unused]] auto guard = m_owner->acquire_shared(); this->check_version(*m_owner); if (m_current == m_end) @@ -174,14 +174,14 @@ WINRT_EXPORT namespace winrt bool HasCurrent() const { - auto guard = m_owner->acquire_shared(); + [[maybe_unused]] auto guard = m_owner->acquire_shared(); this->check_version(*m_owner); return m_current != m_end; } bool MoveNext() { - auto guard = m_owner->acquire_exclusive(); + [[maybe_unused]] auto guard = m_owner->acquire_exclusive(); this->check_version(*m_owner); if (m_current != m_end) { @@ -191,9 +191,9 @@ WINRT_EXPORT namespace winrt return m_current != m_end; } - uint32_t GetMany(array_view values) + std::uint32_t GetMany(array_view values) { - auto guard = m_owner->acquire_exclusive(); + [[maybe_unused]] auto guard = m_owner->acquire_exclusive(); this->check_version(*m_owner); return GetMany(values, typename std::iterator_traits::iterator_category()); } @@ -213,15 +213,15 @@ WINRT_EXPORT namespace winrt } } - uint32_t GetMany(array_view values, std::random_access_iterator_tag) + std::uint32_t GetMany(array_view values, std::random_access_iterator_tag) { - uint32_t const actual = (std::min)(static_cast(m_end - m_current), values.size()); + std::uint32_t const actual = (std::min)(static_cast(m_end - m_current), values.size()); m_owner->copy_n(m_current, actual, values.begin()); m_current += actual; return actual; } - uint32_t GetMany(array_view values, std::input_iterator_tag) + std::uint32_t GetMany(array_view values, std::input_iterator_tag) { auto output = values.begin(); @@ -232,7 +232,7 @@ WINRT_EXPORT namespace winrt ++m_current; } - return static_cast(output - values.begin()); + return static_cast(output - values.begin()); } using iterator_type = decltype(std::declval().get_container().begin()); @@ -246,9 +246,9 @@ WINRT_EXPORT namespace winrt template struct vector_view_base : iterable_base { - T GetAt(uint32_t const index) const + T GetAt(std::uint32_t const index) const { - auto guard = static_cast(*this).acquire_shared(); + [[maybe_unused]] auto guard = static_cast(*this).acquire_shared(); if (index >= container_size()) { throw hresult_out_of_bounds(); @@ -257,42 +257,42 @@ WINRT_EXPORT namespace winrt return static_cast(*this).unwrap_value(*std::next(static_cast(*this).get_container().begin(), index)); } - uint32_t Size() const noexcept + std::uint32_t Size() const noexcept { - auto guard = static_cast(*this).acquire_shared(); + [[maybe_unused]] auto guard = static_cast(*this).acquire_shared(); return container_size(); } - bool IndexOf(T const& value, uint32_t& index) const noexcept + bool IndexOf(T const& value, std::uint32_t& index) const noexcept { - auto guard = static_cast(*this).acquire_shared(); + [[maybe_unused]] auto guard = static_cast(*this).acquire_shared(); auto first = std::find_if(static_cast(*this).get_container().begin(), static_cast(*this).get_container().end(), [&](auto&& match) { return value == static_cast(*this).unwrap_value(match); }); - index = static_cast(first - static_cast(*this).get_container().begin()); + index = static_cast(first - static_cast(*this).get_container().begin()); return index < container_size(); } - uint32_t GetMany(uint32_t const startIndex, array_view values) const + std::uint32_t GetMany(std::uint32_t const startIndex, array_view values) const { - auto guard = static_cast(*this).acquire_shared(); + [[maybe_unused]] auto guard = static_cast(*this).acquire_shared(); if (startIndex >= container_size()) { return 0; } - uint32_t const actual = (std::min)(container_size() - startIndex, values.size()); + std::uint32_t const actual = (std::min)(container_size() - startIndex, values.size()); this->copy_n(static_cast(*this).get_container().begin() + startIndex, actual, values.begin()); return actual; } private: - uint32_t container_size() const noexcept + std::uint32_t container_size() const noexcept { - return static_cast(std::distance(static_cast(*this).get_container().begin(), static_cast(*this).get_container().end())); + return static_cast(std::distance(static_cast(*this).get_container().begin(), static_cast(*this).get_container().end())); } }; @@ -304,11 +304,11 @@ WINRT_EXPORT namespace winrt return static_cast(*this); } - void SetAt(uint32_t const index, T const& value) + void SetAt(std::uint32_t const index, T const& value) { impl::removed_value::value_type> oldValue; - auto guard = static_cast(*this).acquire_exclusive(); + [[maybe_unused]] auto guard = static_cast(*this).acquire_exclusive(); if (index >= static_cast(*this).get_container().size()) { throw hresult_out_of_bounds(); @@ -320,9 +320,9 @@ WINRT_EXPORT namespace winrt pos = static_cast(*this).wrap_value(value); } - void InsertAt(uint32_t const index, T const& value) + void InsertAt(std::uint32_t const index, T const& value) { - auto guard = static_cast(*this).acquire_exclusive(); + [[maybe_unused]] auto guard = static_cast(*this).acquire_exclusive(); if (index > static_cast(*this).get_container().size()) { throw hresult_out_of_bounds(); @@ -332,11 +332,11 @@ WINRT_EXPORT namespace winrt static_cast(*this).get_container().insert(static_cast(*this).get_container().begin() + index, static_cast(*this).wrap_value(value)); } - void RemoveAt(uint32_t const index) + void RemoveAt(std::uint32_t const index) { impl::removed_value::value_type> removedValue; - auto guard = static_cast(*this).acquire_exclusive(); + [[maybe_unused]] auto guard = static_cast(*this).acquire_exclusive(); if (index >= static_cast(*this).get_container().size()) { throw hresult_out_of_bounds(); @@ -350,7 +350,7 @@ WINRT_EXPORT namespace winrt void Append(T const& value) { - auto guard = static_cast(*this).acquire_exclusive(); + [[maybe_unused]] auto guard = static_cast(*this).acquire_exclusive(); this->increment_version(); static_cast(*this).get_container().push_back(static_cast(*this).wrap_value(value)); } @@ -359,7 +359,7 @@ WINRT_EXPORT namespace winrt { impl::removed_value::value_type> removedValue; - auto guard = static_cast(*this).acquire_exclusive(); + [[maybe_unused]] auto guard = static_cast(*this).acquire_exclusive(); if (static_cast(*this).get_container().empty()) { throw hresult_out_of_bounds(); @@ -374,7 +374,7 @@ WINRT_EXPORT namespace winrt { impl::removed_values oldContainer; - auto guard = static_cast(*this).acquire_exclusive(); + [[maybe_unused]] auto guard = static_cast(*this).acquire_exclusive(); this->increment_version(); oldContainer.assign(static_cast(*this).get_container()); } @@ -383,7 +383,7 @@ WINRT_EXPORT namespace winrt { impl::removed_values oldContainer; - auto guard = static_cast(*this).acquire_exclusive(); + [[maybe_unused]] auto guard = static_cast(*this).acquire_exclusive(); this->increment_version(); oldContainer.assign(static_cast(*this).get_container()); assign(value.begin(), value.end()); @@ -425,19 +425,19 @@ WINRT_EXPORT namespace winrt m_changed.remove(cookie); } - void SetAt(uint32_t const index, T const& value) + void SetAt(std::uint32_t const index, T const& value) { vector_base::SetAt(index, value); call_changed(Windows::Foundation::Collections::CollectionChange::ItemChanged, index); } - void InsertAt(uint32_t const index, T const& value) + void InsertAt(std::uint32_t const index, T const& value) { vector_base::InsertAt(index, value); call_changed(Windows::Foundation::Collections::CollectionChange::ItemInserted, index); } - void RemoveAt(uint32_t const index) + void RemoveAt(std::uint32_t const index) { vector_base::RemoveAt(index); call_changed(Windows::Foundation::Collections::CollectionChange::ItemRemoved, index); @@ -469,7 +469,7 @@ WINRT_EXPORT namespace winrt protected: - void call_changed(Windows::Foundation::Collections::CollectionChange const change, uint32_t const index) + void call_changed(Windows::Foundation::Collections::CollectionChange const change, std::uint32_t const index) { m_changed(static_cast(*this), make(change, index)); } @@ -480,7 +480,7 @@ WINRT_EXPORT namespace winrt struct args : implements { - args(Windows::Foundation::Collections::CollectionChange const change, uint32_t const index) noexcept : + args(Windows::Foundation::Collections::CollectionChange const change, std::uint32_t const index) noexcept : m_change(change), m_index(index) { @@ -491,7 +491,7 @@ WINRT_EXPORT namespace winrt return m_change; } - uint32_t Index() const noexcept + std::uint32_t Index() const noexcept { return m_index; } @@ -499,16 +499,30 @@ WINRT_EXPORT namespace winrt private: Windows::Foundation::Collections::CollectionChange const m_change; - uint32_t const m_index; + std::uint32_t const m_index; }; }; template struct map_view_base : iterable_base, Version> { + // specialization of Lookup that avoids throwing the hresult + std::optional TryLookup(K const& key, trylookup_from_abi_t) const + { + [[maybe_unused]] auto guard = static_cast(*this).acquire_shared(); + auto pair = static_cast(*this).get_container().find(static_cast(*this).wrap_value(key)); + + if (pair == static_cast(*this).get_container().end()) + { + return std::nullopt; + } + + return static_cast(*this).unwrap_value(pair->second); + } + V Lookup(K const& key) const { - auto guard = static_cast(*this).acquire_shared(); + [[maybe_unused]] auto guard = static_cast(*this).acquire_shared(); auto pair = static_cast(*this).get_container().find(static_cast(*this).wrap_value(key)); if (pair == static_cast(*this).get_container().end()) @@ -519,15 +533,15 @@ WINRT_EXPORT namespace winrt return static_cast(*this).unwrap_value(pair->second); } - uint32_t Size() const noexcept + std::uint32_t Size() const noexcept { - auto guard = static_cast(*this).acquire_shared(); - return static_cast(static_cast(*this).get_container().size()); + [[maybe_unused]] auto guard = static_cast(*this).acquire_shared(); + return static_cast(static_cast(*this).get_container().size()); } bool HasKey(K const& key) const noexcept { - auto guard = static_cast(*this).acquire_shared(); + [[maybe_unused]] auto guard = static_cast(*this).acquire_shared(); return static_cast(*this).get_container().find(static_cast(*this).wrap_value(key)) != static_cast(*this).get_container().end(); } @@ -536,6 +550,7 @@ WINRT_EXPORT namespace winrt first = nullptr; second = nullptr; } + }; template @@ -550,7 +565,7 @@ WINRT_EXPORT namespace winrt { impl::removed_value::mapped_type> oldValue; - auto guard = static_cast(*this).acquire_exclusive(); + [[maybe_unused]] auto guard = static_cast(*this).acquire_exclusive(); this->increment_version(); auto [itr, added] = static_cast(*this).get_container().emplace(static_cast(*this).wrap_value(key), static_cast(*this).wrap_value(value)); if (!added) @@ -566,7 +581,7 @@ WINRT_EXPORT namespace winrt { typename impl::container_type_t::node_type removedNode; - auto guard = static_cast(*this).acquire_exclusive(); + [[maybe_unused]] auto guard = static_cast(*this).acquire_exclusive(); auto& container = static_cast(*this).get_container(); auto found = container.find(static_cast(*this).wrap_value(key)); if (found == container.end()) @@ -581,7 +596,7 @@ WINRT_EXPORT namespace winrt { impl::removed_values oldContainer; - auto guard = static_cast(*this).acquire_exclusive(); + [[maybe_unused]] auto guard = static_cast(*this).acquire_exclusive(); this->increment_version(); oldContainer.assign(static_cast(*this).get_container()); } @@ -619,15 +634,17 @@ WINRT_EXPORT namespace winrt call_changed(Windows::Foundation::Collections::CollectionChange::Reset, impl::empty_value()); } - private: - - event> m_changed; + protected: void call_changed(Windows::Foundation::Collections::CollectionChange const change, K const& key) { m_changed(static_cast(*this), make(change, key)); } + private: + + event> m_changed; + struct args : implements> { args(Windows::Foundation::Collections::CollectionChange const change, K const& key) noexcept : diff --git a/strings/base_collections_input_iterable.h b/strings/base_collections_input_iterable.h index e75211c30..e9d3af251 100644 --- a/strings/base_collections_input_iterable.h +++ b/strings/base_collections_input_iterable.h @@ -1,5 +1,5 @@ -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template struct input_iterable : diff --git a/strings/base_collections_input_map.h b/strings/base_collections_input_map.h index b33975fe6..3fe146bf6 100644 --- a/strings/base_collections_input_map.h +++ b/strings/base_collections_input_map.h @@ -1,5 +1,5 @@ -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template struct map_impl : diff --git a/strings/base_collections_input_map_view.h b/strings/base_collections_input_map_view.h index bfd8d82a9..d79eed61d 100644 --- a/strings/base_collections_input_map_view.h +++ b/strings/base_collections_input_map_view.h @@ -1,5 +1,5 @@ -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template struct input_map_view : diff --git a/strings/base_collections_input_vector.h b/strings/base_collections_input_vector.h index b5b76de38..a06e73b33 100644 --- a/strings/base_collections_input_vector.h +++ b/strings/base_collections_input_vector.h @@ -1,5 +1,5 @@ -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template struct vector_impl : diff --git a/strings/base_collections_input_vector_view.h b/strings/base_collections_input_vector_view.h index 3793e239a..30768c18e 100644 --- a/strings/base_collections_input_vector_view.h +++ b/strings/base_collections_input_vector_view.h @@ -1,5 +1,5 @@ -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template struct input_vector_view : diff --git a/strings/base_collections_map.h b/strings/base_collections_map.h index f4bd74baf..6bf884236 100644 --- a/strings/base_collections_map.h +++ b/strings/base_collections_map.h @@ -1,5 +1,5 @@ -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template using multi_threaded_map = map_impl; @@ -116,15 +116,15 @@ WINRT_EXPORT namespace winrt } } -namespace std +WINRT_EXPORT namespace std { template struct tuple_size> - : integral_constant + : integral_constant { }; - template + template struct tuple_element> { static_assert(Idx < 2, "key-value pair index out of bounds"); @@ -132,9 +132,9 @@ namespace std }; } -namespace winrt::Windows::Foundation::Collections +WINRT_EXPORT namespace winrt::Windows::Foundation::Collections { - template + template std::tuple_element_t> get(IKeyValuePair const& kvp) { static_assert(Idx < 2, "key-value pair index out of bounds"); diff --git a/strings/base_collections_vector.h b/strings/base_collections_vector.h index ff0ad6bec..3388806af 100644 --- a/strings/base_collections_vector.h +++ b/strings/base_collections_vector.h @@ -1,5 +1,5 @@ -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template using multi_threaded_vector = vector_impl; @@ -82,7 +82,7 @@ namespace winrt::impl operator wfc::IIterator() { - auto guard = container->acquire_shared(); + [[maybe_unused]] auto guard = container->acquire_shared(); return make(container); } }; @@ -90,12 +90,12 @@ namespace winrt::impl return result{ this }; } - auto GetAt(uint32_t const index) const + auto GetAt(std::uint32_t const index) const { struct result { base_type const* container; - uint32_t const index; + std::uint32_t const index; operator T() const { @@ -113,7 +113,7 @@ namespace winrt::impl using base_type::IndexOf; - bool IndexOf(Windows::Foundation::IInspectable const& value, uint32_t& index) const + bool IndexOf(Windows::Foundation::IInspectable const& value, std::uint32_t& index) const { if constexpr (is_com_interface_v) { @@ -139,15 +139,15 @@ namespace winrt::impl using base_type::GetMany; - uint32_t GetMany(uint32_t const startIndex, array_view values) const + std::uint32_t GetMany(std::uint32_t const startIndex, array_view values) const { - auto guard = this->acquire_shared(); + [[maybe_unused]] auto guard = this->acquire_shared(); if (startIndex >= m_values.size()) { return 0; } - uint32_t const actual = (std::min)(static_cast(m_values.size() - startIndex), values.size()); + std::uint32_t const actual = (std::min)(static_cast(m_values.size() - startIndex), values.size()); std::transform(m_values.begin() + startIndex, m_values.begin() + startIndex + actual, values.begin(), [&](auto && value) { @@ -179,14 +179,14 @@ namespace winrt::impl using base_type::SetAt; - void SetAt(uint32_t const index, Windows::Foundation::IInspectable const& value) + void SetAt(std::uint32_t const index, Windows::Foundation::IInspectable const& value) { SetAt(index, unbox_value(value)); } using base_type::InsertAt; - void InsertAt(uint32_t const index, Windows::Foundation::IInspectable const& value) + void InsertAt(std::uint32_t const index, Windows::Foundation::IInspectable const& value) { InsertAt(index, unbox_value(value)); } @@ -239,7 +239,7 @@ namespace winrt::impl Windows::Foundation::IInspectable Current() const { - auto guard = m_owner->acquire_shared(); + [[maybe_unused]] auto guard = m_owner->acquire_shared(); check_version(*m_owner); if (m_current == m_end) { @@ -251,14 +251,14 @@ namespace winrt::impl bool HasCurrent() const { - auto guard = m_owner->acquire_shared(); + [[maybe_unused]] auto guard = m_owner->acquire_shared(); check_version(*m_owner); return m_current != m_end; } bool MoveNext() { - auto guard = m_owner->acquire_exclusive(); + [[maybe_unused]] auto guard = m_owner->acquire_exclusive(); check_version(*m_owner); if (m_current != m_end) { @@ -268,11 +268,11 @@ namespace winrt::impl return m_current != m_end; } - uint32_t GetMany(array_view values) + std::uint32_t GetMany(array_view values) { - auto guard = m_owner->acquire_exclusive(); + [[maybe_unused]] auto guard = m_owner->acquire_exclusive(); check_version(*m_owner); - uint32_t const actual = (std::min)(static_cast(std::distance(m_current, m_end)), values.size()); + std::uint32_t const actual = (std::min)(static_cast(std::distance(m_current, m_end)), values.size()); std::transform(m_current, m_current + actual, values.begin(), [&](auto && value) { diff --git a/strings/base_com_ptr.h b/strings/base_com_ptr.h index 14a9a0851..0f02fabeb 100644 --- a/strings/base_com_ptr.h +++ b/strings/base_com_ptr.h @@ -5,7 +5,7 @@ WINRT_EXPORT namespace winrt struct com_ptr; } -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { struct capture_decay { @@ -19,19 +19,19 @@ namespace winrt::impl }; template - int32_t capture_to(void**result, F function, Args&& ...args) + std::int32_t capture_to(void**result, F function, Args&& ...args) { return function(args..., guid_of(), capture_decay{ result }); } template || std::is_union_v, int> = 0> - int32_t capture_to(void** result, O* object, M method, Args&& ...args) + std::int32_t capture_to(void** result, O* object, M method, Args&& ...args) { return (object->*method)(args..., guid_of(), capture_decay{ result }); } template - int32_t capture_to(void** result, com_ptr const& object, M method, Args&& ...args); + std::int32_t capture_to(void** result, com_ptr const& object, M method, Args&& ...args); } WINRT_EXPORT namespace winrt @@ -349,10 +349,10 @@ WINRT_EXPORT namespace winrt } } -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template - int32_t capture_to(void** result, com_ptr const& object, M method, Args&& ...args) + std::int32_t capture_to(void** result, com_ptr const& object, M method, Args&& ...args) { return (object.get()->*(method))(args..., guid_of(), capture_decay{ result }); } diff --git a/strings/base_composable.h b/strings/base_composable.h index 7f675c970..5a7712ef7 100644 --- a/strings/base_composable.h +++ b/strings/base_composable.h @@ -1,9 +1,13 @@ -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template struct composable_factory { +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4702) // Compiler bug causing spurious "unreachable code" warnings +#endif template static I CreateInstance(const Windows::Foundation::IInspectable& outer, Windows::Foundation::IInspectable& inner, Args&&... args) { @@ -11,6 +15,9 @@ namespace winrt::impl inner = CreateInstanceImpl(outer, std::forward(args)...); return inner.as(); } +#ifdef _MSC_VER +#pragma warning(pop) +#endif private: template diff --git a/strings/base_coroutine_foundation.h b/strings/base_coroutine_foundation.h index 670a65403..82582ee64 100644 --- a/strings/base_coroutine_foundation.h +++ b/strings/base_coroutine_foundation.h @@ -1,5 +1,5 @@ -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template struct async_completed_handler; @@ -47,7 +47,7 @@ namespace winrt::impl } template - auto wait_for_completed(Async const& async, uint32_t const timeout) + auto wait_for_completed(Async const& async, std::uint32_t const timeout) { struct shared_type { @@ -72,8 +72,8 @@ namespace winrt::impl { check_sta_blocking_wait(); auto const milliseconds = std::chrono::duration_cast(timeout).count(); - WINRT_ASSERT((milliseconds >= 0) && (static_cast(milliseconds) < 0xFFFFFFFFull)); // Within uint32_t range and not INFINITE - return wait_for_completed(async, static_cast(milliseconds)); + WINRT_ASSERT((milliseconds >= 0) && (static_cast(milliseconds) < 0xFFFFFFFFull)); // Within std::uint32_t range and not INFINITE + return wait_for_completed(async, static_cast(milliseconds)); } inline void check_status_canceled(Windows::Foundation::AsyncStatus status) @@ -99,12 +99,26 @@ namespace winrt::impl return async.GetResults(); } + template + auto wait_get_bypass_sta_check(Async const& async) + { + auto status = async.Status(); + if (status == Windows::Foundation::AsyncStatus::Started) + { + status = wait_for_completed(async, 0xFFFFFFFF); // INFINITE + } + check_status_canceled(status); + + return async.GetResults(); + } + +#ifdef WINRT_IMPL_COROUTINES struct ignore_apartment_context {}; template struct disconnect_aware_handler : private std::conditional_t { - disconnect_aware_handler(Awaiter* awaiter, coroutine_handle<> handle) noexcept + disconnect_aware_handler(Awaiter* awaiter, std::coroutine_handle<> handle) noexcept : m_awaiter(awaiter), m_handle(handle) { } disconnect_aware_handler(disconnect_aware_handler&& other) = default; @@ -123,7 +137,7 @@ namespace winrt::impl private: movable_primitive m_awaiter; - movable_primitive, nullptr> m_handle; + movable_primitive, nullptr> m_handle; void Complete() { @@ -149,7 +163,6 @@ namespace winrt::impl } }; -#ifdef WINRT_IMPL_COROUTINES template struct await_adapter : cancellable_awaiter> { @@ -158,7 +171,7 @@ namespace winrt::impl std::conditional_t async; Windows::Foundation::AsyncStatus status = Windows::Foundation::AsyncStatus::Started; - int32_t failure = 0; + std::int32_t failure = 0; std::atomic suspending = true; void enable_cancellation(cancellable_promise* promise) @@ -175,7 +188,7 @@ namespace winrt::impl } template - bool await_suspend(coroutine_handle handle) + bool await_suspend(std::coroutine_handle handle) { this->set_cancellable_promise_from_handle(handle); return register_completed_callback(handle); @@ -189,7 +202,7 @@ namespace winrt::impl } private: - bool register_completed_callback(coroutine_handle<> handle) + bool register_completed_callback(std::coroutine_handle<> handle) { if constexpr (!preserve_context) { @@ -220,6 +233,11 @@ namespace winrt::impl impl::wait_get(static_cast(static_cast(*this))); } template + auto consume_Windows_Foundation_IAsyncAction::get_unchecked() const + { + impl::wait_get_bypass_sta_check(static_cast(static_cast(*this))); + } + template auto consume_Windows_Foundation_IAsyncAction::wait_for(Windows::Foundation::TimeSpan const& timeout) const { return impl::wait_for(static_cast(static_cast(*this)), timeout); @@ -231,6 +249,11 @@ namespace winrt::impl return impl::wait_get(static_cast const&>(static_cast(*this))); } template + auto consume_Windows_Foundation_IAsyncOperation::get_unchecked() const + { + return impl::wait_get_bypass_sta_check(static_cast const&>(static_cast(*this))); + } + template auto consume_Windows_Foundation_IAsyncOperation::wait_for(Windows::Foundation::TimeSpan const& timeout) const { return impl::wait_for(static_cast const&>(static_cast(*this)), timeout); @@ -242,6 +265,11 @@ namespace winrt::impl impl::wait_get(static_cast const&>(static_cast(*this))); } template + auto consume_Windows_Foundation_IAsyncActionWithProgress::get_unchecked() const + { + impl::wait_get_bypass_sta_check(static_cast const&>(static_cast(*this))); + } + template auto consume_Windows_Foundation_IAsyncActionWithProgress::wait_for(Windows::Foundation::TimeSpan const& timeout) const { return impl::wait_for(static_cast const&>(static_cast(*this)), timeout); @@ -253,6 +281,11 @@ namespace winrt::impl return impl::wait_get(static_cast const&>(static_cast(*this))); } template + auto consume_Windows_Foundation_IAsyncOperationWithProgress::get_unchecked() const + { + return impl::wait_get_bypass_sta_check(static_cast const&>(static_cast(*this))); + } + template auto consume_Windows_Foundation_IAsyncOperationWithProgress::wait_for(Windows::Foundation::TimeSpan const& timeout) const { return impl::wait_for(static_cast const&>(static_cast(*this)), timeout); @@ -294,7 +327,6 @@ WINRT_EXPORT namespace winrt::Windows::Foundation return{ async }; } } -#endif WINRT_EXPORT namespace winrt { @@ -313,7 +345,7 @@ WINRT_EXPORT namespace winrt } } -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template struct cancellation_token @@ -327,7 +359,7 @@ namespace winrt::impl return true; } - void await_suspend(coroutine_handle<>) const noexcept + void await_suspend(std::coroutine_handle<>) const noexcept { } @@ -351,6 +383,10 @@ namespace winrt::impl return m_promise->enable_cancellation_propagation(value); } + bool originate_on_cancel(bool value = true) const noexcept + { + return m_promise->originate_on_cancel(value); + } private: Promise* m_promise; @@ -369,7 +405,7 @@ namespace winrt::impl return true; } - void await_suspend(coroutine_handle<>) const noexcept + void await_suspend(std::coroutine_handle<>) const noexcept { } @@ -402,12 +438,12 @@ namespace winrt::impl unsigned long __stdcall Release() noexcept { - uint32_t const remaining = this->subtract_reference(); + std::uint32_t const remaining = this->subtract_reference(); if (remaining == 0) { std::atomic_thread_fence(std::memory_order_acquire); - coroutine_handle::from_promise(*static_cast(this)).destroy(); + std::coroutine_handle::from_promise(*static_cast(this)).destroy(); } return remaining; @@ -447,7 +483,7 @@ namespace winrt::impl return m_completed; } - uint32_t Id() const noexcept + std::uint32_t Id() const noexcept { return 1; } @@ -484,7 +520,14 @@ namespace winrt::impl if (m_status.load(std::memory_order_relaxed) == AsyncStatus::Started) { m_status.store(AsyncStatus::Canceled, std::memory_order_relaxed); - m_exception = std::make_exception_ptr(hresult_canceled()); + if (cancellable_promise::originate_on_cancel()) + { + m_exception = std::make_exception_ptr(hresult_canceled()); + } + else + { + m_exception = std::make_exception_ptr(hresult_canceled(hresult_error::no_originate)); + } cancel = std::move(m_cancel); } } @@ -566,7 +609,7 @@ namespace winrt::impl } } - suspend_never initial_suspend() const noexcept + std::suspend_never initial_suspend() const noexcept { return{}; } @@ -584,10 +627,10 @@ namespace winrt::impl { } - bool await_suspend(coroutine_handle<>) const noexcept + bool await_suspend(std::coroutine_handle<>) const noexcept { promise->set_completed(); - uint32_t const remaining = promise->subtract_reference(); + std::uint32_t const remaining = promise->subtract_reference(); if (remaining == 0) { @@ -628,7 +671,14 @@ namespace winrt::impl { if (Status() == AsyncStatus::Canceled) { - throw winrt::hresult_canceled(); + if (cancellable_promise::originate_on_cancel()) + { + throw winrt::hresult_canceled(); + } + else + { + throw winrt::hresult_canceled(hresult_error::no_originate); + } } return std::forward(expression); @@ -687,11 +737,7 @@ namespace winrt::impl }; } -#ifdef __cpp_lib_coroutine -namespace std -#else -namespace std::experimental -#endif +WINRT_IMPL_STD_EXPORT namespace std { template struct coroutine_traits @@ -826,7 +872,6 @@ namespace std::experimental WINRT_EXPORT namespace winrt { -#ifdef WINRT_IMPL_COROUTINES template Windows::Foundation::IAsyncAction when_all(T... async) { @@ -872,5 +917,5 @@ WINRT_EXPORT namespace winrt impl::check_status_canceled(shared->status); co_return shared->result.GetResults(); } -#endif } +#endif diff --git a/strings/base_coroutine_system.h b/strings/base_coroutine_system.h index b893bd1b5..f79fe0671 100644 --- a/strings/base_coroutine_system.h +++ b/strings/base_coroutine_system.h @@ -1,4 +1,5 @@ +#ifdef WINRT_IMPL_COROUTINES WINRT_EXPORT namespace winrt { [[nodiscard]] inline auto resume_foreground( @@ -23,7 +24,7 @@ WINRT_EXPORT namespace winrt return m_queued; } - bool await_suspend(impl::coroutine_handle<> handle) + bool await_suspend(std::coroutine_handle<> handle) { return m_dispatcher.TryEnqueue(m_priority, [handle, this] { @@ -41,10 +42,9 @@ WINRT_EXPORT namespace winrt return awaitable{ dispatcher, priority }; }; -#ifdef WINRT_IMPL_COROUTINES inline auto operator co_await(Windows::System::DispatcherQueue const& dispatcher) { return resume_foreground(dispatcher); } -#endif } +#endif diff --git a/strings/base_coroutine_system_winui.h b/strings/base_coroutine_system_winui.h deleted file mode 100644 index ecb3cf766..000000000 --- a/strings/base_coroutine_system_winui.h +++ /dev/null @@ -1,50 +0,0 @@ - -WINRT_EXPORT namespace winrt -{ - [[nodiscard]] inline auto resume_foreground( - Microsoft::System::DispatcherQueue const& dispatcher, - Microsoft::System::DispatcherQueuePriority const priority = Microsoft::System::DispatcherQueuePriority::Normal) noexcept - { - struct awaitable - { - awaitable(Microsoft::System::DispatcherQueue const& dispatcher, Microsoft::System::DispatcherQueuePriority const priority) noexcept : - m_dispatcher(dispatcher), - m_priority(priority) - { - } - - bool await_ready() const noexcept - { - return false; - } - - bool await_resume() const noexcept - { - return m_queued; - } - - bool await_suspend(impl::coroutine_handle<> handle) - { - return m_dispatcher.TryEnqueue(m_priority, [handle, this] - { - m_queued = true; - handle(); - }); - } - - private: - Microsoft::System::DispatcherQueue const& m_dispatcher; - Microsoft::System::DispatcherQueuePriority const m_priority; - bool m_queued{}; - }; - - return awaitable{ dispatcher, priority }; - }; - -#ifdef WINRT_IMPL_COROUTINES - inline auto operator co_await(Microsoft::System::DispatcherQueue const& dispatcher) - { - return resume_foreground(dispatcher); - } -#endif -} diff --git a/strings/base_coroutine_threadpool.h b/strings/base_coroutine_threadpool.h index 0faaa1acd..c901b94ba 100644 --- a/strings/base_coroutine_threadpool.h +++ b/strings/base_coroutine_threadpool.h @@ -1,6 +1,7 @@ -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { +#ifdef WINRT_IMPL_COROUTINES inline auto submit_threadpool_callback(void(__stdcall* callback)(void*, void* context), void* context) { if (!WINRT_IMPL_TrySubmitThreadpoolCallback(callback, context, nullptr)) @@ -11,18 +12,19 @@ namespace winrt::impl inline void __stdcall resume_background_callback(void*, void* context) noexcept { - coroutine_handle<>::from_address(context)(); + std::coroutine_handle<>::from_address(context)(); }; - inline auto resume_background(coroutine_handle<> handle) + inline auto resume_background(std::coroutine_handle<> handle) { submit_threadpool_callback(resume_background_callback, handle.address()); } +#endif - inline std::pair get_apartment_type() noexcept + inline std::pair get_apartment_type() noexcept { - int32_t aptType; - int32_t aptTypeQualifier; + std::int32_t aptType; + std::int32_t aptTypeQualifier; if (0 == WINRT_IMPL_CoGetApartmentType(&aptType, &aptTypeQualifier)) { return { aptType, aptTypeQualifier }; @@ -48,6 +50,7 @@ namespace winrt::impl return false; } +#ifdef WINRT_IMPL_COROUTINES struct resume_apartment_context { resume_apartment_context() = default; @@ -59,16 +62,16 @@ namespace winrt::impl } com_ptr m_context = try_capture(WINRT_IMPL_CoGetObjectContext); - movable_primitive m_context_type = get_apartment_type().first; + movable_primitive m_context_type = get_apartment_type().first; }; - inline int32_t __stdcall resume_apartment_callback(com_callback_args* args) noexcept + inline std::int32_t __stdcall resume_apartment_callback(com_callback_args* args) noexcept { - coroutine_handle<>::from_address(args->data)(); + std::coroutine_handle<>::from_address(args->data)(); return 0; }; - [[nodiscard]] inline bool resume_apartment_sync(com_ptr const& context, coroutine_handle<> handle, int32_t* failure) + [[nodiscard]] inline bool resume_apartment_sync(com_ptr const& context, std::coroutine_handle<> handle, std::int32_t* failure) { com_callback_args args{}; args.data = handle.address(); @@ -85,11 +88,11 @@ namespace winrt::impl struct threadpool_resume { - threadpool_resume(com_ptr const& context, coroutine_handle<> handle, int32_t* failure) : + threadpool_resume(com_ptr const& context, std::coroutine_handle<> handle, std::int32_t* failure) : m_context(context), m_handle(handle), m_failure(failure) { } com_ptr m_context; - coroutine_handle<> m_handle; - int32_t* m_failure; + std::coroutine_handle<> m_handle; + std::int32_t* m_failure; }; inline void __stdcall fallback_submit_threadpool_callback(void*, void* p) noexcept @@ -101,14 +104,14 @@ namespace winrt::impl } } - inline void resume_apartment_on_threadpool(com_ptr const& context, coroutine_handle<> handle, int32_t* failure) + inline void resume_apartment_on_threadpool(com_ptr const& context, std::coroutine_handle<> handle, std::int32_t* failure) { auto state = std::make_unique(context, handle, failure); submit_threadpool_callback(fallback_submit_threadpool_callback, state.get()); state.release(); } - [[nodiscard]] inline auto resume_apartment(resume_apartment_context const& context, coroutine_handle<> handle, int32_t* failure) + [[nodiscard]] inline auto resume_apartment(resume_apartment_context const& context, std::coroutine_handle<> handle, std::int32_t* failure) { WINRT_ASSERT(context.valid()); if ((context.m_context == nullptr) || (context.m_context == try_capture(WINRT_IMPL_CoGetObjectContext))) @@ -130,8 +133,10 @@ namespace winrt::impl return resume_apartment_sync(context.m_context, handle, failure); } } +#endif } +#ifdef WINRT_IMPL_COROUTINES WINRT_EXPORT namespace winrt { struct cancellable_promise @@ -141,32 +146,42 @@ WINRT_EXPORT namespace winrt void set_canceller(canceller_t canceller, void* context) { m_context = context; - m_canceller.store(canceller, std::memory_order_release); + canceller_t expected = nullptr; + m_canceller.compare_exchange_strong(expected, canceller, std::memory_order_release, std::memory_order_relaxed); } void revoke_canceller() { - while (m_canceller.exchange(nullptr, std::memory_order_acquire) == cancelling_ptr) + auto existing = m_canceller.load(std::memory_order_relaxed); + do { - std::this_thread::yield(); + while (existing == cancelling_ptr) + { + std::this_thread::yield(); + existing = m_canceller.load(std::memory_order_relaxed); + } } + while (!m_canceller.compare_exchange_weak(existing, nullptr, std::memory_order_acquire, std::memory_order_relaxed)); } void cancel() { auto canceller = m_canceller.exchange(cancelling_ptr, std::memory_order_acquire); - struct unique_cancellation_lock + if (canceller != cancelling_ptr) { - cancellable_promise* promise; - ~unique_cancellation_lock() + struct unique_cancellation_lock { - promise->m_canceller.store(nullptr, std::memory_order_release); + cancellable_promise* promise; + ~unique_cancellation_lock() + { + promise->m_canceller.store(nullptr, std::memory_order_release); + } + } lock{ this }; + + if (canceller != nullptr) + { + canceller(m_context); } - } lock{ this }; - - if ((canceller != nullptr) && (canceller != cancelling_ptr)) - { - canceller(m_context); } } @@ -180,12 +195,23 @@ WINRT_EXPORT namespace winrt return m_propagate_cancellation; } + bool originate_on_cancel(bool value = true) noexcept + { + return std::exchange(m_originate_on_cancel, value); + } + + bool should_originate_on_cancel() const noexcept + { + return m_originate_on_cancel; + } + private: static inline auto const cancelling_ptr = reinterpret_cast(1); std::atomic m_canceller{ nullptr }; void* m_context{ nullptr }; bool m_propagate_cancellation{ false }; + bool m_originate_on_cancel{ true }; // By default, will call RoOriginateError before throwing a cancel error code. }; template @@ -206,7 +232,7 @@ WINRT_EXPORT namespace winrt protected: template - void set_cancellable_promise_from_handle(impl::coroutine_handle const& handle) + void set_cancellable_promise_from_handle(std::coroutine_handle const& handle) { if constexpr (std::is_base_of_v) { @@ -226,10 +252,7 @@ WINRT_EXPORT namespace winrt cancellable_promise* m_promise = nullptr; }; -} -WINRT_EXPORT namespace winrt -{ [[nodiscard]] inline auto resume_background() noexcept { struct awaitable @@ -243,7 +266,7 @@ WINRT_EXPORT namespace winrt { } - void await_suspend(impl::coroutine_handle<> handle) const + void await_suspend(std::coroutine_handle<> handle) const { impl::resume_background(handle); } @@ -270,7 +293,7 @@ WINRT_EXPORT namespace winrt { } - void await_suspend(impl::coroutine_handle<> resume) + void await_suspend(std::coroutine_handle<> resume) { m_resume = resume; @@ -290,7 +313,7 @@ WINRT_EXPORT namespace winrt } T const& m_context; - impl::coroutine_handle<> m_resume{ nullptr }; + std::coroutine_handle<> m_resume{ nullptr }; }; return awaitable{ context }; @@ -308,12 +331,12 @@ WINRT_EXPORT namespace winrt }; } -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { struct apartment_awaiter { apartment_context const& context; - int32_t failure = 0; + std::int32_t failure = 0; bool await_ready() const noexcept { @@ -325,7 +348,7 @@ namespace winrt::impl check_hresult(failure); } - bool await_suspend(impl::coroutine_handle<> handle) + bool await_suspend(std::coroutine_handle<> handle) { auto context_copy = context; return impl::resume_apartment(context_copy.context, handle, &failure); @@ -370,7 +393,7 @@ namespace winrt::impl } template - void await_suspend(impl::coroutine_handle handle) + void await_suspend(std::coroutine_handle handle) { set_cancellable_promise_from_handle(handle); @@ -390,7 +413,7 @@ namespace winrt::impl void create_threadpool_timer() { m_timer.attach(check_pointer(WINRT_IMPL_CreateThreadpoolTimer(callback, this, nullptr))); - int64_t relative_count = -m_duration.count(); + std::int64_t relative_count = -m_duration.count(); WINRT_IMPL_SetThreadpoolTimer(m_timer.get(), &relative_count, 0, 0); state expected = state::idle; @@ -404,7 +427,7 @@ namespace winrt::impl { if (WINRT_IMPL_SetThreadpoolTimerEx(m_timer.get(), nullptr, 0, 0)) { - int64_t now = 0; + std::int64_t now = 0; WINRT_IMPL_SetThreadpoolTimer(m_timer.get(), &now, 0, 0); } } @@ -434,7 +457,7 @@ namespace winrt::impl handle_type m_timer; Windows::Foundation::TimeSpan m_duration; - impl::coroutine_handle<> m_handle; + std::coroutine_handle<> m_handle; std::atomic m_state{ state::idle }; }; @@ -478,7 +501,7 @@ namespace winrt::impl } template - void await_suspend(impl::coroutine_handle resume) + void await_suspend(std::coroutine_handle resume) { set_cancellable_promise_from_handle(resume); @@ -500,8 +523,8 @@ namespace winrt::impl void create_threadpool_wait() { m_wait.attach(check_pointer(WINRT_IMPL_CreateThreadpoolWait(callback, this, nullptr))); - int64_t relative_count = -m_timeout.count(); - int64_t* file_time = relative_count != 0 ? &relative_count : nullptr; + std::int64_t relative_count = -m_timeout.count(); + std::int64_t* file_time = relative_count != 0 ? &relative_count : nullptr; WINRT_IMPL_SetThreadpoolWait(m_wait.get(), m_handle, file_time); state expected = state::idle; @@ -515,12 +538,12 @@ namespace winrt::impl { if (WINRT_IMPL_SetThreadpoolWaitEx(m_wait.get(), nullptr, nullptr, nullptr)) { - int64_t now = 0; + std::int64_t now = 0; WINRT_IMPL_SetThreadpoolWait(m_wait.get(), WINRT_IMPL_GetCurrentProcess(), &now); } } - static void __stdcall callback(void*, void* context, void*, uint32_t result) noexcept + static void __stdcall callback(void*, void* context, void*, std::uint32_t result) noexcept { auto that = static_cast(context); that->m_result = result; @@ -547,32 +570,28 @@ namespace winrt::impl handle_type m_wait; Windows::Foundation::TimeSpan m_timeout; void* m_handle; - uint32_t m_result{}; - impl::coroutine_handle<> m_resume{ nullptr }; + std::uint32_t m_result{}; + std::coroutine_handle<> m_resume{ nullptr }; std::atomic m_state{ state::idle }; }; } WINRT_EXPORT namespace winrt { -#ifdef WINRT_IMPL_COROUTINES inline impl::apartment_awaiter operator co_await(apartment_context const& context) { return{ context }; } -#endif [[nodiscard]] inline impl::timespan_awaiter resume_after(Windows::Foundation::TimeSpan duration) noexcept { return impl::timespan_awaiter{ duration }; } -#ifdef WINRT_IMPL_COROUTINES inline impl::timespan_awaiter operator co_await(Windows::Foundation::TimeSpan duration) { return resume_after(duration); } -#endif [[nodiscard]] inline impl::signal_awaiter resume_on_signal(void* handle, Windows::Foundation::TimeSpan timeout = {}) noexcept { @@ -587,7 +606,7 @@ WINRT_EXPORT namespace winrt m_environment.Pool = m_pool.get(); } - void thread_limits(uint32_t const high, uint32_t const low) + void thread_limits(std::uint32_t const high, std::uint32_t const low) { WINRT_IMPL_SetThreadpoolThreadMaximum(m_pool.get(), high); check_bool(WINRT_IMPL_SetThreadpoolThreadMinimum(m_pool.get(), low)); @@ -602,7 +621,7 @@ WINRT_EXPORT namespace winrt { } - void await_suspend(impl::coroutine_handle<> handle) + void await_suspend(std::coroutine_handle<> handle) { if (!WINRT_IMPL_TrySubmitThreadpoolCallback(callback, handle.address(), &m_environment)) { @@ -614,7 +633,7 @@ WINRT_EXPORT namespace winrt static void __stdcall callback(void*, void* context) noexcept { - impl::coroutine_handle<>::from_address(context)(); + std::coroutine_handle<>::from_address(context)(); } struct pool_traits @@ -634,7 +653,7 @@ WINRT_EXPORT namespace winrt struct environment // TP_CALLBACK_ENVIRON { - uint32_t Version{ 3 }; + std::uint32_t Version{ 3 }; void* Pool{}; void* CleanupGroup{}; void* CleanupGroupCancelCallback{}; @@ -643,16 +662,16 @@ WINRT_EXPORT namespace winrt void* FinalizationCallback{}; union { - uint32_t Flags{}; + std::uint32_t Flags{}; struct { - uint32_t LongFunction : 1; - uint32_t Persistent : 1; - uint32_t Private : 30; + std::uint32_t LongFunction : 1; + std::uint32_t Persistent : 1; + std::uint32_t Private : 30; } s; } u; - int32_t CallbackPriority{ 1 }; - uint32_t Size{ sizeof(environment) }; + std::int32_t CallbackPriority{ 1 }; + std::uint32_t Size{ sizeof(environment) }; }; handle_type m_pool; @@ -662,11 +681,7 @@ WINRT_EXPORT namespace winrt struct fire_and_forget {}; } -#ifdef __cpp_lib_coroutine -namespace std -#else -namespace std::experimental -#endif +WINRT_IMPL_STD_EXPORT namespace std { template struct coroutine_traits @@ -682,12 +697,12 @@ namespace std::experimental { } - suspend_never initial_suspend() const noexcept + std::suspend_never initial_suspend() const noexcept { return{}; } - suspend_never final_suspend() const noexcept + std::suspend_never final_suspend() const noexcept { return{}; } @@ -699,3 +714,4 @@ namespace std::experimental }; }; } +#endif diff --git a/strings/base_coroutine_ui_core.h b/strings/base_coroutine_ui_core.h index dab34c8de..7efed5174 100644 --- a/strings/base_coroutine_ui_core.h +++ b/strings/base_coroutine_ui_core.h @@ -1,4 +1,5 @@ +#ifdef WINRT_IMPL_COROUTINES WINRT_EXPORT namespace winrt { [[nodiscard]] inline auto resume_foreground( @@ -22,7 +23,7 @@ WINRT_EXPORT namespace winrt { } - void await_suspend(impl::coroutine_handle<> handle) const + void await_suspend(std::coroutine_handle<> handle) const { m_dispatcher.RunAsync(m_priority, [handle] { @@ -39,10 +40,9 @@ WINRT_EXPORT namespace winrt return awaitable{ dispatcher, priority }; }; -#ifdef WINRT_IMPL_COROUTINES inline auto operator co_await(Windows::UI::Core::CoreDispatcher const& dispatcher) { return resume_foreground(dispatcher); } -#endif } +#endif diff --git a/strings/base_deferral.h b/strings/base_deferral.h index ceab1cd4b..cc6f724e5 100644 --- a/strings/base_deferral.h +++ b/strings/base_deferral.h @@ -1,7 +1,7 @@ +#ifdef WINRT_IMPL_COROUTINES WINRT_EXPORT namespace winrt { -#ifdef WINRT_IMPL_COROUTINES template struct deferrable_event_args { @@ -22,9 +22,9 @@ WINRT_EXPORT namespace winrt [[nodiscard]] Windows::Foundation::IAsyncAction wait_for_deferrals() { - struct awaitable : impl::suspend_always + struct awaitable : std::suspend_always { - bool await_suspend(coroutine_handle handle) + bool await_suspend(std::coroutine_handle<> handle) { return m_deferrable.await_suspend(handle); } @@ -37,11 +37,9 @@ WINRT_EXPORT namespace winrt private: - using coroutine_handle = impl::coroutine_handle<>; - void one_deferral_completed() { - coroutine_handle resume = nullptr; + std::coroutine_handle<> resume = nullptr; { slim_lock_guard const guard(m_lock); @@ -62,7 +60,7 @@ WINRT_EXPORT namespace winrt } } - bool await_suspend(coroutine_handle handle) noexcept + bool await_suspend(std::coroutine_handle<> handle) noexcept { slim_lock_guard const guard(m_lock); m_handle = handle; @@ -70,8 +68,8 @@ WINRT_EXPORT namespace winrt } slim_mutex m_lock; - int32_t m_outstanding_deferrals = 0; - coroutine_handle m_handle = nullptr; + std::int32_t m_outstanding_deferrals = 0; + std::coroutine_handle<> m_handle = nullptr; }; -#endif } +#endif diff --git a/strings/base_delegate.h b/strings/base_delegate.h index 8902b3cc6..1fe00ecd1 100644 --- a/strings/base_delegate.h +++ b/strings/base_delegate.h @@ -1,5 +1,5 @@ -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { #if defined(_MSC_VER) #pragma warning(push) @@ -8,17 +8,17 @@ namespace winrt::impl struct implements_delegate_base { - WINRT_IMPL_NOINLINE uint32_t increment_reference() noexcept + WINRT_IMPL_NOINLINE std::uint32_t increment_reference() noexcept { return ++m_references; } - WINRT_IMPL_NOINLINE uint32_t decrement_reference() noexcept + WINRT_IMPL_NOINLINE std::uint32_t decrement_reference() noexcept { return --m_references; } - WINRT_IMPL_NOINLINE uint32_t query_interface(guid const& id, void** result, unknown_abi* derivedAbiPtr, guid const& derivedId) noexcept + WINRT_IMPL_NOINLINE std::uint32_t query_interface(guid const& id, void** result, unknown_abi* derivedAbiPtr, guid const& derivedId) noexcept { if (id == derivedId || is_guid_of(id) || is_guid_of(id)) { @@ -47,17 +47,17 @@ namespace winrt::impl { } - int32_t __stdcall QueryInterface(guid const& id, void** result) noexcept final + std::int32_t __stdcall QueryInterface(guid const& id, void** result) noexcept final { return query_interface(id, result, static_cast*>(this), guid_of()); } - uint32_t __stdcall AddRef() noexcept final + std::uint32_t __stdcall AddRef() noexcept final { return increment_reference(); } - uint32_t __stdcall Release() noexcept final + std::uint32_t __stdcall Release() noexcept final { auto const remaining = decrement_reference(); @@ -109,7 +109,7 @@ namespace winrt::impl } template - struct WINRT_IMPL_NOVTABLE variadic_delegate_abi : unknown_abi + struct WINRT_IMPL_ABI_DECL variadic_delegate_abi : unknown_abi { virtual R invoke(Args const& ...) = 0; }; @@ -133,17 +133,17 @@ namespace winrt::impl } } - int32_t __stdcall QueryInterface(guid const& id, void** result) noexcept final + std::int32_t __stdcall QueryInterface(guid const& id, void** result) noexcept final { return query_interface(id, result, static_cast(this), guid_of()); } - uint32_t __stdcall AddRef() noexcept final + std::uint32_t __stdcall AddRef() noexcept final { return increment_reference(); } - uint32_t __stdcall Release() noexcept final + std::uint32_t __stdcall Release() noexcept final { auto const remaining = decrement_reference(); diff --git a/strings/base_detect_numerics.h b/strings/base_detect_numerics.h new file mode 100644 index 000000000..6a93a8ffa --- /dev/null +++ b/strings/base_detect_numerics.h @@ -0,0 +1,4 @@ + +#if __has_include() +#define WINRT_IMPL_NUMERICS +#endif diff --git a/strings/base_error.h b/strings/base_error.h index 6e0aa103a..d42ca516b 100644 --- a/strings/base_error.h +++ b/strings/base_error.h @@ -7,7 +7,7 @@ #define WINRT_IMPL_RETURNADDRESS() nullptr #endif -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { struct heap_traits { @@ -41,11 +41,11 @@ namespace winrt::impl using bstr_handle = handle_type; - inline hstring trim_hresult_message(wchar_t const* const message, uint32_t size) noexcept + inline hstring trim_hresult_message(wchar_t const* const message, std::uint32_t size) noexcept { wchar_t const* back = message + size - 1; - while (size&& iswspace(*back)) + while (size && std::iswspace(*back)) { --size; --back; @@ -58,7 +58,7 @@ namespace winrt::impl { handle_type message; - uint32_t const size = WINRT_IMPL_FormatMessageW(0x00001300, // FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS + std::uint32_t const size = WINRT_IMPL_FormatMessageW(0x00001300, // FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS nullptr, code, 0x00000400, // MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT) @@ -69,14 +69,14 @@ namespace winrt::impl return trim_hresult_message(message.get(), size); } - constexpr int32_t hresult_from_win32(uint32_t const x) noexcept + constexpr std::int32_t hresult_from_win32(std::uint32_t const x) noexcept { - return (int32_t)(x) <= 0 ? (int32_t)(x) : (int32_t)(((x) & 0x0000FFFF) | (7 << 16) | 0x80000000); + return (std::int32_t)(x) <= 0 ? (std::int32_t)(x) : (std::int32_t)(((x) & 0x0000FFFF) | (7 << 16) | 0x80000000); } - constexpr int32_t hresult_from_nt(uint32_t const x) noexcept + constexpr std::int32_t hresult_from_nt(std::uint32_t const x) noexcept { - return ((int32_t)((x) | 0x10000000)); + return ((std::int32_t)((x) | 0x10000000)); } } @@ -84,6 +84,9 @@ WINRT_EXPORT namespace winrt { struct hresult_error { + struct no_originate_t {}; + static constexpr no_originate_t no_originate{}; + using from_abi_t = take_ownership_from_abi_t; static constexpr auto from_abi{ take_ownership_from_abi }; @@ -104,17 +107,21 @@ WINRT_EXPORT namespace winrt return *this; } - explicit hresult_error(hresult const code WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : m_code(verify_error(code)) + explicit hresult_error(hresult const code, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : m_code(verify_error(code)) + { + originate(code, nullptr, sourceInformation); + } + + explicit hresult_error(hresult const code, no_originate_t) noexcept : m_code(verify_error(code)) { - originate(code, nullptr WINRT_IMPL_SOURCE_LOCATION_FORWARD); } - hresult_error(hresult const code, param::hstring const& message WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : m_code(verify_error(code)) + hresult_error(hresult const code, param::hstring const& message, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : m_code(verify_error(code)) { - originate(code, get_abi(message) WINRT_IMPL_SOURCE_LOCATION_FORWARD); + originate(code, get_abi(message), sourceInformation); } - hresult_error(hresult const code, take_ownership_from_abi_t WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : m_code(verify_error(code)) + hresult_error(hresult const code, take_ownership_from_abi_t, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : m_code(verify_error(code)) { com_ptr info; WINRT_IMPL_GetErrorInfo(0, info.put_void()); @@ -144,7 +151,7 @@ WINRT_EXPORT namespace winrt message = impl::trim_hresult_message(legacy.get(), WINRT_IMPL_SysStringLen(legacy.get())); } - originate(code, get_abi(message) WINRT_IMPL_SOURCE_LOCATION_FORWARD); + originate(code, get_abi(message), sourceInformation); } } @@ -157,7 +164,7 @@ WINRT_EXPORT namespace winrt { if (m_info) { - int32_t code{}; + std::int32_t code{}; impl::bstr_handle fallback; impl::bstr_handle message; impl::bstr_handle unused; @@ -199,7 +206,7 @@ WINRT_EXPORT namespace winrt private: - void originate(hresult const code, void* message WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept + void originate(hresult const code, void* message, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept { WINRT_VERIFY(WINRT_IMPL_RoOriginateLanguageException(code, message, nullptr)); @@ -208,11 +215,7 @@ WINRT_EXPORT namespace winrt // information is available on the caller who generated the error. if (winrt_throw_hresult_handler) { -#ifdef WINRT_SOURCE_LOCATION_ACTIVE winrt_throw_hresult_handler(sourceInformation.line(), sourceInformation.file_name(), sourceInformation.function_name(), WINRT_IMPL_RETURNADDRESS(), code); -#else - winrt_throw_hresult_handler(0, nullptr, nullptr, WINRT_IMPL_RETURNADDRESS(), code); -#endif } com_ptr info; @@ -233,7 +236,7 @@ WINRT_EXPORT namespace winrt #endif impl::bstr_handle m_debug_reference; - uint32_t m_debug_magic{ 0xAABBCCDD }; + std::uint32_t m_debug_magic{ 0xAABBCCDD }; hresult m_code{ impl::error_fail }; com_ptr m_info; @@ -244,104 +247,101 @@ WINRT_EXPORT namespace winrt struct hresult_access_denied : hresult_error { - hresult_access_denied(WINRT_IMPL_SOURCE_LOCATION_ARGS_SINGLE_PARAM) noexcept : hresult_error(impl::error_access_denied WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_access_denied(param::hstring const& message WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_access_denied, message WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_access_denied(take_ownership_from_abi_t WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_access_denied, take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} + hresult_access_denied(winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_access_denied, sourceInformation) {} + hresult_access_denied(param::hstring const& message, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_access_denied, message, sourceInformation) {} + hresult_access_denied(take_ownership_from_abi_t, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_access_denied, take_ownership_from_abi, sourceInformation) {} }; struct hresult_wrong_thread : hresult_error { - hresult_wrong_thread(WINRT_IMPL_SOURCE_LOCATION_ARGS_SINGLE_PARAM) noexcept : hresult_error(impl::error_wrong_thread WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_wrong_thread(param::hstring const& message WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_wrong_thread, message WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_wrong_thread(take_ownership_from_abi_t WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_wrong_thread, take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} + hresult_wrong_thread(winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_wrong_thread, sourceInformation) {} + hresult_wrong_thread(param::hstring const& message, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_wrong_thread, message, sourceInformation) {} + hresult_wrong_thread(take_ownership_from_abi_t, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_wrong_thread, take_ownership_from_abi, sourceInformation) {} }; struct hresult_not_implemented : hresult_error { - hresult_not_implemented(WINRT_IMPL_SOURCE_LOCATION_ARGS_SINGLE_PARAM) noexcept : hresult_error(impl::error_not_implemented WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_not_implemented(param::hstring const& message WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_not_implemented, message WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_not_implemented(take_ownership_from_abi_t WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_not_implemented, take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} + hresult_not_implemented(winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_not_implemented, sourceInformation) {} + hresult_not_implemented(param::hstring const& message, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_not_implemented, message, sourceInformation) {} + hresult_not_implemented(take_ownership_from_abi_t, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_not_implemented, take_ownership_from_abi, sourceInformation) {} }; struct hresult_invalid_argument : hresult_error { - hresult_invalid_argument(WINRT_IMPL_SOURCE_LOCATION_ARGS_SINGLE_PARAM) noexcept : hresult_error(impl::error_invalid_argument WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_invalid_argument(param::hstring const& message WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_invalid_argument, message WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_invalid_argument(take_ownership_from_abi_t WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_invalid_argument, take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} + hresult_invalid_argument(winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_invalid_argument, sourceInformation) {} + hresult_invalid_argument(param::hstring const& message, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_invalid_argument, message, sourceInformation) {} + hresult_invalid_argument(take_ownership_from_abi_t, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_invalid_argument, take_ownership_from_abi, sourceInformation) {} }; struct hresult_out_of_bounds : hresult_error { - hresult_out_of_bounds(WINRT_IMPL_SOURCE_LOCATION_ARGS_SINGLE_PARAM) noexcept : hresult_error(impl::error_out_of_bounds WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_out_of_bounds(param::hstring const& message WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_out_of_bounds, message WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_out_of_bounds(take_ownership_from_abi_t WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_out_of_bounds, take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} + hresult_out_of_bounds(winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_out_of_bounds, sourceInformation) {} + hresult_out_of_bounds(param::hstring const& message, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_out_of_bounds, message, sourceInformation) {} + hresult_out_of_bounds(take_ownership_from_abi_t, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_out_of_bounds, take_ownership_from_abi, sourceInformation) {} }; struct hresult_no_interface : hresult_error { - hresult_no_interface(WINRT_IMPL_SOURCE_LOCATION_ARGS_SINGLE_PARAM) noexcept : hresult_error(impl::error_no_interface WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_no_interface(param::hstring const& message WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_no_interface, message WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_no_interface(take_ownership_from_abi_t WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_no_interface, take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} + hresult_no_interface(winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_no_interface, sourceInformation) {} + hresult_no_interface(param::hstring const& message, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_no_interface, message, sourceInformation) {} + hresult_no_interface(take_ownership_from_abi_t, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_no_interface, take_ownership_from_abi, sourceInformation) {} }; struct hresult_class_not_available : hresult_error { - hresult_class_not_available(WINRT_IMPL_SOURCE_LOCATION_ARGS_SINGLE_PARAM) noexcept : hresult_error(impl::error_class_not_available WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_class_not_available(param::hstring const& message WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_class_not_available, message WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_class_not_available(take_ownership_from_abi_t WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_class_not_available, take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} + hresult_class_not_available(winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_class_not_available, sourceInformation) {} + hresult_class_not_available(param::hstring const& message, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_class_not_available, message, sourceInformation) {} + hresult_class_not_available(take_ownership_from_abi_t, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_class_not_available, take_ownership_from_abi, sourceInformation) {} }; struct hresult_class_not_registered : hresult_error { - hresult_class_not_registered(WINRT_IMPL_SOURCE_LOCATION_ARGS_SINGLE_PARAM) noexcept : hresult_error(impl::error_class_not_registered WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_class_not_registered(param::hstring const& message WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_class_not_registered, message WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_class_not_registered(take_ownership_from_abi_t WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_class_not_registered, take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} + hresult_class_not_registered(winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_class_not_registered, sourceInformation) {} + hresult_class_not_registered(param::hstring const& message, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_class_not_registered, message, sourceInformation) {} + hresult_class_not_registered(take_ownership_from_abi_t, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_class_not_registered, take_ownership_from_abi, sourceInformation) {} }; struct hresult_changed_state : hresult_error { - hresult_changed_state(WINRT_IMPL_SOURCE_LOCATION_ARGS_SINGLE_PARAM) noexcept : hresult_error(impl::error_changed_state WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_changed_state(param::hstring const& message WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_changed_state, message WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_changed_state(take_ownership_from_abi_t WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_changed_state, take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} + hresult_changed_state(winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_changed_state, sourceInformation) {} + hresult_changed_state(param::hstring const& message, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_changed_state, message, sourceInformation) {} + hresult_changed_state(take_ownership_from_abi_t, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_changed_state, take_ownership_from_abi, sourceInformation) {} }; struct hresult_illegal_method_call : hresult_error { - hresult_illegal_method_call(WINRT_IMPL_SOURCE_LOCATION_ARGS_SINGLE_PARAM) noexcept : hresult_error(impl::error_illegal_method_call WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_illegal_method_call(param::hstring const& message WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_illegal_method_call, message WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_illegal_method_call(take_ownership_from_abi_t WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_illegal_method_call, take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} + hresult_illegal_method_call(winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_illegal_method_call, sourceInformation) {} + hresult_illegal_method_call(param::hstring const& message, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_illegal_method_call, message, sourceInformation) {} + hresult_illegal_method_call(take_ownership_from_abi_t, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_illegal_method_call, take_ownership_from_abi, sourceInformation) {} }; struct hresult_illegal_state_change : hresult_error { - hresult_illegal_state_change(WINRT_IMPL_SOURCE_LOCATION_ARGS_SINGLE_PARAM) noexcept : hresult_error(impl::error_illegal_state_change WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_illegal_state_change(param::hstring const& message WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_illegal_state_change, message WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_illegal_state_change(take_ownership_from_abi_t WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_illegal_state_change, take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} + hresult_illegal_state_change(winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_illegal_state_change, sourceInformation) {} + hresult_illegal_state_change(param::hstring const& message, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_illegal_state_change, message, sourceInformation) {} + hresult_illegal_state_change(take_ownership_from_abi_t, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_illegal_state_change, take_ownership_from_abi, sourceInformation) {} }; struct hresult_illegal_delegate_assignment : hresult_error { - hresult_illegal_delegate_assignment(WINRT_IMPL_SOURCE_LOCATION_ARGS_SINGLE_PARAM) noexcept : hresult_error(impl::error_illegal_delegate_assignment WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_illegal_delegate_assignment(param::hstring const& message WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_illegal_delegate_assignment, message WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_illegal_delegate_assignment(take_ownership_from_abi_t WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_illegal_delegate_assignment, take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} + hresult_illegal_delegate_assignment(winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_illegal_delegate_assignment, sourceInformation) {} + hresult_illegal_delegate_assignment(param::hstring const& message, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_illegal_delegate_assignment, message, sourceInformation) {} + hresult_illegal_delegate_assignment(take_ownership_from_abi_t, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_illegal_delegate_assignment, take_ownership_from_abi, sourceInformation) {} }; struct hresult_canceled : hresult_error { - hresult_canceled(WINRT_IMPL_SOURCE_LOCATION_ARGS_SINGLE_PARAM) noexcept : hresult_error(impl::error_canceled WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_canceled(param::hstring const& message WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_canceled, message WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_canceled(take_ownership_from_abi_t WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_canceled, take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} + hresult_canceled(winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_canceled, sourceInformation) {} + hresult_canceled(hresult_error::no_originate_t) noexcept : hresult_error(impl::error_canceled, hresult_error::no_originate) {} + hresult_canceled(param::hstring const& message, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_canceled, message, sourceInformation) {} + hresult_canceled(take_ownership_from_abi_t, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_canceled, take_ownership_from_abi, sourceInformation) {} }; - [[noreturn]] inline WINRT_IMPL_NOINLINE void throw_hresult(hresult const result WINRT_IMPL_SOURCE_LOCATION_ARGS) + [[noreturn]] inline WINRT_IMPL_NOINLINE void throw_hresult(hresult const result, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) { if (winrt_throw_hresult_handler) { -#ifdef WINRT_SOURCE_LOCATION_ACTIVE winrt_throw_hresult_handler(sourceInformation.line(), sourceInformation.file_name(), sourceInformation.function_name(), WINRT_IMPL_RETURNADDRESS(), result); -#else - winrt_throw_hresult_handler(0, nullptr, nullptr, WINRT_IMPL_RETURNADDRESS(), result); -#endif } if (result == impl::error_bad_alloc) @@ -351,70 +351,70 @@ WINRT_EXPORT namespace winrt if (result == impl::error_access_denied) { - throw hresult_access_denied(take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD); + throw hresult_access_denied(take_ownership_from_abi, sourceInformation); } if (result == impl::error_wrong_thread) { - throw hresult_wrong_thread(take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD); + throw hresult_wrong_thread(take_ownership_from_abi, sourceInformation); } if (result == impl::error_not_implemented) { - throw hresult_not_implemented(take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD); + throw hresult_not_implemented(take_ownership_from_abi, sourceInformation); } if (result == impl::error_invalid_argument) { - throw hresult_invalid_argument(take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD); + throw hresult_invalid_argument(take_ownership_from_abi, sourceInformation); } if (result == impl::error_out_of_bounds) { - throw hresult_out_of_bounds(take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD); + throw hresult_out_of_bounds(take_ownership_from_abi, sourceInformation); } if (result == impl::error_no_interface) { - throw hresult_no_interface(take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD); + throw hresult_no_interface(take_ownership_from_abi, sourceInformation); } if (result == impl::error_class_not_available) { - throw hresult_class_not_available(take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD); + throw hresult_class_not_available(take_ownership_from_abi, sourceInformation); } if (result == impl::error_class_not_registered) { - throw hresult_class_not_registered(take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD); + throw hresult_class_not_registered(take_ownership_from_abi, sourceInformation); } if (result == impl::error_changed_state) { - throw hresult_changed_state(take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD); + throw hresult_changed_state(take_ownership_from_abi, sourceInformation); } if (result == impl::error_illegal_method_call) { - throw hresult_illegal_method_call(take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD); + throw hresult_illegal_method_call(take_ownership_from_abi, sourceInformation); } if (result == impl::error_illegal_state_change) { - throw hresult_illegal_state_change(take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD); + throw hresult_illegal_state_change(take_ownership_from_abi, sourceInformation); } if (result == impl::error_illegal_delegate_assignment) { - throw hresult_illegal_delegate_assignment(take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD); + throw hresult_illegal_delegate_assignment(take_ownership_from_abi, sourceInformation); } if (result == impl::error_canceled) { - throw hresult_canceled(take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD); + throw hresult_canceled(take_ownership_from_abi, sourceInformation); } - throw hresult_error(result, take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD); + throw hresult_error(result, take_ownership_from_abi, sourceInformation); } inline WINRT_IMPL_NOINLINE hresult to_hresult() noexcept @@ -471,59 +471,59 @@ WINRT_EXPORT namespace winrt } catch (...) { - abort(); + std::abort(); } } - [[noreturn]] inline void throw_last_error(WINRT_IMPL_SOURCE_LOCATION_ARGS_SINGLE_PARAM) + [[noreturn]] inline void throw_last_error(winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) { - throw_hresult(impl::hresult_from_win32(WINRT_IMPL_GetLastError()) WINRT_IMPL_SOURCE_LOCATION_FORWARD); + throw_hresult(impl::hresult_from_win32(WINRT_IMPL_GetLastError()), sourceInformation); } - inline hresult check_hresult(hresult const result WINRT_IMPL_SOURCE_LOCATION_ARGS_NO_DEFAULT) + inline hresult check_hresult(hresult const result, winrt::impl::slim_source_location const& sourceInformation) { if (result < 0) { - throw_hresult(result WINRT_IMPL_SOURCE_LOCATION_FORWARD); + throw_hresult(result, sourceInformation); } return result; } template - void check_nt(T result WINRT_IMPL_SOURCE_LOCATION_ARGS) + void check_nt(T result, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) { if (result != 0) { - throw_hresult(impl::hresult_from_nt(result) WINRT_IMPL_SOURCE_LOCATION_FORWARD); + throw_hresult(impl::hresult_from_nt(result), sourceInformation); } } template - void check_win32(T result WINRT_IMPL_SOURCE_LOCATION_ARGS) + void check_win32(T result, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) { if (result != 0) { - throw_hresult(impl::hresult_from_win32(result) WINRT_IMPL_SOURCE_LOCATION_FORWARD); + throw_hresult(impl::hresult_from_win32(result), sourceInformation); } } template - T check_bool(T result WINRT_IMPL_SOURCE_LOCATION_ARGS) + T check_bool(T result, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) { if (!result) { - winrt::throw_last_error(WINRT_IMPL_SOURCE_LOCATION_FORWARD_SINGLE_PARAM); + winrt::throw_last_error(sourceInformation); } return result; } template - T* check_pointer(T* pointer WINRT_IMPL_SOURCE_LOCATION_ARGS) + T* check_pointer(T* pointer, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) { if (!pointer) { - throw_last_error(WINRT_IMPL_SOURCE_LOCATION_FORWARD_SINGLE_PARAM); + throw_last_error(sourceInformation); } return pointer; @@ -532,17 +532,17 @@ WINRT_EXPORT namespace winrt [[noreturn]] inline void terminate() noexcept { WINRT_IMPL_RoFailFastWithErrorContext(to_hresult()); - abort(); + std::abort(); } } -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { - inline hresult check_hresult_allow_bounds(hresult const result WINRT_IMPL_SOURCE_LOCATION_ARGS) + inline hresult check_hresult_allow_bounds(hresult const result, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) { if (result != impl::error_out_of_bounds && result != impl::error_fail && result != impl::error_file_not_found) { - check_hresult(result WINRT_IMPL_SOURCE_LOCATION_FORWARD); + check_hresult(result, sourceInformation); } return result; } diff --git a/strings/base_events.h b/strings/base_events.h index 77952474e..c21124e9c 100644 --- a/strings/base_events.h +++ b/strings/base_events.h @@ -3,7 +3,7 @@ WINRT_EXPORT namespace winrt { struct event_token { - int64_t value{}; + std::int64_t value{}; explicit operator bool() const noexcept { @@ -22,7 +22,7 @@ WINRT_EXPORT namespace winrt template struct event_revoker { - using method_type = int32_t(__stdcall impl::abi_t::*)(winrt::event_token); + using method_type = std::int32_t(__stdcall impl::abi_t::*)(winrt::event_token); event_revoker() noexcept = default; event_revoker(event_revoker const&) = delete; @@ -77,7 +77,7 @@ WINRT_EXPORT namespace winrt template struct factory_event_revoker { - using method_type = int32_t(__stdcall impl::abi_t::*)(winrt::event_token); + using method_type = std::int32_t(__stdcall impl::abi_t::*)(winrt::event_token); factory_event_revoker() noexcept = default; factory_event_revoker(factory_event_revoker const&) = delete; @@ -130,7 +130,7 @@ WINRT_EXPORT namespace winrt }; } -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template struct event_revoker @@ -267,7 +267,7 @@ namespace winrt::impl using pointer = value_type*; using iterator = value_type*; - explicit event_array(uint32_t const count) noexcept : m_size(count) + explicit event_array(std::uint32_t const count) noexcept : m_size(count) { std::uninitialized_fill_n(data(), count, value_type()); } @@ -306,7 +306,7 @@ namespace winrt::impl return data() + m_size; } - uint32_t size() const noexcept + std::uint32_t size() const noexcept { return m_size; } @@ -324,11 +324,11 @@ namespace winrt::impl } atomic_ref_count m_references{ 1 }; - uint32_t m_size{ 0 }; + std::uint32_t m_size{ 0 }; }; template - com_ptr> make_event_array(uint32_t const capacity) + com_ptr> make_event_array(std::uint32_t const capacity) { void* raw = ::operator new(sizeof(event_array) + (sizeof(T)* capacity)); #ifdef _MSC_VER @@ -339,12 +339,12 @@ namespace winrt::impl WINRT_IMPL_NOINLINE inline bool report_failed_invoke() { - int32_t const code = to_hresult(); + std::int32_t const code = to_hresult(); WINRT_IMPL_RoTransformError(code, 0, nullptr); - if (code == static_cast(0x80010108) || // RPC_E_DISCONNECTED - code == static_cast(0x800706BA) || // HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE) - code == static_cast(0x89020001)) // JSCRIPT_E_CANTEXECUTE + if (code == static_cast(0x80010108) || // RPC_E_DISCONNECTED + code == static_cast(0x800706BA) || // HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE) + code == static_cast(0x89020001)) // JSCRIPT_E_CANTEXECUTE { return false; } @@ -402,7 +402,7 @@ WINRT_EXPORT namespace winrt return; } - uint32_t available_slots = m_targets->size() - 1; + std::uint32_t available_slots = m_targets->size() - 1; delegate_array new_targets; bool removed = false; @@ -516,7 +516,7 @@ WINRT_EXPORT namespace winrt event_token get_token(delegate_type const& delegate) const noexcept { - return event_token{ reinterpret_cast(WINRT_IMPL_EncodePointer(get_abi(delegate))) }; + return event_token{ reinterpret_cast(WINRT_IMPL_EncodePointer(get_abi(delegate))) }; } using delegate_array = com_ptr>; diff --git a/strings/base_extern.h b/strings/base_extern.h index 92872d416..a17908ac4 100644 --- a/strings/base_extern.h +++ b/strings/base_extern.h @@ -1,8 +1,11 @@ -__declspec(selectany) int32_t(__stdcall* winrt_to_hresult_handler)(void* address) noexcept {}; -__declspec(selectany) winrt::hstring(__stdcall* winrt_to_message_handler)(void* address) {}; -__declspec(selectany) void(__stdcall* winrt_throw_hresult_handler)(uint32_t lineNumber, char const* fileName, char const* functionName, void* returnAddress, winrt::hresult const result) noexcept {}; -__declspec(selectany) int32_t(__stdcall* winrt_activation_handler)(void* classId, winrt::guid const& iid, void** factory) noexcept {}; +// These global function pointers must use WINRT_EXPORT (which expands to +// 'export extern "C++"' in module builds) so that module and non-module TUs +// in the same binary share the same instances. +WINRT_EXPORT __declspec(selectany) std::int32_t(__stdcall* winrt_to_hresult_handler)(void* address) noexcept {}; +WINRT_EXPORT __declspec(selectany) winrt::hstring(__stdcall* winrt_to_message_handler)(void* address) {}; +WINRT_EXPORT __declspec(selectany) void(__stdcall* winrt_throw_hresult_handler)(std::uint32_t lineNumber, char const* fileName, char const* functionName, void* returnAddress, winrt::hresult const result) noexcept {}; +WINRT_EXPORT __declspec(selectany) std::int32_t(__stdcall* winrt_activation_handler)(void* classId, winrt::guid const& iid, void** factory) noexcept {}; #if defined(_MSC_VER) #ifdef _M_HYBRID @@ -24,87 +27,88 @@ __declspec(selectany) int32_t(__stdcall* winrt_activation_handler)(void* classId extern "C" { - int32_t __stdcall WINRT_IMPL_RoGetActivationFactory(void* classId, winrt::guid const& iid, void** factory) noexcept WINRT_IMPL_LINK(RoGetActivationFactory, 12); - int32_t __stdcall WINRT_IMPL_RoGetAgileReference(uint32_t options, winrt::guid const& iid, void* object, void** reference) noexcept WINRT_IMPL_LINK(RoGetAgileReference, 16); - int32_t __stdcall WINRT_IMPL_SetThreadpoolTimerEx(winrt::impl::ptp_timer, void*, uint32_t, uint32_t) noexcept WINRT_IMPL_LINK(SetThreadpoolTimerEx, 16); - int32_t __stdcall WINRT_IMPL_SetThreadpoolWaitEx(winrt::impl::ptp_wait, void*, void*, void*) noexcept WINRT_IMPL_LINK(SetThreadpoolWaitEx, 16); - int32_t __stdcall WINRT_IMPL_RoOriginateLanguageException(int32_t error, void* message, void* exception) noexcept WINRT_IMPL_LINK(RoOriginateLanguageException, 12); - void __stdcall WINRT_IMPL_RoFailFastWithErrorContext(int32_t) noexcept WINRT_IMPL_LINK(RoFailFastWithErrorContext, 4); - int32_t __stdcall WINRT_IMPL_RoTransformError(int32_t, int32_t, void*) noexcept WINRT_IMPL_LINK(RoTransformError, 12); + std::int32_t __stdcall WINRT_IMPL_RoGetActivationFactory(void* classId, winrt::guid const& iid, void** factory) noexcept WINRT_IMPL_LINK(RoGetActivationFactory, 12); + std::int32_t __stdcall WINRT_IMPL_RoGetAgileReference(std::uint32_t options, winrt::guid const& iid, void* object, void** reference) noexcept WINRT_IMPL_LINK(RoGetAgileReference, 16); + std::int32_t __stdcall WINRT_IMPL_SetThreadpoolTimerEx(winrt::impl::ptp_timer, void*, std::uint32_t, std::uint32_t) noexcept WINRT_IMPL_LINK(SetThreadpoolTimerEx, 16); + std::int32_t __stdcall WINRT_IMPL_SetThreadpoolWaitEx(winrt::impl::ptp_wait, void*, void*, void*) noexcept WINRT_IMPL_LINK(SetThreadpoolWaitEx, 16); + std::int32_t __stdcall WINRT_IMPL_RoOriginateLanguageException(std::int32_t error, void* message, void* exception) noexcept WINRT_IMPL_LINK(RoOriginateLanguageException, 12); + std::int32_t __stdcall WINRT_IMPL_RoCaptureErrorContext(std::int32_t error) noexcept WINRT_IMPL_LINK(RoCaptureErrorContext, 4); + void __stdcall WINRT_IMPL_RoFailFastWithErrorContext(std::int32_t) noexcept WINRT_IMPL_LINK(RoFailFastWithErrorContext, 4); + std::int32_t __stdcall WINRT_IMPL_RoTransformError(std::int32_t, std::int32_t, void*) noexcept WINRT_IMPL_LINK(RoTransformError, 12); - void* __stdcall WINRT_IMPL_LoadLibraryExW(wchar_t const* name, void* unused, uint32_t flags) noexcept WINRT_IMPL_LINK(LoadLibraryExW, 12); - int32_t __stdcall WINRT_IMPL_FreeLibrary(void* library) noexcept WINRT_IMPL_LINK(FreeLibrary, 4); + void* __stdcall WINRT_IMPL_LoadLibraryExW(wchar_t const* name, void* unused, std::uint32_t flags) noexcept WINRT_IMPL_LINK(LoadLibraryExW, 12); + std::int32_t __stdcall WINRT_IMPL_FreeLibrary(void* library) noexcept WINRT_IMPL_LINK(FreeLibrary, 4); void* __stdcall WINRT_IMPL_GetProcAddress(void* library, char const* name) noexcept WINRT_IMPL_LINK(GetProcAddress, 8); - int32_t __stdcall WINRT_IMPL_SetErrorInfo(uint32_t reserved, void* info) noexcept WINRT_IMPL_LINK(SetErrorInfo, 8); - int32_t __stdcall WINRT_IMPL_GetErrorInfo(uint32_t reserved, void** info) noexcept WINRT_IMPL_LINK(GetErrorInfo, 8); - int32_t __stdcall WINRT_IMPL_CoInitializeEx(void*, uint32_t type) noexcept WINRT_IMPL_LINK(CoInitializeEx, 8); + std::int32_t __stdcall WINRT_IMPL_SetErrorInfo(std::uint32_t reserved, void* info) noexcept WINRT_IMPL_LINK(SetErrorInfo, 8); + std::int32_t __stdcall WINRT_IMPL_GetErrorInfo(std::uint32_t reserved, void** info) noexcept WINRT_IMPL_LINK(GetErrorInfo, 8); + std::int32_t __stdcall WINRT_IMPL_CoInitializeEx(void*, std::uint32_t type) noexcept WINRT_IMPL_LINK(CoInitializeEx, 8); void __stdcall WINRT_IMPL_CoUninitialize() noexcept WINRT_IMPL_LINK(CoUninitialize, 0); - int32_t __stdcall WINRT_IMPL_CoCreateFreeThreadedMarshaler(void* outer, void** marshaler) noexcept WINRT_IMPL_LINK(CoCreateFreeThreadedMarshaler, 8); - int32_t __stdcall WINRT_IMPL_CoCreateInstance(winrt::guid const& clsid, void* outer, uint32_t context, winrt::guid const& iid, void** object) noexcept WINRT_IMPL_LINK(CoCreateInstance, 20); - int32_t __stdcall WINRT_IMPL_CoGetCallContext(winrt::guid const& iid, void** object) noexcept WINRT_IMPL_LINK(CoGetCallContext, 8); - int32_t __stdcall WINRT_IMPL_CoGetObjectContext(winrt::guid const& iid, void** object) noexcept WINRT_IMPL_LINK(CoGetObjectContext, 8); - int32_t __stdcall WINRT_IMPL_CoGetApartmentType(int32_t* type, int32_t* qualifier) noexcept WINRT_IMPL_LINK(CoGetApartmentType, 8); + std::int32_t __stdcall WINRT_IMPL_CoCreateFreeThreadedMarshaler(void* outer, void** marshaler) noexcept WINRT_IMPL_LINK(CoCreateFreeThreadedMarshaler, 8); + std::int32_t __stdcall WINRT_IMPL_CoCreateInstance(winrt::guid const& clsid, void* outer, std::uint32_t context, winrt::guid const& iid, void** object) noexcept WINRT_IMPL_LINK(CoCreateInstance, 20); + std::int32_t __stdcall WINRT_IMPL_CoGetCallContext(winrt::guid const& iid, void** object) noexcept WINRT_IMPL_LINK(CoGetCallContext, 8); + std::int32_t __stdcall WINRT_IMPL_CoGetObjectContext(winrt::guid const& iid, void** object) noexcept WINRT_IMPL_LINK(CoGetObjectContext, 8); + std::int32_t __stdcall WINRT_IMPL_CoGetApartmentType(std::int32_t* type, std::int32_t* qualifier) noexcept WINRT_IMPL_LINK(CoGetApartmentType, 8); void* __stdcall WINRT_IMPL_CoTaskMemAlloc(std::size_t size) noexcept WINRT_IMPL_LINK(CoTaskMemAlloc, 4); void __stdcall WINRT_IMPL_CoTaskMemFree(void* ptr) noexcept WINRT_IMPL_LINK(CoTaskMemFree, 4); winrt::impl::bstr __stdcall WINRT_IMPL_SysAllocString(wchar_t const* value) noexcept WINRT_IMPL_LINK(SysAllocString, 4); void __stdcall WINRT_IMPL_SysFreeString(winrt::impl::bstr string) noexcept WINRT_IMPL_LINK(SysFreeString, 4); - uint32_t __stdcall WINRT_IMPL_SysStringLen(winrt::impl::bstr string) noexcept WINRT_IMPL_LINK(SysStringLen, 4); - int32_t __stdcall WINRT_IMPL_IIDFromString(wchar_t const* string, winrt::guid* iid) noexcept WINRT_IMPL_LINK(IIDFromString, 8); - int32_t __stdcall WINRT_IMPL_MultiByteToWideChar(uint32_t codepage, uint32_t flags, char const* in_string, int32_t in_size, wchar_t* out_string, int32_t out_size) noexcept WINRT_IMPL_LINK(MultiByteToWideChar, 24); - int32_t __stdcall WINRT_IMPL_WideCharToMultiByte(uint32_t codepage, uint32_t flags, wchar_t const* int_string, int32_t in_size, char* out_string, int32_t out_size, char const* default_char, int32_t* default_used) noexcept WINRT_IMPL_LINK(WideCharToMultiByte, 32); - void* __stdcall WINRT_IMPL_HeapAlloc(void* heap, uint32_t flags, size_t bytes) noexcept WINRT_IMPL_LINK(HeapAlloc, 12); - int32_t __stdcall WINRT_IMPL_HeapFree(void* heap, uint32_t flags, void* value) noexcept WINRT_IMPL_LINK(HeapFree, 12); + std::uint32_t __stdcall WINRT_IMPL_SysStringLen(winrt::impl::bstr string) noexcept WINRT_IMPL_LINK(SysStringLen, 4); + std::int32_t __stdcall WINRT_IMPL_IIDFromString(wchar_t const* string, winrt::guid* iid) noexcept WINRT_IMPL_LINK(IIDFromString, 8); + std::int32_t __stdcall WINRT_IMPL_MultiByteToWideChar(std::uint32_t codepage, std::uint32_t flags, char const* in_string, std::int32_t in_size, wchar_t* out_string, std::int32_t out_size) noexcept WINRT_IMPL_LINK(MultiByteToWideChar, 24); + std::int32_t __stdcall WINRT_IMPL_WideCharToMultiByte(std::uint32_t codepage, std::uint32_t flags, wchar_t const* int_string, std::int32_t in_size, char* out_string, std::int32_t out_size, char const* default_char, std::int32_t* default_used) noexcept WINRT_IMPL_LINK(WideCharToMultiByte, 32); + void* __stdcall WINRT_IMPL_HeapAlloc(void* heap, std::uint32_t flags, std::size_t bytes) noexcept WINRT_IMPL_LINK(HeapAlloc, 12); + std::int32_t __stdcall WINRT_IMPL_HeapFree(void* heap, std::uint32_t flags, void* value) noexcept WINRT_IMPL_LINK(HeapFree, 12); void* __stdcall WINRT_IMPL_GetProcessHeap() noexcept WINRT_IMPL_LINK(GetProcessHeap, 0); - uint32_t __stdcall WINRT_IMPL_FormatMessageW(uint32_t flags, void const* source, uint32_t code, uint32_t language, wchar_t* buffer, uint32_t size, va_list* arguments) noexcept WINRT_IMPL_LINK(FormatMessageW, 28); - uint32_t __stdcall WINRT_IMPL_GetLastError() noexcept WINRT_IMPL_LINK(GetLastError, 0); + std::uint32_t __stdcall WINRT_IMPL_FormatMessageW(std::uint32_t flags, void const* source, std::uint32_t code, std::uint32_t language, wchar_t* buffer, std::uint32_t size, va_list* arguments) noexcept WINRT_IMPL_LINK(FormatMessageW, 28); + std::uint32_t __stdcall WINRT_IMPL_GetLastError() noexcept WINRT_IMPL_LINK(GetLastError, 0); void __stdcall WINRT_IMPL_GetSystemTimePreciseAsFileTime(void* result) noexcept WINRT_IMPL_LINK(GetSystemTimePreciseAsFileTime, 4); - uintptr_t __stdcall WINRT_IMPL_VirtualQuery(void* address, void* buffer, uintptr_t length) noexcept WINRT_IMPL_LINK(VirtualQuery, 12); + std::uintptr_t __stdcall WINRT_IMPL_VirtualQuery(void* address, void* buffer, std::uintptr_t length) noexcept WINRT_IMPL_LINK(VirtualQuery, 12); void* __stdcall WINRT_IMPL_EncodePointer(void* ptr) noexcept WINRT_IMPL_LINK(EncodePointer, 4); - int32_t __stdcall WINRT_IMPL_OpenProcessToken(void* process, uint32_t access, void** token) noexcept WINRT_IMPL_LINK(OpenProcessToken, 12); + std::int32_t __stdcall WINRT_IMPL_OpenProcessToken(void* process, std::uint32_t access, void** token) noexcept WINRT_IMPL_LINK(OpenProcessToken, 12); void* __stdcall WINRT_IMPL_GetCurrentProcess() noexcept WINRT_IMPL_LINK(GetCurrentProcess, 0); - int32_t __stdcall WINRT_IMPL_DuplicateToken(void* existing, uint32_t level, void** duplicate) noexcept WINRT_IMPL_LINK(DuplicateToken, 12); - int32_t __stdcall WINRT_IMPL_OpenThreadToken(void* thread, uint32_t access, int32_t self, void** token) noexcept WINRT_IMPL_LINK(OpenThreadToken, 16); + std::int32_t __stdcall WINRT_IMPL_DuplicateToken(void* existing, std::uint32_t level, void** duplicate) noexcept WINRT_IMPL_LINK(DuplicateToken, 12); + std::int32_t __stdcall WINRT_IMPL_OpenThreadToken(void* thread, std::uint32_t access, std::int32_t self, void** token) noexcept WINRT_IMPL_LINK(OpenThreadToken, 16); void* __stdcall WINRT_IMPL_GetCurrentThread() noexcept WINRT_IMPL_LINK(GetCurrentThread, 0); - int32_t __stdcall WINRT_IMPL_SetThreadToken(void** thread, void* token) noexcept WINRT_IMPL_LINK(SetThreadToken, 8); + std::int32_t __stdcall WINRT_IMPL_SetThreadToken(void** thread, void* token) noexcept WINRT_IMPL_LINK(SetThreadToken, 8); void __stdcall WINRT_IMPL_AcquireSRWLockExclusive(winrt::impl::srwlock* lock) noexcept WINRT_IMPL_LINK(AcquireSRWLockExclusive, 4); void __stdcall WINRT_IMPL_AcquireSRWLockShared(winrt::impl::srwlock* lock) noexcept WINRT_IMPL_LINK(AcquireSRWLockShared, 4); - uint8_t __stdcall WINRT_IMPL_TryAcquireSRWLockExclusive(winrt::impl::srwlock* lock) noexcept WINRT_IMPL_LINK(TryAcquireSRWLockExclusive, 4); - uint8_t __stdcall WINRT_IMPL_TryAcquireSRWLockShared(winrt::impl::srwlock* lock) noexcept WINRT_IMPL_LINK(TryAcquireSRWLockShared, 4); + std::uint8_t __stdcall WINRT_IMPL_TryAcquireSRWLockExclusive(winrt::impl::srwlock* lock) noexcept WINRT_IMPL_LINK(TryAcquireSRWLockExclusive, 4); + std::uint8_t __stdcall WINRT_IMPL_TryAcquireSRWLockShared(winrt::impl::srwlock* lock) noexcept WINRT_IMPL_LINK(TryAcquireSRWLockShared, 4); void __stdcall WINRT_IMPL_ReleaseSRWLockExclusive(winrt::impl::srwlock* lock) noexcept WINRT_IMPL_LINK(ReleaseSRWLockExclusive, 4); void __stdcall WINRT_IMPL_ReleaseSRWLockShared(winrt::impl::srwlock* lock) noexcept WINRT_IMPL_LINK(ReleaseSRWLockShared, 4); - int32_t __stdcall WINRT_IMPL_SleepConditionVariableSRW(winrt::impl::condition_variable* cv, winrt::impl::srwlock* lock, uint32_t milliseconds, uint32_t flags) noexcept WINRT_IMPL_LINK(SleepConditionVariableSRW, 16); + std::int32_t __stdcall WINRT_IMPL_SleepConditionVariableSRW(winrt::impl::condition_variable* cv, winrt::impl::srwlock* lock, std::uint32_t milliseconds, std::uint32_t flags) noexcept WINRT_IMPL_LINK(SleepConditionVariableSRW, 16); void __stdcall WINRT_IMPL_WakeConditionVariable(winrt::impl::condition_variable* cv) noexcept WINRT_IMPL_LINK(WakeConditionVariable, 4); void __stdcall WINRT_IMPL_WakeAllConditionVariable(winrt::impl::condition_variable* cv) noexcept WINRT_IMPL_LINK(WakeAllConditionVariable, 4); void* __stdcall WINRT_IMPL_InterlockedPushEntrySList(void* head, void* entry) noexcept WINRT_IMPL_LINK(InterlockedPushEntrySList, 8); void* __stdcall WINRT_IMPL_InterlockedFlushSList(void* head) noexcept WINRT_IMPL_LINK(InterlockedFlushSList, 4); - void* __stdcall WINRT_IMPL_CreateEventW(void*, int32_t, int32_t, void*) noexcept WINRT_IMPL_LINK(CreateEventW, 16); - int32_t __stdcall WINRT_IMPL_SetEvent(void*) noexcept WINRT_IMPL_LINK(SetEvent, 4); - int32_t __stdcall WINRT_IMPL_CloseHandle(void* hObject) noexcept WINRT_IMPL_LINK(CloseHandle, 4); - uint32_t __stdcall WINRT_IMPL_WaitForSingleObject(void* handle, uint32_t milliseconds) noexcept WINRT_IMPL_LINK(WaitForSingleObject, 8); + void* __stdcall WINRT_IMPL_CreateEventW(void*, std::int32_t, std::int32_t, void*) noexcept WINRT_IMPL_LINK(CreateEventW, 16); + std::int32_t __stdcall WINRT_IMPL_SetEvent(void*) noexcept WINRT_IMPL_LINK(SetEvent, 4); + std::int32_t __stdcall WINRT_IMPL_CloseHandle(void* hObject) noexcept WINRT_IMPL_LINK(CloseHandle, 4); + std::uint32_t __stdcall WINRT_IMPL_WaitForSingleObject(void* handle, std::uint32_t milliseconds) noexcept WINRT_IMPL_LINK(WaitForSingleObject, 8); - int32_t __stdcall WINRT_IMPL_TrySubmitThreadpoolCallback(void(__stdcall *callback)(void*, void* context), void* context, void*) noexcept WINRT_IMPL_LINK(TrySubmitThreadpoolCallback, 12); + std::int32_t __stdcall WINRT_IMPL_TrySubmitThreadpoolCallback(void(__stdcall *callback)(void*, void* context), void* context, void*) noexcept WINRT_IMPL_LINK(TrySubmitThreadpoolCallback, 12); winrt::impl::ptp_timer __stdcall WINRT_IMPL_CreateThreadpoolTimer(void(__stdcall *callback)(void*, void* context, void*), void* context, void*) noexcept WINRT_IMPL_LINK(CreateThreadpoolTimer, 12); - void __stdcall WINRT_IMPL_SetThreadpoolTimer(winrt::impl::ptp_timer timer, void* time, uint32_t period, uint32_t window) noexcept WINRT_IMPL_LINK(SetThreadpoolTimer, 16); + void __stdcall WINRT_IMPL_SetThreadpoolTimer(winrt::impl::ptp_timer timer, void* time, std::uint32_t period, std::uint32_t window) noexcept WINRT_IMPL_LINK(SetThreadpoolTimer, 16); void __stdcall WINRT_IMPL_CloseThreadpoolTimer(winrt::impl::ptp_timer timer) noexcept WINRT_IMPL_LINK(CloseThreadpoolTimer, 4); - winrt::impl::ptp_wait __stdcall WINRT_IMPL_CreateThreadpoolWait(void(__stdcall *callback)(void*, void* context, void*, uint32_t result), void* context, void*) noexcept WINRT_IMPL_LINK(CreateThreadpoolWait, 12); + winrt::impl::ptp_wait __stdcall WINRT_IMPL_CreateThreadpoolWait(void(__stdcall *callback)(void*, void* context, void*, std::uint32_t result), void* context, void*) noexcept WINRT_IMPL_LINK(CreateThreadpoolWait, 12); void __stdcall WINRT_IMPL_SetThreadpoolWait(winrt::impl::ptp_wait wait, void* handle, void* timeout) noexcept WINRT_IMPL_LINK(SetThreadpoolWait, 12); void __stdcall WINRT_IMPL_CloseThreadpoolWait(winrt::impl::ptp_wait wait) noexcept WINRT_IMPL_LINK(CloseThreadpoolWait, 4); - winrt::impl::ptp_io __stdcall WINRT_IMPL_CreateThreadpoolIo(void* object, void(__stdcall *callback)(void*, void* context, void* overlapped, uint32_t result, std::size_t bytes, void*) noexcept, void* context, void*) noexcept WINRT_IMPL_LINK(CreateThreadpoolIo, 16); + winrt::impl::ptp_io __stdcall WINRT_IMPL_CreateThreadpoolIo(void* object, void(__stdcall *callback)(void*, void* context, void* overlapped, std::uint32_t result, std::size_t bytes, void*) noexcept, void* context, void*) noexcept WINRT_IMPL_LINK(CreateThreadpoolIo, 16); void __stdcall WINRT_IMPL_StartThreadpoolIo(winrt::impl::ptp_io io) noexcept WINRT_IMPL_LINK(StartThreadpoolIo, 4); void __stdcall WINRT_IMPL_CancelThreadpoolIo(winrt::impl::ptp_io io) noexcept WINRT_IMPL_LINK(CancelThreadpoolIo, 4); void __stdcall WINRT_IMPL_CloseThreadpoolIo(winrt::impl::ptp_io io) noexcept WINRT_IMPL_LINK(CloseThreadpoolIo, 4); winrt::impl::ptp_pool __stdcall WINRT_IMPL_CreateThreadpool(void* reserved) noexcept WINRT_IMPL_LINK(CreateThreadpool, 4); - void __stdcall WINRT_IMPL_SetThreadpoolThreadMaximum(winrt::impl::ptp_pool pool, uint32_t value) noexcept WINRT_IMPL_LINK(SetThreadpoolThreadMaximum, 8); - int32_t __stdcall WINRT_IMPL_SetThreadpoolThreadMinimum(winrt::impl::ptp_pool pool, uint32_t value) noexcept WINRT_IMPL_LINK(SetThreadpoolThreadMinimum, 8); + void __stdcall WINRT_IMPL_SetThreadpoolThreadMaximum(winrt::impl::ptp_pool pool, std::uint32_t value) noexcept WINRT_IMPL_LINK(SetThreadpoolThreadMaximum, 8); + std::int32_t __stdcall WINRT_IMPL_SetThreadpoolThreadMinimum(winrt::impl::ptp_pool pool, std::uint32_t value) noexcept WINRT_IMPL_LINK(SetThreadpoolThreadMinimum, 8); void __stdcall WINRT_IMPL_CloseThreadpool(winrt::impl::ptp_pool pool) noexcept WINRT_IMPL_LINK(CloseThreadpool, 4); - int32_t __stdcall WINRT_CanUnloadNow() noexcept; - int32_t __stdcall WINRT_GetActivationFactory(void* classId, void** factory) noexcept; + std::int32_t __stdcall WINRT_CanUnloadNow() noexcept; + std::int32_t __stdcall WINRT_GetActivationFactory(void* classId, void** factory) noexcept; } #undef WINRT_IMPL_LINK diff --git a/strings/base_fast_forward.h b/strings/base_fast_forward.h index 88d99469a..a73e70a04 100644 --- a/strings/base_fast_forward.h +++ b/strings/base_fast_forward.h @@ -1,5 +1,7 @@ #include #include +#include +#include #define WINRT_IMPL_STRING_1(expression) #expression #define WINRT_IMPL_STRING(expression) WINRT_IMPL_STRING_1(expression) @@ -10,6 +12,16 @@ #define WINRT_IMPL_FF_NOVTABLE #endif +#if defined(__clang__) && defined(__has_attribute) +#if __has_attribute(__lto_visibility_public__) +#define WINRT_IMPL_FF_PUBLIC __attribute__((lto_visibility_public)) +#else +#define WINRT_IMPL_FF_PUBLIC +#endif // __has_attribute(__lto_visibility_public__) +#else +#define WINRT_IMPL_FF_PUBLIC +#endif + #if !defined(WINRT_FAST_ABI_SIZE) #define WINRT_FAST_ABI_SIZE % #endif @@ -18,7 +30,11 @@ static_assert(WINRT_FAST_ABI_SIZE >= %); #pragma detect_mismatch("WINRT_FAST_ABI_SIZE", WINRT_IMPL_STRING(WINRT_FAST_ABI_SIZE)) -namespace winrt::impl +#ifndef WINRT_EXPORT +#define WINRT_EXPORT +#endif // WINRT_EXPORT + +WINRT_EXPORT namespace winrt::impl { // Thunk definitions are in arch-specific assembly sources % @@ -26,34 +42,34 @@ namespace winrt::impl { struct guid { - uint32_t Data1; - uint16_t Data2; - uint16_t Data3; - uint8_t Data4[8]; + std::uint32_t Data1; + std::uint16_t Data2; + std::uint16_t Data3; + std::uint8_t Data4[8]; inline bool operator!=(guid const& right) const noexcept { - return memcmp(this, &right, sizeof(guid)); + return std::memcmp(this, &right, sizeof(guid)); } }; - struct WINRT_IMPL_FF_NOVTABLE inspectable + struct WINRT_IMPL_FF_NOVTABLE WINRT_IMPL_FF_PUBLIC inspectable { - virtual int32_t __stdcall QueryInterface(guid const& id, void** object) noexcept = 0; - virtual uint32_t __stdcall AddRef() noexcept = 0; - virtual uint32_t __stdcall Release() noexcept = 0; - virtual int32_t __stdcall GetIids(uint32_t* count, guid** ids) noexcept = 0; - virtual int32_t __stdcall GetRuntimeClassName(void** name) noexcept = 0; - virtual int32_t __stdcall GetTrustLevel(uint32_t* level) noexcept = 0; + virtual std::int32_t __stdcall QueryInterface(guid const& id, void** object) noexcept = 0; + virtual std::uint32_t __stdcall AddRef() noexcept = 0; + virtual std::uint32_t __stdcall Release() noexcept = 0; + virtual std::int32_t __stdcall GetIids(std::uint32_t* count, guid** ids) noexcept = 0; + virtual std::int32_t __stdcall GetRuntimeClassName(void** name) noexcept = 0; + virtual std::int32_t __stdcall GetTrustLevel(std::uint32_t* level) noexcept = 0; }; void* const* m_vfptr; inspectable* m_owner; std::size_t m_offset; guid m_iid; - std::atomic m_references{ 1 }; + std::atomic m_references{ 1 }; fast_abi_forwarder(void* owner, guid const& iid, std::size_t offset) noexcept : - m_vfptr(s_vtable), m_owner(static_cast(owner)), m_iid(iid), m_offset(offset) + m_vfptr(s_vtable), m_owner(static_cast(owner)), m_offset(offset), m_iid(iid) { m_owner->AddRef(); } @@ -63,7 +79,7 @@ namespace winrt::impl m_owner->Release(); } - static int32_t __stdcall QueryInterface(fast_abi_forwarder* self, guid const& iid, void** object) noexcept + static std::int32_t __stdcall QueryInterface(fast_abi_forwarder* self, guid const& iid, void** object) noexcept { if (iid != self->m_iid) { @@ -75,14 +91,14 @@ namespace winrt::impl } // Note: COM interfaces use stdcall, not thiscall, ('this' gets no special treatment), permitting static implementations - static uint32_t __stdcall AddRef(fast_abi_forwarder* self) noexcept + static std::uint32_t __stdcall AddRef(fast_abi_forwarder* self) noexcept { return 1 + self->m_references.fetch_add(1, std::memory_order_relaxed); } - static uint32_t __stdcall Release(fast_abi_forwarder* self) noexcept + static std::uint32_t __stdcall Release(fast_abi_forwarder* self) noexcept { - uint32_t const remaining = self->m_references.fetch_sub(1, std::memory_order_release) - 1; + std::uint32_t const remaining = self->m_references.fetch_sub(1, std::memory_order_release) - 1; if (remaining == 0) { std::atomic_thread_fence(std::memory_order_acquire); @@ -91,21 +107,26 @@ namespace winrt::impl return remaining; } - static uint32_t __stdcall GetIids(fast_abi_forwarder* self, uint32_t* count, guid** iids) noexcept + static std::uint32_t __stdcall GetIids(fast_abi_forwarder* self, std::uint32_t* count, guid** iids) noexcept { return self->m_owner->GetIids(count, iids); } - static uint32_t __stdcall GetRuntimeClassName(fast_abi_forwarder* self, void** name) noexcept + static std::uint32_t __stdcall GetRuntimeClassName(fast_abi_forwarder* self, void** name) noexcept { return self->m_owner->GetRuntimeClassName(name); } - static uint32_t __stdcall GetTrustLevel(fast_abi_forwarder* self, uint32_t* level) noexcept + static std::uint32_t __stdcall GetTrustLevel(fast_abi_forwarder* self, std::uint32_t* level) noexcept { return self->m_owner->GetTrustLevel(level); } + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wmicrosoft-cast" +#endif static inline void* const s_vtable[] = { QueryInterface, @@ -115,6 +136,9 @@ namespace winrt::impl GetRuntimeClassName, GetTrustLevel, % }; +#ifdef __clang__ +#pragma clang diagnostic pop +#endif }; // Enforce assumptions made by thunk asm code @@ -126,7 +150,7 @@ namespace winrt::impl namespace winrt { template - auto make_fast_abi_forwarder(void* owner, TGuid const& guid, size_t offset) + auto make_fast_abi_forwarder(void* owner, TGuid const& guid, std::size_t offset) { using ff_guid = impl::fast_abi_forwarder::guid; static_assert(sizeof(ff_guid) == sizeof(TGuid)); @@ -137,3 +161,4 @@ namespace winrt #undef WINRT_IMPL_STRING #undef WINRT_IMPL_STRING_1 #undef WINRT_IMPL_FF_NOVTABLE +#undef WINRT_IMPL_FF_PUBLIC diff --git a/strings/base_foundation.h b/strings/base_foundation.h index ea8881edc..083252753 100644 --- a/strings/base_foundation.h +++ b/strings/base_foundation.h @@ -100,7 +100,7 @@ WINRT_EXPORT namespace winrt::Windows::Foundation } } -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template <> inline constexpr auto& name_v = L"Windows.Foundation.Point"; template <> inline constexpr auto& name_v = L"Windows.Foundation.Size"; diff --git a/strings/base_identity.h b/strings/base_identity.h index 0f4a163b6..4a5bedbb1 100644 --- a/strings/base_identity.h +++ b/strings/base_identity.h @@ -11,39 +11,39 @@ WINRT_EXPORT namespace winrt } template - bool is_guid_of(guid const& id) noexcept + constexpr bool is_guid_of(guid const& id) noexcept { return ((id == guid_of()) || ...); } } -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { - template + template constexpr std::array to_array(T const* value, std::index_sequence const) noexcept { return { value[Index]... }; } - template + template constexpr auto to_array(std::array const& value) noexcept { return value; } - template + template constexpr auto to_array(char const(&value)[Size]) noexcept { return to_array(value, std::make_index_sequence()); } - template + template constexpr auto to_array(wchar_t const(&value)[Size]) noexcept { return to_array(value, std::make_index_sequence()); } - template + template constexpr std::array concat( [[maybe_unused]] std::array const& left, [[maybe_unused]] std::array const& right, @@ -53,31 +53,31 @@ namespace winrt::impl return { left[LeftIndex]..., right[RightIndex]... }; } - template + template constexpr auto concat(std::array const& left, std::array const& right) noexcept { return concat(left, right, std::make_index_sequence(), std::make_index_sequence()); } - template + template constexpr auto concat(std::array const& left, T const(&right)[RightSize]) noexcept { return concat(left, to_array(right)); } - template + template constexpr auto concat(T const(&left)[LeftSize], std::array const& right) noexcept { return concat(to_array(left), right); } - template + template constexpr auto concat(std::array const& left, T const right) noexcept { return concat(left, std::array{right}); } - template + template constexpr auto concat(T const left, std::array const& right) noexcept { return concat(std::array{left}, right); @@ -96,31 +96,31 @@ namespace winrt::impl } } - template + template constexpr std::array zconcat_base(std::array const& left, std::array const& right, std::index_sequence const, std::index_sequence const) noexcept { return { left[LI]..., right[RI]..., T{} }; } - template + template constexpr auto zconcat(std::array const& left, std::array const& right) noexcept { return zconcat_base(left, right, std::make_index_sequence(), std::make_index_sequence()); } - template + template constexpr std::array to_zarray_base(T const(&value)[S], std::index_sequence const) noexcept { return { value[I]... }; } - template + template constexpr auto to_zarray(T const(&value)[S]) noexcept { return to_zarray_base(value, std::make_index_sequence()); } - template + template constexpr auto to_zarray(std::array const& value) noexcept { return value; @@ -139,43 +139,43 @@ namespace winrt::impl } } - constexpr std::array to_array(uint32_t value) noexcept + constexpr std::array to_array(std::uint32_t value) noexcept { - return { static_cast(value & 0x000000ff), static_cast((value & 0x0000ff00) >> 8), static_cast((value & 0x00ff0000) >> 16), static_cast((value & 0xff000000) >> 24) }; + return { static_cast(value & 0x000000ff), static_cast((value & 0x0000ff00) >> 8), static_cast((value & 0x00ff0000) >> 16), static_cast((value & 0xff000000) >> 24) }; } - constexpr std::array to_array(uint16_t value) noexcept + constexpr std::array to_array(std::uint16_t value) noexcept { - return { static_cast(value & 0x00ff), static_cast((value & 0xff00) >> 8) }; + return { static_cast(value & 0x00ff), static_cast((value & 0xff00) >> 8) }; } constexpr auto to_array(guid const& value) noexcept { return combine(to_array(value.Data1), to_array(value.Data2), to_array(value.Data3), - std::array{ value.Data4[0], value.Data4[1], value.Data4[2], value.Data4[3], value.Data4[4], value.Data4[5], value.Data4[6], value.Data4[7] }); + std::array{ value.Data4[0], value.Data4[1], value.Data4[2], value.Data4[3], value.Data4[4], value.Data4[5], value.Data4[6], value.Data4[7] }); } template - constexpr T to_hex_digit(uint8_t value) noexcept + constexpr T to_hex_digit(std::uint8_t value) noexcept { value &= 0xF; return value < 10 ? static_cast('0') + value : static_cast('a') + (value - 10); } template - constexpr std::array uint8_to_hex(uint8_t const value) noexcept + constexpr std::array uint8_to_hex(std::uint8_t const value) noexcept { return { to_hex_digit(value >> 4), to_hex_digit(value & 0xF) }; } template - constexpr auto uint16_to_hex(uint16_t value) noexcept + constexpr auto uint16_to_hex(std::uint16_t value) noexcept { - return combine(uint8_to_hex(static_cast(value >> 8)), uint8_to_hex(value & 0xFF)); + return combine(uint8_to_hex(static_cast(value >> 8)), uint8_to_hex(value & 0xFF)); } template - constexpr auto uint32_to_hex(uint32_t const value) noexcept + constexpr auto uint32_to_hex(std::uint32_t const value) noexcept { return combine(uint16_to_hex(value >> 16), uint16_to_hex(value & 0xFFFF)); } @@ -197,18 +197,18 @@ namespace winrt::impl ); } - constexpr uint32_t to_guid(uint8_t a, uint8_t b, uint8_t c, uint8_t d) noexcept + constexpr std::uint32_t to_guid(std::uint8_t a, std::uint8_t b, std::uint8_t c, std::uint8_t d) noexcept { - return (static_cast(d) << 24) | (static_cast(c) << 16) | (static_cast(b) << 8) | static_cast(a); + return (static_cast(d) << 24) | (static_cast(c) << 16) | (static_cast(b) << 8) | static_cast(a); } - constexpr uint16_t to_guid(uint8_t a, uint8_t b) noexcept + constexpr std::uint16_t to_guid(std::uint8_t a, std::uint8_t b) noexcept { - return (static_cast(b) << 8) | static_cast(a); + return (static_cast(b) << 8) | static_cast(a); } - template - constexpr guid to_guid(std::array const& arr) noexcept + template + constexpr guid to_guid(std::array const& arr) noexcept { return { @@ -219,12 +219,12 @@ namespace winrt::impl }; } - constexpr uint32_t endian_swap(uint32_t value) noexcept + constexpr std::uint32_t endian_swap(std::uint32_t value) noexcept { return (value & 0xFF000000) >> 24 | (value & 0x00FF0000) >> 8 | (value & 0x0000FF00) << 8 | (value & 0x000000FF) << 24; } - constexpr uint16_t endian_swap(uint16_t value) noexcept + constexpr std::uint16_t endian_swap(std::uint16_t value) noexcept { return (value & 0xFF00) >> 8 | (value & 0x00FF) << 8; } @@ -239,51 +239,51 @@ namespace winrt::impl constexpr guid set_named_guid_fields(guid value) noexcept { - value.Data3 = static_cast((value.Data3 & 0x0fff) | (5 << 12)); - value.Data4[0] = static_cast((value.Data4[0] & 0x3f) | 0x80); + value.Data3 = static_cast((value.Data3 & 0x0fff) | (5 << 12)); + value.Data4[0] = static_cast((value.Data4[0] & 0x3f) | 0x80); return value; } - template - constexpr std::array char_to_byte_array(std::array const& value, std::index_sequence const) noexcept + template + constexpr std::array char_to_byte_array(std::array const& value, std::index_sequence const) noexcept { - return { static_cast(value[Index])... }; + return { static_cast(value[Index])... }; } - constexpr auto sha1_rotl(uint8_t bits, uint32_t word) noexcept + constexpr auto sha1_rotl(std::uint8_t bits, std::uint32_t word) noexcept { return (word << bits) | (word >> (32 - bits)); } - constexpr auto sha_ch(uint32_t x, uint32_t y, uint32_t z) noexcept + constexpr auto sha_ch(std::uint32_t x, std::uint32_t y, std::uint32_t z) noexcept { return (x & y) ^ ((~x) & z); } - constexpr auto sha_parity(uint32_t x, uint32_t y, uint32_t z) noexcept + constexpr auto sha_parity(std::uint32_t x, std::uint32_t y, std::uint32_t z) noexcept { return x ^ y ^ z; } - constexpr auto sha_maj(uint32_t x, uint32_t y, uint32_t z) noexcept + constexpr auto sha_maj(std::uint32_t x, std::uint32_t y, std::uint32_t z) noexcept { return (x & y) ^ (x & z) ^ (y & z); } - constexpr std::array process_msg_block(uint8_t const* input, size_t start_pos, std::array const& intermediate_hash) noexcept + constexpr std::array process_msg_block(std::uint8_t const* input, std::size_t start_pos, std::array const& intermediate_hash) noexcept { - uint32_t const K[4] = { 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6 }; - std::array W = {}; + std::uint32_t const K[4] = { 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6 }; + std::array W = {}; - size_t t = 0; - uint32_t temp = 0; + std::size_t t = 0; + std::uint32_t temp = 0; for (t = 0; t < 16; t++) { - W[t] = static_cast(input[start_pos + t * 4]) << 24; - W[t] = W[t] | static_cast(input[start_pos + t * 4 + 1]) << 16; - W[t] = W[t] | static_cast(input[start_pos + t * 4 + 2]) << 8; - W[t] = W[t] | static_cast(input[start_pos + t * 4 + 3]); + W[t] = static_cast(input[start_pos + t * 4]) << 24; + W[t] = W[t] | static_cast(input[start_pos + t * 4 + 1]) << 16; + W[t] = W[t] | static_cast(input[start_pos + t * 4 + 2]) << 8; + W[t] = W[t] | static_cast(input[start_pos + t * 4 + 3]); } for (t = 16; t < 80; t++) @@ -291,11 +291,11 @@ namespace winrt::impl W[t] = sha1_rotl(1, W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16]); } - uint32_t A = intermediate_hash[0]; - uint32_t B = intermediate_hash[1]; - uint32_t C = intermediate_hash[2]; - uint32_t D = intermediate_hash[3]; - uint32_t E = intermediate_hash[4]; + std::uint32_t A = intermediate_hash[0]; + std::uint32_t B = intermediate_hash[1]; + std::uint32_t C = intermediate_hash[2]; + std::uint32_t D = intermediate_hash[3]; + std::uint32_t E = intermediate_hash[4]; for (t = 0; t < 20; t++) { @@ -340,54 +340,54 @@ namespace winrt::impl return { intermediate_hash[0] + A, intermediate_hash[1] + B, intermediate_hash[2] + C, intermediate_hash[3] + D, intermediate_hash[4] + E }; } - template - constexpr std::array process_msg_block(std::array const& input, size_t start_pos, std::array const& intermediate_hash) noexcept + template + constexpr std::array process_msg_block(std::array const& input, std::size_t start_pos, std::array const& intermediate_hash) noexcept { return process_msg_block(input.data(), start_pos, intermediate_hash); } - constexpr std::array size_to_bytes(size_t size) noexcept + constexpr std::array size_to_bytes(std::size_t size) noexcept { return { - static_cast((size & 0xff00000000000000) >> 56), - static_cast((size & 0x00ff000000000000) >> 48), - static_cast((size & 0x0000ff0000000000) >> 40), - static_cast((size & 0x000000ff00000000) >> 32), - static_cast((size & 0x00000000ff000000) >> 24), - static_cast((size & 0x0000000000ff0000) >> 16), - static_cast((size & 0x000000000000ff00) >> 8), - static_cast((size & 0x00000000000000ff) >> 0) + static_cast((size & 0xff00000000000000) >> 56), + static_cast((size & 0x00ff000000000000) >> 48), + static_cast((size & 0x0000ff0000000000) >> 40), + static_cast((size & 0x000000ff00000000) >> 32), + static_cast((size & 0x00000000ff000000) >> 24), + static_cast((size & 0x0000000000ff0000) >> 16), + static_cast((size & 0x000000000000ff00) >> 8), + static_cast((size & 0x00000000000000ff) >> 0) }; } - template - constexpr std::array make_remaining([[maybe_unused]] std::array const& input, [[maybe_unused]] size_t start_pos, std::index_sequence) noexcept + template + constexpr std::array make_remaining([[maybe_unused]] std::array const& input, [[maybe_unused]] std::size_t start_pos, std::index_sequence) noexcept { return { input[Index + start_pos]..., 0x80 }; } - template - constexpr auto make_remaining(std::array const& input, size_t start_pos) noexcept + template + constexpr auto make_remaining(std::array const& input, std::size_t start_pos) noexcept { constexpr auto remaining_size = Size % 64; return make_remaining(input, start_pos, std::make_index_sequence()); } - template - constexpr auto make_buffer(std::array const& remaining_buffer) noexcept + template + constexpr auto make_buffer(std::array const& remaining_buffer) noexcept { constexpr auto message_length = (RemainderSize + 8 <= 64) ? 64 : 64 * 2; constexpr auto padding_length = message_length - RemainderSize - 8; - auto padding_buffer = std::array{}; + auto padding_buffer = std::array{}; auto length_buffer = size_to_bytes(InputSize * 8); return combine(remaining_buffer, padding_buffer, length_buffer); } - template - constexpr std::array finalize_remaining_buffer(std::array const& input, std::array const& intermediate_hash) noexcept + template + constexpr std::array finalize_remaining_buffer(std::array const& input, std::array const& intermediate_hash) noexcept { if constexpr (Size == 64) { @@ -399,22 +399,22 @@ namespace winrt::impl } } - template - constexpr std::array get_result(std::array const& intermediate_hash, std::index_sequence) noexcept + template + constexpr std::array get_result(std::array const& intermediate_hash, std::index_sequence) noexcept { - return { static_cast(intermediate_hash[Index >> 2] >> (8 * (3 - (Index & 0x03))))... }; + return { static_cast(intermediate_hash[Index >> 2] >> (8 * (3 - (Index & 0x03))))... }; } - constexpr auto get_result(std::array const& intermediate_hash) noexcept + constexpr auto get_result(std::array const& intermediate_hash) noexcept { return get_result(intermediate_hash, std::make_index_sequence<20>{}); } - template - constexpr auto calculate_sha1(std::array const& input) noexcept + template + constexpr auto calculate_sha1(std::array const& input) noexcept { - std::array intermediate_hash{ 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0 }; - size_t i = 0; + std::array intermediate_hash{ 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0 }; + std::size_t i = 0; while (i + 64 <= Size) { @@ -426,7 +426,7 @@ namespace winrt::impl return get_result(intermediate_hash); } - template + template constexpr guid generate_guid(std::array const& value) noexcept { guid namespace_guid = { 0xd57af411, 0x737b, 0xc042,{ 0xab, 0xae, 0x87, 0x8b, 0x1e, 0x16, 0xad, 0xee } }; @@ -472,7 +472,7 @@ namespace winrt::impl ) }; - constexpr size_t to_utf8_size(wchar_t const value) noexcept + constexpr std::size_t to_utf8_size(wchar_t const value) noexcept { if (value <= 0x7F) { @@ -487,7 +487,7 @@ namespace winrt::impl return 3; } - constexpr size_t to_utf8(wchar_t const value, char* buffer) noexcept + constexpr std::size_t to_utf8(wchar_t const value, char* buffer) noexcept { if (value <= 0x7F) { @@ -509,10 +509,10 @@ namespace winrt::impl } template - constexpr size_t to_utf8_size() noexcept + constexpr std::size_t to_utf8_size() noexcept { auto input = to_array(name_v); - size_t length = 0; + std::size_t length = 0; for (wchar_t const element : input) { @@ -527,7 +527,7 @@ namespace winrt::impl { auto input = to_array(name_v); std::array()> output{}; - size_t offset{}; + std::size_t offset{}; for (wchar_t const element : input) { @@ -544,14 +544,14 @@ namespace winrt::impl constexpr auto& basic_signature_v = ""; template <> inline constexpr auto& basic_signature_v = "b1"; - template <> inline constexpr auto& basic_signature_v = "i1"; - template <> inline constexpr auto& basic_signature_v = "i2"; - template <> inline constexpr auto& basic_signature_v = "i4"; - template <> inline constexpr auto& basic_signature_v = "i8"; - template <> inline constexpr auto& basic_signature_v = "u1"; - template <> inline constexpr auto& basic_signature_v = "u2"; - template <> inline constexpr auto& basic_signature_v = "u4"; - template <> inline constexpr auto& basic_signature_v = "u8"; + template <> inline constexpr auto& basic_signature_v = "i1"; + template <> inline constexpr auto& basic_signature_v = "i2"; + template <> inline constexpr auto& basic_signature_v = "i4"; + template <> inline constexpr auto& basic_signature_v = "i8"; + template <> inline constexpr auto& basic_signature_v = "u1"; + template <> inline constexpr auto& basic_signature_v = "u2"; + template <> inline constexpr auto& basic_signature_v = "u4"; + template <> inline constexpr auto& basic_signature_v = "u8"; template <> inline constexpr auto& basic_signature_v = "f4"; template <> inline constexpr auto& basic_signature_v = "f8"; template <> inline constexpr auto& basic_signature_v = "c2"; @@ -560,14 +560,14 @@ namespace winrt::impl template <> inline constexpr auto& basic_signature_v = "cinterface(IInspectable)"; template <> inline constexpr auto& name_v = L"Boolean"; - template <> inline constexpr auto& name_v = L"Int8"; - template <> inline constexpr auto& name_v = L"Int16"; - template <> inline constexpr auto& name_v = L"Int32"; - template <> inline constexpr auto& name_v = L"Int64"; - template <> inline constexpr auto& name_v = L"UInt8"; - template <> inline constexpr auto& name_v = L"UInt16"; - template <> inline constexpr auto& name_v = L"UInt32"; - template <> inline constexpr auto& name_v = L"UInt64"; + template <> inline constexpr auto& name_v = L"Int8"; + template <> inline constexpr auto& name_v = L"Int16"; + template <> inline constexpr auto& name_v = L"Int32"; + template <> inline constexpr auto& name_v = L"Int64"; + template <> inline constexpr auto& name_v = L"UInt8"; + template <> inline constexpr auto& name_v = L"UInt16"; + template <> inline constexpr auto& name_v = L"UInt32"; + template <> inline constexpr auto& name_v = L"UInt64"; template <> inline constexpr auto& name_v = L"Single"; template <> inline constexpr auto& name_v = L"Double"; template <> inline constexpr auto& name_v = L"Char16"; @@ -581,23 +581,23 @@ namespace winrt::impl template <> inline constexpr auto& name_v = L"IAgileObject"; template <> struct category { using type = basic_category; }; - template <> struct category { using type = basic_category; }; - template <> struct category { using type = basic_category; }; - template <> struct category { using type = basic_category; }; - template <> struct category { using type = basic_category; }; - template <> struct category { using type = basic_category; }; - template <> struct category { using type = basic_category; }; - template <> struct category { using type = basic_category; }; - template <> struct category { using type = basic_category; }; + template <> struct category { using type = basic_category; }; + template <> struct category { using type = basic_category; }; + template <> struct category { using type = basic_category; }; + template <> struct category { using type = basic_category; }; + template <> struct category { using type = basic_category; }; + template <> struct category { using type = basic_category; }; + template <> struct category { using type = basic_category; }; + template <> struct category { using type = basic_category; }; template <> struct category { using type = basic_category; }; template <> struct category { using type = basic_category; }; template <> struct category { using type = basic_category; }; template <> struct category { using type = basic_category; }; - template <> struct category { using type = struct_category; }; - template <> struct category { using type = struct_category; }; + template <> struct category { using type = struct_category; }; + template <> struct category { using type = struct_category; }; template <> struct category { using type = basic_category; }; - template <> struct category { using type = struct_category; }; - template <> struct category { using type = struct_category; }; + template <> struct category { using type = struct_category; }; + template <> struct category { using type = struct_category; }; template struct category_signature @@ -642,13 +642,13 @@ namespace winrt::impl constexpr static auto data{ combine("delegate(", to_array(guid_of()), ")") }; }; - template + template constexpr std::wstring_view to_wstring_view(std::array const& value) noexcept { return { value.data(), Size - 1 }; } - template + template constexpr std::wstring_view to_wstring_view(wchar_t const (&value)[Size]) noexcept { return { value, Size - 1 }; diff --git a/strings/base_implements.h b/strings/base_implements.h index d0bb09012..0eb8db0bd 100644 --- a/strings/base_implements.h +++ b/strings/base_implements.h @@ -6,7 +6,7 @@ #endif #endif -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { struct marker { @@ -30,7 +30,7 @@ WINRT_EXPORT namespace winrt struct implements; } -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template using tuple_cat_t = decltype(std::tuple_cat(std::declval()...)); @@ -216,11 +216,11 @@ namespace winrt::impl } template - void zero_abi([[maybe_unused]] void* ptr, [[maybe_unused]] uint32_t const capacity) noexcept + void zero_abi([[maybe_unused]] void* ptr, [[maybe_unused]] std::uint32_t const capacity) noexcept { if constexpr (!std::is_trivially_destructible_v) { - memset(ptr, 0, sizeof(T) * capacity); + std::memset(ptr, 0, sizeof(T) * capacity); } } @@ -229,7 +229,7 @@ namespace winrt::impl { if constexpr (!std::is_trivially_destructible_v) { - memset(ptr, 0, sizeof(T)); + std::memset(ptr, 0, sizeof(T)); } } } @@ -267,7 +267,7 @@ WINRT_EXPORT namespace winrt } } -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template struct interface_list; @@ -522,32 +522,32 @@ namespace winrt::impl return*static_cast(reinterpret_cast*>(this)); } - int32_t __stdcall QueryInterface(guid const& id, void** object) noexcept override + std::int32_t __stdcall QueryInterface(guid const& id, void** object) noexcept override { return shim().QueryInterface(id, object); } - uint32_t __stdcall AddRef() noexcept override + std::uint32_t __stdcall AddRef() noexcept override { return shim().AddRef(); } - uint32_t __stdcall Release() noexcept override + std::uint32_t __stdcall Release() noexcept override { return shim().Release(); } - int32_t __stdcall GetIids(uint32_t* count, guid** array) noexcept override + std::int32_t __stdcall GetIids(std::uint32_t* count, guid** array) noexcept override { return shim().GetIids(reinterpret_cast(count), reinterpret_cast(array)); } - int32_t __stdcall GetRuntimeClassName(void** name) noexcept override + std::int32_t __stdcall GetRuntimeClassName(void** name) noexcept override { return shim().abi_GetRuntimeClassName(name); } - int32_t __stdcall GetTrustLevel(Windows::Foundation::TrustLevel* trustLevel) noexcept final + std::int32_t __stdcall GetTrustLevel(Windows::Foundation::TrustLevel* trustLevel) noexcept final { return shim().abi_GetTrustLevel(trustLevel); } @@ -579,27 +579,27 @@ namespace winrt::impl template struct produce : produce_base { - int32_t __stdcall QueryInterface(guid const& id, void** object) noexcept final + std::int32_t __stdcall QueryInterface(guid const& id, void** object) noexcept final { return this->shim().NonDelegatingQueryInterface(id, object); } - uint32_t __stdcall AddRef() noexcept final + std::uint32_t __stdcall AddRef() noexcept final { return this->shim().NonDelegatingAddRef(); } - uint32_t __stdcall Release() noexcept final + std::uint32_t __stdcall Release() noexcept final { return this->shim().NonDelegatingRelease(); } - int32_t __stdcall GetIids(uint32_t* count, guid** array) noexcept final + std::int32_t __stdcall GetIids(std::uint32_t* count, guid** array) noexcept final { return this->shim().NonDelegatingGetIids(count, array); } - int32_t __stdcall GetRuntimeClassName(void** name) noexcept final + std::int32_t __stdcall GetRuntimeClassName(void** name) noexcept final { return this->shim().NonDelegatingGetRuntimeClassName(name); } @@ -619,7 +619,7 @@ namespace winrt::impl return static_cast*>(reinterpret_cast*>(this)); } - int32_t __stdcall QueryInterface(guid const& id, void** object) noexcept final + std::int32_t __stdcall QueryInterface(guid const& id, void** object) noexcept final { if (is_guid_of(id)) { @@ -631,17 +631,17 @@ namespace winrt::impl return that()->m_object->QueryInterface(id, object); } - uint32_t __stdcall AddRef() noexcept final + std::uint32_t __stdcall AddRef() noexcept final { return that()->increment_strong(); } - uint32_t __stdcall Release() noexcept final + std::uint32_t __stdcall Release() noexcept final { return that()->m_object->Release(); } - int32_t __stdcall GetWeakReference(IWeakReference** weakReference) noexcept final + std::int32_t __stdcall GetWeakReference(IWeakReference** weakReference) noexcept final { *weakReference = that(); that()->AddRef(); @@ -659,14 +659,14 @@ namespace winrt::impl template struct weak_ref final : IWeakReference, weak_source_producer { - weak_ref(unknown_abi* object, uint32_t const strong) noexcept : + weak_ref(unknown_abi* object, std::uint32_t const strong) noexcept : m_object(object), m_strong(strong) { WINRT_ASSERT(object); } - int32_t __stdcall QueryInterface(guid const& id, void** object) noexcept final + std::int32_t __stdcall QueryInterface(guid const& id, void** object) noexcept final { if (is_guid_of(id) || is_guid_of(id)) { @@ -694,14 +694,14 @@ namespace winrt::impl return error_no_interface; } - uint32_t __stdcall AddRef() noexcept final + std::uint32_t __stdcall AddRef() noexcept final { return 1 + m_weak.fetch_add(1, std::memory_order_relaxed); } - uint32_t __stdcall Release() noexcept final + std::uint32_t __stdcall Release() noexcept final { - uint32_t const target = m_weak.fetch_sub(1, std::memory_order_relaxed) - 1; + std::uint32_t const target = m_weak.fetch_sub(1, std::memory_order_relaxed) - 1; if (target == 0) { @@ -711,9 +711,9 @@ namespace winrt::impl return target; } - int32_t __stdcall Resolve(guid const& id, void** objectReference) noexcept final + std::int32_t __stdcall Resolve(guid const& id, void** objectReference) noexcept final { - uint32_t target = m_strong.load(std::memory_order_relaxed); + std::uint32_t target = m_strong.load(std::memory_order_relaxed); while (true) { @@ -725,26 +725,26 @@ namespace winrt::impl if (m_strong.compare_exchange_weak(target, target + 1, std::memory_order_acquire, std::memory_order_relaxed)) { - int32_t hr = m_object->QueryInterface(id, objectReference); + std::int32_t hr = m_object->QueryInterface(id, objectReference); m_strong.fetch_sub(1, std::memory_order_relaxed); return hr; } } } - void set_strong(uint32_t const count) noexcept + void set_strong(std::uint32_t const count) noexcept { m_strong = count; } - uint32_t increment_strong() noexcept + std::uint32_t increment_strong() noexcept { return 1 + m_strong.fetch_add(1, std::memory_order_relaxed); } - uint32_t decrement_strong() noexcept + std::uint32_t decrement_strong() noexcept { - uint32_t const target = m_strong.fetch_sub(1, std::memory_order_release) - 1; + std::uint32_t const target = m_strong.fetch_sub(1, std::memory_order_release) - 1; if (target == 0) { @@ -767,8 +767,8 @@ namespace winrt::impl static_assert(sizeof(weak_source_producer) == sizeof(weak_source)); unknown_abi* m_object{}; - std::atomic m_strong{ 1 }; - std::atomic m_weak{ 1 }; + std::atomic m_strong{ 1 }; + std::atomic m_weak{ 1 }; }; template @@ -792,9 +792,20 @@ namespace winrt::impl { return m_inner.operator bool(); } + + template + friend auto winrt::impl::try_as_with_reason(From ptr, hresult& code) noexcept; + protected: static constexpr bool is_composing = true; Windows::Foundation::IInspectable m_inner; + + private: + template + auto try_as_with_reason(hresult& code) const noexcept + { + return m_inner.try_as_with_reason(code); + } }; template @@ -831,14 +842,14 @@ namespace winrt::impl using IInspectable = Windows::Foundation::IInspectable; using root_implements_type = root_implements; - int32_t __stdcall QueryInterface(guid const& id, void** object) noexcept + std::int32_t __stdcall QueryInterface(guid const& id, void** object) noexcept { if (this->outer()) { return this->outer()->QueryInterface(id, object); } - int32_t result = query_interface(id, object); + std::int32_t result = query_interface(id, object); if (result == error_no_interface && this->m_inner) { @@ -848,7 +859,7 @@ namespace winrt::impl return result; } - uint32_t __stdcall AddRef() noexcept + std::uint32_t __stdcall AddRef() noexcept { if (this->outer()) { @@ -858,7 +869,7 @@ namespace winrt::impl return NonDelegatingAddRef(); } - uint32_t __stdcall Release() noexcept + std::uint32_t __stdcall Release() noexcept { if (this->outer()) { @@ -896,7 +907,7 @@ namespace winrt::impl protected: - virtual int32_t query_interface_tearoff(guid const&, void**) const noexcept + virtual std::int32_t query_interface_tearoff(guid const&, void**) const noexcept { return error_no_interface; } @@ -911,7 +922,7 @@ namespace winrt::impl subtract_final_reference(); } - int32_t __stdcall GetIids(uint32_t* count, guid** array) noexcept + std::int32_t __stdcall GetIids(std::uint32_t* count, guid** array) noexcept { if (this->outer()) { @@ -921,7 +932,7 @@ namespace winrt::impl return NonDelegatingGetIids(count, array); } - int32_t __stdcall abi_GetRuntimeClassName(void** name) noexcept + std::int32_t __stdcall abi_GetRuntimeClassName(void** name) noexcept { if (this->outer()) { @@ -931,7 +942,7 @@ namespace winrt::impl return NonDelegatingGetRuntimeClassName(name); } - int32_t __stdcall abi_GetTrustLevel(Windows::Foundation::TrustLevel* trustLevel) noexcept + std::int32_t __stdcall abi_GetTrustLevel(Windows::Foundation::TrustLevel* trustLevel) noexcept { if (this->outer()) { @@ -941,11 +952,11 @@ namespace winrt::impl return NonDelegatingGetTrustLevel(trustLevel); } - uint32_t __stdcall NonDelegatingAddRef() noexcept + std::uint32_t __stdcall NonDelegatingAddRef() noexcept { if constexpr (is_weak_ref_source::value) { - uintptr_t count_or_pointer = m_references.load(std::memory_order_relaxed); + std::uintptr_t count_or_pointer = m_references.load(std::memory_order_relaxed); while (true) { @@ -954,11 +965,11 @@ namespace winrt::impl return decode_weak_ref(count_or_pointer)->increment_strong(); } - uintptr_t const target = count_or_pointer + 1; + std::uintptr_t const target = count_or_pointer + 1; if (m_references.compare_exchange_weak(count_or_pointer, target, std::memory_order_relaxed)) { - return static_cast(target); + return static_cast(target); } } } @@ -968,9 +979,9 @@ namespace winrt::impl } } - uint32_t __stdcall NonDelegatingRelease() noexcept + std::uint32_t __stdcall NonDelegatingRelease() noexcept { - uint32_t const target = subtract_reference(); + std::uint32_t const target = subtract_reference(); if (target == 0) { @@ -987,7 +998,7 @@ namespace winrt::impl return target; } - int32_t __stdcall NonDelegatingQueryInterface(guid const& id, void** object) noexcept + std::int32_t __stdcall NonDelegatingQueryInterface(guid const& id, void** object) noexcept { if (is_guid_of(id) || is_guid_of(id)) { @@ -997,7 +1008,7 @@ namespace winrt::impl return 0; } - int32_t result = query_interface(id, object); + std::int32_t result = query_interface(id, object); if (result == error_no_interface && this->m_inner) { @@ -1007,10 +1018,10 @@ namespace winrt::impl return result; } - int32_t __stdcall NonDelegatingGetIids(uint32_t* count, guid** array) noexcept + std::int32_t __stdcall NonDelegatingGetIids(std::uint32_t* count, guid** array) noexcept { auto const& local_iids = static_cast(this)->get_local_iids(); - uint32_t const& local_count = local_iids.first; + std::uint32_t const& local_count = local_iids.first; if constexpr (root_implements_type::is_composing) { if (local_count > 0) @@ -1022,8 +1033,8 @@ namespace winrt::impl { return error_bad_alloc; } - *array = std::copy(local_iids.second, local_iids.second + local_count, *array); - std::copy(inner_iids.cbegin(), inner_iids.cend(), *array); + auto next = std::copy(local_iids.second, local_iids.second + local_count, *array); + std::copy(inner_iids.cbegin(), inner_iids.cend(), next); } else { @@ -1051,25 +1062,25 @@ namespace winrt::impl return 0; } - int32_t __stdcall NonDelegatingGetRuntimeClassName(void** name) noexcept try + std::int32_t __stdcall NonDelegatingGetRuntimeClassName(void** name) noexcept try { *name = detach_abi(static_cast(this)->GetRuntimeClassName()); return 0; } catch (...) { return to_hresult(); } - int32_t __stdcall NonDelegatingGetTrustLevel(Windows::Foundation::TrustLevel* trustLevel) noexcept try + std::int32_t __stdcall NonDelegatingGetTrustLevel(Windows::Foundation::TrustLevel* trustLevel) noexcept try { *trustLevel = static_cast(this)->GetTrustLevel(); return 0; } catch (...) { return to_hresult(); } - uint32_t subtract_final_reference() noexcept + std::uint32_t subtract_final_reference() noexcept { if constexpr (is_weak_ref_source::value) { - uintptr_t count_or_pointer = m_references.load(std::memory_order_relaxed); + std::uintptr_t count_or_pointer = m_references.load(std::memory_order_relaxed); while (true) { @@ -1078,11 +1089,11 @@ namespace winrt::impl return decode_weak_ref(count_or_pointer)->decrement_strong(); } - uintptr_t const target = count_or_pointer - 1; + std::uintptr_t const target = count_or_pointer - 1; if (m_references.compare_exchange_weak(count_or_pointer, target, std::memory_order_release, std::memory_order_relaxed)) { - return static_cast(target); + return static_cast(target); } } } @@ -1092,9 +1103,9 @@ namespace winrt::impl } } - uint32_t subtract_reference() noexcept + std::uint32_t subtract_reference() noexcept { - uint32_t result = subtract_final_reference(); + std::uint32_t result = subtract_final_reference(); if (result == 0) { @@ -1144,9 +1155,9 @@ namespace winrt::impl using use_module_lock = std::negation...>>; using weak_ref_t = impl::weak_ref; - std::atomic> m_references{ 1 }; + std::atomic> m_references{ 1 }; - int32_t query_interface(guid const& id, void** object) noexcept + std::int32_t query_interface(guid const& id, void** object) noexcept { *object = static_cast(this)->find_interface(id); @@ -1159,7 +1170,7 @@ namespace winrt::impl return query_interface_common(id, object); } - WINRT_IMPL_NOINLINE int32_t query_interface_common(guid const& id, void** object) noexcept + WINRT_IMPL_NOINLINE std::int32_t query_interface_common(guid const& id, void** object) noexcept { if (is_guid_of(id)) { @@ -1209,21 +1220,21 @@ namespace winrt::impl { if constexpr (is_weak_ref_source::value) { - uintptr_t count_or_pointer = m_references.load(std::memory_order_relaxed); + std::uintptr_t count_or_pointer = m_references.load(std::memory_order_relaxed); if (is_weak_ref(count_or_pointer)) { return decode_weak_ref(count_or_pointer)->get_source(); } - com_ptr weak_ref(new (std::nothrow) weak_ref_t(get_unknown(), static_cast(count_or_pointer)), take_ownership_from_abi); + com_ptr weak_ref(new (std::nothrow) weak_ref_t(get_unknown(), static_cast(count_or_pointer)), take_ownership_from_abi); if (!weak_ref) { return nullptr; } - uintptr_t const encoding = encode_weak_ref(weak_ref.get()); + std::uintptr_t const encoding = encode_weak_ref(weak_ref.get()); while (true) { @@ -1239,7 +1250,7 @@ namespace winrt::impl return decode_weak_ref(count_or_pointer)->get_source(); } - weak_ref->set_strong(static_cast(count_or_pointer)); + weak_ref->set_strong(static_cast(count_or_pointer)); } } else @@ -1249,28 +1260,28 @@ namespace winrt::impl } } - static bool is_weak_ref(intptr_t const value) noexcept + static bool is_weak_ref(std::intptr_t const value) noexcept { static_assert(is_weak_ref_source::value, "Weak references are not supported because no_weak_ref was specified."); return value < 0; } - static weak_ref_t* decode_weak_ref(uintptr_t const value) noexcept + static weak_ref_t* decode_weak_ref(std::uintptr_t const value) noexcept { static_assert(is_weak_ref_source::value, "Weak references are not supported because no_weak_ref was specified."); return reinterpret_cast(value << 1); } - static uintptr_t encode_weak_ref(weak_ref_t* value) noexcept + static std::uintptr_t encode_weak_ref(weak_ref_t* value) noexcept { static_assert(is_weak_ref_source::value, "Weak references are not supported because no_weak_ref was specified."); - constexpr uintptr_t pointer_flag = static_cast(1) << ((sizeof(uintptr_t) * 8) - 1); - WINRT_ASSERT((reinterpret_cast(value) & 1) == 0); - return (reinterpret_cast(value) >> 1) | pointer_flag; + constexpr std::uintptr_t pointer_flag = static_cast(1) << ((sizeof(std::uintptr_t) * 8) - 1); + WINRT_ASSERT((reinterpret_cast(value) & 1) == 0); + return (reinterpret_cast(value) >> 1) | pointer_flag; } virtual unknown_abi* get_unknown() const noexcept = 0; - virtual std::pair get_local_iids() const noexcept = 0; + virtual std::pair get_local_iids() const noexcept = 0; virtual hstring GetRuntimeClassName() const = 0; virtual void* find_interface(guid const&) const noexcept = 0; virtual inspectable_abi* find_inspectable() const noexcept = 0; @@ -1379,6 +1390,10 @@ namespace winrt::impl WINRT_EXPORT namespace winrt { +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4702) // Compiler bug causing spurious "unreachable code" warnings +#endif template auto make(Args&&... args) { @@ -1432,6 +1447,9 @@ WINRT_EXPORT namespace winrt return { impl::create_and_initialize(std::forward(args)...), take_ownership_from_abi }; } } +#ifdef _MSC_VER +#pragma warning(pop) +#endif template inline void clear_factory_static_lifetime() @@ -1510,7 +1528,7 @@ WINRT_EXPORT namespace winrt impl::hresult_type __stdcall GetIids(impl::count_type* count, impl::guid_type** iids) noexcept { - return root_implements_type::GetIids(reinterpret_cast(count), reinterpret_cast(iids)); + return root_implements_type::GetIids(reinterpret_cast(count), reinterpret_cast(iids)); } impl::hresult_type __stdcall GetRuntimeClassName(impl::hstring_type* value) noexcept @@ -1538,11 +1556,11 @@ WINRT_EXPORT namespace winrt return impl::find_inspectable(static_cast(this)); } - std::pair get_local_iids() const noexcept override + std::pair get_local_iids() const noexcept override { using interfaces = impl::uncloaked_interfaces; using local_iids = impl::uncloaked_iids; - return { static_cast(local_iids::value.size()), local_iids::value.data() }; + return { static_cast(local_iids::value.size()), local_iids::value.data() }; } private: diff --git a/strings/base_include_numerics.h b/strings/base_include_numerics.h new file mode 100644 index 000000000..4b7658fff --- /dev/null +++ b/strings/base_include_numerics.h @@ -0,0 +1,19 @@ + +// Includes when WINRT_IMPL_NUMERICS is defined. +// Requires to already be included (via base_detect_numerics). +// The types are redirected into winrt::Windows::Foundation::Numerics via macro wrapping. +// Uses WINRT_EXPORT for the namespace declaration, which resolves to 'export extern "C++"' +// in module builds and nothing in header builds. +#ifdef WINRT_IMPL_NUMERICS +#ifndef WINRT_EXPORT +#define WINRT_EXPORT +#endif +#include +#define _WINDOWS_NUMERICS_NAMESPACE_ winrt::Windows::Foundation::Numerics +#define _WINDOWS_NUMERICS_BEGIN_NAMESPACE_ WINRT_EXPORT namespace winrt::Windows::Foundation::Numerics +#define _WINDOWS_NUMERICS_END_NAMESPACE_ +#include +#undef _WINDOWS_NUMERICS_NAMESPACE_ +#undef _WINDOWS_NUMERICS_BEGIN_NAMESPACE_ +#undef _WINDOWS_NUMERICS_END_NAMESPACE_ +#endif // WINRT_IMPL_NUMERICS diff --git a/strings/base_includes.h b/strings/base_includes.h index ee22bc0aa..bac7358bd 100644 --- a/strings/base_includes.h +++ b/strings/base_includes.h @@ -6,11 +6,18 @@ #include #include #include +#include +#include #include +#include +#include +#include #include +#include #include #include #include +#include #include #include #include @@ -25,11 +32,6 @@ #include #endif -#if __has_include() -#define WINRT_IMPL_NUMERICS -#include -#endif - #ifndef WINRT_LEAN_AND_MEAN #include #endif @@ -47,31 +49,7 @@ #endif #ifdef __cpp_lib_coroutine - #include - -namespace winrt::impl -{ - template - using coroutine_handle = std::coroutine_handle; - - using suspend_always = std::suspend_always; - using suspend_never = std::suspend_never; -} - -#elif __has_include() - -#include - -namespace winrt::impl -{ - template - using coroutine_handle = std::experimental::coroutine_handle; - - using suspend_always = std::experimental::suspend_always; - using suspend_never = std::experimental::suspend_never; -} - -#else -#error C++/WinRT requires coroutine support, which is currently missing. Try enabling C++20 in your compiler. +#elif defined(_RESUMABLE_FUNCTIONS_SUPPORTED) +#error "C++/WinRT no longer supports pre-standardization coroutines. If you use co_await, switch to /await:strict or upgrade to C++20. If you do not, remove /await from the compiler flags." #endif diff --git a/strings/base_iterator.h b/strings/base_iterator.h index b0ad7836d..46c0c6b63 100644 --- a/strings/base_iterator.h +++ b/strings/base_iterator.h @@ -1,5 +1,5 @@ -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template struct fast_iterator @@ -7,13 +7,13 @@ namespace winrt::impl using iterator_concept = std::random_access_iterator_tag; using iterator_category = std::input_iterator_tag; using value_type = decltype(std::declval().GetAt(0)); - using difference_type = ptrdiff_t; + using difference_type = std::ptrdiff_t; using pointer = void; using reference = value_type; fast_iterator() noexcept = default; - fast_iterator(T const& collection, uint32_t const index) noexcept : + fast_iterator(T const& collection, std::uint32_t const index) noexcept : m_collection(&collection), m_index(index) {} @@ -46,7 +46,7 @@ namespace winrt::impl fast_iterator& operator+=(difference_type n) noexcept { - m_index += static_cast(n); + m_index += static_cast(n); return *this; } @@ -78,7 +78,7 @@ namespace winrt::impl reference operator[](difference_type n) const { - return m_collection->GetAt(m_index + static_cast(n)); + return m_collection->GetAt(m_index + static_cast(n)); } bool operator==(fast_iterator const& other) const noexcept @@ -127,7 +127,7 @@ namespace winrt::impl private: T const* m_collection = nullptr; - uint32_t m_index = 0; + std::uint32_t m_index = 0; }; template diff --git a/strings/base_lock.h b/strings/base_lock.h index cf70a001a..a0d6261e4 100644 --- a/strings/base_lock.h +++ b/strings/base_lock.h @@ -117,7 +117,7 @@ WINRT_EXPORT namespace winrt return false; } - if (!WINRT_IMPL_SleepConditionVariableSRW(&m_cv, x.get(), static_cast(milliseconds), 0)) + if (!WINRT_IMPL_SleepConditionVariableSRW(&m_cv, x.get(), static_cast(milliseconds), 0)) { return predicate(); } diff --git a/strings/base_macros.h b/strings/base_macros.h index e0167d152..850d0c627 100644 --- a/strings/base_macros.h +++ b/strings/base_macros.h @@ -1,3 +1,6 @@ +#pragma once +#ifndef WINRT_BASE_MACROS_H +#define WINRT_BASE_MACROS_H #ifdef _DEBUG @@ -11,7 +14,11 @@ #define WINRT_VERIFY(expression) (void)(expression) #define WINRT_VERIFY_(result, expression) (void)(expression) -#endif +#endif // _DEBUG + +#if defined(__cpp_lib_coroutine) +#define WINRT_IMPL_COROUTINES +#endif // __cpp_lib_coroutine #define WINRT_IMPL_SHIM(...) (*(abi_t<__VA_ARGS__>**)&static_cast<__VA_ARGS__ const&>(static_cast(*this))) @@ -21,25 +28,30 @@ // Note: this is a workaround for a false-positive warning produced by the Visual C++ 16.3 compiler. #pragma warning(disable : 4268) -#endif -#if defined(__cpp_lib_coroutine) || defined(__cpp_coroutines) || defined(_RESUMABLE_FUNCTIONS_SUPPORTED) -#define WINRT_IMPL_COROUTINES -#endif +// C++ module warnings by /W4 +#pragma warning(disable : 4499) +#pragma warning(disable : 4630) +#endif // _MSC_VER #ifndef WINRT_EXPORT +#ifdef WINRT_IMPL_BUILD_MODULE +#define WINRT_EXPORT export extern "C++" +#else #define WINRT_EXPORT -#endif - -#ifdef WINRT_IMPL_NUMERICS -#define _WINDOWS_NUMERICS_NAMESPACE_ winrt::Windows::Foundation::Numerics -#define _WINDOWS_NUMERICS_BEGIN_NAMESPACE_ WINRT_EXPORT namespace winrt::Windows::Foundation::Numerics -#define _WINDOWS_NUMERICS_END_NAMESPACE_ -#include -#undef _WINDOWS_NUMERICS_NAMESPACE_ -#undef _WINDOWS_NUMERICS_BEGIN_NAMESPACE_ -#undef _WINDOWS_NUMERICS_END_NAMESPACE_ -#endif +#endif // WINRT_IMPL_BUILD_MODULE +#endif // WINRT_EXPORT + +// Template specializations in namespace std (hash, coroutine_traits) need extern "C++" +// linkage in module builds for proper merging with the std module, but must NOT be +// exported - exporting namespace std would make all of std transitively visible. +#ifndef WINRT_IMPL_STD_EXPORT +#ifdef WINRT_IMPL_BUILD_MODULE +#define WINRT_IMPL_STD_EXPORT extern "C++" +#else +#define WINRT_IMPL_STD_EXPORT +#endif // WINRT_IMPL_BUILD_MODULE +#endif // WINRT_IMPL_STD_EXPORT #if defined(_MSC_VER) #define WINRT_IMPL_NOINLINE __declspec(noinline) @@ -61,6 +73,18 @@ #define WINRT_IMPL_NOVTABLE #endif +#if defined(__clang__) && defined(__has_attribute) +#if __has_attribute(__lto_visibility_public__) +#define WINRT_IMPL_PUBLIC __attribute__((lto_visibility_public)) +#else +#define WINRT_IMPL_PUBLIC +#endif // __has_attribute(__lto_visibility_public__) +#else +#define WINRT_IMPL_PUBLIC +#endif + +#define WINRT_IMPL_ABI_DECL WINRT_IMPL_NOVTABLE WINRT_IMPL_PUBLIC + #if defined(__clang__) #define WINRT_IMPL_HAS_DECLSPEC_UUID __has_declspec_attribute(uuid) #elif defined(_MSC_VER) @@ -69,7 +93,7 @@ #define WINRT_IMPL_HAS_DECLSPEC_UUID 0 #endif -#ifdef __IUnknown_INTERFACE_DEFINED__ +#if defined(__IUnknown_INTERFACE_DEFINED__) || defined(WINRT_ENABLE_LEGACY_COM) #define WINRT_IMPL_IUNKNOWN_DEFINED #else // Forward declare so we can talk about it. @@ -77,104 +101,17 @@ struct IUnknown; typedef struct _GUID GUID; #endif -// std::source_location is a C++20 feature, which is above the C++17 feature floor for cppwinrt. The source location needs -// to be the calling code, not cppwinrt itself, so that it is useful to developers building on top of this library. As a -// result any public-facing method that can result in an error needs a default-constructed source_location argument. Because -// this type does not exist in C++17 we need to use a macro to optionally add parameters and forwarding wherever appropriate. -// -// Some projects may decide to disable std::source_location support to prevent source code information from ending up in their -// release binaries, or to reduce binary size. Defining WINRT_NO_SOURCE_LOCATION will prevent this feature from activating. -#if defined(__cpp_lib_source_location) && !defined(WINRT_NO_SOURCE_LOCATION) - -namespace winrt::impl -{ - // This struct is intended to be highly similar to std::source_location. The key difference is - // that function_name is NOT included. Function names do not fold to identical strings and can - // have heavy binary size overhead when templates cause many permutations to exist. - struct slim_source_location - { - [[nodiscard]] static consteval slim_source_location current( - const std::uint_least32_t line = __builtin_LINE(), - const char* const file = __builtin_FILE()) noexcept - { - return slim_source_location{ line, file }; - } - - [[nodiscard]] constexpr slim_source_location() noexcept = default; - - [[nodiscard]] constexpr slim_source_location(const std::uint_least32_t line, - const char* const file) noexcept : - m_line(line), - m_file(file) - {} - - [[nodiscard]] constexpr std::uint_least32_t line() const noexcept - { - return m_line; - } - - [[nodiscard]] constexpr const char* file_name() const noexcept - { - return m_file; - } - - constexpr const char* function_name() const noexcept - { - // This is intentionally not included. See comment above. - return nullptr; - } - - private: - const std::uint_least32_t m_line{}; - const char* const m_file{}; - }; -} - -// std::source_location includes function_name which can be helpful but creates a lot of binary size impact. Many consumers -// have defined WINRT_NO_SOURCE_LOCATION to prevent this impact, losing the value of source_location. We have defined a -// slim_source_location struct that is equivalent but excludes function_name. This should have the vast majority of the -// usefulness of source_location while having a much smaller binary impact. -// -// When building _DEBUG binary size is not usually much of a concern, so we can use the full source_location type. -#ifdef _DEBUG -#define WINRT_IMPL_SOURCE_LOCATION_ARGS_NO_DEFAULT , std::source_location const& sourceInformation -#define WINRT_IMPL_SOURCE_LOCATION_ARGS , std::source_location const& sourceInformation = std::source_location::current() -#define WINRT_IMPL_SOURCE_LOCATION_ARGS_SINGLE_PARAM std::source_location const& sourceInformation = std::source_location::current() - -#define WINRT_IMPL_SOURCE_LOCATION_FORWARD , sourceInformation -#define WINRT_IMPL_SOURCE_LOCATION_FORWARD_SINGLE_PARAM sourceInformation - -#define WINRT_SOURCE_LOCATION_ACTIVE - -#ifdef _MSC_VER -#pragma detect_mismatch("WINRT_SOURCE_LOCATION", "true") -#endif // _MSC_VER - -#else // !_DEBUG -#define WINRT_IMPL_SOURCE_LOCATION_ARGS_NO_DEFAULT , winrt::impl::slim_source_location const& sourceInformation -#define WINRT_IMPL_SOURCE_LOCATION_ARGS , winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current() -#define WINRT_IMPL_SOURCE_LOCATION_ARGS_SINGLE_PARAM winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current() - -#define WINRT_IMPL_SOURCE_LOCATION_FORWARD , sourceInformation -#define WINRT_IMPL_SOURCE_LOCATION_FORWARD_SINGLE_PARAM sourceInformation - -#define WINRT_SOURCE_LOCATION_ACTIVE - -#ifdef _MSC_VER -#pragma detect_mismatch("WINRT_SOURCE_LOCATION", "slim") -#endif // _MSC_VER - -#endif // _DEBUG - +#if defined(__cpp_consteval) +#define WINRT_IMPL_CONSTEVAL consteval #else -#define WINRT_IMPL_SOURCE_LOCATION_ARGS_NO_DEFAULT -#define WINRT_IMPL_SOURCE_LOCATION_ARGS -#define WINRT_IMPL_SOURCE_LOCATION_ARGS_SINGLE_PARAM +#define WINRT_IMPL_CONSTEVAL constexpr +#endif -#define WINRT_IMPL_SOURCE_LOCATION_FORWARD -#define WINRT_IMPL_SOURCE_LOCATION_FORWARD_SINGLE_PARAM +// CPPWINRT_VERSION is defined here so it is available in module global fragments. +// In header builds, base_version_odr.h defines it first (before base_macros.h is included), +// so the #ifndef guard prevents redefinition. +#ifndef CPPWINRT_VERSION +#define CPPWINRT_VERSION "%" +#endif -#ifdef _MSC_VER -#pragma detect_mismatch("WINRT_SOURCE_LOCATION", "false") -#endif // _MSC_VER -#endif // defined(__cpp_lib_source_location) && !defined(WINRT_NO_SOURCE_LOCATION) +#endif // WINRT_BASE_MACROS_H diff --git a/strings/base_marshaler.h b/strings/base_marshaler.h index 359cf3b47..526f4d4c3 100644 --- a/strings/base_marshaler.h +++ b/strings/base_marshaler.h @@ -1,7 +1,7 @@ namespace winrt::impl { - inline int32_t make_marshaler(unknown_abi* outer, void** result) noexcept + inline std::int32_t make_marshaler(unknown_abi* outer, void** result) noexcept { struct marshaler final : IMarshal { @@ -10,7 +10,7 @@ namespace winrt::impl m_object.copy_from(object); } - int32_t __stdcall QueryInterface(guid const& id, void** object) noexcept final + std::int32_t __stdcall QueryInterface(guid const& id, void** object) noexcept final { if (is_guid_of(id)) { @@ -22,12 +22,12 @@ namespace winrt::impl return m_object->QueryInterface(id, object); } - uint32_t __stdcall AddRef() noexcept final + std::uint32_t __stdcall AddRef() noexcept final { return ++m_references; } - uint32_t __stdcall Release() noexcept final + std::uint32_t __stdcall Release() noexcept final { auto const remaining = --m_references; @@ -39,7 +39,7 @@ namespace winrt::impl return remaining; } - int32_t __stdcall GetUnmarshalClass(guid const& riid, void* pv, uint32_t dwDestContext, void* pvDestContext, uint32_t mshlflags, guid* pCid) noexcept final + std::int32_t __stdcall GetUnmarshalClass(guid const& riid, void* pv, std::uint32_t dwDestContext, void* pvDestContext, std::uint32_t mshlflags, guid* pCid) noexcept final { if (m_marshaler) { @@ -49,7 +49,7 @@ namespace winrt::impl return error_bad_alloc; } - int32_t __stdcall GetMarshalSizeMax(guid const& riid, void* pv, uint32_t dwDestContext, void* pvDestContext, uint32_t mshlflags, uint32_t* pSize) noexcept final + std::int32_t __stdcall GetMarshalSizeMax(guid const& riid, void* pv, std::uint32_t dwDestContext, void* pvDestContext, std::uint32_t mshlflags, std::uint32_t* pSize) noexcept final { if (m_marshaler) { @@ -59,7 +59,7 @@ namespace winrt::impl return error_bad_alloc; } - int32_t __stdcall MarshalInterface(void* pStm, guid const& riid, void* pv, uint32_t dwDestContext, void* pvDestContext, uint32_t mshlflags) noexcept final + std::int32_t __stdcall MarshalInterface(void* pStm, guid const& riid, void* pv, std::uint32_t dwDestContext, void* pvDestContext, std::uint32_t mshlflags) noexcept final { if (m_marshaler) { @@ -69,7 +69,7 @@ namespace winrt::impl return error_bad_alloc; } - int32_t __stdcall UnmarshalInterface(void* pStm, guid const& riid, void** ppv) noexcept final + std::int32_t __stdcall UnmarshalInterface(void* pStm, guid const& riid, void** ppv) noexcept final { if (m_marshaler) { @@ -80,7 +80,7 @@ namespace winrt::impl return error_bad_alloc; } - int32_t __stdcall ReleaseMarshalData(void* pStm) noexcept final + std::int32_t __stdcall ReleaseMarshalData(void* pStm) noexcept final { if (m_marshaler) { @@ -90,7 +90,7 @@ namespace winrt::impl return error_bad_alloc; } - int32_t __stdcall DisconnectObject(uint32_t dwReserved) noexcept final + std::int32_t __stdcall DisconnectObject(std::uint32_t dwReserved) noexcept final { if (m_marshaler) { diff --git a/strings/base_meta.h b/strings/base_meta.h index 2c1796e9c..6b28640ef 100644 --- a/strings/base_meta.h +++ b/strings/base_meta.h @@ -1,7 +1,7 @@ WINRT_EXPORT namespace winrt { - hresult check_hresult(hresult const result WINRT_IMPL_SOURCE_LOCATION_ARGS); + hresult check_hresult(hresult const result, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()); hresult to_hresult() noexcept; template @@ -10,6 +10,10 @@ WINRT_EXPORT namespace winrt struct take_ownership_from_abi_t {}; inline constexpr take_ownership_from_abi_t take_ownership_from_abi{}; + // Map implementations can implement TryLookup with trylookup_from_abi_t as an optimization + struct trylookup_from_abi_t {}; + inline constexpr trylookup_from_abi_t trylookup_from_abi{}; + template struct com_ptr; @@ -44,7 +48,7 @@ WINRT_EXPORT namespace winrt } } -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { using namespace std::literals; @@ -298,4 +302,16 @@ namespace winrt::impl return (func(Types{}) || ...); } }; + + template + struct has_TryLookup + { + template ().TryLookup(std::declval(), trylookup_from_abi))> static constexpr bool get_value(int) { return true; } + template static constexpr bool get_value(...) { return false; } + public: + static constexpr bool value = get_value(0); + }; + + template + inline constexpr bool has_TryLookup_v = has_TryLookup::value; } diff --git a/strings/base_module_base_ixx.h b/strings/base_module_base_ixx.h new file mode 100644 index 000000000..5930f54ea --- /dev/null +++ b/strings/base_module_base_ixx.h @@ -0,0 +1,13 @@ + +#include +#include + +#ifdef WINRT_ENABLE_LEGACY_COM +#include +#include +#endif + +export module winrt_base; + +import std; +export import winrt_numerics; diff --git a/strings/base_module_ixx_preamble.h b/strings/base_module_ixx_preamble.h new file mode 100644 index 000000000..114873dc7 --- /dev/null +++ b/strings/base_module_ixx_preamble.h @@ -0,0 +1,11 @@ +module; +#define WINRT_IMPL_BUILD_MODULE + +#if defined(_MSC_VER) && _MSC_VER < 1950 +#pragma message("warning: C++/WinRT modules require MSVC toolset v14.50 (v145) or later. Building with an older toolset is not supported and may produce unexpected errors.") +#endif + +#include +#ifdef _DEBUG +#include +#endif // _DEBUG diff --git a/strings/base_module_numerics_ixx.h b/strings/base_module_numerics_ixx.h new file mode 100644 index 000000000..f1ade01ff --- /dev/null +++ b/strings/base_module_numerics_ixx.h @@ -0,0 +1,6 @@ + +#include + +#if defined(_MSC_VER) +#pragma detect_mismatch("C++/WinRT version", CPPWINRT_VERSION) +#endif diff --git a/strings/base_natvis.h b/strings/base_natvis.h index 8ff4bd145..9e78563cb 100644 --- a/strings/base_natvis.h +++ b/strings/base_natvis.h @@ -5,7 +5,7 @@ #ifdef WINRT_NATVIS -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { struct natvis { @@ -15,19 +15,19 @@ namespace winrt::impl { bool b; wchar_t c; - int8_t i1; - int16_t i2; - int32_t i4; - int64_t i8; - uint8_t u1; - uint16_t u2; - uint32_t u4; - uint64_t u8; + std::int8_t i1; + std::int16_t i2; + std::int32_t i4; + std::int64_t i8; + std::uint8_t u1; + std::uint16_t u2; + std::uint32_t u4; + std::uint64_t u8; float r4; double r8; guid g; void* s; - uint8_t v[1024]; + std::uint8_t v[1024]; } value; value.s = 0; @@ -38,16 +38,16 @@ namespace winrt::impl { void* base_address; void* allocation_base; - uint32_t allocation_protect; + std::uint32_t allocation_protect; #ifdef _WIN64 - uint32_t __alignment1; + std::uint32_t __alignment1; #endif - uintptr_t region_size; - uint32_t state; - uint32_t protect; - uint32_t type; + std::uintptr_t region_size; + std::uint32_t state; + std::uint32_t protect; + std::uint32_t type; #ifdef _WIN64 - uint32_t __alignment2; + std::uint32_t __alignment2; #endif }; memory_basic_information info; @@ -66,7 +66,7 @@ namespace winrt::impl // validate method pointer is executable if ((WINRT_IMPL_VirtualQuery(vfunc, &info, sizeof(info)) != 0) && ((info.protect & 0xF0) != 0)) { - typedef int32_t(__stdcall inspectable_abi:: * PropertyAccessor)(void*); + typedef std::int32_t(__stdcall inspectable_abi:: * PropertyAccessor)(void*); (pinsp->**(PropertyAccessor*)&vfunc)(&value); pinsp->Release(); } diff --git a/strings/base_reference_produce.h b/strings/base_reference_produce.h index 8ea2de5b9..db9639cc3 100644 --- a/strings/base_reference_produce.h +++ b/strings/base_reference_produce.h @@ -1,100 +1,198 @@ -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template - struct reference : implements, Windows::Foundation::IReference, Windows::Foundation::IPropertyValue> + struct reference; + + template + struct reference_array; + + template + inline constexpr bool is_stock_reference_v = + std::is_same_v || std::is_same_v || + std::is_same_v || std::is_same_v || + std::is_same_v || std::is_same_v || + std::is_same_v || std::is_same_v || + std::is_same_v || std::is_same_v || + std::is_same_v || std::is_same_v || + std::is_same_v || std::is_same_v || + std::is_same_v || std::is_same_v; + + template + constexpr Windows::Foundation::PropertyType scalar_property_type() noexcept + { + using pt = Windows::Foundation::PropertyType; + + if constexpr (std::is_same_v) { return pt::UInt8; } + else if constexpr (std::is_same_v) { return pt::Int16; } + else if constexpr (std::is_same_v) { return pt::UInt16; } + else if constexpr (std::is_same_v) { return pt::Int32; } + else if constexpr (std::is_same_v) { return pt::UInt32; } + else if constexpr (std::is_same_v) { return pt::Int64; } + else if constexpr (std::is_same_v) { return pt::UInt64; } + else if constexpr (std::is_same_v) { return pt::Single; } + else if constexpr (std::is_same_v) { return pt::Double; } + else if constexpr (std::is_same_v) { return pt::Char16; } + else if constexpr (std::is_same_v) { return pt::Boolean; } + else if constexpr (std::is_same_v) { return pt::String; } + else if constexpr (std::is_same_v) { return pt::Inspectable; } + else if constexpr (std::is_same_v) { return pt::Guid; } + else if constexpr (std::is_same_v) { return pt::DateTime; } + else if constexpr (std::is_same_v) { return pt::TimeSpan; } + else if constexpr (std::is_same_v) { return pt::Point; } + else if constexpr (std::is_same_v) { return pt::Size; } + else if constexpr (std::is_same_v) { return pt::Rect; } + else { return pt::OtherType; } + } + + template + constexpr Windows::Foundation::PropertyType array_property_type() noexcept { - reference(T const& value) : m_value(value) - { - } + return static_cast( + static_cast(scalar_property_type()) + 1024); + } - T Value() const - { - return m_value; - } + template + inline constexpr bool is_numeric_scalar_v = + (std::is_arithmetic_v && !std::is_same_v && !std::is_same_v) || std::is_enum_v; + template + struct reference_producer : implements, non_agile, marker>> + { Windows::Foundation::PropertyType Type() const noexcept { - return Windows::Foundation::PropertyType::OtherType; + if constexpr (IsArray) { return array_property_type(); } + else { return scalar_property_type(); } } static constexpr bool IsNumericScalar() noexcept { - return std::is_arithmetic_v || std::is_enum_v; + return !IsArray && is_numeric_scalar_v; } - uint8_t GetUInt8() const - { - return to_scalar(); - } + std::uint8_t GetUInt8() const { return derived()->template get_as(); } + std::int16_t GetInt16() const { return derived()->template get_as(); } + std::uint16_t GetUInt16() const { return derived()->template get_as(); } + std::int32_t GetInt32() const { return derived()->template get_as(); } + std::uint32_t GetUInt32() const { return derived()->template get_as(); } + std::int64_t GetInt64() const { return derived()->template get_as(); } + std::uint64_t GetUInt64() const { return derived()->template get_as(); } + float GetSingle() const { return derived()->template get_as(); } + double GetDouble() const { return derived()->template get_as(); } + char16_t GetChar16() const { return derived()->template get_as(); } + bool GetBoolean() const { return derived()->template get_as(); } + hstring GetString() const { return derived()->template get_as(); } + guid GetGuid() const { return derived()->template get_as(); } + Windows::Foundation::DateTime GetDateTime() const { return derived()->template get_as(); } + Windows::Foundation::TimeSpan GetTimeSpan() const { return derived()->template get_as(); } + Windows::Foundation::Point GetPoint() const { return derived()->template get_as(); } + Windows::Foundation::Size GetSize() const { return derived()->template get_as(); } + Windows::Foundation::Rect GetRect() const { return derived()->template get_as(); } + void GetUInt8Array(com_array& value) const { derived()->get_as(value); } + void GetInt16Array(com_array& value) const { derived()->get_as(value); } + void GetUInt16Array(com_array& value) const { derived()->get_as(value); } + void GetInt32Array(com_array& value) const { derived()->get_as(value); } + void GetUInt32Array(com_array& value) const { derived()->get_as(value); } + void GetInt64Array(com_array& value) const { derived()->get_as(value); } + void GetUInt64Array(com_array& value) const { derived()->get_as(value); } + void GetSingleArray(com_array& value) const { derived()->get_as(value); } + void GetDoubleArray(com_array& value) const { derived()->get_as(value); } + void GetChar16Array(com_array& value) const { derived()->get_as(value); } + void GetBooleanArray(com_array& value) const { derived()->get_as(value); } + void GetStringArray(com_array& value) const { derived()->get_as(value); } + void GetInspectableArray(com_array& value) const { derived()->get_as(value); } + void GetGuidArray(com_array& value) const { derived()->get_as(value); } + void GetDateTimeArray(com_array& value) const { derived()->get_as(value); } + void GetTimeSpanArray(com_array& value) const { derived()->get_as(value); } + void GetPointArray(com_array& value) const { derived()->get_as(value); } + void GetSizeArray(com_array& value) const { derived()->get_as(value); } + void GetRectArray(com_array& value) const { derived()->get_as(value); } - int16_t GetInt16() const - { - return to_scalar(); - } + private: - uint16_t GetUInt16() const - { - return to_scalar(); - } + Derived const* derived() const noexcept { return static_cast(this); } - int32_t GetInt32() const + std::int32_t query_interface_tearoff(guid const& id, void** object) const noexcept override { - return to_scalar(); - } + if constexpr (is_stock_reference_v) + { + if (is_guid_of(id)) + { + try + { + auto marshal = derived()->create_property_value().template as(); + *object = detach_abi(marshal); + return error_ok; + } + catch (...) + { + *object = nullptr; + return to_hresult(); + } + } - uint32_t GetUInt32() const - { - return to_scalar(); + if (is_guid_of(id)) + { + auto unknown = reinterpret_cast(to_abi(derived())); + unknown->AddRef(); + *object = unknown; + return error_ok; + } + } + + *object = nullptr; + return error_no_interface; } + }; - int64_t GetInt64() const + template + struct reference : reference_producer, T, Windows::Foundation::IReference, false> + { + reference(T const& value) : m_value(value) { - return to_scalar(); } - uint64_t GetUInt64() const + T Value() const { - return to_scalar(); + return m_value; } - float GetSingle() { throw hresult_not_implemented(); } - double GetDouble() { throw hresult_not_implemented(); } - char16_t GetChar16() { throw hresult_not_implemented(); } - bool GetBoolean() { throw hresult_not_implemented(); } - hstring GetString() { throw hresult_not_implemented(); } - guid GetGuid() { throw hresult_not_implemented(); } - Windows::Foundation::DateTime GetDateTime() { throw hresult_not_implemented(); } - Windows::Foundation::TimeSpan GetTimeSpan() { throw hresult_not_implemented(); } - Windows::Foundation::Point GetPoint() { throw hresult_not_implemented(); } - Windows::Foundation::Size GetSize() { throw hresult_not_implemented(); } - Windows::Foundation::Rect GetRect() { throw hresult_not_implemented(); } - void GetUInt8Array(com_array &) { throw hresult_not_implemented(); } - void GetInt16Array(com_array &) { throw hresult_not_implemented(); } - void GetUInt16Array(com_array &) { throw hresult_not_implemented(); } - void GetInt32Array(com_array &) { throw hresult_not_implemented(); } - void GetUInt32Array(com_array &) { throw hresult_not_implemented(); } - void GetInt64Array(com_array &) { throw hresult_not_implemented(); } - void GetUInt64Array(com_array &) { throw hresult_not_implemented(); } - void GetSingleArray(com_array &) { throw hresult_not_implemented(); } - void GetDoubleArray(com_array &) { throw hresult_not_implemented(); } - void GetChar16Array(com_array &) { throw hresult_not_implemented(); } - void GetBooleanArray(com_array &) { throw hresult_not_implemented(); } - void GetStringArray(com_array &) { throw hresult_not_implemented(); } - void GetInspectableArray(com_array &) { throw hresult_not_implemented(); } - void GetGuidArray(com_array &) { throw hresult_not_implemented(); } - void GetDateTimeArray(com_array &) { throw hresult_not_implemented(); } - void GetTimeSpanArray(com_array &) { throw hresult_not_implemented(); } - void GetPointArray(com_array &) { throw hresult_not_implemented(); } - void GetSizeArray(com_array &) { throw hresult_not_implemented(); } - void GetRectArray(com_array &) { throw hresult_not_implemented(); } - private: + template friend struct reference_producer; + + Windows::Foundation::IInspectable create_property_value() const + { + using pv = Windows::Foundation::PropertyValue; + + if constexpr (std::is_same_v) { return pv::CreateUInt8(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateInt16(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateUInt16(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateInt32(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateUInt32(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateInt64(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateUInt64(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateSingle(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateDouble(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateChar16(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateBoolean(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateString(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateGuid(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateDateTime(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateTimeSpan(m_value); } + else if constexpr (std::is_same_v) { return pv::CreatePoint(m_value); } + else { return nullptr; } + } + template - To to_scalar() const + To get_as() const { - if constexpr (IsNumericScalar()) + if constexpr (std::is_same_v) + { + return m_value; + } + else if constexpr (is_numeric_scalar_v && is_numeric_scalar_v) { return static_cast(m_value); } @@ -104,98 +202,81 @@ namespace winrt::impl } } + template + void get_as(com_array const&) const + { + throw hresult_not_implemented(); + } + T m_value; }; template - struct reference_traits - { - static auto make(T const& value) { return winrt::make>(value); } - using itf = Windows::Foundation::IReference; - }; - - template <> - struct reference_traits - { - static auto make(uint8_t value) { return Windows::Foundation::PropertyValue::CreateUInt8(value); } - using itf = Windows::Foundation::IReference; - }; - - template <> - struct reference_traits - { - static auto make(uint16_t value) { return Windows::Foundation::PropertyValue::CreateUInt16(value); } - using itf = Windows::Foundation::IReference; - }; - - template <> - struct reference_traits + struct reference_array : reference_producer, T, Windows::Foundation::IReferenceArray, true> { - static auto make(int16_t value) { return Windows::Foundation::PropertyValue::CreateInt16(value); } - using itf = Windows::Foundation::IReference; - }; + reference_array(array_view const& value) : m_value(value.begin(), value.end()) + { + } - template <> - struct reference_traits - { - static auto make(uint32_t value) { return Windows::Foundation::PropertyValue::CreateUInt32(value); } - using itf = Windows::Foundation::IReference; - }; + com_array Value() const + { + return com_array(m_value.begin(), m_value.end()); + } - template <> - struct reference_traits - { - static auto make(int32_t value) { return Windows::Foundation::PropertyValue::CreateInt32(value); } - using itf = Windows::Foundation::IReference; - }; + private: - template <> - struct reference_traits - { - static auto make(uint64_t value) { return Windows::Foundation::PropertyValue::CreateUInt64(value); } - using itf = Windows::Foundation::IReference; - }; + template friend struct reference_producer; - template <> - struct reference_traits - { - static auto make(int64_t value) { return Windows::Foundation::PropertyValue::CreateInt64(value); } - using itf = Windows::Foundation::IReference; - }; - - template <> - struct reference_traits - { - static auto make(float value) { return Windows::Foundation::PropertyValue::CreateSingle(value); } - using itf = Windows::Foundation::IReference; - }; + Windows::Foundation::IInspectable create_property_value() const + { + using pv = Windows::Foundation::PropertyValue; + + if constexpr (std::is_same_v) { return pv::CreateUInt8Array(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateInt16Array(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateUInt16Array(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateInt32Array(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateUInt32Array(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateInt64Array(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateUInt64Array(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateSingleArray(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateDoubleArray(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateChar16Array(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateBooleanArray(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateStringArray(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateGuidArray(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateDateTimeArray(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateTimeSpanArray(m_value); } + else if constexpr (std::is_same_v) { return pv::CreatePointArray(m_value); } + else { return nullptr; } + } - template <> - struct reference_traits - { - static auto make(double value) { return Windows::Foundation::PropertyValue::CreateDouble(value); } - using itf = Windows::Foundation::IReference; - }; + template + To get_as() const + { + throw hresult_not_implemented(); + } - template <> - struct reference_traits - { - static auto make(char16_t value) { return Windows::Foundation::PropertyValue::CreateChar16(value); } - using itf = Windows::Foundation::IReference; - }; + template + void get_as(com_array& value) const + { + if constexpr (std::is_same_v) + { + value = com_array(m_value.begin(), m_value.end()); + } + else + { + throw hresult_not_implemented(); + } + } - template <> - struct reference_traits - { - static auto make(bool value) { return Windows::Foundation::PropertyValue::CreateBoolean(value); } - using itf = Windows::Foundation::IReference; + com_array m_value; }; - template <> - struct reference_traits + template + struct reference_traits { - static auto make(hstring const& value) { return Windows::Foundation::PropertyValue::CreateString(value); } - using itf = Windows::Foundation::IReference; + static auto make(T const& value) { return winrt::make>(value); } + using itf = Windows::Foundation::IReference; }; template <> @@ -205,41 +286,13 @@ namespace winrt::impl using itf = Windows::Foundation::IInspectable; }; - template <> - struct reference_traits - { - static auto make(guid const& value) { return Windows::Foundation::PropertyValue::CreateGuid(value); } - using itf = Windows::Foundation::IReference; - }; - template <> struct reference_traits { - static auto make(GUID const& value) { return Windows::Foundation::PropertyValue::CreateGuid(reinterpret_cast(value)); } + static auto make(GUID const& value) { return reference_traits::make(reinterpret_cast(value)); } using itf = Windows::Foundation::IReference; }; - template <> - struct reference_traits - { - static auto make(Windows::Foundation::DateTime value) { return Windows::Foundation::PropertyValue::CreateDateTime(value); } - using itf = Windows::Foundation::IReference; - }; - - template <> - struct reference_traits - { - static auto make(Windows::Foundation::TimeSpan value) { return Windows::Foundation::PropertyValue::CreateTimeSpan(value); } - using itf = Windows::Foundation::IReference; - }; - - template <> - struct reference_traits - { - static auto make(Windows::Foundation::Point const& value) { return Windows::Foundation::PropertyValue::CreatePoint(value); } - using itf = Windows::Foundation::IReference; - }; - template <> struct reference_traits { @@ -255,79 +308,79 @@ namespace winrt::impl }; template <> - struct reference_traits> + struct reference_traits> { - static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateUInt8Array(value); } - using itf = Windows::Foundation::IReferenceArray; + static auto make(array_view const& value) { return winrt::make>(value); } + using itf = Windows::Foundation::IReferenceArray; }; template <> - struct reference_traits> + struct reference_traits> { - static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateInt16Array(value); } - using itf = Windows::Foundation::IReferenceArray; + static auto make(array_view const& value) { return winrt::make>(value); } + using itf = Windows::Foundation::IReferenceArray; }; template <> - struct reference_traits> + struct reference_traits> { - static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateUInt16Array(value); } - using itf = Windows::Foundation::IReferenceArray; + static auto make(array_view const& value) { return winrt::make>(value); } + using itf = Windows::Foundation::IReferenceArray; }; template <> - struct reference_traits> + struct reference_traits> { - static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateInt32Array(value); } - using itf = Windows::Foundation::IReferenceArray; + static auto make(array_view const& value) { return winrt::make>(value); } + using itf = Windows::Foundation::IReferenceArray; }; template <> - struct reference_traits> + struct reference_traits> { - static auto make(com_array const& value) { return Windows::Foundation::PropertyValue::CreateUInt32Array(value); } - using itf = Windows::Foundation::IReferenceArray; + static auto make(com_array const& value) { return winrt::make>(value); } + using itf = Windows::Foundation::IReferenceArray; }; template <> - struct reference_traits> + struct reference_traits> { - static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateInt64Array(value); } - using itf = Windows::Foundation::IReferenceArray; + static auto make(array_view const& value) { return winrt::make>(value); } + using itf = Windows::Foundation::IReferenceArray; }; template <> - struct reference_traits> + struct reference_traits> { - static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateUInt64Array(value); } - using itf = Windows::Foundation::IReferenceArray; + static auto make(array_view const& value) { return winrt::make>(value); } + using itf = Windows::Foundation::IReferenceArray; }; template <> struct reference_traits> { - static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateSingleArray(value); } + static auto make(array_view const& value) { return winrt::make>(value); } using itf = Windows::Foundation::IReferenceArray; }; template <> struct reference_traits> { - static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateDoubleArray(value); } + static auto make(array_view const& value) { return winrt::make>(value); } using itf = Windows::Foundation::IReferenceArray; }; template <> struct reference_traits> { - static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateChar16Array(value); } + static auto make(array_view const& value) { return winrt::make>(value); } using itf = Windows::Foundation::IReferenceArray; }; template <> struct reference_traits> { - static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateBooleanArray(value); } + static auto make(array_view const& value) { return winrt::make>(value); } using itf = Windows::Foundation::IReferenceArray; }; @@ -348,14 +401,14 @@ namespace winrt::impl template <> struct reference_traits> { - static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateGuidArray(value); } + static auto make(array_view const& value) { return winrt::make>(value); } using itf = Windows::Foundation::IReferenceArray; }; template <> struct reference_traits> { - static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateGuidArray(reinterpret_cast const&>(value)); } + static auto make(array_view const& value) { return winrt::make>(reinterpret_cast const&>(value)); } using itf = Windows::Foundation::IReferenceArray; }; @@ -376,7 +429,7 @@ namespace winrt::impl template <> struct reference_traits> { - static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreatePointArray(value); } + static auto make(array_view const& value) { return winrt::make>(value); } using itf = Windows::Foundation::IReferenceArray; }; @@ -420,7 +473,7 @@ WINRT_EXPORT namespace winrt::Windows::Foundation } } -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template T unbox_value_type(From&& value) @@ -509,12 +562,13 @@ namespace winrt::impl WINRT_EXPORT namespace winrt { - inline Windows::Foundation::IInspectable box_value(param::hstring const& value) + template , int> = 0> + Windows::Foundation::IInspectable box_value(T&& value) { - return Windows::Foundation::IReference(*(hstring*)(&value)); + return Windows::Foundation::IReference(hstring(std::forward(value))); } - template , int> = 0> + template , int> = 0> Windows::Foundation::IInspectable box_value(T const& value) { if constexpr (std::is_base_of_v) diff --git a/strings/base_security.h b/strings/base_security.h index 8160f11ad..a912487e4 100644 --- a/strings/base_security.h +++ b/strings/base_security.h @@ -18,7 +18,7 @@ WINRT_EXPORT namespace winrt if (!WINRT_IMPL_OpenThreadToken(WINRT_IMPL_GetCurrentThread(), 0x0004 /*TOKEN_IMPERSONATE*/, 1, token.put())) { - uint32_t const error = WINRT_IMPL_GetLastError(); + std::uint32_t const error = WINRT_IMPL_GetLastError(); if (error != 1008 /*ERROR_NO_TOKEN*/) { diff --git a/strings/base_source_location.h b/strings/base_source_location.h new file mode 100644 index 000000000..c0fd81f9f --- /dev/null +++ b/strings/base_source_location.h @@ -0,0 +1,97 @@ + +// The intrinsics (such as __builtin_FILE()) that power std::source_location are also used to power winrt:impl::slim_source_location. +// The source location needs to be for the calling code, not cppwinrt itself, so that it is useful to developers building on top of +// this library. As a result any public-facing method that can result in an error needs a default-constructed slim_source_location +// argument so that it will collect source information from the application code that is calling into cppwinrt. +// +// We do not directly use std::source_location for two reasons: +// 1) std::source_location::function_name() is unavoidable. These strings end up in the final binary, bloating their size. This +// is particularly impactful for code bases that use templates heavily. Cases of 50% binary size growth have been observed. +// 2) std::source_location is a cpp20 feature, which is above the cpp17 feature floor for cppwinrt. By defining our own version +// we can avoid ODR violations in mixed cpp17/cpp20 builds. cpp17 callers will have an ABI that matches cpp20 callers (they +// will just not have useful file/line/function information). +// +// Some projects may decide that the source information binary size impact is not worth the benefit. Defining WINRT_NO_SOURCE_LOCATION +// will prevent this feature from activating. The slim_source_location type will be forwarded around but it will not include any +// nonzero data. That eliminates the biggest source of binary size overhead. +// +// To help with debugging the __builtin_FUNCTION() intrinsic will be used in _DEBUG builds. This will provide a bit more diagnostic +// value at the cost of binary size. The assumption is that binary size is considered less important in debug builds so this tradeoff +// is acceptable. +// +// The different behavior of the default parameters to winrt::impl::slim_source_location::current() is technically an ODR violation, +// albeit a minor one. There should be no serious consequence to this violation. In practice it means that mixing cpp17/cpp20, +// or mixing WINRT_NO_SOURCE_LOCATION with undefining it, will lead to inconsistent source location information. It may be missing +// when it is expected to be included, or it may be present when it is not expected. The behavior will depend on the linker's choice +// when there are multiple translation units with different options. This violation is tracked by https://github.com/microsoft/cppwinrt/issues/1445. + +#if !defined(__cpp_lib_source_location) || defined(WINRT_NO_SOURCE_LOCATION) +// Case1: cpp17 mode. The source_location intrinsics are not available. +// Case2: The caller has disabled source_location support. Ensure that there is no binary size overhead for line/file/function. +#define WINRT_IMPL_BUILTIN_LINE 0 +#define WINRT_IMPL_BUILTIN_FILE nullptr +#define WINRT_IMPL_BUILTIN_FUNCTION nullptr +#elif _DEBUG +// cpp20 _DEBUG builds include function information, which has a heavy binary size impact, in addition to file/line. +#define WINRT_IMPL_BUILTIN_LINE __builtin_LINE() +#define WINRT_IMPL_BUILTIN_FILE __builtin_FILE() +#define WINRT_IMPL_BUILTIN_FUNCTION __builtin_FUNCTION() +#else +// Release builds in cpp20 mode get file and line information but NOT function information. Function strings +// quickly add up to a substantial binary size impact, especially when templates are heavily used. +#define WINRT_IMPL_BUILTIN_LINE __builtin_LINE() +#define WINRT_IMPL_BUILTIN_FILE __builtin_FILE() +#define WINRT_IMPL_BUILTIN_FUNCTION nullptr +#endif + +WINRT_EXPORT namespace winrt::impl +{ + // This struct is intended to be highly similar to std::source_location. The key difference is + // that function_name is NOT included. Function names do not fold to identical strings and can + // have heavy binary size overhead when templates cause many permutations to exist. + struct slim_source_location + { + [[nodiscard]] static WINRT_IMPL_CONSTEVAL slim_source_location current( + const std::uint_least32_t line = WINRT_IMPL_BUILTIN_LINE, + const char* const file = WINRT_IMPL_BUILTIN_FILE, + const char* const function = WINRT_IMPL_BUILTIN_FUNCTION) noexcept + { + return slim_source_location{ line, file, function }; + } + + [[nodiscard]] constexpr slim_source_location() noexcept = default; + + [[nodiscard]] constexpr slim_source_location( + const std::uint_least32_t line, + const char* const file, + const char* const function) noexcept : + m_line(line), + m_file(file), + m_function(function) + {} + + [[nodiscard]] constexpr std::uint_least32_t line() const noexcept + { + return m_line; + } + + [[nodiscard]] constexpr const char* file_name() const noexcept + { + return m_file; + } + + [[nodiscard]] constexpr const char* function_name() const noexcept + { + return m_function; + } + + private: + const std::uint_least32_t m_line{}; + const char* const m_file{}; + const char* const m_function{}; + }; +} + +#ifdef _MSC_VER +#pragma detect_mismatch("WINRT_SOURCE_LOCATION", "slim") +#endif // _MSC_VER diff --git a/strings/base_std_hash.h b/strings/base_std_hash.h index eb97db0e9..4777f8082 100644 --- a/strings/base_std_hash.h +++ b/strings/base_std_hash.h @@ -1,19 +1,19 @@ -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { - inline size_t hash_data(void const* ptr, size_t const bytes) noexcept + inline std::size_t hash_data(void const* ptr, std::size_t const bytes) noexcept { #ifdef _WIN64 - constexpr size_t fnv_offset_basis = 14695981039346656037ULL; - constexpr size_t fnv_prime = 1099511628211ULL; + constexpr std::size_t fnv_offset_basis = 14695981039346656037ULL; + constexpr std::size_t fnv_prime = 1099511628211ULL; #else - constexpr size_t fnv_offset_basis = 2166136261U; - constexpr size_t fnv_prime = 16777619U; + constexpr std::size_t fnv_offset_basis = 2166136261U; + constexpr std::size_t fnv_prime = 16777619U; #endif - size_t result = fnv_offset_basis; - uint8_t const* const buffer = static_cast(ptr); + std::size_t result = fnv_offset_basis; + std::uint8_t const* const buffer = static_cast(ptr); - for (size_t next = 0; next < bytes; ++next) + for (std::size_t next = 0; next < bytes; ++next) { result ^= buffer[next]; result *= fnv_prime; @@ -24,7 +24,7 @@ namespace winrt::impl struct hash_base { - size_t operator()(Windows::Foundation::IUnknown const& value) const noexcept + std::size_t operator()(Windows::Foundation::IUnknown const& value) const noexcept { void* const abi_value = get_abi(value.try_as()); return std::hash{}(abi_value); @@ -32,11 +32,11 @@ namespace winrt::impl }; } -namespace std +WINRT_IMPL_STD_EXPORT namespace std { template<> struct hash { - size_t operator()(winrt::hstring const& value) const noexcept + std::size_t operator()(winrt::hstring const& value) const noexcept { return std::hash{}(value); } @@ -48,7 +48,7 @@ namespace std template<> struct hash { - size_t operator()(winrt::guid const& value) const noexcept + std::size_t operator()(winrt::guid const& value) const noexcept { return winrt::impl::hash_data(&value, sizeof(value)); } diff --git a/strings/base_string.h b/strings/base_string.h index e70eed925..50a248c02 100644 --- a/strings/base_string.h +++ b/strings/base_string.h @@ -1,25 +1,25 @@ -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { struct atomic_ref_count { atomic_ref_count() noexcept = default; - explicit atomic_ref_count(uint32_t count) noexcept : m_count(count) + explicit atomic_ref_count(std::uint32_t count) noexcept : m_count(count) { } - uint32_t operator=(uint32_t count) noexcept + std::uint32_t operator=(std::uint32_t count) noexcept { return m_count = count; } - uint32_t operator++() noexcept + std::uint32_t operator++() noexcept { - return static_cast(m_count.fetch_add(1, std::memory_order_relaxed) + 1); + return static_cast(m_count.fetch_add(1, std::memory_order_relaxed) + 1); } - uint32_t operator--() noexcept + std::uint32_t operator--() noexcept { auto const remaining = m_count.fetch_sub(1, std::memory_order_release) - 1; @@ -29,30 +29,30 @@ namespace winrt::impl } else if (remaining < 0) { - abort(); + std::abort(); } - return static_cast(remaining); + return static_cast(remaining); } - operator uint32_t() const noexcept + operator std::uint32_t() const noexcept { - return static_cast(m_count); + return static_cast(m_count); } private: - std::atomic m_count; + std::atomic m_count; }; - constexpr uint32_t hstring_reference_flag{ 1 }; + inline constexpr std::uint32_t hstring_reference_flag{ 1 }; struct hstring_header { - uint32_t flags; - uint32_t length; - uint32_t padding1; - uint32_t padding2; + std::uint32_t flags; + std::uint32_t length; + std::uint32_t padding1; + std::uint32_t padding2; wchar_t const* ptr; }; @@ -72,12 +72,12 @@ namespace winrt::impl } } - inline shared_hstring_header* precreate_hstring_on_heap(uint32_t length) + inline shared_hstring_header* precreate_hstring_on_heap(std::uint32_t length) { WINRT_ASSERT(length != 0); - uint64_t bytes_required = static_cast(sizeof(shared_hstring_header)) + static_cast(sizeof(wchar_t)) * static_cast(length); + std::uint64_t bytes_required = static_cast(sizeof(shared_hstring_header)) + static_cast(sizeof(wchar_t)) * static_cast(length); - if (bytes_required > UINT_MAX) + if (bytes_required > (std::numeric_limits::max)()) { throw std::invalid_argument("length"); } @@ -97,7 +97,7 @@ namespace winrt::impl return header; } - inline hstring_header* create_hstring_on_heap(wchar_t const* value, uint32_t length) + inline hstring_header* create_hstring_on_heap(wchar_t const* value, std::uint32_t length) { if (!length) { @@ -105,18 +105,18 @@ namespace winrt::impl } auto header = precreate_hstring_on_heap(length); - memcpy_s(header->buffer, sizeof(wchar_t) * length, value, sizeof(wchar_t) * length); + std::copy_n(value, length, header->buffer); return header; } - inline void create_hstring_on_stack(hstring_header& header, wchar_t const* value, uint32_t length) noexcept + inline void create_hstring_on_stack(hstring_header& header, wchar_t const* value, std::uint32_t length) noexcept { WINRT_ASSERT(value); WINRT_ASSERT(length != 0); if (value[length] != 0) { - abort(); + std::abort(); } header.flags = hstring_reference_flag; @@ -155,6 +155,24 @@ namespace winrt::impl return nullptr; } }; + + template + struct hstring_literal_storage + { + static constexpr std::size_t size = N; + wchar_t value[N]; + + constexpr hstring_literal_storage(wchar_t const (&str)[N]) noexcept + { + for (std::size_t i = 0; i != N; ++i) + { + value[i] = str[i]; + } + } + }; + + template + hstring_literal_storage(wchar_t const (&)[N]) -> hstring_literal_storage; } WINRT_EXPORT namespace winrt @@ -162,7 +180,7 @@ WINRT_EXPORT namespace winrt struct hstring { using value_type = wchar_t; - using size_type = uint32_t; + using size_type = std::uint32_t; using const_reference = value_type const&; using pointer = value_type*; using const_pointer = value_type const*; @@ -191,7 +209,7 @@ WINRT_EXPORT namespace winrt hstring& operator=(std::nullptr_t) = delete; hstring(std::initializer_list value) : - hstring(value.begin(), static_cast(value.size())) + hstring(value.begin(), static_cast(value.size())) {} hstring(wchar_t const* value) : @@ -386,6 +404,30 @@ WINRT_EXPORT namespace winrt handle_type m_handle; }; + struct hstring_reference + { + constexpr hstring_reference() noexcept = default; + + constexpr explicit hstring_reference(impl::hstring_header const* header) noexcept : + m_handle(const_cast(header)) + { + } + + operator hstring const&() const noexcept + { + return *reinterpret_cast(this); + } + + private: + + [[maybe_unused]] void* m_handle{}; + }; + + inline void* get_abi(hstring_reference const& object) noexcept + { + return *(void**)(&object); + } + inline void* get_abi(hstring const& object) noexcept { return *(void**)(&object); @@ -428,21 +470,59 @@ WINRT_EXPORT namespace winrt inline void* detach_abi(std::wstring_view const& value) { - return impl::create_hstring_on_heap(value.data(), static_cast(value.size())); + return impl::create_hstring_on_heap(value.data(), static_cast(value.size())); } inline void* detach_abi(wchar_t const* const value) { - return impl::create_hstring_on_heap(value, static_cast(wcslen(value))); + return impl::create_hstring_on_heap(value, static_cast(std::wcslen(value))); } } +#if defined(__cpp_nontype_template_args) && __cpp_nontype_template_args >= 201911L + +WINRT_EXPORT namespace winrt::impl +{ + template + inline constexpr hstring_header hstring_literal_header + { + hstring_reference_flag, + static_cast(Literal.size - 1), + 0, + 0, + Literal.value + }; +} + +WINRT_EXPORT namespace winrt +{ + inline namespace literals + { + template + constexpr hstring_reference operator ""_hs() noexcept + { + static_assert(Literal.value[Literal.size - 1] == L'\0', "_hs requires a null-terminated wide string literal"); + + if constexpr (Literal.size <= 1) + { + return hstring_reference{}; + } + else + { + return hstring_reference{ &impl::hstring_literal_header }; + } + } + } +} + +#endif + #ifdef __cpp_lib_format template<> struct std::formatter : std::formatter {}; #endif -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template <> struct abi { @@ -459,7 +539,7 @@ namespace winrt::impl hstring_builder(hstring_builder const&) = delete; hstring_builder& operator=(hstring_builder const&) = delete; - explicit hstring_builder(uint32_t const size) : + explicit hstring_builder(std::uint32_t const size) : m_handle(impl::precreate_hstring_on_heap(size)) { } @@ -574,8 +654,8 @@ namespace winrt::impl // when non-const (e.g. ranges::filter_view) so taking a const reference // as parameter wouldn't work for all scenarios. auto const size = std::formatted_size(args...); - WINRT_ASSERT(size < UINT_MAX); - auto const size32 = static_cast(size); + WINRT_ASSERT(size < static_cast((std::numeric_limits::max)())); + auto const size32 = static_cast(size); hstring_builder builder(size32); WINRT_VERIFY_(size32, std::format_to_n(builder.data(), size32, args...).size); @@ -608,42 +688,42 @@ WINRT_EXPORT namespace winrt }); } - inline hstring to_hstring(uint8_t value) + inline hstring to_hstring(std::uint8_t value) { return impl::hstring_convert(value); } - inline hstring to_hstring(int8_t value) + inline hstring to_hstring(std::int8_t value) { return impl::hstring_convert(value); } - inline hstring to_hstring(uint16_t value) + inline hstring to_hstring(std::uint16_t value) { return impl::hstring_convert(value); } - inline hstring to_hstring(int16_t value) + inline hstring to_hstring(std::int16_t value) { return impl::hstring_convert(value); } - inline hstring to_hstring(uint32_t value) + inline hstring to_hstring(std::uint32_t value) { return impl::hstring_convert(value); } - inline hstring to_hstring(int32_t value) + inline hstring to_hstring(std::int32_t value) { return impl::hstring_convert(value); } - inline hstring to_hstring(uint64_t value) + inline hstring to_hstring(std::uint64_t value) { return impl::hstring_convert(value); } - inline hstring to_hstring(int64_t value) + inline hstring to_hstring(std::int64_t value) { return impl::hstring_convert(value); } @@ -688,7 +768,7 @@ WINRT_EXPORT namespace winrt { wchar_t buffer[40]; //{00000000-0000-0000-0000-000000000000} - swprintf_s(buffer, L"{%08x-%04hx-%04hx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx}", + std::swprintf(buffer, std::size(buffer), L"{%08x-%04hx-%04hx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx}", value.Data1, value.Data2, value.Data3, value.Data4[0], value.Data4[1], value.Data4[2], value.Data4[3], value.Data4[4], value.Data4[5], value.Data4[6], value.Data4[7]); return hstring{ buffer }; @@ -698,7 +778,7 @@ WINRT_EXPORT namespace winrt hstring to_hstring(T const& value) { std::string_view const view(value); - int const size = WINRT_IMPL_MultiByteToWideChar(65001 /*CP_UTF8*/, 0, view.data(), static_cast(view.size()), nullptr, 0); + int const size = WINRT_IMPL_MultiByteToWideChar(65001 /*CP_UTF8*/, 0, view.data(), static_cast(view.size()), nullptr, 0); if (size == 0) { @@ -706,13 +786,13 @@ WINRT_EXPORT namespace winrt } impl::hstring_builder result(size); - WINRT_VERIFY_(size, WINRT_IMPL_MultiByteToWideChar(65001 /*CP_UTF8*/, 0, view.data(), static_cast(view.size()), result.data(), size)); + WINRT_VERIFY_(size, WINRT_IMPL_MultiByteToWideChar(65001 /*CP_UTF8*/, 0, view.data(), static_cast(view.size()), result.data(), size)); return result.to_hstring(); } inline std::string to_string(std::wstring_view value) { - int const size = WINRT_IMPL_WideCharToMultiByte(65001 /*CP_UTF8*/, 0, value.data(), static_cast(value.size()), nullptr, 0, nullptr, nullptr); + int const size = WINRT_IMPL_WideCharToMultiByte(65001 /*CP_UTF8*/, 0, value.data(), static_cast(value.size()), nullptr, 0, nullptr, nullptr); if (size == 0) { @@ -720,7 +800,7 @@ WINRT_EXPORT namespace winrt } std::string result(size, '?'); - WINRT_VERIFY_(size, WINRT_IMPL_WideCharToMultiByte(65001 /*CP_UTF8*/, 0, value.data(), static_cast(value.size()), result.data(), size, nullptr, nullptr)); + WINRT_VERIFY_(size, WINRT_IMPL_WideCharToMultiByte(65001 /*CP_UTF8*/, 0, value.data(), static_cast(value.size()), result.data(), size, nullptr, nullptr)); return result; } } diff --git a/strings/base_string_input.h b/strings/base_string_input.h index 8cfea212b..ccf955547 100644 --- a/strings/base_string_input.h +++ b/strings/base_string_input.h @@ -18,6 +18,10 @@ WINRT_EXPORT namespace winrt::param { } + hstring(winrt::hstring_reference const& value) noexcept : m_handle(get_abi(value)) + { + } + hstring(std::wstring_view const& value) noexcept { create_string_reference(value.data(), value.size()); @@ -30,7 +34,7 @@ WINRT_EXPORT namespace winrt::param hstring(wchar_t const* const value) noexcept { - create_string_reference(value, wcslen(value)); + create_string_reference(value, std::wcslen(value)); } operator winrt::hstring const&() const noexcept @@ -39,10 +43,10 @@ WINRT_EXPORT namespace winrt::param } private: - void create_string_reference(wchar_t const* const data, size_t size) noexcept + void create_string_reference(wchar_t const* const data, std::size_t size) noexcept { - WINRT_ASSERT(size < UINT_MAX); - auto size32 = static_cast(size); + WINRT_ASSERT(size < (std::numeric_limits::max)()); + auto size32 = static_cast(size); if (size32 == 0) { @@ -65,7 +69,7 @@ WINRT_EXPORT namespace winrt::param } } -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template using param_type = std::conditional_t, param::hstring, T>; diff --git a/strings/base_string_operators.h b/strings/base_string_operators.h index b00150f92..223769d01 100644 --- a/strings/base_string_operators.h +++ b/strings/base_string_operators.h @@ -94,18 +94,18 @@ WINRT_EXPORT namespace winrt bool operator>=(std::nullptr_t left, hstring const& right) = delete; } -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { inline hstring concat_hstring(std::wstring_view const& left, std::wstring_view const& right) { - auto size = static_cast(left.size() + right.size()); + auto size = static_cast(left.size() + right.size()); if (size == 0) { return{}; } hstring_builder text(size); - memcpy_s(text.data(), left.size() * sizeof(wchar_t), left.data(), left.size() * sizeof(wchar_t)); - memcpy_s(text.data() + left.size(), right.size() * sizeof(wchar_t), right.data(), right.size() * sizeof(wchar_t)); + std::copy_n(left.data(), left.size(), text.data()); + std::copy_n(right.data(), right.size(), text.data() + left.size()); return text.to_hstring(); } } diff --git a/strings/base_stringable_streams.h b/strings/base_stringable_streams.h index 52b481d6f..fa17b0f3e 100644 --- a/strings/base_stringable_streams.h +++ b/strings/base_stringable_streams.h @@ -1,8 +1,11 @@ #ifndef WINRT_LEAN_AND_MEAN -inline std::wostream& operator<<(std::wostream& stream, winrt::Windows::Foundation::IStringable const& stringable) +namespace winrt::Windows::Foundation { - stream << stringable.ToString(); - return stream; + inline std::wostream& operator<<(std::wostream& stream, winrt::Windows::Foundation::IStringable const& stringable) + { + stream << stringable.ToString(); + return stream; + } } #endif diff --git a/strings/base_types.h b/strings/base_types.h index 84cf22f5d..dc2b13632 100644 --- a/strings/base_types.h +++ b/strings/base_types.h @@ -1,5 +1,5 @@ -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { using ptp_io = struct tp_io*; using ptp_timer = struct tp_timer*; @@ -14,25 +14,25 @@ namespace winrt::impl struct com_callback_args { - uint32_t reserved1; - uint32_t reserved2; + std::uint32_t reserved1; + std::uint32_t reserved2; void* data; }; template - constexpr uint8_t hex_to_uint(T const c) + constexpr std::uint8_t hex_to_uint(T const c) { if (c >= '0' && c <= '9') { - return static_cast(c - '0'); + return static_cast(c - '0'); } else if (c >= 'A' && c <= 'F') { - return static_cast(10 + c - 'A'); + return static_cast(10 + c - 'A'); } else if (c >= 'a' && c <= 'f') { - return static_cast(10 + c - 'a'); + return static_cast(10 + c - 'a'); } else { @@ -41,20 +41,20 @@ namespace winrt::impl } template - constexpr uint8_t hex_to_uint8(T const a, T const b) + constexpr std::uint8_t hex_to_uint8(T const a, T const b) { return (hex_to_uint(a) << 4) | hex_to_uint(b); } - constexpr uint16_t uint8_to_uint16(uint8_t a, uint8_t b) + constexpr std::uint16_t uint8_to_uint16(std::uint8_t a, std::uint8_t b) { - return (static_cast(a) << 8) | static_cast(b); + return (static_cast(a) << 8) | static_cast(b); } - constexpr uint32_t uint8_to_uint32(uint8_t a, uint8_t b, uint8_t c, uint8_t d) + constexpr std::uint32_t uint8_to_uint32(std::uint8_t a, std::uint8_t b, std::uint8_t c, std::uint8_t d) { - return (static_cast(uint8_to_uint16(a, b)) << 16) | - static_cast(uint8_to_uint16(c, d)); + return (static_cast(uint8_to_uint16(a, b)) << 16) | + static_cast(uint8_to_uint16(c, d)); } } @@ -66,15 +66,15 @@ WINRT_EXPORT namespace winrt struct hresult { - int32_t value{}; + std::int32_t value{}; constexpr hresult() noexcept = default; - constexpr hresult(int32_t const value) noexcept : value(value) + constexpr hresult(std::int32_t const value) noexcept : value(value) { } - constexpr operator int32_t() const noexcept + constexpr operator std::int32_t() const noexcept { return value; } @@ -133,14 +133,14 @@ WINRT_EXPORT namespace winrt public: - uint32_t Data1; - uint16_t Data2; - uint16_t Data3; - uint8_t Data4[8]; + std::uint32_t Data1; + std::uint16_t Data2; + std::uint16_t Data3; + std::uint8_t Data4[8]; guid() noexcept = default; - constexpr guid(uint32_t const Data1, uint16_t const Data2, uint16_t const Data3, std::array const& Data4) noexcept : + constexpr guid(std::uint32_t const Data1, std::uint16_t const Data2, std::uint16_t const Data3, std::array const& Data4) noexcept : Data1(Data1), Data2(Data2), Data3(Data3), @@ -178,7 +178,7 @@ WINRT_EXPORT namespace winrt inline bool operator==(guid const& left, guid const& right) noexcept { - return !memcmp(&left, &right, sizeof(left)); + return !std::memcmp(&left, &right, sizeof(left)); } inline bool operator!=(guid const& left, guid const& right) noexcept @@ -188,13 +188,13 @@ WINRT_EXPORT namespace winrt inline bool operator<(guid const& left, guid const& right) noexcept { - return memcmp(&left, &right, sizeof(left)) < 0; + return std::memcmp(&left, &right, sizeof(left)) < 0; } } WINRT_EXPORT namespace winrt::Windows::Foundation { - enum class TrustLevel : int32_t + enum class TrustLevel : std::int32_t { BaseTrust, PartialTrust, @@ -204,19 +204,19 @@ WINRT_EXPORT namespace winrt::Windows::Foundation struct IUnknown; struct IInspectable; struct IActivationFactory; - using TimeSpan = std::chrono::duration; + using TimeSpan = std::chrono::duration; using DateTime = std::chrono::time_point; } -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { #ifdef WINRT_IMPL_IUNKNOWN_DEFINED using hresult_type = long; using count_type = unsigned long; using guid_type = GUID; #else - using hresult_type = int32_t; - using count_type = uint32_t; + using hresult_type = std::int32_t; + using count_type = std::uint32_t; using guid_type = guid; #endif diff --git a/strings/base_version.h b/strings/base_version.h index adb3608da..13d21fb2a 100644 --- a/strings/base_version.h +++ b/strings/base_version.h @@ -16,7 +16,9 @@ char const * const WINRT_version = "C++/WinRT version:" CPPWINRT_VERSION; WINRT_EXPORT namespace winrt { - template + inline constexpr char cppwinrt_version[] = CPPWINRT_VERSION; + + template constexpr bool check_version(char const(&base)[BaseSize], char const(&component)[ComponentSize]) noexcept { if constexpr (BaseSize != ComponentSize) @@ -24,7 +26,7 @@ WINRT_EXPORT namespace winrt return false; } - for (size_t i = 0; i != BaseSize - 1; ++i) + for (std::size_t i = 0; i != BaseSize - 1; ++i) { if (base[i] != component[i]) { diff --git a/strings/base_windows.h b/strings/base_windows.h index 41030d368..dcd164574 100644 --- a/strings/base_windows.h +++ b/strings/base_windows.h @@ -1,17 +1,17 @@ -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { #ifdef WINRT_DIAGNOSTICS struct factory_diagnostics_info { bool is_agile{ true }; - uint32_t requests{ 0 }; + std::uint32_t requests{ 0 }; }; struct diagnostics_info { - std::map queries; + std::map queries; std::map factories; }; @@ -131,6 +131,30 @@ namespace winrt::impl ptr->QueryInterface(guid_of(), &result); return wrap_as_result(result); } + + template , int> = 0> + com_ref try_as_with_reason(From* ptr, hresult& code) noexcept + { +#ifdef WINRT_DIAGNOSTICS + get_diagnostics_info().add_query(); +#endif + + if (!ptr) + { + code = 0; + return nullptr; + } + + void* result{}; + code = ptr->QueryInterface(guid_of(), &result); + return wrap_as_result(result); + } + + template + auto try_as_with_reason(From ptr, hresult& code) noexcept + { + return ptr->template try_as_with_reason(code); + } } WINRT_EXPORT namespace winrt::Windows::Foundation @@ -139,7 +163,7 @@ WINRT_EXPORT namespace winrt::Windows::Foundation { IUnknown() noexcept = default; IUnknown(std::nullptr_t) noexcept {} - void* operator new(size_t) = delete; + void* operator new(std::size_t) = delete; IUnknown(void* ptr, take_ownership_from_abi_t) noexcept : m_ptr(static_cast(ptr)) { @@ -205,6 +229,12 @@ WINRT_EXPORT namespace winrt::Windows::Foundation return impl::try_as(m_ptr); } + template + auto try_as_with_reason(hresult& code) const noexcept + { + return impl::try_as_with_reason(m_ptr, code); + } + template void as(To& to) const { @@ -421,3 +451,60 @@ WINRT_EXPORT namespace winrt::Windows::Foundation IInspectable(void* ptr, take_ownership_from_abi_t) noexcept : IUnknown(ptr, take_ownership_from_abi) {} }; } + +WINRT_EXPORT namespace winrt::impl +{ + template + void consume_noexcept_remove_overload(Derive const* d, MemberPointer mptr, Args&&... args) noexcept + { + if constexpr (!std::is_same_v) + { + winrt::hresult _winrt_cast_result_code; + auto const _winrt_casted_result = try_as_with_reason(d, _winrt_cast_result_code); + check_hresult(_winrt_cast_result_code); + auto const _winrt_abi_type = *(abi_t**)&_winrt_casted_result; + (_winrt_abi_type->*mptr)(std::forward(args)...); + } + else + { + auto const _winrt_abi_type = *(abi_t**)d; + (_winrt_abi_type->*mptr)(std::forward(args)...); + } + } + + template + void consume_noexcept(Derive const* d, MemberPointer mptr, Args&&... args) noexcept + { + if constexpr (!std::is_same_v) + { + winrt::hresult _winrt_cast_result_code; + auto const _winrt_casted_result = try_as_with_reason(d, _winrt_cast_result_code); + check_hresult(_winrt_cast_result_code); + auto const _winrt_abi_type = *(abi_t**)&_winrt_casted_result; + WINRT_VERIFY_(0, (_winrt_abi_type->*mptr)(std::forward(args)...)); + } + else + { + auto const _winrt_abi_type = *(abi_t**)d; + WINRT_VERIFY_(0, (_winrt_abi_type->*mptr)(std::forward(args)...)); + } + } + + template + void consume_general(Derive const* d, MemberPointer mptr, Args&&... args) + { + if constexpr (!std::is_same_v) + { + winrt::hresult _winrt_cast_result_code; + auto const _winrt_casted_result = try_as_with_reason(d, _winrt_cast_result_code); + check_hresult(_winrt_cast_result_code); + auto const _winrt_abi_type = *(abi_t**)&_winrt_casted_result; + check_hresult((_winrt_abi_type->*mptr)(std::forward(args)...)); + } + else + { + auto const _winrt_abi_type = *(abi_t**)d; + check_hresult((_winrt_abi_type->*mptr)(std::forward(args)...)); + } + } +} diff --git a/strings/base_xaml_component_connector.h b/strings/base_xaml_component_connector.h index 366e18e22..092944613 100644 --- a/strings/base_xaml_component_connector.h +++ b/strings/base_xaml_component_connector.h @@ -17,7 +17,7 @@ WINRT_EXPORT namespace winrt::Windows::UI::Xaml::Markup D::InitializeComponent(); } - void Connect(int32_t connectionId, winrt::Windows::Foundation::IInspectable const& target) + void Connect(std::int32_t connectionId, winrt::Windows::Foundation::IInspectable const& target) { if constexpr (m_has_connectable_base) { @@ -30,7 +30,7 @@ WINRT_EXPORT namespace winrt::Windows::UI::Xaml::Markup D::Connect(connectionId, target); } - auto GetBindingConnector(int32_t connectionId, winrt::Windows::Foundation::IInspectable const& target) + auto GetBindingConnector(std::int32_t connectionId, winrt::Windows::Foundation::IInspectable const& target) { if constexpr (m_has_connectable_base) { diff --git a/strings/base_xaml_component_connector_winui.h b/strings/base_xaml_component_connector_winui.h index 4a1f0326a..312f5af29 100644 --- a/strings/base_xaml_component_connector_winui.h +++ b/strings/base_xaml_component_connector_winui.h @@ -17,7 +17,7 @@ WINRT_EXPORT namespace winrt::Microsoft::UI::Xaml::Markup D::InitializeComponent(); } - void Connect(int32_t connectionId, winrt::Windows::Foundation::IInspectable const& target) + void Connect(std::int32_t connectionId, winrt::Windows::Foundation::IInspectable const& target) { if constexpr (m_has_connectable_base) { @@ -30,7 +30,7 @@ WINRT_EXPORT namespace winrt::Microsoft::UI::Xaml::Markup D::Connect(connectionId, target); } - auto GetBindingConnector(int32_t connectionId, winrt::Windows::Foundation::IInspectable const& target) + auto GetBindingConnector(std::int32_t connectionId, winrt::Windows::Foundation::IInspectable const& target) { if constexpr (m_has_connectable_base) { diff --git a/strings/base_xaml_typename.h b/strings/base_xaml_typename.h index 4a782fc72..2cc45b0bb 100644 --- a/strings/base_xaml_typename.h +++ b/strings/base_xaml_typename.h @@ -1,5 +1,5 @@ -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template struct xaml_typename_name @@ -66,42 +66,42 @@ namespace winrt::impl static constexpr Windows::UI::Xaml::Interop::TypeKind value = Windows::UI::Xaml::Interop::TypeKind::Primitive; }; template<> - struct xaml_typename_kind + struct xaml_typename_kind { static constexpr Windows::UI::Xaml::Interop::TypeKind value = Windows::UI::Xaml::Interop::TypeKind::Primitive; }; template<> - struct xaml_typename_kind + struct xaml_typename_kind { static constexpr Windows::UI::Xaml::Interop::TypeKind value = Windows::UI::Xaml::Interop::TypeKind::Primitive; }; template<> - struct xaml_typename_kind + struct xaml_typename_kind { static constexpr Windows::UI::Xaml::Interop::TypeKind value = Windows::UI::Xaml::Interop::TypeKind::Primitive; }; template<> - struct xaml_typename_kind + struct xaml_typename_kind { static constexpr Windows::UI::Xaml::Interop::TypeKind value = Windows::UI::Xaml::Interop::TypeKind::Primitive; }; template<> - struct xaml_typename_kind + struct xaml_typename_kind { static constexpr Windows::UI::Xaml::Interop::TypeKind value = Windows::UI::Xaml::Interop::TypeKind::Primitive; }; template<> - struct xaml_typename_kind + struct xaml_typename_kind { static constexpr Windows::UI::Xaml::Interop::TypeKind value = Windows::UI::Xaml::Interop::TypeKind::Primitive; }; template<> - struct xaml_typename_kind + struct xaml_typename_kind { static constexpr Windows::UI::Xaml::Interop::TypeKind value = Windows::UI::Xaml::Interop::TypeKind::Primitive; }; template<> - struct xaml_typename_kind + struct xaml_typename_kind { static constexpr Windows::UI::Xaml::Interop::TypeKind value = Windows::UI::Xaml::Interop::TypeKind::Primitive; }; diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index ed1515526..e5ca6e0fb 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -105,6 +105,7 @@ set(SKIP_LARGE_PCH FALSE CACHE BOOL "Skip building large precompiled headers.") add_subdirectory(test) +add_subdirectory(test_nocoro) add_subdirectory(test_cpp20) add_subdirectory(test_cpp20_no_sourcelocation) diff --git a/test/catch.hpp b/test/catch.hpp index e949ee88c..d008973a6 100644 --- a/test/catch.hpp +++ b/test/catch.hpp @@ -7779,7 +7779,7 @@ namespace Catch { result = -erfc_inv(2.0 * p); // result *= normal distribution standard deviation (1.0) * sqrt(2) result *= /*sd * */ ROOT_TWO; - // result += normal disttribution mean (0) + // result += normal distribution mean (0) return result; } @@ -11310,7 +11310,7 @@ namespace Catch { std::string TagInfo::all() const { size_t size = 0; for (auto const& spelling : spellings) { - // Add 2 for the brackes + // Add 2 for the brackets size += spelling.size() + 2; } diff --git a/test/nuget/ConsoleApplication1/ConsoleApplication1.vcxproj b/test/nuget/ConsoleApplication1/ConsoleApplication1.vcxproj index 94248f8a2..38f3ee4cc 100644 --- a/test/nuget/ConsoleApplication1/ConsoleApplication1.vcxproj +++ b/test/nuget/ConsoleApplication1/ConsoleApplication1.vcxproj @@ -1,6 +1,5 @@ - true @@ -14,10 +13,18 @@ + + Debug + ARM64 + Debug Win32 + + Release + ARM64 + Release Win32 @@ -54,7 +61,6 @@ - @@ -64,6 +70,7 @@ $(IntDir)pch.pch _CONSOLE;WIN32_LEAN_AND_MEAN;WINRT_LEAN_AND_MEAN;%(PreprocessorDefinitions) Level4 + true %(AdditionalOptions) /permissive- /bigobj @@ -121,11 +128,4 @@ - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - \ No newline at end of file diff --git a/test/nuget/ConsoleApplication1/packages.config b/test/nuget/ConsoleApplication1/packages.config deleted file mode 100644 index be196b1fc..000000000 --- a/test/nuget/ConsoleApplication1/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/test/nuget/Directory.Build.props b/test/nuget/Directory.Build.props index 9f410480b..a54887b1e 100644 --- a/test/nuget/Directory.Build.props +++ b/test/nuget/Directory.Build.props @@ -23,7 +23,7 @@ $(IntDir)Generated Files\ high $(Platform) - x86 + x86 $(SolutionDir)..\..\_build\$(CppWinRTPlatform)\$(Configuration)\ diff --git a/test/nuget/NuGetTest.sln b/test/nuget/NuGetTest.sln index db32e2b61..c836b2551 100644 --- a/test/nuget/NuGetTest.sln +++ b/test/nuget/NuGetTest.sln @@ -1,4 +1,4 @@ - + Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.5.33516.290 @@ -47,278 +47,305 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ConsoleApplication1", "Cons EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestProxyStub", "TestProxyStub\TestProxyStub.vcxproj", "{98E28FC8-2EB7-4544-9B6A-941462C6D3E2}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestModuleApp", "TestModuleApp\TestModuleApp.vcxproj", "{8679913F-D38D-468F-A8B7-75B187A7A8BC}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestModuleBuilder", "TestModuleBuilder\TestModuleBuilder.vcxproj", "{AEE91B86-AA17-4C22-B0C2-08B2C287E375}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestModuleComponent1", "TestModuleComponent1\TestModuleComponent1.vcxproj", "{F54D9A50-84D7-4953-8350-BEFE73CC36F6}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestModuleComponent2", "TestModuleComponent2\TestModuleComponent2.vcxproj", "{126E9412-E861-47C6-8684-C8F9BF32C0BD}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestModuleConsumerApp", "TestModuleConsumerApp\TestModuleConsumerApp.vcxproj", "{FB7FEAA7-09DE-465C-BA0E-60374D3EFFD9}" + ProjectSection(ProjectDependencies) = postProject + {AEE91B86-AA17-4C22-B0C2-08B2C287E375} = {AEE91B86-AA17-4C22-B0C2-08B2C287E375} + {F54D9A50-84D7-4953-8350-BEFE73CC36F6} = {F54D9A50-84D7-4953-8350-BEFE73CC36F6} + {126E9412-E861-47C6-8684-C8F9BF32C0BD} = {126E9412-E861-47C6-8684-C8F9BF32C0BD} + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|ARM = Debug|ARM Debug|ARM64 = Debug|ARM64 Debug|x64 = Debug|x64 Debug|x86 = Debug|x86 - Release|ARM = Release|ARM Release|ARM64 = Release|ARM64 Release|x64 = Release|x64 Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Debug|ARM.ActiveCfg = Debug|ARM - {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Debug|ARM.Build.0 = Debug|ARM - {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Debug|ARM.Deploy.0 = Debug|ARM - {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Debug|ARM64.ActiveCfg = Debug|Win32 + {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Debug|ARM64.Build.0 = Debug|ARM64 + {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Debug|ARM64.Deploy.0 = Debug|ARM64 {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Debug|x64.ActiveCfg = Debug|x64 {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Debug|x64.Build.0 = Debug|x64 {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Debug|x64.Deploy.0 = Debug|x64 {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Debug|x86.ActiveCfg = Debug|Win32 {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Debug|x86.Build.0 = Debug|Win32 {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Debug|x86.Deploy.0 = Debug|Win32 - {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Release|ARM.ActiveCfg = Release|ARM - {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Release|ARM.Build.0 = Release|ARM - {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Release|ARM.Deploy.0 = Release|ARM - {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Release|ARM64.ActiveCfg = Release|Win32 + {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Release|ARM64.ActiveCfg = Release|ARM64 + {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Release|ARM64.Build.0 = Release|ARM64 + {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Release|ARM64.Deploy.0 = Release|ARM64 {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Release|x64.ActiveCfg = Release|x64 {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Release|x64.Build.0 = Release|x64 {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Release|x64.Deploy.0 = Release|x64 {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Release|x86.ActiveCfg = Release|Win32 {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Release|x86.Build.0 = Release|Win32 {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Release|x86.Deploy.0 = Release|Win32 - {E0EBBE54-C046-4611-B048-3CE893B1DF8A}.Debug|ARM.ActiveCfg = Debug|ARM - {E0EBBE54-C046-4611-B048-3CE893B1DF8A}.Debug|ARM.Build.0 = Debug|ARM - {E0EBBE54-C046-4611-B048-3CE893B1DF8A}.Debug|ARM64.ActiveCfg = Debug|Win32 + {E0EBBE54-C046-4611-B048-3CE893B1DF8A}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {E0EBBE54-C046-4611-B048-3CE893B1DF8A}.Debug|ARM64.Build.0 = Debug|ARM64 {E0EBBE54-C046-4611-B048-3CE893B1DF8A}.Debug|x64.ActiveCfg = Debug|x64 {E0EBBE54-C046-4611-B048-3CE893B1DF8A}.Debug|x64.Build.0 = Debug|x64 {E0EBBE54-C046-4611-B048-3CE893B1DF8A}.Debug|x86.ActiveCfg = Debug|Win32 {E0EBBE54-C046-4611-B048-3CE893B1DF8A}.Debug|x86.Build.0 = Debug|Win32 - {E0EBBE54-C046-4611-B048-3CE893B1DF8A}.Release|ARM.ActiveCfg = Release|ARM - {E0EBBE54-C046-4611-B048-3CE893B1DF8A}.Release|ARM.Build.0 = Release|ARM - {E0EBBE54-C046-4611-B048-3CE893B1DF8A}.Release|ARM64.ActiveCfg = Release|Win32 + {E0EBBE54-C046-4611-B048-3CE893B1DF8A}.Release|ARM64.ActiveCfg = Release|ARM64 + {E0EBBE54-C046-4611-B048-3CE893B1DF8A}.Release|ARM64.Build.0 = Release|ARM64 {E0EBBE54-C046-4611-B048-3CE893B1DF8A}.Release|x64.ActiveCfg = Release|x64 {E0EBBE54-C046-4611-B048-3CE893B1DF8A}.Release|x64.Build.0 = Release|x64 {E0EBBE54-C046-4611-B048-3CE893B1DF8A}.Release|x86.ActiveCfg = Release|Win32 {E0EBBE54-C046-4611-B048-3CE893B1DF8A}.Release|x86.Build.0 = Release|Win32 - {4BBB2DE7-4596-4DA6-A923-E65E838363B5}.Debug|ARM.ActiveCfg = Debug|ARM - {4BBB2DE7-4596-4DA6-A923-E65E838363B5}.Debug|ARM.Build.0 = Debug|ARM - {4BBB2DE7-4596-4DA6-A923-E65E838363B5}.Debug|ARM64.ActiveCfg = Debug|Win32 + {4BBB2DE7-4596-4DA6-A923-E65E838363B5}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {4BBB2DE7-4596-4DA6-A923-E65E838363B5}.Debug|ARM64.Build.0 = Debug|ARM64 {4BBB2DE7-4596-4DA6-A923-E65E838363B5}.Debug|x64.ActiveCfg = Debug|x64 {4BBB2DE7-4596-4DA6-A923-E65E838363B5}.Debug|x64.Build.0 = Debug|x64 {4BBB2DE7-4596-4DA6-A923-E65E838363B5}.Debug|x86.ActiveCfg = Debug|Win32 {4BBB2DE7-4596-4DA6-A923-E65E838363B5}.Debug|x86.Build.0 = Debug|Win32 - {4BBB2DE7-4596-4DA6-A923-E65E838363B5}.Release|ARM.ActiveCfg = Release|ARM - {4BBB2DE7-4596-4DA6-A923-E65E838363B5}.Release|ARM.Build.0 = Release|ARM - {4BBB2DE7-4596-4DA6-A923-E65E838363B5}.Release|ARM64.ActiveCfg = Release|Win32 + {4BBB2DE7-4596-4DA6-A923-E65E838363B5}.Release|ARM64.ActiveCfg = Release|ARM64 + {4BBB2DE7-4596-4DA6-A923-E65E838363B5}.Release|ARM64.Build.0 = Release|ARM64 {4BBB2DE7-4596-4DA6-A923-E65E838363B5}.Release|x64.ActiveCfg = Release|x64 {4BBB2DE7-4596-4DA6-A923-E65E838363B5}.Release|x64.Build.0 = Release|x64 {4BBB2DE7-4596-4DA6-A923-E65E838363B5}.Release|x86.ActiveCfg = Release|Win32 {4BBB2DE7-4596-4DA6-A923-E65E838363B5}.Release|x86.Build.0 = Release|Win32 - {2158F418-CA97-4599-8103-EFC133850BAA}.Debug|ARM.ActiveCfg = Debug|Win32 - {2158F418-CA97-4599-8103-EFC133850BAA}.Debug|ARM64.ActiveCfg = Debug|Win32 + {2158F418-CA97-4599-8103-EFC133850BAA}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {2158F418-CA97-4599-8103-EFC133850BAA}.Debug|ARM64.Build.0 = Debug|ARM64 {2158F418-CA97-4599-8103-EFC133850BAA}.Debug|x64.ActiveCfg = Debug|x64 {2158F418-CA97-4599-8103-EFC133850BAA}.Debug|x64.Build.0 = Debug|x64 {2158F418-CA97-4599-8103-EFC133850BAA}.Debug|x86.ActiveCfg = Debug|Win32 {2158F418-CA97-4599-8103-EFC133850BAA}.Debug|x86.Build.0 = Debug|Win32 - {2158F418-CA97-4599-8103-EFC133850BAA}.Release|ARM.ActiveCfg = Release|Win32 - {2158F418-CA97-4599-8103-EFC133850BAA}.Release|ARM64.ActiveCfg = Release|Win32 + {2158F418-CA97-4599-8103-EFC133850BAA}.Release|ARM64.ActiveCfg = Release|ARM64 + {2158F418-CA97-4599-8103-EFC133850BAA}.Release|ARM64.Build.0 = Release|ARM64 {2158F418-CA97-4599-8103-EFC133850BAA}.Release|x64.ActiveCfg = Release|x64 {2158F418-CA97-4599-8103-EFC133850BAA}.Release|x64.Build.0 = Release|x64 {2158F418-CA97-4599-8103-EFC133850BAA}.Release|x86.ActiveCfg = Release|Win32 {2158F418-CA97-4599-8103-EFC133850BAA}.Release|x86.Build.0 = Release|Win32 - {0011F69F-2363-4DFD-B02A-1E7E909BCE89}.Debug|ARM.ActiveCfg = Debug|Win32 - {0011F69F-2363-4DFD-B02A-1E7E909BCE89}.Debug|ARM64.ActiveCfg = Debug|Win32 + {0011F69F-2363-4DFD-B02A-1E7E909BCE89}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {0011F69F-2363-4DFD-B02A-1E7E909BCE89}.Debug|ARM64.Build.0 = Debug|ARM64 {0011F69F-2363-4DFD-B02A-1E7E909BCE89}.Debug|x64.ActiveCfg = Debug|x64 {0011F69F-2363-4DFD-B02A-1E7E909BCE89}.Debug|x64.Build.0 = Debug|x64 {0011F69F-2363-4DFD-B02A-1E7E909BCE89}.Debug|x86.ActiveCfg = Debug|Win32 {0011F69F-2363-4DFD-B02A-1E7E909BCE89}.Debug|x86.Build.0 = Debug|Win32 - {0011F69F-2363-4DFD-B02A-1E7E909BCE89}.Release|ARM.ActiveCfg = Release|Win32 - {0011F69F-2363-4DFD-B02A-1E7E909BCE89}.Release|ARM64.ActiveCfg = Release|Win32 + {0011F69F-2363-4DFD-B02A-1E7E909BCE89}.Release|ARM64.ActiveCfg = Release|ARM64 + {0011F69F-2363-4DFD-B02A-1E7E909BCE89}.Release|ARM64.Build.0 = Release|ARM64 {0011F69F-2363-4DFD-B02A-1E7E909BCE89}.Release|x64.ActiveCfg = Release|x64 {0011F69F-2363-4DFD-B02A-1E7E909BCE89}.Release|x64.Build.0 = Release|x64 {0011F69F-2363-4DFD-B02A-1E7E909BCE89}.Release|x86.ActiveCfg = Release|Win32 {0011F69F-2363-4DFD-B02A-1E7E909BCE89}.Release|x86.Build.0 = Release|Win32 - {C2820B98-A31F-46D0-A96D-B8F24392B049}.Debug|ARM.ActiveCfg = Debug|ARM - {C2820B98-A31F-46D0-A96D-B8F24392B049}.Debug|ARM.Build.0 = Debug|ARM - {C2820B98-A31F-46D0-A96D-B8F24392B049}.Debug|ARM64.ActiveCfg = Debug|Win32 + {C2820B98-A31F-46D0-A96D-B8F24392B049}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {C2820B98-A31F-46D0-A96D-B8F24392B049}.Debug|ARM64.Build.0 = Debug|ARM64 {C2820B98-A31F-46D0-A96D-B8F24392B049}.Debug|x64.ActiveCfg = Debug|x64 {C2820B98-A31F-46D0-A96D-B8F24392B049}.Debug|x64.Build.0 = Debug|x64 {C2820B98-A31F-46D0-A96D-B8F24392B049}.Debug|x86.ActiveCfg = Debug|Win32 {C2820B98-A31F-46D0-A96D-B8F24392B049}.Debug|x86.Build.0 = Debug|Win32 - {C2820B98-A31F-46D0-A96D-B8F24392B049}.Release|ARM.ActiveCfg = Release|ARM - {C2820B98-A31F-46D0-A96D-B8F24392B049}.Release|ARM.Build.0 = Release|ARM - {C2820B98-A31F-46D0-A96D-B8F24392B049}.Release|ARM64.ActiveCfg = Release|Win32 + {C2820B98-A31F-46D0-A96D-B8F24392B049}.Release|ARM64.ActiveCfg = Release|ARM64 + {C2820B98-A31F-46D0-A96D-B8F24392B049}.Release|ARM64.Build.0 = Release|ARM64 {C2820B98-A31F-46D0-A96D-B8F24392B049}.Release|x64.ActiveCfg = Release|x64 {C2820B98-A31F-46D0-A96D-B8F24392B049}.Release|x64.Build.0 = Release|x64 {C2820B98-A31F-46D0-A96D-B8F24392B049}.Release|x86.ActiveCfg = Release|Win32 {C2820B98-A31F-46D0-A96D-B8F24392B049}.Release|x86.Build.0 = Release|Win32 - {1350E626-038B-4BDF-8E1D-C751EF33D90F}.Debug|ARM.ActiveCfg = Debug|ARM - {1350E626-038B-4BDF-8E1D-C751EF33D90F}.Debug|ARM.Build.0 = Debug|ARM - {1350E626-038B-4BDF-8E1D-C751EF33D90F}.Debug|ARM64.ActiveCfg = Debug|Win32 + {1350E626-038B-4BDF-8E1D-C751EF33D90F}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {1350E626-038B-4BDF-8E1D-C751EF33D90F}.Debug|ARM64.Build.0 = Debug|ARM64 {1350E626-038B-4BDF-8E1D-C751EF33D90F}.Debug|x64.ActiveCfg = Debug|x64 {1350E626-038B-4BDF-8E1D-C751EF33D90F}.Debug|x64.Build.0 = Debug|x64 {1350E626-038B-4BDF-8E1D-C751EF33D90F}.Debug|x86.ActiveCfg = Debug|Win32 {1350E626-038B-4BDF-8E1D-C751EF33D90F}.Debug|x86.Build.0 = Debug|Win32 - {1350E626-038B-4BDF-8E1D-C751EF33D90F}.Release|ARM.ActiveCfg = Release|ARM - {1350E626-038B-4BDF-8E1D-C751EF33D90F}.Release|ARM.Build.0 = Release|ARM - {1350E626-038B-4BDF-8E1D-C751EF33D90F}.Release|ARM64.ActiveCfg = Release|Win32 + {1350E626-038B-4BDF-8E1D-C751EF33D90F}.Release|ARM64.ActiveCfg = Release|ARM64 + {1350E626-038B-4BDF-8E1D-C751EF33D90F}.Release|ARM64.Build.0 = Release|ARM64 {1350E626-038B-4BDF-8E1D-C751EF33D90F}.Release|x64.ActiveCfg = Release|x64 {1350E626-038B-4BDF-8E1D-C751EF33D90F}.Release|x64.Build.0 = Release|x64 {1350E626-038B-4BDF-8E1D-C751EF33D90F}.Release|x86.ActiveCfg = Release|Win32 {1350E626-038B-4BDF-8E1D-C751EF33D90F}.Release|x86.Build.0 = Release|Win32 - {ADC53200-B456-4386-9851-5BF69DFB8928}.Debug|ARM.ActiveCfg = Debug|ARM - {ADC53200-B456-4386-9851-5BF69DFB8928}.Debug|ARM.Build.0 = Debug|ARM {ADC53200-B456-4386-9851-5BF69DFB8928}.Debug|ARM64.ActiveCfg = Debug|ARM64 {ADC53200-B456-4386-9851-5BF69DFB8928}.Debug|ARM64.Build.0 = Debug|ARM64 {ADC53200-B456-4386-9851-5BF69DFB8928}.Debug|x64.ActiveCfg = Debug|x64 {ADC53200-B456-4386-9851-5BF69DFB8928}.Debug|x64.Build.0 = Debug|x64 {ADC53200-B456-4386-9851-5BF69DFB8928}.Debug|x86.ActiveCfg = Debug|Win32 {ADC53200-B456-4386-9851-5BF69DFB8928}.Debug|x86.Build.0 = Debug|Win32 - {ADC53200-B456-4386-9851-5BF69DFB8928}.Release|ARM.ActiveCfg = Release|ARM - {ADC53200-B456-4386-9851-5BF69DFB8928}.Release|ARM.Build.0 = Release|ARM {ADC53200-B456-4386-9851-5BF69DFB8928}.Release|ARM64.ActiveCfg = Release|ARM64 {ADC53200-B456-4386-9851-5BF69DFB8928}.Release|ARM64.Build.0 = Release|ARM64 {ADC53200-B456-4386-9851-5BF69DFB8928}.Release|x64.ActiveCfg = Release|x64 {ADC53200-B456-4386-9851-5BF69DFB8928}.Release|x64.Build.0 = Release|x64 {ADC53200-B456-4386-9851-5BF69DFB8928}.Release|x86.ActiveCfg = Release|Win32 {ADC53200-B456-4386-9851-5BF69DFB8928}.Release|x86.Build.0 = Release|Win32 - {432068A4-B206-4468-9254-446CCEB15A2C}.Debug|ARM.ActiveCfg = Debug|ARM - {432068A4-B206-4468-9254-446CCEB15A2C}.Debug|ARM.Build.0 = Debug|ARM - {432068A4-B206-4468-9254-446CCEB15A2C}.Debug|ARM64.ActiveCfg = Debug|Win32 + {432068A4-B206-4468-9254-446CCEB15A2C}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {432068A4-B206-4468-9254-446CCEB15A2C}.Debug|ARM64.Build.0 = Debug|ARM64 {432068A4-B206-4468-9254-446CCEB15A2C}.Debug|x64.ActiveCfg = Debug|x64 {432068A4-B206-4468-9254-446CCEB15A2C}.Debug|x64.Build.0 = Debug|x64 {432068A4-B206-4468-9254-446CCEB15A2C}.Debug|x86.ActiveCfg = Debug|Win32 {432068A4-B206-4468-9254-446CCEB15A2C}.Debug|x86.Build.0 = Debug|Win32 - {432068A4-B206-4468-9254-446CCEB15A2C}.Release|ARM.ActiveCfg = Release|ARM - {432068A4-B206-4468-9254-446CCEB15A2C}.Release|ARM.Build.0 = Release|ARM - {432068A4-B206-4468-9254-446CCEB15A2C}.Release|ARM64.ActiveCfg = Release|Win32 + {432068A4-B206-4468-9254-446CCEB15A2C}.Release|ARM64.ActiveCfg = Release|ARM64 + {432068A4-B206-4468-9254-446CCEB15A2C}.Release|ARM64.Build.0 = Release|ARM64 {432068A4-B206-4468-9254-446CCEB15A2C}.Release|x64.ActiveCfg = Release|x64 {432068A4-B206-4468-9254-446CCEB15A2C}.Release|x64.Build.0 = Release|x64 {432068A4-B206-4468-9254-446CCEB15A2C}.Release|x86.ActiveCfg = Release|Win32 {432068A4-B206-4468-9254-446CCEB15A2C}.Release|x86.Build.0 = Release|Win32 - {8456C55F-BF01-4798-B79B-7388681C398F}.Debug|ARM.ActiveCfg = Debug|ARM - {8456C55F-BF01-4798-B79B-7388681C398F}.Debug|ARM.Build.0 = Debug|ARM - {8456C55F-BF01-4798-B79B-7388681C398F}.Debug|ARM64.ActiveCfg = Debug|Win32 + {8456C55F-BF01-4798-B79B-7388681C398F}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {8456C55F-BF01-4798-B79B-7388681C398F}.Debug|ARM64.Build.0 = Debug|ARM64 {8456C55F-BF01-4798-B79B-7388681C398F}.Debug|x64.ActiveCfg = Debug|x64 {8456C55F-BF01-4798-B79B-7388681C398F}.Debug|x64.Build.0 = Debug|x64 {8456C55F-BF01-4798-B79B-7388681C398F}.Debug|x86.ActiveCfg = Debug|Win32 {8456C55F-BF01-4798-B79B-7388681C398F}.Debug|x86.Build.0 = Debug|Win32 - {8456C55F-BF01-4798-B79B-7388681C398F}.Release|ARM.ActiveCfg = Release|ARM - {8456C55F-BF01-4798-B79B-7388681C398F}.Release|ARM.Build.0 = Release|ARM - {8456C55F-BF01-4798-B79B-7388681C398F}.Release|ARM64.ActiveCfg = Release|Win32 + {8456C55F-BF01-4798-B79B-7388681C398F}.Release|ARM64.ActiveCfg = Release|ARM64 + {8456C55F-BF01-4798-B79B-7388681C398F}.Release|ARM64.Build.0 = Release|ARM64 {8456C55F-BF01-4798-B79B-7388681C398F}.Release|x64.ActiveCfg = Release|x64 {8456C55F-BF01-4798-B79B-7388681C398F}.Release|x64.Build.0 = Release|x64 {8456C55F-BF01-4798-B79B-7388681C398F}.Release|x86.ActiveCfg = Release|Win32 {8456C55F-BF01-4798-B79B-7388681C398F}.Release|x86.Build.0 = Release|Win32 - {DC435C3F-C38E-43D1-B702-DC03F530A3CB}.Debug|ARM.ActiveCfg = Debug|ARM - {DC435C3F-C38E-43D1-B702-DC03F530A3CB}.Debug|ARM.Build.0 = Debug|ARM - {DC435C3F-C38E-43D1-B702-DC03F530A3CB}.Debug|ARM64.ActiveCfg = Debug|Win32 + {DC435C3F-C38E-43D1-B702-DC03F530A3CB}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {DC435C3F-C38E-43D1-B702-DC03F530A3CB}.Debug|ARM64.Build.0 = Debug|ARM64 {DC435C3F-C38E-43D1-B702-DC03F530A3CB}.Debug|x64.ActiveCfg = Debug|x64 {DC435C3F-C38E-43D1-B702-DC03F530A3CB}.Debug|x64.Build.0 = Debug|x64 {DC435C3F-C38E-43D1-B702-DC03F530A3CB}.Debug|x86.ActiveCfg = Debug|Win32 {DC435C3F-C38E-43D1-B702-DC03F530A3CB}.Debug|x86.Build.0 = Debug|Win32 - {DC435C3F-C38E-43D1-B702-DC03F530A3CB}.Release|ARM.ActiveCfg = Release|ARM - {DC435C3F-C38E-43D1-B702-DC03F530A3CB}.Release|ARM.Build.0 = Release|ARM - {DC435C3F-C38E-43D1-B702-DC03F530A3CB}.Release|ARM64.ActiveCfg = Release|Win32 + {DC435C3F-C38E-43D1-B702-DC03F530A3CB}.Release|ARM64.ActiveCfg = Release|ARM64 + {DC435C3F-C38E-43D1-B702-DC03F530A3CB}.Release|ARM64.Build.0 = Release|ARM64 {DC435C3F-C38E-43D1-B702-DC03F530A3CB}.Release|x64.ActiveCfg = Release|x64 {DC435C3F-C38E-43D1-B702-DC03F530A3CB}.Release|x64.Build.0 = Release|x64 {DC435C3F-C38E-43D1-B702-DC03F530A3CB}.Release|x86.ActiveCfg = Release|Win32 {DC435C3F-C38E-43D1-B702-DC03F530A3CB}.Release|x86.Build.0 = Release|Win32 - {DC435C3F-C38E-43D1-B702-DC03F530A3DD}.Debug|ARM.ActiveCfg = Debug|ARM - {DC435C3F-C38E-43D1-B702-DC03F530A3DD}.Debug|ARM.Build.0 = Debug|ARM - {DC435C3F-C38E-43D1-B702-DC03F530A3DD}.Debug|ARM64.ActiveCfg = Debug|Win32 + {DC435C3F-C38E-43D1-B702-DC03F530A3DD}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {DC435C3F-C38E-43D1-B702-DC03F530A3DD}.Debug|ARM64.Build.0 = Debug|ARM64 {DC435C3F-C38E-43D1-B702-DC03F530A3DD}.Debug|x64.ActiveCfg = Debug|x64 {DC435C3F-C38E-43D1-B702-DC03F530A3DD}.Debug|x64.Build.0 = Debug|x64 {DC435C3F-C38E-43D1-B702-DC03F530A3DD}.Debug|x86.ActiveCfg = Debug|Win32 {DC435C3F-C38E-43D1-B702-DC03F530A3DD}.Debug|x86.Build.0 = Debug|Win32 - {DC435C3F-C38E-43D1-B702-DC03F530A3DD}.Release|ARM.ActiveCfg = Release|ARM - {DC435C3F-C38E-43D1-B702-DC03F530A3DD}.Release|ARM.Build.0 = Release|ARM - {DC435C3F-C38E-43D1-B702-DC03F530A3DD}.Release|ARM64.ActiveCfg = Release|Win32 + {DC435C3F-C38E-43D1-B702-DC03F530A3DD}.Release|ARM64.ActiveCfg = Release|ARM64 + {DC435C3F-C38E-43D1-B702-DC03F530A3DD}.Release|ARM64.Build.0 = Release|ARM64 {DC435C3F-C38E-43D1-B702-DC03F530A3DD}.Release|x64.ActiveCfg = Release|x64 {DC435C3F-C38E-43D1-B702-DC03F530A3DD}.Release|x64.Build.0 = Release|x64 {DC435C3F-C38E-43D1-B702-DC03F530A3DD}.Release|x86.ActiveCfg = Release|Win32 {DC435C3F-C38E-43D1-B702-DC03F530A3DD}.Release|x86.Build.0 = Release|Win32 - {C47F8562-A2B9-4BA3-87AC-B42D015E241D}.Debug|ARM.ActiveCfg = Debug|ARM - {C47F8562-A2B9-4BA3-87AC-B42D015E241D}.Debug|ARM.Build.0 = Debug|ARM {C47F8562-A2B9-4BA3-87AC-B42D015E241D}.Debug|ARM64.ActiveCfg = Debug|ARM64 {C47F8562-A2B9-4BA3-87AC-B42D015E241D}.Debug|ARM64.Build.0 = Debug|ARM64 {C47F8562-A2B9-4BA3-87AC-B42D015E241D}.Debug|x64.ActiveCfg = Debug|x64 {C47F8562-A2B9-4BA3-87AC-B42D015E241D}.Debug|x64.Build.0 = Debug|x64 {C47F8562-A2B9-4BA3-87AC-B42D015E241D}.Debug|x86.ActiveCfg = Debug|x86 {C47F8562-A2B9-4BA3-87AC-B42D015E241D}.Debug|x86.Build.0 = Debug|x86 - {C47F8562-A2B9-4BA3-87AC-B42D015E241D}.Release|ARM.ActiveCfg = Release|ARM - {C47F8562-A2B9-4BA3-87AC-B42D015E241D}.Release|ARM.Build.0 = Release|ARM {C47F8562-A2B9-4BA3-87AC-B42D015E241D}.Release|ARM64.ActiveCfg = Release|ARM64 {C47F8562-A2B9-4BA3-87AC-B42D015E241D}.Release|ARM64.Build.0 = Release|ARM64 {C47F8562-A2B9-4BA3-87AC-B42D015E241D}.Release|x64.ActiveCfg = Release|x64 {C47F8562-A2B9-4BA3-87AC-B42D015E241D}.Release|x64.Build.0 = Release|x64 {C47F8562-A2B9-4BA3-87AC-B42D015E241D}.Release|x86.ActiveCfg = Release|x86 {C47F8562-A2B9-4BA3-87AC-B42D015E241D}.Release|x86.Build.0 = Release|x86 - {8717FA32-34A8-457D-B77B-AE005703EB55}.Debug|ARM.ActiveCfg = Debug|ARM - {8717FA32-34A8-457D-B77B-AE005703EB55}.Debug|ARM.Build.0 = Debug|ARM - {8717FA32-34A8-457D-B77B-AE005703EB55}.Debug|ARM64.ActiveCfg = Debug|Win32 + {8717FA32-34A8-457D-B77B-AE005703EB55}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {8717FA32-34A8-457D-B77B-AE005703EB55}.Debug|ARM64.Build.0 = Debug|ARM64 {8717FA32-34A8-457D-B77B-AE005703EB55}.Debug|x64.ActiveCfg = Debug|x64 {8717FA32-34A8-457D-B77B-AE005703EB55}.Debug|x64.Build.0 = Debug|x64 {8717FA32-34A8-457D-B77B-AE005703EB55}.Debug|x86.ActiveCfg = Debug|Win32 {8717FA32-34A8-457D-B77B-AE005703EB55}.Debug|x86.Build.0 = Debug|Win32 - {8717FA32-34A8-457D-B77B-AE005703EB55}.Release|ARM.ActiveCfg = Release|ARM - {8717FA32-34A8-457D-B77B-AE005703EB55}.Release|ARM.Build.0 = Release|ARM - {8717FA32-34A8-457D-B77B-AE005703EB55}.Release|ARM64.ActiveCfg = Release|Win32 + {8717FA32-34A8-457D-B77B-AE005703EB55}.Release|ARM64.ActiveCfg = Release|ARM64 + {8717FA32-34A8-457D-B77B-AE005703EB55}.Release|ARM64.Build.0 = Release|ARM64 {8717FA32-34A8-457D-B77B-AE005703EB55}.Release|x64.ActiveCfg = Release|x64 {8717FA32-34A8-457D-B77B-AE005703EB55}.Release|x64.Build.0 = Release|x64 {8717FA32-34A8-457D-B77B-AE005703EB55}.Release|x86.ActiveCfg = Release|Win32 {8717FA32-34A8-457D-B77B-AE005703EB55}.Release|x86.Build.0 = Release|Win32 - {FF846D79-F4B8-495A-9FB4-79BAAEB98E4F}.Debug|ARM.ActiveCfg = Debug|ARM - {FF846D79-F4B8-495A-9FB4-79BAAEB98E4F}.Debug|ARM.Build.0 = Debug|ARM {FF846D79-F4B8-495A-9FB4-79BAAEB98E4F}.Debug|ARM64.ActiveCfg = Debug|ARM64 {FF846D79-F4B8-495A-9FB4-79BAAEB98E4F}.Debug|ARM64.Build.0 = Debug|ARM64 {FF846D79-F4B8-495A-9FB4-79BAAEB98E4F}.Debug|x64.ActiveCfg = Debug|x64 {FF846D79-F4B8-495A-9FB4-79BAAEB98E4F}.Debug|x64.Build.0 = Debug|x64 {FF846D79-F4B8-495A-9FB4-79BAAEB98E4F}.Debug|x86.ActiveCfg = Debug|Win32 {FF846D79-F4B8-495A-9FB4-79BAAEB98E4F}.Debug|x86.Build.0 = Debug|Win32 - {FF846D79-F4B8-495A-9FB4-79BAAEB98E4F}.Release|ARM.ActiveCfg = Release|ARM - {FF846D79-F4B8-495A-9FB4-79BAAEB98E4F}.Release|ARM.Build.0 = Release|ARM {FF846D79-F4B8-495A-9FB4-79BAAEB98E4F}.Release|ARM64.ActiveCfg = Release|ARM64 {FF846D79-F4B8-495A-9FB4-79BAAEB98E4F}.Release|ARM64.Build.0 = Release|ARM64 {FF846D79-F4B8-495A-9FB4-79BAAEB98E4F}.Release|x64.ActiveCfg = Release|x64 {FF846D79-F4B8-495A-9FB4-79BAAEB98E4F}.Release|x64.Build.0 = Release|x64 {FF846D79-F4B8-495A-9FB4-79BAAEB98E4F}.Release|x86.ActiveCfg = Release|Win32 {FF846D79-F4B8-495A-9FB4-79BAAEB98E4F}.Release|x86.Build.0 = Release|Win32 - {F89C2185-7834-443D-A449-53BD52FFEA3B}.Debug|ARM.ActiveCfg = Debug|ARM - {F89C2185-7834-443D-A449-53BD52FFEA3B}.Debug|ARM.Build.0 = Debug|ARM - {F89C2185-7834-443D-A449-53BD52FFEA3B}.Debug|ARM64.ActiveCfg = Debug|Win32 + {F89C2185-7834-443D-A449-53BD52FFEA3B}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {F89C2185-7834-443D-A449-53BD52FFEA3B}.Debug|ARM64.Build.0 = Debug|ARM64 {F89C2185-7834-443D-A449-53BD52FFEA3B}.Debug|x64.ActiveCfg = Debug|x64 {F89C2185-7834-443D-A449-53BD52FFEA3B}.Debug|x64.Build.0 = Debug|x64 {F89C2185-7834-443D-A449-53BD52FFEA3B}.Debug|x86.ActiveCfg = Debug|Win32 {F89C2185-7834-443D-A449-53BD52FFEA3B}.Debug|x86.Build.0 = Debug|Win32 - {F89C2185-7834-443D-A449-53BD52FFEA3B}.Release|ARM.ActiveCfg = Release|ARM - {F89C2185-7834-443D-A449-53BD52FFEA3B}.Release|ARM.Build.0 = Release|ARM - {F89C2185-7834-443D-A449-53BD52FFEA3B}.Release|ARM64.ActiveCfg = Release|Win32 + {F89C2185-7834-443D-A449-53BD52FFEA3B}.Release|ARM64.ActiveCfg = Release|ARM64 + {F89C2185-7834-443D-A449-53BD52FFEA3B}.Release|ARM64.Build.0 = Release|ARM64 {F89C2185-7834-443D-A449-53BD52FFEA3B}.Release|x64.ActiveCfg = Release|x64 {F89C2185-7834-443D-A449-53BD52FFEA3B}.Release|x64.Build.0 = Release|x64 {F89C2185-7834-443D-A449-53BD52FFEA3B}.Release|x86.ActiveCfg = Release|Win32 {F89C2185-7834-443D-A449-53BD52FFEA3B}.Release|x86.Build.0 = Release|Win32 - {4DD64EAE-4B27-415A-863E-55CB8D5863DD}.Debug|ARM.ActiveCfg = Debug|Win32 - {4DD64EAE-4B27-415A-863E-55CB8D5863DD}.Debug|ARM64.ActiveCfg = Debug|Win32 + {4DD64EAE-4B27-415A-863E-55CB8D5863DD}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {4DD64EAE-4B27-415A-863E-55CB8D5863DD}.Debug|ARM64.Build.0 = Debug|ARM64 {4DD64EAE-4B27-415A-863E-55CB8D5863DD}.Debug|x64.ActiveCfg = Debug|x64 {4DD64EAE-4B27-415A-863E-55CB8D5863DD}.Debug|x64.Build.0 = Debug|x64 {4DD64EAE-4B27-415A-863E-55CB8D5863DD}.Debug|x86.ActiveCfg = Debug|Win32 {4DD64EAE-4B27-415A-863E-55CB8D5863DD}.Debug|x86.Build.0 = Debug|Win32 - {4DD64EAE-4B27-415A-863E-55CB8D5863DD}.Release|ARM.ActiveCfg = Release|Win32 - {4DD64EAE-4B27-415A-863E-55CB8D5863DD}.Release|ARM64.ActiveCfg = Release|Win32 + {4DD64EAE-4B27-415A-863E-55CB8D5863DD}.Release|ARM64.ActiveCfg = Release|ARM64 + {4DD64EAE-4B27-415A-863E-55CB8D5863DD}.Release|ARM64.Build.0 = Release|ARM64 {4DD64EAE-4B27-415A-863E-55CB8D5863DD}.Release|x64.ActiveCfg = Release|x64 {4DD64EAE-4B27-415A-863E-55CB8D5863DD}.Release|x64.Build.0 = Release|x64 {4DD64EAE-4B27-415A-863E-55CB8D5863DD}.Release|x86.ActiveCfg = Release|Win32 {4DD64EAE-4B27-415A-863E-55CB8D5863DD}.Release|x86.Build.0 = Release|Win32 - {98E28FC8-2EB7-4544-9B6A-941462C6D3E2}.Debug|ARM.ActiveCfg = Debug|x64 - {98E28FC8-2EB7-4544-9B6A-941462C6D3E2}.Debug|ARM.Build.0 = Debug|x64 {98E28FC8-2EB7-4544-9B6A-941462C6D3E2}.Debug|ARM64.ActiveCfg = Debug|ARM64 {98E28FC8-2EB7-4544-9B6A-941462C6D3E2}.Debug|ARM64.Build.0 = Debug|ARM64 {98E28FC8-2EB7-4544-9B6A-941462C6D3E2}.Debug|x64.ActiveCfg = Debug|x64 {98E28FC8-2EB7-4544-9B6A-941462C6D3E2}.Debug|x64.Build.0 = Debug|x64 {98E28FC8-2EB7-4544-9B6A-941462C6D3E2}.Debug|x86.ActiveCfg = Debug|Win32 {98E28FC8-2EB7-4544-9B6A-941462C6D3E2}.Debug|x86.Build.0 = Debug|Win32 - {98E28FC8-2EB7-4544-9B6A-941462C6D3E2}.Release|ARM.ActiveCfg = Release|x64 - {98E28FC8-2EB7-4544-9B6A-941462C6D3E2}.Release|ARM.Build.0 = Release|x64 {98E28FC8-2EB7-4544-9B6A-941462C6D3E2}.Release|ARM64.ActiveCfg = Release|ARM64 {98E28FC8-2EB7-4544-9B6A-941462C6D3E2}.Release|ARM64.Build.0 = Release|ARM64 {98E28FC8-2EB7-4544-9B6A-941462C6D3E2}.Release|x64.ActiveCfg = Release|x64 {98E28FC8-2EB7-4544-9B6A-941462C6D3E2}.Release|x64.Build.0 = Release|x64 {98E28FC8-2EB7-4544-9B6A-941462C6D3E2}.Release|x86.ActiveCfg = Release|Win32 {98E28FC8-2EB7-4544-9B6A-941462C6D3E2}.Release|x86.Build.0 = Release|Win32 + {8679913F-D38D-468F-A8B7-75B187A7A8BC}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {8679913F-D38D-468F-A8B7-75B187A7A8BC}.Debug|ARM64.Build.0 = Debug|ARM64 + {8679913F-D38D-468F-A8B7-75B187A7A8BC}.Debug|x64.ActiveCfg = Debug|x64 + {8679913F-D38D-468F-A8B7-75B187A7A8BC}.Debug|x64.Build.0 = Debug|x64 + {8679913F-D38D-468F-A8B7-75B187A7A8BC}.Debug|x86.ActiveCfg = Debug|Win32 + {8679913F-D38D-468F-A8B7-75B187A7A8BC}.Debug|x86.Build.0 = Debug|Win32 + {8679913F-D38D-468F-A8B7-75B187A7A8BC}.Release|ARM64.ActiveCfg = Release|ARM64 + {8679913F-D38D-468F-A8B7-75B187A7A8BC}.Release|ARM64.Build.0 = Release|ARM64 + {8679913F-D38D-468F-A8B7-75B187A7A8BC}.Release|x64.ActiveCfg = Release|x64 + {8679913F-D38D-468F-A8B7-75B187A7A8BC}.Release|x64.Build.0 = Release|x64 + {8679913F-D38D-468F-A8B7-75B187A7A8BC}.Release|x86.ActiveCfg = Release|Win32 + {8679913F-D38D-468F-A8B7-75B187A7A8BC}.Release|x86.Build.0 = Release|Win32 + {AEE91B86-AA17-4C22-B0C2-08B2C287E375}.Debug|ARM64.ActiveCfg = Release|ARM64 + {AEE91B86-AA17-4C22-B0C2-08B2C287E375}.Debug|x64.ActiveCfg = Release|x64 + {AEE91B86-AA17-4C22-B0C2-08B2C287E375}.Debug|x64.Build.0 = Release|x64 + {AEE91B86-AA17-4C22-B0C2-08B2C287E375}.Debug|x86.ActiveCfg = Release|Win32 + {AEE91B86-AA17-4C22-B0C2-08B2C287E375}.Release|ARM64.ActiveCfg = Release|ARM64 + {AEE91B86-AA17-4C22-B0C2-08B2C287E375}.Release|ARM64.Build.0 = Release|ARM64 + {AEE91B86-AA17-4C22-B0C2-08B2C287E375}.Release|x64.ActiveCfg = Release|x64 + {AEE91B86-AA17-4C22-B0C2-08B2C287E375}.Release|x64.Build.0 = Release|x64 + {AEE91B86-AA17-4C22-B0C2-08B2C287E375}.Release|x86.ActiveCfg = Release|Win32 + {AEE91B86-AA17-4C22-B0C2-08B2C287E375}.Release|x86.Build.0 = Release|Win32 + {F54D9A50-84D7-4953-8350-BEFE73CC36F6}.Debug|ARM64.ActiveCfg = Release|ARM64 + {F54D9A50-84D7-4953-8350-BEFE73CC36F6}.Debug|x64.ActiveCfg = Release|x64 + {F54D9A50-84D7-4953-8350-BEFE73CC36F6}.Debug|x64.Build.0 = Release|x64 + {F54D9A50-84D7-4953-8350-BEFE73CC36F6}.Debug|x86.ActiveCfg = Release|Win32 + {F54D9A50-84D7-4953-8350-BEFE73CC36F6}.Release|ARM64.ActiveCfg = Release|ARM64 + {F54D9A50-84D7-4953-8350-BEFE73CC36F6}.Release|ARM64.Build.0 = Release|ARM64 + {F54D9A50-84D7-4953-8350-BEFE73CC36F6}.Release|x64.ActiveCfg = Release|x64 + {F54D9A50-84D7-4953-8350-BEFE73CC36F6}.Release|x64.Build.0 = Release|x64 + {F54D9A50-84D7-4953-8350-BEFE73CC36F6}.Release|x86.ActiveCfg = Release|Win32 + {F54D9A50-84D7-4953-8350-BEFE73CC36F6}.Release|x86.Build.0 = Release|Win32 + {126E9412-E861-47C6-8684-C8F9BF32C0BD}.Debug|ARM64.ActiveCfg = Release|ARM64 + {126E9412-E861-47C6-8684-C8F9BF32C0BD}.Debug|x64.ActiveCfg = Release|x64 + {126E9412-E861-47C6-8684-C8F9BF32C0BD}.Debug|x64.Build.0 = Release|x64 + {126E9412-E861-47C6-8684-C8F9BF32C0BD}.Debug|x86.ActiveCfg = Release|Win32 + {126E9412-E861-47C6-8684-C8F9BF32C0BD}.Release|ARM64.ActiveCfg = Release|ARM64 + {126E9412-E861-47C6-8684-C8F9BF32C0BD}.Release|ARM64.Build.0 = Release|ARM64 + {126E9412-E861-47C6-8684-C8F9BF32C0BD}.Release|x64.ActiveCfg = Release|x64 + {126E9412-E861-47C6-8684-C8F9BF32C0BD}.Release|x64.Build.0 = Release|x64 + {126E9412-E861-47C6-8684-C8F9BF32C0BD}.Release|x86.ActiveCfg = Release|Win32 + {126E9412-E861-47C6-8684-C8F9BF32C0BD}.Release|x86.Build.0 = Release|Win32 + {FB7FEAA7-09DE-465C-BA0E-60374D3EFFD9}.Debug|ARM64.ActiveCfg = Release|ARM64 + {FB7FEAA7-09DE-465C-BA0E-60374D3EFFD9}.Debug|x64.ActiveCfg = Release|x64 + {FB7FEAA7-09DE-465C-BA0E-60374D3EFFD9}.Debug|x64.Build.0 = Release|x64 + {FB7FEAA7-09DE-465C-BA0E-60374D3EFFD9}.Debug|x86.ActiveCfg = Release|Win32 + {FB7FEAA7-09DE-465C-BA0E-60374D3EFFD9}.Release|ARM64.ActiveCfg = Release|ARM64 + {FB7FEAA7-09DE-465C-BA0E-60374D3EFFD9}.Release|ARM64.Build.0 = Release|ARM64 + {FB7FEAA7-09DE-465C-BA0E-60374D3EFFD9}.Release|x64.ActiveCfg = Release|x64 + {FB7FEAA7-09DE-465C-BA0E-60374D3EFFD9}.Release|x64.Build.0 = Release|x64 + {FB7FEAA7-09DE-465C-BA0E-60374D3EFFD9}.Release|x86.ActiveCfg = Release|Win32 + {FB7FEAA7-09DE-465C-BA0E-60374D3EFFD9}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/test/nuget/TestApp/TestApp.vcxproj b/test/nuget/TestApp/TestApp.vcxproj index 582b95103..f14bd9f0b 100644 --- a/test/nuget/TestApp/TestApp.vcxproj +++ b/test/nuget/TestApp/TestApp.vcxproj @@ -16,9 +16,9 @@ - + Debug - ARM + ARM64 Debug @@ -28,9 +28,9 @@ Debug x64 - + Release - ARM + ARM64 Release @@ -70,6 +70,7 @@ pch.h $(IntDir)pch.pch Level4 + true %(AdditionalOptions) /bigobj diff --git a/test/nuget/TestModuleApp/CustomDependencyObject.cpp b/test/nuget/TestModuleApp/CustomDependencyObject.cpp new file mode 100644 index 000000000..81631e387 --- /dev/null +++ b/test/nuget/TestModuleApp/CustomDependencyObject.cpp @@ -0,0 +1,8 @@ +#include "pch.h" + +#define WINRT_IMPORT_MODULE +import winrt.Windows.Foundation; +import winrt.Windows.UI.Xaml; + +#include "CustomDependencyObject.h" +#include "CustomDependencyObject.g.cpp" diff --git a/test/nuget/TestModuleApp/CustomDependencyObject.h b/test/nuget/TestModuleApp/CustomDependencyObject.h new file mode 100644 index 000000000..79fd6b1ff --- /dev/null +++ b/test/nuget/TestModuleApp/CustomDependencyObject.h @@ -0,0 +1,23 @@ +#pragma once +#include "CustomDependencyObject.g.h" + +namespace winrt::TestModuleApp::implementation +{ + struct CustomDependencyObject : CustomDependencyObjectT + { + CustomDependencyObject() = default; + + hstring Name() { return m_name; } + void Name(hstring const& value) { m_name = value; } + + private: + hstring m_name; + }; +} + +namespace winrt::TestModuleApp::factory_implementation +{ + struct CustomDependencyObject : CustomDependencyObjectT + { + }; +} diff --git a/test/nuget/TestModuleApp/ModuleTestHelper.cpp b/test/nuget/TestModuleApp/ModuleTestHelper.cpp new file mode 100644 index 000000000..1e3d7bc1a --- /dev/null +++ b/test/nuget/TestModuleApp/ModuleTestHelper.cpp @@ -0,0 +1,7 @@ +#include "pch.h" + +#define WINRT_IMPORT_MODULE +import winrt.Windows.Foundation; + +#include "ModuleTestHelper.h" +#include "ModuleTestHelper.g.cpp" diff --git a/test/nuget/TestModuleApp/ModuleTestHelper.h b/test/nuget/TestModuleApp/ModuleTestHelper.h new file mode 100644 index 000000000..c5a699c6b --- /dev/null +++ b/test/nuget/TestModuleApp/ModuleTestHelper.h @@ -0,0 +1,27 @@ +#pragma once +#include "ModuleTestHelper.g.h" + +namespace winrt::TestModuleApp::implementation +{ + struct ModuleTestHelper : ModuleTestHelperT + { + ModuleTestHelper() = default; + + Windows::Foundation::Uri CreateUri(hstring const& url) + { + return Windows::Foundation::Uri(url); + } + + Windows::Foundation::IAsyncOperation GetStringAsync() + { + co_return L"hello from module"; + } + }; +} + +namespace winrt::TestModuleApp::factory_implementation +{ + struct ModuleTestHelper : ModuleTestHelperT + { + }; +} diff --git a/test/nuget/TestModuleApp/PropertySheet.props b/test/nuget/TestModuleApp/PropertySheet.props new file mode 100644 index 000000000..379c2c3a2 --- /dev/null +++ b/test/nuget/TestModuleApp/PropertySheet.props @@ -0,0 +1,7 @@ + + + + + + + diff --git a/test/nuget/TestModuleApp/TestModuleApp.def b/test/nuget/TestModuleApp/TestModuleApp.def new file mode 100644 index 000000000..53d2e7cbf --- /dev/null +++ b/test/nuget/TestModuleApp/TestModuleApp.def @@ -0,0 +1,3 @@ +EXPORTS +DllCanUnloadNow = WINRT_CanUnloadNow PRIVATE +DllGetActivationFactory = WINRT_GetActivationFactory PRIVATE diff --git a/test/nuget/TestModuleApp/TestModuleApp.idl b/test/nuget/TestModuleApp/TestModuleApp.idl new file mode 100644 index 000000000..ab3c56707 --- /dev/null +++ b/test/nuget/TestModuleApp/TestModuleApp.idl @@ -0,0 +1,20 @@ +namespace TestModuleApp +{ + // A type that inherits from Windows.UI.Xaml.DependencyObject to exercise + // cross-namespace inheritance in module builds. + [default_interface] + unsealed runtimeclass CustomDependencyObject : Windows.UI.Xaml.DependencyObject + { + CustomDependencyObject(); + String Name{ get; set; }; + } + + // A simple runtime class using platform SDK types. + [default_interface] + runtimeclass ModuleTestHelper + { + ModuleTestHelper(); + Windows.Foundation.Uri CreateUri(String url); + Windows.Foundation.IAsyncOperation GetStringAsync(); + } +} diff --git a/test/nuget/TestModuleApp/TestModuleApp.vcxproj b/test/nuget/TestModuleApp/TestModuleApp.vcxproj new file mode 100644 index 000000000..522e0d911 --- /dev/null +++ b/test/nuget/TestModuleApp/TestModuleApp.vcxproj @@ -0,0 +1,127 @@ + + + + + true + true + true + Windows;TestModuleApp + true + {8679913F-D38D-468F-A8B7-75B187A7A8BC} + TestModuleApp + TestModuleApp + en-US + 14.0 + + + + + Debug + Win32 + + + Debug + x64 + + + Debug + ARM64 + + + Release + Win32 + + + Release + x64 + + + Release + ARM64 + + + + Application + v145 + Unicode + + + true + + + false + true + + + + + + + + + + + + + + + + + Use + pch.h + $(IntDir)pch.pch + stdcpplatest + Level4 + true + %(AdditionalOptions) /bigobj + 5311;28204 + NOMINMAX;%(PreprocessorDefinitions) + true + $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) + + + Console + + + + + _DEBUG;%(PreprocessorDefinitions) + + + + + NDEBUG;%(PreprocessorDefinitions) + + + + + + TestModuleApp.idl + + + TestModuleApp.idl + + + + + Create + + + + TestModuleApp.idl + + + TestModuleApp.idl + + + + + + + + + + + + + diff --git a/test/nuget/TestModuleApp/main.cpp b/test/nuget/TestModuleApp/main.cpp new file mode 100644 index 000000000..907e4afed --- /dev/null +++ b/test/nuget/TestModuleApp/main.cpp @@ -0,0 +1,42 @@ +#include "pch.h" + +#define WINRT_IMPORT_MODULE +import std; +import winrt.Windows.Foundation; +import winrt.Windows.UI.Xaml; + +#include "ModuleTestHelper.h" +#include "CustomDependencyObject.h" + +using namespace winrt; +using namespace Windows::Foundation; + +int main() +{ + init_apartment(); + + // Test ModuleTestHelper + auto helper = TestModuleApp::ModuleTestHelper(); + auto uri = helper.CreateUri(L"https://example.com"); + std::printf("URI: %ls\n", uri.AbsoluteUri().c_str()); + + auto str = helper.GetStringAsync().get(); + std::printf("Async: %ls\n", str.c_str()); + + // Test CustomDependencyObject (inherits from DependencyObject) + // Note: DependencyObject requires XAML runtime, which isn't available in a console app. + // We verify the type compiles and links correctly; runtime creation would need a XAML host. + try + { + auto obj = winrt::make(); + obj.Name(L"test"); + std::printf("Name: %ls\n", obj.Name().c_str()); + } + catch (winrt::hresult_error const& e) + { + std::printf("CustomDependencyObject: expected runtime error (no XAML host): %ls\n", e.message().c_str()); + } + + std::printf("All module tests passed.\n"); + return 0; +} diff --git a/test/nuget/TestModuleApp/pch.cpp b/test/nuget/TestModuleApp/pch.cpp new file mode 100644 index 000000000..1d9f38c57 --- /dev/null +++ b/test/nuget/TestModuleApp/pch.cpp @@ -0,0 +1 @@ +#include "pch.h" diff --git a/test/nuget/TestModuleApp/pch.h b/test/nuget/TestModuleApp/pch.h new file mode 100644 index 000000000..6f70f09be --- /dev/null +++ b/test/nuget/TestModuleApp/pch.h @@ -0,0 +1 @@ +#pragma once diff --git a/test/nuget/TestModuleBuilder/PropertySheet.props b/test/nuget/TestModuleBuilder/PropertySheet.props new file mode 100644 index 000000000..379c2c3a2 --- /dev/null +++ b/test/nuget/TestModuleBuilder/PropertySheet.props @@ -0,0 +1,7 @@ + + + + + + + diff --git a/test/nuget/TestModuleBuilder/TestModuleBuilder.vcxproj b/test/nuget/TestModuleBuilder/TestModuleBuilder.vcxproj new file mode 100644 index 000000000..d2d852240 --- /dev/null +++ b/test/nuget/TestModuleBuilder/TestModuleBuilder.vcxproj @@ -0,0 +1,67 @@ + + + + + true + Windows.Foundation + Windows.Foundation.Diagnostics + true + {AEE91B86-AA17-4C22-B0C2-08B2C287E375} + TestModuleBuilder + TestModuleBuilder + en-US + 14.0 + + + + + Release + Win32 + + + Release + x64 + + + Release + ARM64 + + + + StaticLibrary + v145 + Unicode + + + false + true + + + + + + + + + + Use + pch.h + stdcpplatest + Level4 + true + %(AdditionalOptions) /bigobj + true + NOMINMAX;%(PreprocessorDefinitions) + + + + + + + + Create + + + + + diff --git a/test/nuget/TestModuleBuilder/pch.cpp b/test/nuget/TestModuleBuilder/pch.cpp new file mode 100644 index 000000000..1d9f38c57 --- /dev/null +++ b/test/nuget/TestModuleBuilder/pch.cpp @@ -0,0 +1 @@ +#include "pch.h" diff --git a/test/nuget/TestModuleBuilder/pch.h b/test/nuget/TestModuleBuilder/pch.h new file mode 100644 index 000000000..6f70f09be --- /dev/null +++ b/test/nuget/TestModuleBuilder/pch.h @@ -0,0 +1 @@ +#pragma once diff --git a/test/nuget/TestModuleComponent1/Greeter.cpp b/test/nuget/TestModuleComponent1/Greeter.cpp new file mode 100644 index 000000000..04c668e10 --- /dev/null +++ b/test/nuget/TestModuleComponent1/Greeter.cpp @@ -0,0 +1,8 @@ +#include "pch.h" + +#define WINRT_IMPORT_MODULE +import winrt_base; +import winrt.Windows.Foundation; + +#include "Greeter.h" +#include "Greeter.g.cpp" diff --git a/test/nuget/TestModuleComponent1/Greeter.h b/test/nuget/TestModuleComponent1/Greeter.h new file mode 100644 index 000000000..726fb7d22 --- /dev/null +++ b/test/nuget/TestModuleComponent1/Greeter.h @@ -0,0 +1,25 @@ +#pragma once +#include "Greeter.g.h" + +namespace winrt::TestModuleComponent1::implementation +{ + struct Greeter : GreeterT + { + Greeter() : m_name(L"World") {} + Greeter(hstring const& name) : m_name(name) {} + + hstring Name() { return m_name; } + hstring Greet() { return L"Hello, " + m_name + L"!"; } + Windows::Foundation::Uri Homepage() { return Windows::Foundation::Uri(L"https://example.com/" + m_name); } + + private: + hstring m_name; + }; +} + +namespace winrt::TestModuleComponent1::factory_implementation +{ + struct Greeter : GreeterT + { + }; +} diff --git a/test/nuget/TestModuleComponent1/PropertySheet.props b/test/nuget/TestModuleComponent1/PropertySheet.props new file mode 100644 index 000000000..379c2c3a2 --- /dev/null +++ b/test/nuget/TestModuleComponent1/PropertySheet.props @@ -0,0 +1,7 @@ + + + + + + + diff --git a/test/nuget/TestModuleComponent1/TestModuleComponent1.def b/test/nuget/TestModuleComponent1/TestModuleComponent1.def new file mode 100644 index 000000000..53d2e7cbf --- /dev/null +++ b/test/nuget/TestModuleComponent1/TestModuleComponent1.def @@ -0,0 +1,3 @@ +EXPORTS +DllCanUnloadNow = WINRT_CanUnloadNow PRIVATE +DllGetActivationFactory = WINRT_GetActivationFactory PRIVATE diff --git a/test/nuget/TestModuleComponent1/TestModuleComponent1.idl b/test/nuget/TestModuleComponent1/TestModuleComponent1.idl new file mode 100644 index 000000000..73a983ee2 --- /dev/null +++ b/test/nuget/TestModuleComponent1/TestModuleComponent1.idl @@ -0,0 +1,12 @@ +namespace TestModuleComponent1 +{ + [default_interface] + runtimeclass Greeter + { + Greeter(); + Greeter(String name); + String Name{ get; }; + String Greet(); + Windows.Foundation.Uri Homepage{ get; }; + } +} diff --git a/test/nuget/TestModuleComponent1/TestModuleComponent1.vcxproj b/test/nuget/TestModuleComponent1/TestModuleComponent1.vcxproj new file mode 100644 index 000000000..669b25ff0 --- /dev/null +++ b/test/nuget/TestModuleComponent1/TestModuleComponent1.vcxproj @@ -0,0 +1,92 @@ + + + + + true + true + true + true + {F54D9A50-84D7-4953-8350-BEFE73CC36F6} + TestModuleComponent1 + TestModuleComponent1 + en-US + 14.0 + + + + + Release + Win32 + + + Release + x64 + + + Release + ARM64 + + + + DynamicLibrary + v145 + Unicode + + + false + true + + + + + + + + + + Use + pch.h + stdcpplatest + Level4 + true + %(AdditionalOptions) /bigobj + true + _WINRT_DLL;NOMINMAX;%(PreprocessorDefinitions) + $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) + + + Console + false + TestModuleComponent1.def + + + + + + TestModuleComponent1.idl + + + + + Create + + + TestModuleComponent1.idl + + + + + + + + + + + + + true + + + + + diff --git a/test/nuget/TestModuleComponent1/pch.cpp b/test/nuget/TestModuleComponent1/pch.cpp new file mode 100644 index 000000000..1d9f38c57 --- /dev/null +++ b/test/nuget/TestModuleComponent1/pch.cpp @@ -0,0 +1 @@ +#include "pch.h" diff --git a/test/nuget/TestModuleComponent1/pch.h b/test/nuget/TestModuleComponent1/pch.h new file mode 100644 index 000000000..6f70f09be --- /dev/null +++ b/test/nuget/TestModuleComponent1/pch.h @@ -0,0 +1 @@ +#pragma once diff --git a/test/nuget/TestModuleComponent2/GreeterGroup.cpp b/test/nuget/TestModuleComponent2/GreeterGroup.cpp new file mode 100644 index 000000000..7c6410b44 --- /dev/null +++ b/test/nuget/TestModuleComponent2/GreeterGroup.cpp @@ -0,0 +1,9 @@ +#include "pch.h" + +#define WINRT_IMPORT_MODULE +import std; +import winrt.Windows.Foundation; +import winrt.TestModuleComponent1; + +#include "GreeterGroup.h" +#include "GreeterGroup.g.cpp" diff --git a/test/nuget/TestModuleComponent2/GreeterGroup.h b/test/nuget/TestModuleComponent2/GreeterGroup.h new file mode 100644 index 000000000..461570425 --- /dev/null +++ b/test/nuget/TestModuleComponent2/GreeterGroup.h @@ -0,0 +1,36 @@ +#pragma once +#include "GreeterGroup.g.h" + +namespace winrt::TestModuleComponent2::implementation +{ + struct GreeterGroup : GreeterGroupT + { + GreeterGroup() = default; + + void Add(winrt::TestModuleComponent1::Greeter const& greeter) + { + m_greeters.push_back(greeter); + } + + hstring GreetAll() + { + hstring result; + for (auto const& g : m_greeters) + { + if (!result.empty()) result = result + L", "; + result = result + g.Greet(); + } + return result; + } + + private: + std::vector m_greeters; + }; +} + +namespace winrt::TestModuleComponent2::factory_implementation +{ + struct GreeterGroup : GreeterGroupT + { + }; +} diff --git a/test/nuget/TestModuleComponent2/PropertySheet.props b/test/nuget/TestModuleComponent2/PropertySheet.props new file mode 100644 index 000000000..379c2c3a2 --- /dev/null +++ b/test/nuget/TestModuleComponent2/PropertySheet.props @@ -0,0 +1,7 @@ + + + + + + + diff --git a/test/nuget/TestModuleComponent2/TestModuleComponent2.def b/test/nuget/TestModuleComponent2/TestModuleComponent2.def new file mode 100644 index 000000000..53d2e7cbf --- /dev/null +++ b/test/nuget/TestModuleComponent2/TestModuleComponent2.def @@ -0,0 +1,3 @@ +EXPORTS +DllCanUnloadNow = WINRT_CanUnloadNow PRIVATE +DllGetActivationFactory = WINRT_GetActivationFactory PRIVATE diff --git a/test/nuget/TestModuleComponent2/TestModuleComponent2.idl b/test/nuget/TestModuleComponent2/TestModuleComponent2.idl new file mode 100644 index 000000000..e45eed438 --- /dev/null +++ b/test/nuget/TestModuleComponent2/TestModuleComponent2.idl @@ -0,0 +1,10 @@ +namespace TestModuleComponent2 +{ + [default_interface] + runtimeclass GreeterGroup + { + GreeterGroup(); + void Add(TestModuleComponent1.Greeter greeter); + String GreetAll(); + } +} diff --git a/test/nuget/TestModuleComponent2/TestModuleComponent2.vcxproj b/test/nuget/TestModuleComponent2/TestModuleComponent2.vcxproj new file mode 100644 index 000000000..ff4982965 --- /dev/null +++ b/test/nuget/TestModuleComponent2/TestModuleComponent2.vcxproj @@ -0,0 +1,93 @@ + + + + + true + true + true + true + {126E9412-E861-47C6-8684-C8F9BF32C0BD} + TestModuleComponent2 + TestModuleComponent2 + en-US + 14.0 + + + + + Release + Win32 + + + Release + x64 + + + Release + ARM64 + + + + DynamicLibrary + v145 + Unicode + + + false + true + + + + + + + + + + Use + pch.h + stdcpplatest + Level4 + true + %(AdditionalOptions) /bigobj + true + _WINRT_DLL;NOMINMAX;%(PreprocessorDefinitions) + $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) + + + Console + false + TestModuleComponent2.def + + + + + + TestModuleComponent2.idl + + + + + Create + + + TestModuleComponent2.idl + + + + + + + + + + + + + true + + + + + + diff --git a/test/nuget/TestModuleComponent2/pch.cpp b/test/nuget/TestModuleComponent2/pch.cpp new file mode 100644 index 000000000..1d9f38c57 --- /dev/null +++ b/test/nuget/TestModuleComponent2/pch.cpp @@ -0,0 +1 @@ +#include "pch.h" diff --git a/test/nuget/TestModuleComponent2/pch.h b/test/nuget/TestModuleComponent2/pch.h new file mode 100644 index 000000000..6f70f09be --- /dev/null +++ b/test/nuget/TestModuleComponent2/pch.h @@ -0,0 +1 @@ +#pragma once diff --git a/test/nuget/TestModuleConsumerApp/PropertySheet.props b/test/nuget/TestModuleConsumerApp/PropertySheet.props new file mode 100644 index 000000000..379c2c3a2 --- /dev/null +++ b/test/nuget/TestModuleConsumerApp/PropertySheet.props @@ -0,0 +1,7 @@ + + + + + + + diff --git a/test/nuget/TestModuleConsumerApp/TestModuleConsumerApp.vcxproj b/test/nuget/TestModuleConsumerApp/TestModuleConsumerApp.vcxproj new file mode 100644 index 000000000..910586a0c --- /dev/null +++ b/test/nuget/TestModuleConsumerApp/TestModuleConsumerApp.vcxproj @@ -0,0 +1,76 @@ + + + + + true + true + {FB7FEAA7-09DE-465C-BA0E-60374D3EFFD9} + TestModuleConsumerApp + TestModuleConsumerApp + en-US + 14.0 + + + + + Release + Win32 + + + Release + x64 + + + Release + ARM64 + + + + Application + v145 + Unicode + + + false + true + + + + + + + + + + Use + pch.h + stdcpplatest + Level4 + true + %(AdditionalOptions) /bigobj + true + NOMINMAX;%(PreprocessorDefinitions) + + + Console + + + + + + + + Create + + + + + + true + + + + + + + diff --git a/test/nuget/TestModuleConsumerApp/main.cpp b/test/nuget/TestModuleConsumerApp/main.cpp new file mode 100644 index 000000000..da930703b --- /dev/null +++ b/test/nuget/TestModuleConsumerApp/main.cpp @@ -0,0 +1,32 @@ +#include "pch.h" + +import std; +import winrt.Windows.Foundation; +import winrt.TestModuleComponent1; +import winrt.TestModuleComponent2; + +using namespace winrt; +using namespace Windows::Foundation; + +int main() +{ + init_apartment(); + + // Platform types from pre-built modules + Uri uri(L"https://example.com/consumer"); + std::printf("URI: %ls\n", uri.AbsoluteUri().c_str()); + + // Component1 + auto greeter = TestModuleComponent1::Greeter(L"Modules"); + std::printf("Greet: %ls\n", greeter.Greet().c_str()); + std::printf("Homepage: %ls\n", greeter.Homepage().AbsoluteUri().c_str()); + + // Component2 (depends on Component1) + auto group = TestModuleComponent2::GreeterGroup(); + group.Add(TestModuleComponent1::Greeter(L"Alice")); + group.Add(TestModuleComponent1::Greeter(L"Bob")); + std::printf("GreetAll: %ls\n", group.GreetAll().c_str()); + + std::printf("All consumer tests passed.\n"); + return 0; +} diff --git a/test/nuget/TestModuleConsumerApp/pch.cpp b/test/nuget/TestModuleConsumerApp/pch.cpp new file mode 100644 index 000000000..1d9f38c57 --- /dev/null +++ b/test/nuget/TestModuleConsumerApp/pch.cpp @@ -0,0 +1 @@ +#include "pch.h" diff --git a/test/nuget/TestModuleConsumerApp/pch.h b/test/nuget/TestModuleConsumerApp/pch.h new file mode 100644 index 000000000..6f70f09be --- /dev/null +++ b/test/nuget/TestModuleConsumerApp/pch.h @@ -0,0 +1 @@ +#pragma once diff --git a/test/nuget/TestProxyStub/TestProxyStub.vcxproj b/test/nuget/TestProxyStub/TestProxyStub.vcxproj index 899a5c11c..cd646da7f 100644 --- a/test/nuget/TestProxyStub/TestProxyStub.vcxproj +++ b/test/nuget/TestProxyStub/TestProxyStub.vcxproj @@ -35,13 +35,11 @@ 10.0.22621.0 10.0.18362.0 - false false DynamicLibrary - v143 Unicode @@ -55,6 +53,8 @@ Use pch.h %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory) + Level4 + true Windows diff --git a/test/nuget/TestRuntimeComponent1/TestRuntimeComponent1.vcxproj b/test/nuget/TestRuntimeComponent1/TestRuntimeComponent1.vcxproj index 7827c2b21..b1ee4f43f 100644 --- a/test/nuget/TestRuntimeComponent1/TestRuntimeComponent1.vcxproj +++ b/test/nuget/TestRuntimeComponent1/TestRuntimeComponent1.vcxproj @@ -16,9 +16,9 @@ - + Debug - ARM + ARM64 Debug @@ -28,9 +28,9 @@ Debug x64 - + Release - ARM + ARM64 Release @@ -74,6 +74,7 @@ pch.h $(IntDir)pch.pch Level4 + true %(AdditionalOptions) /bigobj 28204 _WINRT_DLL;%(PreprocessorDefinitions) diff --git a/test/nuget/TestRuntimeComponent2/TestRuntimeComponent2.vcxproj b/test/nuget/TestRuntimeComponent2/TestRuntimeComponent2.vcxproj index eb12311c1..c27db2602 100644 --- a/test/nuget/TestRuntimeComponent2/TestRuntimeComponent2.vcxproj +++ b/test/nuget/TestRuntimeComponent2/TestRuntimeComponent2.vcxproj @@ -17,9 +17,9 @@ - + Debug - ARM + ARM64 Debug @@ -29,9 +29,9 @@ Debug x64 - + Release - ARM + ARM64 Release @@ -75,6 +75,7 @@ pch.h $(IntDir)pch.pch Level4 + true %(AdditionalOptions) /bigobj 28204 _WINRT_DLL;%(PreprocessorDefinitions) diff --git a/test/nuget/TestRuntimeComponent3/TestRuntimeComponent3.vcxproj b/test/nuget/TestRuntimeComponent3/TestRuntimeComponent3.vcxproj index 24d061de0..01c84d830 100644 --- a/test/nuget/TestRuntimeComponent3/TestRuntimeComponent3.vcxproj +++ b/test/nuget/TestRuntimeComponent3/TestRuntimeComponent3.vcxproj @@ -17,9 +17,9 @@ - + Debug - ARM + ARM64 Debug @@ -29,9 +29,9 @@ Debug x64 - + Release - ARM + ARM64 Release @@ -75,6 +75,7 @@ pch.h $(IntDir)pch.pch Level4 + true %(AdditionalOptions) /bigobj 28204 _WINRT_DLL;%(PreprocessorDefinitions) diff --git a/test/nuget/TestRuntimeComponentCSharp/TestRuntimeComponentCSharp.csproj b/test/nuget/TestRuntimeComponentCSharp/TestRuntimeComponentCSharp.csproj index 869819889..167b32ad9 100644 --- a/test/nuget/TestRuntimeComponentCSharp/TestRuntimeComponentCSharp.csproj +++ b/test/nuget/TestRuntimeComponentCSharp/TestRuntimeComponentCSharp.csproj @@ -11,8 +11,8 @@ TestRuntimeComponentCSharp en-US UAP - 10.0.18362.0 - 10.0.15063.0 + $(WindowsSDKVersion.TrimEnd('\')) + 10.0.18362.0 14 512 {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} @@ -36,24 +36,6 @@ false prompt - - ARM - true - DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP - ;2008 - full - false - prompt - - - ARM - TRACE;NETFX_CORE;WINDOWS_UWP - true - ;2008 - pdbonly - false - prompt - ARM64 true @@ -98,9 +80,7 @@ - - 5.4.7 - + 14.0 @@ -113,4 +93,4 @@ --> - \ No newline at end of file + diff --git a/test/nuget/TestRuntimeComponentCX/TestRuntimeComponentCX.vcxproj b/test/nuget/TestRuntimeComponentCX/TestRuntimeComponentCX.vcxproj index 97b5c5613..819cff52b 100644 --- a/test/nuget/TestRuntimeComponentCX/TestRuntimeComponentCX.vcxproj +++ b/test/nuget/TestRuntimeComponentCX/TestRuntimeComponentCX.vcxproj @@ -2,10 +2,6 @@ - - Debug - ARM - Debug ARM64 @@ -18,10 +14,6 @@ Debug x64 - - Release - ARM - Release ARM64 @@ -69,12 +61,6 @@ - - - - - - @@ -95,12 +81,6 @@ false - - false - - - false - false @@ -123,6 +103,8 @@ /bigobj /Zc:twoPhase- %(AdditionalOptions) 28204 true + Level4 + true Console @@ -139,38 +121,8 @@ /bigobj /Zc:twoPhase- %(AdditionalOptions) 28204 true - - - Console - false - - - - - Use - _WINRT_DLL;%(PreprocessorDefinitions) - pch.h - $(IntDir)pch.pch - $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) - /bigobj /Zc:twoPhase- %(AdditionalOptions) - 28204 - true - - - Console - false - - - - - Use - _WINRT_DLL;NDEBUG;%(PreprocessorDefinitions) - pch.h - $(IntDir)pch.pch - $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) - /bigobj /Zc:twoPhase- %(AdditionalOptions) - 28204 - true + Level4 + true Console @@ -187,6 +139,8 @@ /bigobj /Zc:twoPhase- %(AdditionalOptions) 28204 true + Level4 + true Console @@ -203,6 +157,8 @@ /bigobj /Zc:twoPhase- %(AdditionalOptions) 28204 true + Level4 + true Console @@ -219,6 +175,8 @@ /bigobj /Zc:twoPhase- %(AdditionalOptions) 28204 true + Level4 + true Console @@ -235,6 +193,8 @@ /bigobj /Zc:twoPhase- %(AdditionalOptions) 28204 true + Level4 + true Console @@ -251,8 +211,6 @@ Create Create Create - Create - Create Create Create diff --git a/test/nuget/TestRuntimeComponentCXReferencingWinRTStaticLibrary/TestRuntimeComponentCXReferencingWinRTStaticLibrary.vcxproj b/test/nuget/TestRuntimeComponentCXReferencingWinRTStaticLibrary/TestRuntimeComponentCXReferencingWinRTStaticLibrary.vcxproj index 6131345a9..6ce188345 100644 --- a/test/nuget/TestRuntimeComponentCXReferencingWinRTStaticLibrary/TestRuntimeComponentCXReferencingWinRTStaticLibrary.vcxproj +++ b/test/nuget/TestRuntimeComponentCXReferencingWinRTStaticLibrary/TestRuntimeComponentCXReferencingWinRTStaticLibrary.vcxproj @@ -2,10 +2,6 @@ - - Debug - ARM - Debug ARM64 @@ -18,10 +14,6 @@ Debug x64 - - Release - ARM - Release ARM64 @@ -51,10 +43,6 @@ DynamicLibrary true - - DynamicLibrary - true - DynamicLibrary true @@ -68,11 +56,6 @@ false true - - DynamicLibrary - false - true - DynamicLibrary false @@ -94,12 +77,6 @@ - - - - - - @@ -120,12 +97,6 @@ false - - false - - - false - false @@ -146,6 +117,8 @@ $(IntDir)pch.pch $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) /bigobj /Zc:twoPhase- %(AdditionalOptions) + Level4 + true 28204 @@ -161,36 +134,8 @@ $(IntDir)pch.pch $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) /bigobj /Zc:twoPhase- %(AdditionalOptions) - 28204 - - - Console - false - - - - - Use - _WINRT_DLL;%(PreprocessorDefinitions) - pch.h - $(IntDir)pch.pch - $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) - /bigobj /Zc:twoPhase- %(AdditionalOptions) - 28204 - - - Console - false - - - - - Use - _WINRT_DLL;NDEBUG;%(PreprocessorDefinitions) - pch.h - $(IntDir)pch.pch - $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) - /bigobj /Zc:twoPhase- %(AdditionalOptions) + Level4 + true 28204 @@ -206,6 +151,8 @@ $(IntDir)pch.pch $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) /bigobj /Zc:twoPhase- %(AdditionalOptions) + Level4 + true 28204 @@ -221,6 +168,8 @@ $(IntDir)pch.pch $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) /bigobj /Zc:twoPhase- %(AdditionalOptions) + Level4 + true 28204 @@ -236,6 +185,8 @@ $(IntDir)pch.pch $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) /bigobj /Zc:twoPhase- %(AdditionalOptions) + Level4 + true 28204 @@ -251,6 +202,8 @@ $(IntDir)pch.pch $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) /bigobj /Zc:twoPhase- %(AdditionalOptions) + Level4 + true 28204 @@ -268,8 +221,6 @@ Create Create Create - Create - Create Create Create diff --git a/test/nuget/TestRuntimeComponentEmpty/TestRuntimeComponentEmpty.vcxproj b/test/nuget/TestRuntimeComponentEmpty/TestRuntimeComponentEmpty.vcxproj index 66a6713df..60786eddb 100644 --- a/test/nuget/TestRuntimeComponentEmpty/TestRuntimeComponentEmpty.vcxproj +++ b/test/nuget/TestRuntimeComponentEmpty/TestRuntimeComponentEmpty.vcxproj @@ -17,9 +17,9 @@ - + Debug - ARM + ARM64 Debug @@ -29,9 +29,9 @@ Debug x64 - + Release - ARM + ARM64 Release @@ -75,6 +75,7 @@ pch.h $(IntDir)pch.pch Level4 + true %(AdditionalOptions) /bigobj 28204 _WINRT_DLL;%(PreprocessorDefinitions) diff --git a/test/nuget/TestRuntimeComponentNamespaceUnderscore/TestRuntimeComponentNamespaceUnderscore.vcxproj b/test/nuget/TestRuntimeComponentNamespaceUnderscore/TestRuntimeComponentNamespaceUnderscore.vcxproj index b07497f7f..fb8146340 100644 --- a/test/nuget/TestRuntimeComponentNamespaceUnderscore/TestRuntimeComponentNamespaceUnderscore.vcxproj +++ b/test/nuget/TestRuntimeComponentNamespaceUnderscore/TestRuntimeComponentNamespaceUnderscore.vcxproj @@ -17,9 +17,9 @@ - + Debug - ARM + ARM64 Debug @@ -29,9 +29,9 @@ Debug x64 - + Release - ARM + ARM64 Release @@ -75,6 +75,7 @@ pch.h $(IntDir)pch.pch Level4 + true %(AdditionalOptions) /bigobj _WINRT_DLL;WIN32_LEAN_AND_MEAN;WINRT_LEAN_AND_MEAN;%(PreprocessorDefinitions) $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) diff --git a/test/nuget/TestRuntimeComponentNamespaceUnderscore/packages.config b/test/nuget/TestRuntimeComponentNamespaceUnderscore/packages.config deleted file mode 100644 index 17dbbb252..000000000 --- a/test/nuget/TestRuntimeComponentNamespaceUnderscore/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/test/nuget/TestStaticLibrary1/TestStaticLibrary1.vcxproj b/test/nuget/TestStaticLibrary1/TestStaticLibrary1.vcxproj index 679f4b60c..13ac4e201 100644 --- a/test/nuget/TestStaticLibrary1/TestStaticLibrary1.vcxproj +++ b/test/nuget/TestStaticLibrary1/TestStaticLibrary1.vcxproj @@ -18,9 +18,9 @@ - + Debug - ARM + ARM64 Debug @@ -30,9 +30,9 @@ Debug x64 - + Release - ARM + ARM64 Release @@ -70,10 +70,10 @@ - + - + @@ -81,6 +81,7 @@ Use Level4 + true Disabled true WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) @@ -98,6 +99,7 @@ Use Level4 + true Disabled true _DEBUG;_LIB;%(PreprocessorDefinitions) @@ -111,10 +113,11 @@ true - + Use Level4 + true Disabled true _DEBUG;_LIB;%(PreprocessorDefinitions) @@ -132,6 +135,7 @@ Use Level4 + true MaxSpeed true true @@ -153,6 +157,7 @@ Use Level4 + true MaxSpeed true true @@ -170,10 +175,11 @@ true - + Use Level4 + true MaxSpeed true true @@ -202,10 +208,10 @@ Create Create - Create + Create Create Create - Create + Create TestStaticLibrary1Class.idl diff --git a/test/nuget/TestStaticLibrary2/TestStaticLibrary2.vcxproj b/test/nuget/TestStaticLibrary2/TestStaticLibrary2.vcxproj index cb8352c96..b419d183e 100644 --- a/test/nuget/TestStaticLibrary2/TestStaticLibrary2.vcxproj +++ b/test/nuget/TestStaticLibrary2/TestStaticLibrary2.vcxproj @@ -18,9 +18,9 @@ - + Debug - ARM + ARM64 Debug @@ -30,9 +30,9 @@ Debug x64 - + Release - ARM + ARM64 Release @@ -70,10 +70,10 @@ - + - + @@ -81,6 +81,7 @@ Use Level4 + true Disabled true WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) @@ -98,6 +99,7 @@ Use Level4 + true Disabled true _DEBUG;_LIB;%(PreprocessorDefinitions) @@ -111,10 +113,11 @@ true - + Use Level4 + true Disabled true _DEBUG;_LIB;%(PreprocessorDefinitions) @@ -132,6 +135,7 @@ Use Level4 + true MaxSpeed true true @@ -153,6 +157,7 @@ Use Level4 + true MaxSpeed true true @@ -170,10 +175,11 @@ true - + Use Level4 + true MaxSpeed true true @@ -202,10 +208,10 @@ Create Create - Create + Create Create Create - Create + Create TestStaticLibrary2Class.idl diff --git a/test/nuget/TestStaticLibrary3/TestStaticLibrary3.vcxproj b/test/nuget/TestStaticLibrary3/TestStaticLibrary3.vcxproj index 8b2d75f40..210802841 100644 --- a/test/nuget/TestStaticLibrary3/TestStaticLibrary3.vcxproj +++ b/test/nuget/TestStaticLibrary3/TestStaticLibrary3.vcxproj @@ -18,9 +18,9 @@ - + Debug - ARM + ARM64 Debug @@ -30,9 +30,9 @@ Debug x64 - + Release - ARM + ARM64 Release @@ -70,10 +70,10 @@ - + - + @@ -81,6 +81,7 @@ Use Level4 + true Disabled true WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) @@ -98,6 +99,7 @@ Use Level4 + true Disabled true _DEBUG;_LIB;%(PreprocessorDefinitions) @@ -111,10 +113,11 @@ true - + Use Level4 + true Disabled true _DEBUG;_LIB;%(PreprocessorDefinitions) @@ -132,6 +135,7 @@ Use Level4 + true MaxSpeed true true @@ -153,6 +157,7 @@ Use Level4 + true MaxSpeed true true @@ -170,10 +175,11 @@ true - + Use Level4 + true MaxSpeed true true @@ -202,10 +208,10 @@ Create Create - Create + Create Create Create - Create + Create TestStaticLibrary3Class.idl diff --git a/test/nuget/TestStaticLibrary4/TestStaticLibrary4.vcxproj b/test/nuget/TestStaticLibrary4/TestStaticLibrary4.vcxproj index 36fcfb1be..357d0ca70 100644 --- a/test/nuget/TestStaticLibrary4/TestStaticLibrary4.vcxproj +++ b/test/nuget/TestStaticLibrary4/TestStaticLibrary4.vcxproj @@ -2,9 +2,9 @@ - + Debug - ARM + ARM64 Debug @@ -14,9 +14,9 @@ Debug x64 - + Release - ARM + ARM64 Release @@ -65,10 +65,10 @@ - + - + @@ -85,10 +85,10 @@ false - + false - + false @@ -102,6 +102,8 @@ Use false true + Level4 + true Console @@ -114,6 +116,8 @@ Use false true + Level4 + true Console @@ -121,11 +125,13 @@ false - + Use false true + Level4 + true Console @@ -133,11 +139,13 @@ false - + Use false true + Level4 + true Console @@ -150,6 +158,8 @@ Use false true + Level4 + true Console @@ -162,6 +172,8 @@ Use false true + Level4 + true Console @@ -181,10 +193,10 @@ Create Create - Create - Create Create Create + Create + Create Create Create diff --git a/test/nuget/TestStaticLibrary5/TestStaticLibrary5.vcxproj b/test/nuget/TestStaticLibrary5/TestStaticLibrary5.vcxproj index e088b38f8..d93446a05 100644 --- a/test/nuget/TestStaticLibrary5/TestStaticLibrary5.vcxproj +++ b/test/nuget/TestStaticLibrary5/TestStaticLibrary5.vcxproj @@ -2,9 +2,9 @@ - + Debug - ARM + ARM64 Debug @@ -14,9 +14,9 @@ Debug x64 - + Release - ARM + ARM64 Release @@ -65,10 +65,10 @@ - + - + @@ -85,10 +85,10 @@ false - + false - + false @@ -102,6 +102,8 @@ Use false true + Level4 + true Console @@ -114,6 +116,8 @@ Use false true + Level4 + true Console @@ -121,11 +125,13 @@ false - + Use false true + Level4 + true Console @@ -133,11 +139,13 @@ false - + Use false true + Level4 + true Console @@ -150,6 +158,8 @@ Use false true + Level4 + true Console @@ -162,6 +172,8 @@ Use false true + Level4 + true Console @@ -181,10 +193,10 @@ Create Create - Create - Create Create Create + Create + Create Create Create diff --git a/test/nuget/TestStaticLibrary6/TestStaticLibrary6.vcxproj b/test/nuget/TestStaticLibrary6/TestStaticLibrary6.vcxproj index 8cf328f99..626e60dab 100644 --- a/test/nuget/TestStaticLibrary6/TestStaticLibrary6.vcxproj +++ b/test/nuget/TestStaticLibrary6/TestStaticLibrary6.vcxproj @@ -2,9 +2,9 @@ - + Debug - ARM + ARM64 Debug @@ -14,9 +14,9 @@ Debug x64 - + Release - ARM + ARM64 Release @@ -65,10 +65,10 @@ - + - + @@ -85,10 +85,10 @@ false - + false - + false @@ -102,6 +102,8 @@ Use false true + Level4 + true Console @@ -114,6 +116,8 @@ Use false true + Level4 + true Console @@ -121,11 +125,13 @@ false - + Use false true + Level4 + true Console @@ -133,11 +139,13 @@ false - + Use false true + Level4 + true Console @@ -150,6 +158,8 @@ Use false true + Level4 + true Console @@ -162,6 +172,8 @@ Use false true + Level4 + true Console @@ -185,10 +197,10 @@ Create Create - Create - Create Create Create + Create + Create Create Create diff --git a/test/nuget/TestStaticLibrary7/TestStaticLibrary7.vcxproj b/test/nuget/TestStaticLibrary7/TestStaticLibrary7.vcxproj index a8f21c356..85d6bec7f 100644 --- a/test/nuget/TestStaticLibrary7/TestStaticLibrary7.vcxproj +++ b/test/nuget/TestStaticLibrary7/TestStaticLibrary7.vcxproj @@ -1,6 +1,6 @@ - + true true @@ -18,9 +18,9 @@ - + Debug - ARM + ARM64 Debug @@ -30,9 +30,9 @@ Debug x64 - + Release - ARM + ARM64 Release @@ -76,6 +76,7 @@ pch.h $(IntDir)pch.pch Level4 + true %(AdditionalOptions) /bigobj WIN32_LEAN_AND_MEAN;WINRT_LEAN_AND_MEAN;%(PreprocessorDefinitions) $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) @@ -127,13 +128,6 @@ - + - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - diff --git a/test/nuget/TestStaticLibrary7/packages.config b/test/nuget/TestStaticLibrary7/packages.config deleted file mode 100644 index c4867c30b..000000000 --- a/test/nuget/TestStaticLibrary7/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/test/old_tests/Component/Component.idl b/test/old_tests/Component/Component.idl index 157297ee9..ad51b5303 100644 --- a/test/old_tests/Component/Component.idl +++ b/test/old_tests/Component/Component.idl @@ -243,11 +243,13 @@ namespace Component HRESULT Create([in] Windows.Foundation.Collections.IVectorView* _in, [out, retval] FastInputVector** _out); }; + midl_pragma warning(disable: 4066) // A member name has been qualified with an interface name because name collisions occurred across interface members on a runtime class. + [version(1.0), activatable(IFastInputVectorFactory, 1.0)] runtimeclass FastInputVector { // Don't confuse this for a high-performance vector. This is for testing fast-input binding support. - // The default interface is intentionally not one of the collection intefaces to force them to be convertible for testing. + // The default interface is intentionally not one of the collection interfaces to force them to be convertible for testing. [default] interface Windows.Foundation.IClosable; interface Windows.Foundation.Collections.IVector; interface Windows.Foundation.Collections.IVectorView; @@ -265,12 +267,14 @@ namespace Component runtimeclass FastInputMap { // Don't confuse this for a high-performance map. This is for testing fast-input binding support. - // The default interface is intentionally not one of the collection intefaces to force them to be convertible for testing. + // The default interface is intentionally not one of the collection interfaces to force them to be convertible for testing. [default] interface Windows.Foundation.IClosable; interface Windows.Foundation.Collections.IMap; interface Windows.Foundation.Collections.IMapView; }; + midl_pragma warning(default: 4066) + // // Boxing support for enums and their underlying types. // diff --git a/test/old_tests/Component/Component.vcxproj b/test/old_tests/Component/Component.vcxproj index 9af296c51..162c8fec7 100644 --- a/test/old_tests/Component/Component.vcxproj +++ b/test/old_tests/Component/Component.vcxproj @@ -1,10 +1,6 @@ - - Debug - ARM - Debug ARM64 @@ -17,10 +13,6 @@ Debug x64 - - Release - ARM - Release ARM64 @@ -46,11 +38,6 @@ true x64 - - DynamicLibrary - true - x64 - DynamicLibrary true @@ -67,12 +54,6 @@ true x64 - - DynamicLibrary - false - true - x64 - DynamicLibrary false @@ -93,18 +74,12 @@ - - - - - - @@ -119,49 +94,31 @@ false false - ..\..;$(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - Midl - - - false - false - ..\..;$(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl false false - ..\..;$(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl false false - ..\..;$(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - Midl - - - false - false - ..\..;$(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl false false - ..\..;$(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl false false - ..\..;$(VC_ExecutablePath_x64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(FxCopDir);$(PATH); Midl false false - ..\..;$(VC_ExecutablePath_x64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(FxCopDir);$(PATH); Midl @@ -183,6 +140,8 @@ false MultiThreadedDebug NOMINMAX;_WINDLL;%(PreprocessorDefinitions) + Level4 + true 4100;4297;4458 @@ -210,42 +169,6 @@ - - - false - $(ProjectDir);$(OutputPath);Generated Files;..\Composable\Generated Files - false - MultiThreadedDebug - NOMINMAX;_WINDLL;%(PreprocessorDefinitions) - 4100;4297;4458 - - - Console - false - module.def - true - - - - - - - - - ..\Composable - - - - - - - - - - - - - false @@ -253,6 +176,8 @@ false MultiThreadedDebug NOMINMAX;_WINDLL;%(PreprocessorDefinitions) + Level4 + true 4100;4297;4458 @@ -288,6 +213,8 @@ $(ProjectDir);$(OutputPath);Generated Files;..\Composable\Generated Files MultiThreaded NOMINMAX;_WINDLL;%(PreprocessorDefinitions) + Level4 + true 4100;4297;4458 @@ -315,47 +242,14 @@ - - - false - $(ProjectDir);$(OutputPath);Generated Files;..\Composable\Generated Files - MultiThreaded - NOMINMAX;_WINDLL;%(PreprocessorDefinitions) - 4100;4297;4458 - - - Console - false - module.def - true - - - - - - - - - ..\Composable - - - - - - - - - - - - - false $(ProjectDir);$(OutputPath);Generated Files;..\Composable\Generated Files MultiThreaded NOMINMAX;_WINDLL;%(PreprocessorDefinitions) + Level4 + true 4100;4297;4458 @@ -392,6 +286,8 @@ false MultiThreadedDebug NOMINMAX;_WINDLL;%(PreprocessorDefinitions) + Level4 + true 4100;4297;4458 @@ -425,6 +321,8 @@ $(ProjectDir);$(OutputPath);Generated Files;..\Composable\Generated Files MultiThreaded NOMINMAX;_WINDLL;%(PreprocessorDefinitions) + Level4 + true 4100;4297;4458 @@ -478,50 +376,38 @@ $(SystemRoot)\System32\WinMetadata - $(SystemRoot)\System32\WinMetadata $(SystemRoot)\System32\WinMetadata $(SystemRoot)\System32\WinMetadata - $(SystemRoot)\System32\WinMetadata $(SystemRoot)\System32\WinMetadata $(SystemRoot)\System32\WinMetadata $(SystemRoot)\System32\WinMetadata $(OutputPath)$(ProjectName).winmd - $(OutputPath)$(ProjectName).winmd $(OutputPath)$(ProjectName).winmd $(OutputPath)$(ProjectName).winmd - $(OutputPath)$(ProjectName).winmd $(OutputPath)$(ProjectName).winmd $(OutputPath)$(ProjectName).winmd $(OutputPath)$(ProjectName).winmd true - true true true - true true true true $(OutputPath)$(ProjectName)_h.h - $(OutputPath)$(ProjectName)_h.h $(OutputPath)$(ProjectName)_h.h $(OutputPath)$(ProjectName)_h.h - $(OutputPath)$(ProjectName)_h.h $(OutputPath)$(ProjectName)_h.h $(OutputPath)$(ProjectName)_h.h $(OutputPath)$(ProjectName)_h.h ..\Composable - ..\Composable ..\Composable ..\Composable - ..\Composable ..\Composable ..\Composable ..\Composable true - true true true - true true true true diff --git a/test/old_tests/Component/pch.h b/test/old_tests/Component/pch.h index 5d84eecb6..b73230946 100644 --- a/test/old_tests/Component/pch.h +++ b/test/old_tests/Component/pch.h @@ -8,4 +8,7 @@ #include "winrt/Composable.h" // This is used to validate WRL interop support. +#pragma warning(push) +#pragma warning(disable: 4324) // structure was padded due to alignment specifier #include +#pragma warning(pop) \ No newline at end of file diff --git a/test/old_tests/Composable/Base.cpp b/test/old_tests/Composable/Base.cpp index a1a1678ff..af2423569 100644 --- a/test/old_tests/Composable/Base.cpp +++ b/test/old_tests/Composable/Base.cpp @@ -43,7 +43,7 @@ namespace winrt::Composable::implementation int32_t Base::ProtectedMethod() { - return 0xDEADBEEF; + return static_cast(0xDEADBEEF); } hstring Base::Name() const diff --git a/test/old_tests/Composable/Composable.vcxproj b/test/old_tests/Composable/Composable.vcxproj index d13d779b9..fcfd095fc 100644 --- a/test/old_tests/Composable/Composable.vcxproj +++ b/test/old_tests/Composable/Composable.vcxproj @@ -1,10 +1,6 @@ - - Debug - ARM - Debug ARM64 @@ -17,10 +13,6 @@ Debug x64 - - Release - ARM - Release ARM64 @@ -46,11 +38,6 @@ true x64 - - DynamicLibrary - true - x64 - DynamicLibrary true @@ -67,12 +54,6 @@ true x64 - - DynamicLibrary - false - true - x64 - DynamicLibrary false @@ -93,18 +74,12 @@ - - - - - - @@ -119,49 +94,31 @@ false false - ..\..;$(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - Midl - - - false - false - ..\..;$(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl false false - ..\..;$(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl false false - ..\..;$(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - Midl - - - false - false - ..\..;$(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl false false - ..\..;$(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl false false - ..\..;$(VC_ExecutablePath_x64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(FxCopDir);$(PATH); Midl false false - ..\..;$(VC_ExecutablePath_x64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(FxCopDir);$(PATH); Midl @@ -183,6 +140,8 @@ false MultiThreadedDebug NOMINMAX;_WINDLL;%(PreprocessorDefinitions) + Level4 + true 4100;4297;4458 precomp.hpp @@ -210,42 +169,6 @@ - - - false - $(ProjectDir);$(OutDir);Generated Files - false - MultiThreadedDebug - NOMINMAX;_WINDLL;%(PreprocessorDefinitions) - 4100;4297;4458 - precomp.hpp - - - Console - false - module.def - true - - - - - - - - - - - - - - - - - - - - - false @@ -253,6 +176,8 @@ false MultiThreadedDebug NOMINMAX;_WINDLL;%(PreprocessorDefinitions) + Level4 + true 4100;4297;4458 precomp.hpp @@ -288,6 +213,8 @@ $(ProjectDir);$(OutDir);Generated Files MultiThreaded NOMINMAX;_WINDLL;%(PreprocessorDefinitions) + Level4 + true 4100;4297;4458 precomp.hpp @@ -315,47 +242,14 @@ - - - false - $(ProjectDir);$(OutDir);Generated Files - MultiThreaded - NOMINMAX;_WINDLL;%(PreprocessorDefinitions) - 4100;4297;4458 - precomp.hpp - - - Console - false - module.def - true - - - - - - - - - - - - - - - - - - - - - false $(ProjectDir);$(OutDir);Generated Files MultiThreaded NOMINMAX;_WINDLL;%(PreprocessorDefinitions) + Level4 + true 4100;4297;4458 precomp.hpp @@ -392,6 +286,8 @@ false MultiThreadedDebug NOMINMAX;_WINDLL;%(PreprocessorDefinitions) + Level4 + true 4100;4297;4458 precomp.hpp @@ -425,6 +321,8 @@ $(ProjectDir);$(OutDir);Generated Files MultiThreaded NOMINMAX;_WINDLL;%(PreprocessorDefinitions) + Level4 + true 4100;4297;4458 precomp.hpp @@ -470,42 +368,32 @@ $(SystemRoot)\System32\WinMetadata - $(SystemRoot)\System32\WinMetadata $(SystemRoot)\System32\WinMetadata $(SystemRoot)\System32\WinMetadata - $(SystemRoot)\System32\WinMetadata $(SystemRoot)\System32\WinMetadata $(SystemRoot)\System32\WinMetadata $(SystemRoot)\System32\WinMetadata $(OutputPath)$(ProjectName).winmd - $(OutputPath)$(ProjectName).winmd $(OutputPath)$(ProjectName).winmd $(OutputPath)$(ProjectName).winmd - $(OutputPath)$(ProjectName).winmd $(OutputPath)$(ProjectName).winmd $(OutputPath)$(ProjectName).winmd $(OutputPath)$(ProjectName).winmd true - true true true - true true true true $(OutputPath)$(ProjectName)_h.h - $(OutputPath)$(ProjectName)_h.h $(OutputPath)$(ProjectName)_h.h $(OutputPath)$(ProjectName)_h.h - $(OutputPath)$(ProjectName)_h.h $(OutputPath)$(ProjectName)_h.h $(OutputPath)$(ProjectName)_h.h $(OutputPath)$(ProjectName)_h.h true - true true true - true true true true diff --git a/test/old_tests/UnitTests/Boxing2.cpp b/test/old_tests/UnitTests/Boxing2.cpp index cd912ce58..43ca7efd9 100644 --- a/test/old_tests/UnitTests/Boxing2.cpp +++ b/test/old_tests/UnitTests/Boxing2.cpp @@ -41,19 +41,19 @@ namespace REQUIRE(unbox_value_or(wrong_type, v2) == v2); } - REQUIRE(object.as() == v1); - REQUIRE(object.try_as() == v1); - REQUIRE(nothing.try_as() == std::nullopt); + REQUIRE(object.template as() == v1); + REQUIRE(object.template try_as() == v1); + REQUIRE(nothing.template try_as() == std::nullopt); REQUIRE(wrong_type.try_as() == std::nullopt); T result{ v2 }; - object.as(result); + object.template as(result); REQUIRE(result == v1); result = v1; REQUIRE(v1 != empty()); // Test must pass a v1 that is not equal to the empty value. - REQUIRE(!nothing.try_as(result)); + REQUIRE(!nothing.template try_as(result)); REQUIRE(result == empty()); // try_as explicitly empties the result on failure result = v1; diff --git a/test/old_tests/UnitTests/Composable.cpp b/test/old_tests/UnitTests/Composable.cpp index 3cbc283d6..a9d354c08 100644 --- a/test/old_tests/UnitTests/Composable.cpp +++ b/test/old_tests/UnitTests/Composable.cpp @@ -14,7 +14,7 @@ namespace constexpr auto Base_OverridableMethod{ L"Base::OverridableMethod"sv }; constexpr auto Base_OverridableVirtualMethod{ L"Base::OverridableVirtualMethod"sv }; constexpr auto Base_OverridableNoexceptMethod{ 42 }; - constexpr auto Base_ProtectedMethod{ 0xDEADBEEF }; + constexpr auto Base_ProtectedMethod{ static_cast(0xDEADBEEF) }; constexpr auto Derived_VirtualMethod{ L"Derived::VirtualMethod"sv }; constexpr auto Derived_OverridableVirtualMethod{ L"Derived::OverridableVirtualMethod"sv }; @@ -167,4 +167,20 @@ TEST_CASE("Composable conversions") { TestCalls(*make_self()); TestCalls(*make_self()); -} \ No newline at end of file +} + +TEST_CASE("Composable get_interfaces") +{ + struct Foo : Composable::BaseT { + hstring ToString() const { return L"Foo"; } + }; + + auto obj = make(); + auto iids = winrt::get_interfaces(obj); + // BaseOverrides IID gets repeated twice. There are only 4 unique interfaces. + REQUIRE(iids.size() == 5); + REQUIRE(std::find(iids.begin(), iids.end(), guid_of()) != iids.end()); + REQUIRE(std::find(iids.begin(), iids.end(), guid_of()) != iids.end()); + REQUIRE(std::find(iids.begin(), iids.end(), guid_of()) != iids.end()); + REQUIRE(std::find(iids.begin(), iids.end(), guid_of()) != iids.end()); +} diff --git a/test/old_tests/UnitTests/Errors.cpp b/test/old_tests/UnitTests/Errors.cpp index 472d633f1..f8656a508 100644 --- a/test/old_tests/UnitTests/Errors.cpp +++ b/test/old_tests/UnitTests/Errors.cpp @@ -233,6 +233,7 @@ TEST_CASE("Errors") // Make sure trimming works. hresult_error e(E_FAIL, L":) is \u263A \n \t "); + auto x = e.message(); REQUIRE(e.message() == L":) is \u263A"); // Make sure delegates propagate correctly. diff --git a/test/old_tests/UnitTests/IInspectable_GetRuntimeClassName.cpp b/test/old_tests/UnitTests/IInspectable_GetRuntimeClassName.cpp index 7db7ed869..53b5260fb 100644 --- a/test/old_tests/UnitTests/IInspectable_GetRuntimeClassName.cpp +++ b/test/old_tests/UnitTests/IInspectable_GetRuntimeClassName.cpp @@ -18,10 +18,17 @@ struct Test_GetRuntimeClassName_NoOverride : implements { +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Woverloaded-virtual" +#endif hstring GetRuntimeClassName() { return L"GetRuntimeClassName"; } +#ifdef __clang__ +#pragma clang diagnostic pop +#endif }; TEST_CASE("Test_GetRuntimeClassName_NoOverride") diff --git a/test/old_tests/UnitTests/Tests.vcxproj b/test/old_tests/UnitTests/Tests.vcxproj index c0c178442..c5169ad4d 100644 --- a/test/old_tests/UnitTests/Tests.vcxproj +++ b/test/old_tests/UnitTests/Tests.vcxproj @@ -1,10 +1,6 @@  - - Debug - ARM - Debug ARM64 @@ -13,10 +9,6 @@ Debug Win32 - - Release - ARM - Release ARM64 @@ -146,11 +138,6 @@ true x64 - - Application - true - x64 - Application true @@ -162,12 +149,6 @@ x64 true - - Application - false - x64 - true - Application false @@ -193,18 +174,12 @@ - - - - - - @@ -231,25 +206,8 @@ false false MultiThreadedDebug - 4100;4297;4458 - - - Console - true - false - $(OutDir)test_old.exe - - - - - Disabled - _HAS_AUTO_PTR_ETC;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(OutputPath);..\Composable\Generated Files;..\Component\Generated Files;..\Composable;..\Reflection\Generated Files;..\..\; - ProgramDatabase - Default - false - false - MultiThreadedDebug + Level4 + true 4100;4297;4458 @@ -269,6 +227,8 @@ false false MultiThreadedDebug + Level4 + true 4100;4297;4458 @@ -288,6 +248,8 @@ false false MultiThreadedDebug + Level4 + true 4100;4297;4458 @@ -305,25 +267,8 @@ _HAS_AUTO_PTR_ETC;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) $(OutputPath);..\Composable\Generated Files;..\Component\Generated Files;..\Composable;..\Reflection\Generated Files;..\..\; MultiThreaded - 4100;4297;4458 - - - Console - true - true - true - false - $(OutDir)test_old.exe - - - - - MaxSpeed - true - true - _HAS_AUTO_PTR_ETC;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(OutputPath);..\Composable\Generated Files;..\Component\Generated Files;..\Composable;..\Reflection\Generated Files;..\..\; - MultiThreaded + Level4 + true 4100;4297;4458 @@ -343,6 +288,8 @@ _HAS_AUTO_PTR_ETC;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) $(OutputPath);..\Composable\Generated Files;..\Component\Generated Files;..\Composable;..\Reflection\Generated Files;..\..\; MultiThreaded + Level4 + true 4100;4297;4458 @@ -362,6 +309,8 @@ _HAS_AUTO_PTR_ETC;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) $(OutputPath);..\Composable\Generated Files;..\Component\Generated Files;..\Composable;..\Reflection\Generated Files;..\..\; MultiThreaded + Level4 + true 4100;4297;4458 diff --git a/test/old_tests/UnitTests/TryLookup.cpp b/test/old_tests/UnitTests/TryLookup.cpp index 3c6c54580..350fa9006 100644 --- a/test/old_tests/UnitTests/TryLookup.cpp +++ b/test/old_tests/UnitTests/TryLookup.cpp @@ -143,4 +143,129 @@ TEST_CASE("TryLookup TryRemove error") REQUIRE(!map.TryLookup(123)); REQUIRE(!map.TryRemove(123)); -} \ No newline at end of file +} + +TEST_CASE("trylookup_from_abi specialization") +{ + // A map that throws a specific error, used to verify various edge cases. + // and implements tryLookup, to take advantage of an optimization to avoid a throw. + struct map_with_try_lookup : implements> + { + hresult codeToThrow{ S_OK }; + bool shouldThrowOnTryLookup{ false }; + std::optional TryLookup(int, trylookup_from_abi_t) + { + if (shouldThrowOnTryLookup) + { + throw_hresult(codeToThrow); + } + else + { + return { std::nullopt }; + } + } + int Lookup(int) { throw_hresult(E_UNEXPECTED); } // shouldn't be called by the test + int32_t Size() { throw_hresult(E_UNEXPECTED); } // shouldn't be called by the test + bool HasKey(int) { throw_hresult(E_UNEXPECTED); } // shouldn't be called by the test + void Split(IMapView&, IMapView&) { throw_hresult(E_UNEXPECTED); } // shouldn't be called by the test + }; + + auto self = make_self(); + IMapView map = *self; + + // Make sure that we use the TryLookup specialization, and don't throw an unexpected exception. + self->shouldThrowOnTryLookup = false; + REQUIRE(!map.TryLookup(123)); + // make sure regular lookup stll throws bounds + REQUIRE_THROWS_AS(map.Lookup(123), hresult_out_of_bounds); + + // Simulate a non-agile map that is being accessed from the wrong thread. + // "Try" operations should throw rather than erroneously report "not found". + // Because they didn't even try. The operation never got off the ground. + self->shouldThrowOnTryLookup = true; + self->codeToThrow = RPC_E_WRONG_THREAD; + REQUIRE_THROWS_AS(map.TryLookup(123), hresult_wrong_thread); + // regular lookup should throw the same error + REQUIRE_THROWS_AS(map.Lookup(123), hresult_wrong_thread); +} + +TEST_CASE("trylookup_from_abi NOT opt-in, no special tag") +{ + // Makes sure that an existing TryLookup method is not called without the trylookup_from_abi_t tag. + struct map_without_try_lookup : implements> + { + hresult codeToThrow{ S_OK }; + std::optional TryLookup(int) // notice no trylookup_from_abi_t, so no opt-in + { + // throw an unexpectd hresult, this should not be called. + throw_hresult(RPC_E_WRONG_THREAD); + } + int Lookup(int) { return 42; } // Behave as if the item was found + + int32_t Size() { throw_hresult(E_UNEXPECTED); } // shouldn't be called by the test + bool HasKey(int) { throw_hresult(E_UNEXPECTED); } // shouldn't be called by the test + void Split(IMapView&, IMapView&) { throw_hresult(E_UNEXPECTED); } // shouldn't be called by the test + }; + + auto self = make_self(); + IMapView map = *self; + + // Make sure that we don't use the TryLookup specialization, we use the Successful Lookup + REQUIRE(map.TryLookup(123).value() == 42); + REQUIRE(map.Lookup(123) == 42); +} + +TEST_CASE("trylookup_from_abi specialization with IInspectable") +{ + // A map that throws a specific error, used to verify various edge cases. + // and implements tryLookup, to take advantage of an optimization to avoid a throw. + struct map_with_try_lookup : implements> + { + hresult codeToThrow{ S_OK }; + bool shouldThrowOnTryLookup{ false }; + bool returnNullptr{ false }; + std::optional TryLookup(int, trylookup_from_abi_t) + { + if (returnNullptr) + { + return { nullptr }; + } + else if (shouldThrowOnTryLookup) + { + throw_hresult(codeToThrow); + } + else + { + return { std::nullopt }; + } + } + IInspectable Lookup(int) { throw_hresult(E_UNEXPECTED); } // shouldn't be called by the test + int32_t Size() { throw_hresult(E_UNEXPECTED); } // shouldn't be called by the test + bool HasKey(int) { throw_hresult(E_UNEXPECTED); } // shouldn't be called by the test + void Split(IMapView&, IMapView&) { throw_hresult(E_UNEXPECTED); } // shouldn't be called by the test + }; + + auto self = make_self(); + IMapView map = *self; + + // Ensure that we return a value on nullptr, a nullptr is a valid IInspectable in the Map + self->returnNullptr = true; + REQUIRE(map.TryLookup(123) == IInspectable{nullptr}); + REQUIRE(map.Lookup(123) == IInspectable{nullptr}); + + // Make sure that we use the TryLookup specialization, and don't throw an unexpected exception. + self->shouldThrowOnTryLookup = false; + self->returnNullptr = false; + REQUIRE(map.TryLookup(123) == IInspectable{nullptr}); + // make sure regular lookup stll throws bounds + REQUIRE_THROWS_AS(map.Lookup(123), hresult_out_of_bounds); + + // Simulate a non-agile map that is being accessed from the wrong thread. + // "Try" operations should throw rather than erroneously report "not found". + // Because they didn't even try. The operation never got off the ground. + self->shouldThrowOnTryLookup = true; + self->codeToThrow = RPC_E_WRONG_THREAD; + REQUIRE_THROWS_AS(map.TryLookup(123), hresult_wrong_thread); + // regular lookup should throw the same error + REQUIRE_THROWS_AS(map.Lookup(123), hresult_wrong_thread); +} diff --git a/test/old_tests/UnitTests/abi_guard.cpp b/test/old_tests/UnitTests/abi_guard.cpp index 3108baf62..70800323c 100644 --- a/test/old_tests/UnitTests/abi_guard.cpp +++ b/test/old_tests/UnitTests/abi_guard.cpp @@ -12,7 +12,7 @@ using namespace Windows::Foundation; namespace { // - // This implemenetation uses the simplest abi_enter and abi_exit methods. + // This implementation uses the simplest abi_enter and abi_exit methods. // struct A : implements { @@ -60,7 +60,7 @@ namespace } // - // This implemenetation uses the abi_enter but omits the abi_exit method. + // This implementation uses the abi_enter but omits the abi_exit method. // struct B : implements { @@ -102,7 +102,7 @@ namespace } // - // This implemenetation throws from the abi_enter method. + // This implementation throws from the abi_enter method. // struct C : implements { @@ -145,7 +145,7 @@ namespace } // - // This implemenetation provides a nested abi_guard + // This implementation provides a nested abi_guard // struct D : implements { @@ -223,7 +223,7 @@ namespace }; // - // This implemenetation use an abi_guard type alias + // This implementation use an abi_guard type alias // struct E : implements { @@ -275,7 +275,7 @@ namespace }; // - // This implemenetation use an abi_guard type alias that thows + // This implementation use an abi_guard type alias that throws // struct F : implements { diff --git a/test/old_tests/UnitTests/array.cpp b/test/old_tests/UnitTests/array.cpp index f6a7654f3..2b5952004 100644 --- a/test/old_tests/UnitTests/array.cpp +++ b/test/old_tests/UnitTests/array.cpp @@ -17,7 +17,7 @@ using namespace Windows::Security::Cryptography::Certificates; // // This is a helper to create a data reader for use in testing arrays. // -static IAsyncOperation CreateDataReader(std::initializer_list values) +static IAsyncOperation CreateDataReader(std::initializer_list /*values*/) { InMemoryRandomAccessStream stream; DataWriter writer(stream); diff --git a/test/old_tests/UnitTests/async.cpp b/test/old_tests/UnitTests/async.cpp index 979c2aac7..7a7382004 100644 --- a/test/old_tests/UnitTests/async.cpp +++ b/test/old_tests/UnitTests/async.cpp @@ -14,12 +14,6 @@ using namespace std::chrono; namespace { -#ifdef __cpp_lib_coroutine - using std::suspend_never; -#else - using std::experimental::suspend_never; -#endif - IAsyncAction NoSuspend_IAsyncAction() { co_await 0s; @@ -1098,7 +1092,7 @@ TEST_CASE("async, Cancel_IAsyncOperationWithProgress, 2") } // -// These tests confirm the implicit cancelation behavior. The obeservable behavior should be the same as above +// These tests confirm the implicit cancelation behavior. The observable behavior should be the same as above // but the implementation relies on an exception so we confirm that the state changes occur as before. // @@ -1118,7 +1112,7 @@ namespace { signal_done d{ go }; co_await resume_on_signal(go); - co_await suspend_never{}; + co_await std::suspend_never{}; REQUIRE(false); } @@ -1126,7 +1120,7 @@ namespace { signal_done d{ go }; co_await resume_on_signal(go); - co_await suspend_never{}; + co_await std::suspend_never{}; REQUIRE(false); } @@ -1134,7 +1128,7 @@ namespace { signal_done d{ go }; co_await resume_on_signal(go); - co_await suspend_never{}; + co_await std::suspend_never{}; REQUIRE(false); co_return 0; } @@ -1143,7 +1137,7 @@ namespace { signal_done d{ go }; co_await resume_on_signal(go); - co_await suspend_never{}; + co_await std::suspend_never{}; REQUIRE(false); co_return 0; } diff --git a/test/old_tests/UnitTests/delegate.cpp b/test/old_tests/UnitTests/delegate.cpp index ab83a2a65..5951b7bf6 100644 --- a/test/old_tests/UnitTests/delegate.cpp +++ b/test/old_tests/UnitTests/delegate.cpp @@ -680,7 +680,7 @@ TEST_CASE("delegate,MapChangedEventHandler") TEST_CASE("delegate,collection") { // - // Mostly a compiliation test to ensure that we can create collections of delegates. This is a rare corner case that was + // Mostly a compilation test to ensure that we can create collections of delegates. This is a rare corner case that was // previously not working. // diff --git a/test/old_tests/UnitTests/make_self.cpp b/test/old_tests/UnitTests/make_self.cpp index f7c0b1e3e..6ac17a3c0 100644 --- a/test/old_tests/UnitTests/make_self.cpp +++ b/test/old_tests/UnitTests/make_self.cpp @@ -8,7 +8,7 @@ #endif // -// These tests ensure that the make_self function works as expected to provide direct acccess +// These tests ensure that the make_self function works as expected to provide direct access // to an implementation. // // The IMakeSelf IUnknown interface is also tested as this covers an edge case in the implements diff --git a/test/old_tests/UnitTests/marshal.cpp b/test/old_tests/UnitTests/marshal.cpp index e183aa674..b260e7528 100644 --- a/test/old_tests/UnitTests/marshal.cpp +++ b/test/old_tests/UnitTests/marshal.cpp @@ -2,7 +2,7 @@ #include "catch.hpp" // These tests do not attempt to test the FTM itself, but merely to confirm that the presence and -// absence of the non_agile marker does indeed produce the correct reponses from QueryInterface. +// absence of the non_agile marker does indeed produce the correct responses from QueryInterface. // CoMarshalInterfaceXxxx is also used to exercise the code paths. Also, these tests confirm that // the weak reference object inherits the same agility as the source. Although much of this is // tested elsewhere, it was helpful to have these tests as a set. diff --git a/test/old_tests/UnitTests/produce.cpp b/test/old_tests/UnitTests/produce.cpp index 403f0df2b..9ac76ad18 100644 --- a/test/old_tests/UnitTests/produce.cpp +++ b/test/old_tests/UnitTests/produce.cpp @@ -4,7 +4,7 @@ // // These tests cover the production of the three core interfaces namely IUnknown, IInspectable, and IActivationFactory. // Tests ensure that the ABI surface lines up on the consumer and producer sides and this is mainly done simply by calling -// the various inteface methods. +// the various interface methods. // using namespace winrt; @@ -124,10 +124,17 @@ struct produce_IInspectable_No_RuntimeClassName : implements { +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Woverloaded-virtual" +#endif hstring GetRuntimeClassName() { return L"produce_IInspectable_RuntimeClassName"; } +#ifdef __clang__ +#pragma clang diagnostic pop +#endif }; TEST_CASE("produce_IInspectable_RuntimeClassName") diff --git a/test/old_tests/UnitTests/produce_async.cpp b/test/old_tests/UnitTests/produce_async.cpp index e37842e12..ed8ee50db 100644 --- a/test/old_tests/UnitTests/produce_async.cpp +++ b/test/old_tests/UnitTests/produce_async.cpp @@ -4,7 +4,7 @@ // // These tests cover the production of the various async interfaces. // Tests ensure that the ABI surface lines up on the consumer and producer sides and this is mainly done simply by calling -// the various inteface methods. +// the various interface methods. // using namespace winrt; diff --git a/test/old_tests/UnitTests/produce_map.cpp b/test/old_tests/UnitTests/produce_map.cpp index b456082a4..0c66a1820 100644 --- a/test/old_tests/UnitTests/produce_map.cpp +++ b/test/old_tests/UnitTests/produce_map.cpp @@ -5,7 +5,7 @@ // // These tests cover the production of the various map-related interfaces. // Tests ensure that the ABI surface lines up on the consumer and producer sides and this is mainly done simply by calling -// the various inteface methods. +// the various interface methods. // using namespace winrt; diff --git a/test/old_tests/UnitTests/produce_vector.cpp b/test/old_tests/UnitTests/produce_vector.cpp index fbf3d3b84..16111f96d 100644 --- a/test/old_tests/UnitTests/produce_vector.cpp +++ b/test/old_tests/UnitTests/produce_vector.cpp @@ -5,7 +5,7 @@ // // These tests cover the production of the various vector-related interfaces. // Tests ensure that the ABI surface lines up on the consumer and producer sides and this is mainly done simply by calling -// the various inteface methods. +// the various interface methods. // using namespace winrt; diff --git a/test/old_tests/UnitTests/smart_pointers.cpp b/test/old_tests/UnitTests/smart_pointers.cpp index fc760fb48..92dca1396 100644 --- a/test/old_tests/UnitTests/smart_pointers.cpp +++ b/test/old_tests/UnitTests/smart_pointers.cpp @@ -7,6 +7,12 @@ using namespace Windows::Foundation; using namespace Windows::Foundation::Collections; using namespace Component; + +#ifdef __clang__ +#pragma clang diagnostic ignored "-Wself-assign-overloaded" +#pragma clang diagnostic ignored "-Wself-move" +#endif + namespace { struct Type : implements diff --git a/test/old_tests/UnitTests/struct.cpp b/test/old_tests/UnitTests/struct.cpp index bce62e25d..995f495a4 100644 --- a/test/old_tests/UnitTests/struct.cpp +++ b/test/old_tests/UnitTests/struct.cpp @@ -10,7 +10,7 @@ using namespace Windows::Web::Http; // // This first test ensures that structures with HSTRING fields are projected correctly. // In this case, a suitable interface is provided by the Windows SDK to simplify testing. -// IControlTemplate provides the necessary methods for excercising input and output +// IControlTemplate provides the necessary methods for exercising input and output // patterns for code generation. // @@ -47,7 +47,7 @@ TEST_CASE("struct, TypeName") // // This second test ensures that structures with IReference fields are projected correctly. // In this case, a suitable interface is not available in the Windows SDK so we hand-roll the -// the necessary intput and output patterms for code generation. We also rely on a custom +// the necessary input and output patterns for code generation. We also rely on a custom // implementation of IReference so that we can additionally check that the object is // destroyed correctly. // diff --git a/test/old_tests/UnitTests/weak.cpp b/test/old_tests/UnitTests/weak.cpp index 55c40dbe6..46b89bf6f 100644 --- a/test/old_tests/UnitTests/weak.cpp +++ b/test/old_tests/UnitTests/weak.cpp @@ -99,13 +99,13 @@ namespace // Returns an IAsyncAction that has not completed. // Call the resume() handle to complete it. - winrt::Windows::Foundation::IAsyncAction SuspendAction(impl::coroutine_handle<>& resume) + winrt::Windows::Foundation::IAsyncAction SuspendAction(std::coroutine_handle<>& resume) { struct awaiter { - impl::coroutine_handle<>& resume; + std::coroutine_handle<>& resume; bool await_ready() { return false; } - void await_suspend(impl::coroutine_handle<> handle) { resume = handle; } + void await_suspend(std::coroutine_handle<> handle) { resume = handle; } void await_resume() {} }; @@ -516,7 +516,7 @@ TEST_CASE("weak,coroutine") // Start a coroutine but don't complete it yet. // Confirm that weak references resolve. - impl::coroutine_handle<> resume; + std::coroutine_handle<> resume; weak = winrt::weak_ref(SuspendAction(resume)); REQUIRE(weak.get() != nullptr); // Now complete the coroutine. Confirm that weak references no longer resolve. diff --git a/test/test/abi_guard.cpp b/test/test/abi_guard.cpp index c0244a475..b2931b278 100644 --- a/test/test/abi_guard.cpp +++ b/test/test/abi_guard.cpp @@ -6,7 +6,7 @@ using namespace Windows::Foundation; namespace { // - // This implemenetation uses the simplest abi_enter and abi_exit methods + // This implementation uses the simplest abi_enter and abi_exit methods // struct Simple : implements { @@ -34,7 +34,7 @@ namespace }; // - // This implemenetation uses the abi_enter but omits the abi_exit method + // This implementation uses the abi_enter but omits the abi_exit method // struct OnlyEnter : implements { @@ -56,7 +56,7 @@ namespace }; // - // This implemenetation throws from the abi_enter method + // This implementation throws from the abi_enter method // struct Throwing : implements { @@ -83,7 +83,7 @@ namespace }; // - // This implemenetation provides a nested abi_guard + // This implementation provides a nested abi_guard // struct NestedGuard : implements { @@ -138,7 +138,7 @@ namespace }; // - // This implemenetation use an abi_guard type alias + // This implementation use an abi_guard type alias // struct GuardAlias : implements { @@ -167,7 +167,7 @@ namespace }; // - // This implemenetation use an abi_guard type alias that thows + // This implementation use an abi_guard type alias that throws // struct ThrowAlias : implements { diff --git a/test/test/async_auto_cancel.cpp b/test/test/async_auto_cancel.cpp index bffcb6e44..b0a541535 100644 --- a/test/test/async_auto_cancel.cpp +++ b/test/test/async_auto_cancel.cpp @@ -5,12 +5,6 @@ using namespace Windows::Foundation; namespace { -#ifdef __cpp_lib_coroutine - using std::suspend_never; -#else - using std::experimental::suspend_never; -#endif - // // Checks that the coroutine is automatically canceled when reaching a suspension point. // @@ -18,21 +12,21 @@ namespace IAsyncAction Action(HANDLE event) { co_await resume_on_signal(event); - co_await suspend_never(); + co_await std::suspend_never(); REQUIRE(false); } IAsyncActionWithProgress ActionWithProgress(HANDLE event) { co_await resume_on_signal(event); - co_await suspend_never(); + co_await std::suspend_never(); REQUIRE(false); } IAsyncOperation Operation(HANDLE event) { co_await resume_on_signal(event); - co_await suspend_never(); + co_await std::suspend_never(); REQUIRE(false); co_return 1; } @@ -40,7 +34,7 @@ namespace IAsyncOperationWithProgress OperationWithProgress(HANDLE event) { co_await resume_on_signal(event); - co_await suspend_never(); + co_await std::suspend_never(); REQUIRE(false); co_return 1; } @@ -54,7 +48,7 @@ namespace auto cancel = co_await get_cancellation_token(); cancel.callback(nullptr); - co_await suspend_never(); + co_await std::suspend_never(); REQUIRE(false); } diff --git a/test/test/async_cancel_callback.cpp b/test/test/async_cancel_callback.cpp index c99e1dad4..75a3aac0c 100644 --- a/test/test/async_cancel_callback.cpp +++ b/test/test/async_cancel_callback.cpp @@ -5,12 +5,6 @@ using namespace Windows::Foundation; namespace { -#ifdef __cpp_lib_coroutine - using std::suspend_never; -#else - using std::experimental::suspend_never; -#endif - // // Checks that the cancellation callback is invoked. // @@ -29,7 +23,7 @@ namespace }(); co_await resume_on_signal(event); - co_await suspend_never(); + co_await std::suspend_never(); REQUIRE(false); } @@ -44,7 +38,7 @@ namespace }); co_await resume_on_signal(event); - co_await suspend_never(); + co_await std::suspend_never(); REQUIRE(false); } @@ -59,7 +53,7 @@ namespace }); co_await resume_on_signal(event); - co_await suspend_never(); + co_await std::suspend_never(); REQUIRE(false); co_return 1; } @@ -75,7 +69,7 @@ namespace }); co_await resume_on_signal(event); - co_await suspend_never(); + co_await std::suspend_never(); REQUIRE(false); co_return 1; } diff --git a/test/test/async_check_cancel.cpp b/test/test/async_check_cancel.cpp index 7547609f6..c98519f06 100644 --- a/test/test/async_check_cancel.cpp +++ b/test/test/async_check_cancel.cpp @@ -5,11 +5,27 @@ using namespace Windows::Foundation; namespace { -#ifdef __cpp_lib_coroutine - using std::suspend_never; -#else - using std::experimental::suspend_never; -#endif + static bool s_exceptionLoggerCalled = false; + + static struct { + uint32_t lineNumber; + char const* fileName; + char const* functionName; + void* returnAddress; + winrt::hresult result; + } s_exceptionLoggerArgs{}; + + void __stdcall exceptionLogger(uint32_t lineNumber, char const* fileName, char const* functionName, void* returnAddress, winrt::hresult const result) noexcept + { + s_exceptionLoggerArgs = { + /*.lineNumber =*/ lineNumber, + /*.fileName =*/ fileName, + /*.functionName =*/ functionName, + /*.returnAddress =*/ returnAddress, + /*.result =*/ result, + }; + s_exceptionLoggerCalled = true; + } // // Checks that manual cancellation checks work. @@ -26,7 +42,7 @@ namespace canceled = true; } - co_await suspend_never(); + co_await std::suspend_never(); REQUIRE(false); } @@ -41,7 +57,7 @@ namespace canceled = true; } - co_await suspend_never(); + co_await std::suspend_never(); REQUIRE(false); } @@ -56,11 +72,12 @@ namespace canceled = true; } - co_await suspend_never(); + co_await std::suspend_never(); REQUIRE(false); co_return 1; } + IAsyncOperationWithProgress OperationWithProgress(HANDLE event, bool& canceled) { co_await resume_on_signal(event); @@ -72,11 +89,64 @@ namespace canceled = true; } - co_await suspend_never(); + co_await std::suspend_never(); REQUIRE(false); co_return 1; } + IAsyncAction OperationCancelLogged(HANDLE event, bool& canceled) + { + REQUIRE(!s_exceptionLoggerCalled); + REQUIRE(!winrt_throw_hresult_handler); + winrt_throw_hresult_handler = exceptionLogger; + + co_await resume_on_signal(event); + auto cancel = co_await get_cancellation_token(); + + if (cancel()) + { + REQUIRE(!canceled); + canceled = true; + REQUIRE(s_exceptionLoggerCalled); + REQUIRE(s_exceptionLoggerArgs.result == HRESULT_FROM_WIN32(ERROR_CANCELLED)); + } + + winrt_throw_hresult_handler = nullptr; + s_exceptionLoggerCalled = false; + + co_await std::suspend_never(); + + REQUIRE(false); + co_return; + } + + IAsyncAction OperationAvoidLoggingCancel(HANDLE event, bool& canceled) + { + REQUIRE(!s_exceptionLoggerCalled); + REQUIRE(!winrt_throw_hresult_handler); + winrt_throw_hresult_handler = exceptionLogger; + + auto cancel = co_await get_cancellation_token(); + cancel.originate_on_cancel(false); + + co_await resume_on_signal(event); + + if (cancel()) + { + REQUIRE(!canceled); + canceled = true; + REQUIRE(!s_exceptionLoggerCalled); + } + + winrt_throw_hresult_handler = nullptr; + s_exceptionLoggerCalled = false; + + co_await std::suspend_never(); + + REQUIRE(false); + co_return; + } + template void Check(F make) { @@ -96,7 +166,7 @@ namespace async.Cancel(); SetEvent(start.get()); - REQUIRE(WaitForSingleObject(completed.get(), 1000) == WAIT_OBJECT_0); + REQUIRE(WaitForSingleObject(completed.get(), IsDebuggerPresent() ? INFINITE : 1000) == WAIT_OBJECT_0); REQUIRE(async.Status() == AsyncStatus::Canceled); REQUIRE(async.ErrorCode() == HRESULT_FROM_WIN32(ERROR_CANCELLED)); @@ -115,4 +185,6 @@ TEST_CASE("async_check_cancel") Check(ActionWithProgress); Check(Operation); Check(OperationWithProgress); + Check(OperationCancelLogged); + Check(OperationAvoidLoggingCancel); } diff --git a/test/test/box_string.cpp b/test/test/box_string.cpp new file mode 100644 index 000000000..7294eeb79 --- /dev/null +++ b/test/test/box_string.cpp @@ -0,0 +1,53 @@ +#include "pch.h" + +TEST_CASE("box_string") +{ + // hstring + { + winrt::hstring value = L"hstring"; + auto boxed = winrt::box_value(value); + REQUIRE(winrt::unbox_value(boxed) == L"hstring"); + } + + // wchar_t const* (string literal) + { + auto boxed = winrt::box_value(L"literal"); + REQUIRE(winrt::unbox_value(boxed) == L"literal"); + } + + // std::wstring + { + std::wstring value = L"wstring"; + auto boxed = winrt::box_value(value); + REQUIRE(winrt::unbox_value(boxed) == L"wstring"); + } + + // std::wstring_view (null-terminated) + { + std::wstring_view value = L"view"; + auto boxed = winrt::box_value(value); + REQUIRE(winrt::unbox_value(boxed) == L"view"); + } + + // std::wstring_view (not null-terminated) + // Regression test for https://github.com/microsoft/cppwinrt/issues/1527 + { + std::wstring source = L"ABCDE"; + std::wstring_view value(source.data(), 3); // "ABC" + auto boxed = winrt::box_value(value); + REQUIRE(winrt::unbox_value(boxed) == L"ABC"); + } + + // Empty string + { + auto boxed = winrt::box_value(winrt::hstring{}); + REQUIRE(winrt::unbox_value(boxed) == L""); + } + + // Empty wstring_view + { + std::wstring_view value; + auto boxed = winrt::box_value(value); + REQUIRE(winrt::unbox_value(boxed) == L""); + } +} diff --git a/test/test/cmd_reader.cpp b/test/test/cmd_reader.cpp index 731922fd8..a7b9a7ad1 100644 --- a/test/test/cmd_reader.cpp +++ b/test/test/cmd_reader.cpp @@ -122,7 +122,7 @@ TEST_CASE("cmd_reader") REQUIRE_FALSE(args.exists("verbose")); } - // response file #4: really really long path + // response file #4: really, really, long path { const char* argv[] = { "progname", "@respfile.txt" }; const size_t argc = _countof(argv); diff --git a/test/test/disconnected.cpp b/test/test/disconnected.cpp index 53dfbd142..be356fcb3 100644 --- a/test/test/disconnected.cpp +++ b/test/test/disconnected.cpp @@ -148,7 +148,7 @@ struct non_agile_abandoned_action : implements disconnect) : m_disconnect(disconnect) {} - static fire_and_forget final_release(std::unique_ptr self) + static fire_and_forget final_release(std::unique_ptr /*self*/) { // The C++/WinRT m_handler is agile but not context-aware, // so we need to make sure to release it from the context it diff --git a/test/test/event_deferral.cpp b/test/test/event_deferral.cpp index 9b83a2602..e5b538ca2 100644 --- a/test/test/event_deferral.cpp +++ b/test/test/event_deferral.cpp @@ -38,7 +38,7 @@ namespace // This exercises the short-circuit logic in deferrable_event_args. auto NoDeferralHandler() { - return [=](Class const& sender, DeferrableEventArgs const& args) + return [this](Class const& sender, DeferrableEventArgs const& args) { REQUIRE(sender == c); args.IncrementCounter(); @@ -50,7 +50,7 @@ namespace // deferrable_event_args. auto PointlessDeferralHandler() { - return [=](Class const& sender, DeferrableEventArgs const& args) + return [this](Class const& sender, DeferrableEventArgs const& args) { REQUIRE(sender == c); auto deferral = args.GetDeferral(); @@ -61,15 +61,19 @@ namespace auto TakeDeferralHandler(int startState, int finishState) { - return [=](Class sender, DeferrableEventArgs args) -> fire_and_forget + return [this, startState, finishState](Class sender, DeferrableEventArgs args) -> fire_and_forget { + // Captures will go out of scope after the first co_await call. Copy anything needed after that point. + const auto startStateCopy = startState; + const auto finishStateCopy = finishState; + REQUIRE(sender == c); auto deferral = args.GetDeferral(); co_await resume_background(); - wait_for_state(startState); + wait_for_state(startStateCopy); args.IncrementCounter(); deferral.Complete(); - go_to_state(finishState); + go_to_state(finishStateCopy); }; } }; diff --git a/test/test/fast_iterator.cpp b/test/test/fast_iterator.cpp index 71ed6a918..f9e02dcec 100644 --- a/test/test/fast_iterator.cpp +++ b/test/test/fast_iterator.cpp @@ -48,7 +48,7 @@ TEST_CASE("fast_iterator") REQUIRE(2 - (vbegin + 4) > vbegin); REQUIRE(vbegin < vbegin + 2); REQUIRE(vbegin + 2 - 2 == vbegin); - REQUIRE(end(v) - begin(v) == v.Size()); + REQUIRE(static_cast(end(v) - begin(v)) == v.Size()); REQUIRE((begin(v) + 3)[-1] == 4); } { diff --git a/test/test/inspectable_interop.cpp b/test/test/inspectable_interop.cpp index e9094ca77..6a8db907a 100644 --- a/test/test/inspectable_interop.cpp +++ b/test/test/inspectable_interop.cpp @@ -41,11 +41,18 @@ namespace #ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Woverloaded-virtual" +#endif +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Woverloaded-virtual" #endif Windows::Foundation::TrustLevel GetTrustLevel() const noexcept { return Windows::Foundation::TrustLevel::PartialTrust; } +#ifdef __clang__ +#pragma clang diagnostic pop +#endif #ifdef __GNUC__ #pragma GCC diagnostic pop #endif diff --git a/test/test/missing_required_interfaces.cpp b/test/test/missing_required_interfaces.cpp new file mode 100644 index 000000000..237e4ff41 --- /dev/null +++ b/test/test/missing_required_interfaces.cpp @@ -0,0 +1,25 @@ +#include "pch.h" + +// Unset lean and mean so we can implement a type from the test_component namespace +#undef WINRT_LEAN_AND_MEAN +#include + +namespace +{ + struct LiesAboutInheritance : public winrt::implements + { + LiesAboutInheritance() = default; + void StubMethod() {} + }; +} + +TEST_CASE("missing_required_interfaces") +{ + auto lies = winrt::make_self().as(); + REQUIRE(lies); + REQUIRE_NOTHROW(lies.StubMethod()); + + // The IStringable::ToString method does not exist on this type. In previous versions of cppwinrt + // this line would crash with a nullptr deference. It now throws an exception. + REQUIRE_THROWS_AS(lies.ToString(), winrt::hresult_error); +} diff --git a/test/test/multi_threaded_common.h b/test/test/multi_threaded_common.h index 026cb3264..3ed687743 100644 --- a/test/test/multi_threaded_common.h +++ b/test/test/multi_threaded_common.h @@ -45,7 +45,7 @@ namespace concurrent_collections // for the first time on the background thread. enum class collection_action { - none, push_back, insert, erase, at, lookup + none, push_back, insert, erase, at, lookup, advance }; // All of our concurrency tests consists of starting an @@ -165,16 +165,23 @@ namespace concurrent_collections return owner->dereference_iterator(inner()); } - // inherited: pointer operator->() const; + pointer operator->() const + { + auto guard = owner->lock_const(); + owner->call_hook(collection_action::at); + return iterator::operator->(); + } concurrency_checked_random_access_iterator& operator++() { + owner->call_hook(collection_action::advance); ++inner(); return *this; } concurrency_checked_random_access_iterator& operator++(int) { + owner->call_hook(collection_action::advance); auto prev = *this; ++inner(); return prev; @@ -182,12 +189,14 @@ namespace concurrent_collections concurrency_checked_random_access_iterator& operator--() { + owner->call_hook(collection_action::advance); --inner(); return *this; } concurrency_checked_random_access_iterator& operator--(int) { + owner->call_hook(collection_action::advance); auto prev = *this; --inner(); return prev; @@ -195,6 +204,7 @@ namespace concurrent_collections concurrency_checked_random_access_iterator& operator+=(difference_type offset) { + owner->call_hook(collection_action::advance); inner() += offset; return *this; } @@ -206,6 +216,7 @@ namespace concurrent_collections concurrency_checked_random_access_iterator& operator-=(difference_type offset) { + owner->call_hook(collection_action::advance); inner() -= offset; return *this; } diff --git a/test/test/multi_threaded_map.cpp b/test/test/multi_threaded_map.cpp index b2b143f11..ffa9988ba 100644 --- a/test/test/multi_threaded_map.cpp +++ b/test/test/multi_threaded_map.cpp @@ -90,7 +90,7 @@ namespace using const_reverse_iterator = std::reverse_iterator; using node_type = typename inner::node_type; - mapped_type& operator[](const key_type& key) + mapped_type& operator[](const key_type& /*key*/) { auto guard = concurrency_guard::lock_nonconst(); concurrency_guard::call_hook(collection_action::at); @@ -237,7 +237,7 @@ namespace { // MoveNext vs Remove bool moved = false; - race(collection_action::at, [&] + race(collection_action::advance, [&] { try { @@ -273,7 +273,7 @@ namespace { // MoveNext vs Insert bool moved = false; - race(collection_action::at, [&] + race(collection_action::advance, [&] { try { diff --git a/test/test/out_params.cpp b/test/test/out_params.cpp index 7aafb63ae..7fd2f536e 100644 --- a/test/test/out_params.cpp +++ b/test/test/out_params.cpp @@ -134,7 +134,7 @@ TEST_CASE("out_params") REQUIRE(value[3] == nullptr); } { - std::array value{ {L"First", L"Second"} }; + std::array value{ { { L"First" }, { L"Second"} } }; object.RefStructArray(value); REQUIRE(value[0].First == L"1"); REQUIRE(value[0].Second == L"2"); @@ -260,7 +260,7 @@ TEST_CASE("out_params") REQUIRE(value[3] == nullptr); } { - std::array value{ {L"First", L"Second"} }; + std::array value{ { { L"First" }, { L"Second"} } }; REQUIRE_THROWS_AS(object.RefStructArray(value), hresult_invalid_argument); REQUIRE(value[0].First == L""); REQUIRE(value[0].Second == L""); diff --git a/test/test/reference_boxing.cpp b/test/test/reference_boxing.cpp new file mode 100644 index 000000000..c6e300886 --- /dev/null +++ b/test/test/reference_boxing.cpp @@ -0,0 +1,268 @@ +#include "pch.h" +#include +#include +#include + +using namespace winrt; +using namespace Windows::Foundation; + +// Scalar box_value now produces a local IReference/IPropertyValue instead of hopping to +// combase PropertyValue. These confirm it reports the correct PropertyType, keeps combase-style +// numeric conversion on mismatched getters, and round-trips through unbox_value. +TEST_CASE("reference_boxing") +{ + { + auto boxed = box_value(42); + auto pv = boxed.as(); + REQUIRE(pv.Type() == PropertyType::Int32); + REQUIRE(pv.IsNumericScalar()); + REQUIRE(pv.GetInt32() == 42); + REQUIRE(pv.GetInt16() == 42); + REQUIRE(pv.GetDouble() == 42.0); + // A scalar reference holds no array, so every array getter routes through get_as and throws. + { + com_array ints; + REQUIRE_THROWS_AS(pv.GetInt32Array(ints), hresult_not_implemented); + com_array strings; + REQUIRE_THROWS_AS(pv.GetStringArray(strings), hresult_not_implemented); + } + REQUIRE(unbox_value(boxed) == 42); + } + + { + auto pv = box_value(3.5).as(); + REQUIRE(pv.Type() == PropertyType::Double); + REQUIRE(pv.IsNumericScalar()); + REQUIRE(pv.GetDouble() == 3.5); + REQUIRE(pv.GetSingle() == 3.5f); + } + + { + auto pv = box_value(hstring{ L"hello" }).as(); + REQUIRE(pv.Type() == PropertyType::String); + REQUIRE(!pv.IsNumericScalar()); + REQUIRE(pv.GetString() == L"hello"); + REQUIRE_THROWS_AS(pv.GetInt32(), hresult_not_implemented); + } + + { + auto pv = box_value(true).as(); + REQUIRE(pv.Type() == PropertyType::Boolean); + REQUIRE(!pv.IsNumericScalar()); + REQUIRE(pv.GetBoolean()); + REQUIRE_THROWS_AS(pv.GetInt32(), hresult_not_implemented); + } + + { + guid const g{ 0x11223344, 0x5566, 0x7788, { 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x00 } }; + auto pv = box_value(g).as(); + REQUIRE(pv.Type() == PropertyType::Guid); + REQUIRE(!pv.IsNumericScalar()); + REQUIRE(pv.GetGuid() == g); + } + + { + auto pv = box_value(static_cast(7)).as(); + REQUIRE(pv.Type() == PropertyType::UInt8); + REQUIRE(pv.IsNumericScalar()); + REQUIRE(pv.GetUInt8() == 7); + REQUIRE(unbox_value(box_value(static_cast(7))) == 7); + } + + // DateTime, TimeSpan, and Point are also boxed in-process now (they still marshal by value). + { + Point const point{ 3.0f, 4.0f }; + auto pv = box_value(point).as(); + REQUIRE(pv.Type() == PropertyType::Point); + REQUIRE(!pv.IsNumericScalar()); + REQUIRE(pv.GetPoint().X == point.X); + REQUIRE(pv.GetPoint().Y == point.Y); + auto const round_tripped = unbox_value(box_value(point)); + REQUIRE(round_tripped.X == point.X); + REQUIRE(round_tripped.Y == point.Y); + REQUIRE_THROWS_AS(pv.GetInt32(), hresult_not_implemented); + } + + { + TimeSpan const span{ std::chrono::seconds{ 90 } }; + auto pv = box_value(span).as(); + REQUIRE(pv.Type() == PropertyType::TimeSpan); + REQUIRE(!pv.IsNumericScalar()); + REQUIRE(pv.GetTimeSpan() == span); + REQUIRE(unbox_value(box_value(span)) == span); + } + + { + DateTime const when{ TimeSpan{ std::chrono::seconds{ 1000 } } }; + auto pv = box_value(when).as(); + REQUIRE(pv.Type() == PropertyType::DateTime); + REQUIRE(!pv.IsNumericScalar()); + REQUIRE(pv.GetDateTime() == when); + REQUIRE(unbox_value(box_value(when)) == when); + } +} + +// Array boxing produces a local IReferenceArray / IPropertyValue (no combase PropertyValue) for the +// stock element types. Confirm the array PropertyType, round-trips, and the get_as throw behavior. +TEST_CASE("reference_boxing arrays") +{ + { + int32_t values[]{ 0, 42, 1729, -1 }; + auto boxed = box_value(com_array{ std::begin(values), std::end(values) }); + auto pv = boxed.as(); + REQUIRE(pv.Type() == PropertyType::Int32Array); + REQUIRE(!pv.IsNumericScalar()); + + com_array out; + pv.GetInt32Array(out); + REQUIRE(out == array_view{ values }); + + // A scalar getter on an array PV throws, and so does a mismatched-element array getter. + REQUIRE_THROWS_AS(pv.GetInt32(), hresult_not_implemented); + com_array wrong; + REQUIRE_THROWS_AS(pv.GetDoubleArray(wrong), hresult_not_implemented); + + REQUIRE(unbox_value>(boxed) == array_view{ values }); + REQUIRE(boxed.as>().Value() == array_view{ values }); + } + + // guid arrays are local too. + { + guid values[]{ + { 0x11223344, 0x5566, 0x7788, { 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x00 } }, + { 0x00112233, 0x4455, 0x6677, { 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF } } }; + auto boxed = box_value(com_array{ std::begin(values), std::end(values) }); + REQUIRE(boxed.as().Type() == PropertyType::GuidArray); + REQUIRE(unbox_value>(boxed) == array_view{ values }); + } +} + +// The local array reference must marshal by value across processes just like the scalar one: its +// IMarshal reports the same unmarshal class as a genuine combase array PropertyValue, and not the +// free-threaded (by-reference) class. +TEST_CASE("reference_boxing array marshal by value") +{ + int32_t values[]{ 1, 2, 3 }; + auto boxed = box_value(com_array{ std::begin(values), std::end(values) }); + REQUIRE(boxed.try_as()); + auto ours = boxed.as(); + + auto genuine = PropertyValue::CreateInt32Array(values); + auto reference = genuine.as(); + + guid our_clsid{}; + guid reference_clsid{}; + check_hresult(ours->GetUnmarshalClass(guid_of(), get_unknown(boxed), + MSHCTX_DIFFERENTMACHINE, nullptr, MSHLFLAGS_NORMAL, &our_clsid)); + check_hresult(reference->GetUnmarshalClass(guid_of(), get_unknown(genuine), + MSHCTX_DIFFERENTMACHINE, nullptr, MSHLFLAGS_NORMAL, &reference_clsid)); + + REQUIRE(our_clsid == reference_clsid); + + guid const free_threaded_marshaler{ 0x0000033A, 0x0000, 0x0000, { 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 } }; + REQUIRE(our_clsid != free_threaded_marshaler); +} + +// The in-proc reference stays agile but must marshal by value across processes, exactly like a real +// combase PropertyValue. Prove it by confirming our IMarshal reports the SAME unmarshal class as a +// genuine PropertyValue - i.e. we forward marshaling to combase - and specifically NOT the +// free-threaded (marshal-by-reference) class the default agile path would have used. +TEST_CASE("reference_boxing marshal by value") +{ + auto boxed = box_value(42); + REQUIRE(boxed.try_as()); + auto ours = boxed.as(); + + auto genuine = PropertyValue::CreateInt32(42); + auto reference = genuine.as(); + + guid our_clsid{}; + guid reference_clsid{}; + check_hresult(ours->GetUnmarshalClass(guid_of(), get_unknown(boxed), + MSHCTX_DIFFERENTMACHINE, nullptr, MSHLFLAGS_NORMAL, &our_clsid)); + check_hresult(reference->GetUnmarshalClass(guid_of(), get_unknown(genuine), + MSHCTX_DIFFERENTMACHINE, nullptr, MSHLFLAGS_NORMAL, &reference_clsid)); + + REQUIRE(our_clsid == reference_clsid); + + // CLSID_InProcFreeMarshaler - the by-reference class the agile FTM would have produced. + guid const free_threaded_marshaler{ 0x0000033A, 0x0000, 0x0000, { 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 } }; + REQUIRE(our_clsid != free_threaded_marshaler); +} + +// The in-proc reference advertises IAgileObject, so handing it between two single-threaded +// apartments in the same process must resolve to the *same* object pointer - no proxy. The Global +// Interface Table returns an agile object's original pointer directly, but hands back a proxy (a +// different identity) for a non-agile object, so pointer equality here confirms the agile fast path. +TEST_CASE("reference_boxing agile in-proc identity across apartments") +{ + auto identity_of = [](::IUnknown* raw) -> void* + { + com_ptr<::IUnknown> identity; + check_hresult(raw->QueryInterface(IID_PPV_ARGS(identity.put()))); + return identity.get(); + }; + + com_ptr git; + check_hresult(CoCreateInstance(CLSID_StdGlobalInterfaceTable, nullptr, + CLSCTX_INPROC_SERVER, IID_PPV_ARGS(git.put()))); + + Windows::Foundation::IInspectable boxed{ nullptr }; + DWORD cookie{}; + void* original_identity{}; + void* marshaled_identity{}; + HRESULT sta1_hr = S_OK; + HRESULT sta2_hr = S_OK; + + handle registered{ check_pointer(CreateEventW(nullptr, true, false, nullptr)) }; + handle fetched{ check_pointer(CreateEventW(nullptr, true, false, nullptr)) }; + + std::thread sta1([&] + { + sta1_hr = CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); + if (SUCCEEDED(sta1_hr)) + { + boxed = box_value(42); + auto unknown = reinterpret_cast<::IUnknown*>(get_abi(boxed)); + original_identity = identity_of(unknown); + sta1_hr = git->RegisterInterfaceInGlobal(unknown, IID_IUnknown, &cookie); + } + SetEvent(registered.get()); + + WaitForSingleObject(fetched.get(), INFINITE); + if (SUCCEEDED(sta1_hr)) + { + CoUninitialize(); + } + }); + + std::thread sta2([&] + { + WaitForSingleObject(registered.get(), INFINITE); + if (SUCCEEDED(sta1_hr)) + { + sta2_hr = CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); + if (SUCCEEDED(sta2_hr)) + { + ::IUnknown* raw{}; + sta2_hr = git->GetInterfaceFromGlobal(cookie, IID_IUnknown, reinterpret_cast(&raw)); + if (SUCCEEDED(sta2_hr)) + { + marshaled_identity = identity_of(raw); + raw->Release(); + } + git->RevokeInterfaceFromGlobal(cookie); + CoUninitialize(); + } + } + SetEvent(fetched.get()); + }); + + sta1.join(); + sta2.join(); + + REQUIRE(SUCCEEDED(sta1_hr)); + REQUIRE(SUCCEEDED(sta2_hr)); + REQUIRE(original_identity != nullptr); + REQUIRE(original_identity == marshaled_identity); +} diff --git a/test/test/return_params_abi.cpp b/test/test/return_params_abi.cpp index 1d4af9a9f..5e7c11cd3 100644 --- a/test/test/return_params_abi.cpp +++ b/test/test/return_params_abi.cpp @@ -12,12 +12,19 @@ using namespace winrt; namespace { +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-function" +#endif hstring to_hstring(::IInspectable* raw) { winrt::IInspectable object; copy_from_abi(object, raw); return object.as().ToString(); } +#ifdef __clang__ +#pragma clang diagnostic pop +#endif } TEST_CASE("return_params_abi") diff --git a/test/test/struct_delegate.cpp b/test/test/struct_delegate.cpp index 26fcd9e64..785a0fb0a 100644 --- a/test/test/struct_delegate.cpp +++ b/test/test/struct_delegate.cpp @@ -1,5 +1,5 @@ #include "pch.h" -#include "winrt/test_component.delegates.h" +#include "winrt/test_component.Delegates.h" using namespace winrt; using namespace test_component; diff --git a/test/test/test.vcxproj b/test/test/test.vcxproj index b75f2e219..f95584d99 100644 --- a/test/test/test.vcxproj +++ b/test/test/test.vcxproj @@ -1,10 +1,6 @@ - - Debug - ARM - Debug ARM64 @@ -13,10 +9,6 @@ Debug Win32 - - Release - ARM - Release ARM64 @@ -45,10 +37,6 @@ Application true - - Application - true - Application true @@ -58,11 +46,6 @@ false true - - Application - false - true - Application false @@ -85,18 +68,12 @@ - - - - - - @@ -115,6 +92,8 @@ $(OutputPath);Generated Files;..;..\..\cppwinrt _MBCS;%(PreprocessorDefinitions) MultiThreaded + Level4 + true Console @@ -135,24 +114,8 @@ $(OutputPath);Generated Files;..;..\..\cppwinrt _MBCS;%(PreprocessorDefinitions) MultiThreadedDebug - - - Console - - - $(CppWinRTDir)cppwinrt -in $(OutputPath)test_component.winmd $(OutputPath)test_component_no_pch.winmd -out "$(ProjectDir)Generated Files" -ref sdk -verbose -fastabi - - - - - - - - - Disabled - $(OutputPath);Generated Files;..;..\..\cppwinrt - _MBCS;%(PreprocessorDefinitions) - MultiThreadedDebug + Level4 + true Console @@ -171,6 +134,8 @@ $(OutputPath);Generated Files;..;..\..\cppwinrt _MBCS;%(PreprocessorDefinitions) MultiThreadedDebug + Level4 + true Console @@ -189,6 +154,8 @@ $(OutputPath);Generated Files;..;..\..\cppwinrt _MBCS;%(PreprocessorDefinitions) MultiThreadedDebug + Level4 + true Console @@ -209,28 +176,8 @@ $(OutputPath);Generated Files;..;..\..\cppwinrt _MBCS;%(PreprocessorDefinitions) MultiThreaded - - - Console - true - true - - - $(CppWinRTDir)cppwinrt -in $(OutputPath)test_component.winmd $(OutputPath)test_component_no_pch.winmd -out "$(ProjectDir)Generated Files" -ref sdk -verbose -fastabi - - - - - - - - - MaxSpeed - true - true - $(OutputPath);Generated Files;..;..\..\cppwinrt - _MBCS;%(PreprocessorDefinitions) - MultiThreaded + Level4 + true Console @@ -253,6 +200,8 @@ $(OutputPath);Generated Files;..;..\..\cppwinrt _MBCS;%(PreprocessorDefinitions) MultiThreaded + Level4 + true Console @@ -284,14 +233,13 @@ + NotUsing NotUsing NotUsing NotUsing - NotUsing - NotUsing NotUsing NotUsing @@ -300,8 +248,6 @@ NotUsing NotUsing NotUsing - NotUsing - NotUsing NotUsing NotUsing @@ -310,8 +256,6 @@ NotUsing NotUsing NotUsing - NotUsing - NotUsing NotUsing NotUsing @@ -349,8 +293,6 @@ NotUsing NotUsing NotUsing - NotUsing - NotUsing NotUsing NotUsing @@ -361,8 +303,6 @@ NotUsing NotUsing NotUsing - NotUsing - NotUsing NotUsing NotUsing @@ -374,8 +314,6 @@ NotUsing NotUsing NotUsing - NotUsing - NotUsing NotUsing NotUsing @@ -386,14 +324,14 @@ NotUsing + + NotUsing NotUsing NotUsing NotUsing - NotUsing - NotUsing NotUsing NotUsing diff --git a/test/test/thread_pool.cpp b/test/test/thread_pool.cpp index ac75dac18..c55cffe1d 100644 --- a/test/test/thread_pool.cpp +++ b/test/test/thread_pool.cpp @@ -53,7 +53,7 @@ TEST_CASE("thread_pool") uint32_t const stable_counter = test(test_iterations, 1, 1); uint32_t const unstable_counter = test(test_iterations, 10, 10); - // This is determinstic since the queue is single-threaded. + // This is deterministic since the queue is single-threaded. REQUIRE(stable_counter == test_iterations); // This is unlikely to fail since the pool is multi-threaded. diff --git a/test/test/when.cpp b/test/test/when.cpp index 35c9287a8..0b1151abc 100644 --- a/test/test/when.cpp +++ b/test/test/when.cpp @@ -5,13 +5,7 @@ using namespace concurrency; using namespace winrt; using namespace Windows::Foundation; -#ifdef __cpp_lib_coroutine -using std::suspend_never; -#else -using std::experimental::suspend_never; -#endif - -struct CommaStruct : suspend_never +struct CommaStruct : std::suspend_never { // If the comma operator is invoked, we will get a build failure. CommaStruct operator,(CommaStruct) = delete; diff --git a/test/test_component/Class.cpp b/test/test_component/Class.cpp index 4f36df5c1..3f68d96c3 100644 --- a/test/test_component/Class.cpp +++ b/test/test_component/Class.cpp @@ -519,7 +519,14 @@ namespace winrt::test_component::implementation namespace { +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-function" +#endif void ValidateStaticEventAutoRevoke() { auto x = winrt::test_component::Simple::StaticEvent(winrt::auto_revoke, [](auto&&, auto&&) {}); } +#ifdef __clang__ +#pragma clang diagnostic pop +#endif } \ No newline at end of file diff --git a/test/test_component/OverloadClass.cpp b/test/test_component/OverloadClass.cpp new file mode 100644 index 000000000..0f78c5a1c --- /dev/null +++ b/test/test_component/OverloadClass.cpp @@ -0,0 +1,23 @@ +#include "pch.h" +#include "OverloadClass.h" +#include "OverloadClass.g.cpp" + +namespace winrt::test_component::implementation +{ + void OverloadClass::Overload() + { + throw hresult_not_implemented(); + } + void OverloadClass::Overload(int /*a*/) + { + throw hresult_not_implemented(); + } + void OverloadClass::Overload(int /*a*/, int /*b*/) + { + throw hresult_not_implemented(); + } + void OverloadClass::Overload(int /*a*/, int /*b*/, int /*c*/) + { + throw hresult_not_implemented(); + } +} diff --git a/test/test_component/OverloadClass.h b/test/test_component/OverloadClass.h new file mode 100644 index 000000000..1b155e801 --- /dev/null +++ b/test/test_component/OverloadClass.h @@ -0,0 +1,21 @@ +#pragma once +#include "OverloadClass.g.h" + +namespace winrt::test_component::implementation +{ + struct OverloadClass : OverloadClassT + { + OverloadClass() = default; + + void Overload(); + void Overload(int a); + void Overload(int a, int b); + void Overload(int a, int b, int c); + }; +} +namespace winrt::test_component::factory_implementation +{ + struct OverloadClass : OverloadClassT + { + }; +} diff --git a/test/test_component/test_component.idl b/test/test_component/test_component.idl index fb7444889..536a703f5 100644 --- a/test/test_component/test_component.idl +++ b/test/test_component/test_component.idl @@ -163,6 +163,13 @@ namespace test_component static void StaticMethodWithAsyncReturn(); } + // This class declares that it implements another interface but under the covers it actually does + // not. This allows us to test the behavior when QI's that should not fail, do fail. + runtimeclass LiesAboutInheritance : Windows.Foundation.IStringable + { + void StubMethod(); + } + namespace Structs { struct All @@ -327,4 +334,51 @@ namespace test_component delegate void Delegate(); } + + [exclusiveto(test_component.OverloadClass)] + [version(1), uuid(EF902013-00F3-4549-9032-49E86D536C07)] + interface IOverloadClass : IInspectable + { + HRESULT Overload(); + } + + [exclusiveto(test_component.OverloadClass)] + [version(1), uuid(DFDFFB61-EA72-4977-B1A7-3F0D2C32BB58)] + interface IOverloadClassFactory : IInspectable + { + HRESULT CreateInstance([in] IInspectable* baseInterface, [out] IInspectable** innerInterface, [out][retval] test_component.OverloadClass** value); + } + + [exclusiveto(test_component.OverloadClass)] + [version(1), uuid(32510F72-9229-4C69-95BD-DE7B8189C85C)] + interface IOverloadClassOverrides : IInspectable + { + [overload("Overload")] HRESULT OverloadWithOne(int a); + } + + [exclusiveto(test_component.OverloadClass)] + [version(1), uuid(50205BCE-FAD3-4C66-801F-17AAD007B26C)] + interface IOverloadClassOverrides2 : IInspectable + { + [overload("Overload")] HRESULT OverloadWithTwo(int a, int b); + } + + [exclusiveto(test_component.OverloadClass)] + [version(1), uuid(6EDD1A3F-2616-45B7-9731-F84DA9CCECA1)] + interface IOverloadClassProtected : IInspectable + { + [overload("Overload")] HRESULT OverloadWithThree(int a, int b, int c); + } + + [composable(test_component.IOverloadClassFactory, public, 1)] + [marshaling_behavior(agile)] + [threading(both)] + [version(1)] + runtimeclass OverloadClass + { + [default] interface test_component.IOverloadClass; + [protected] interface test_component.IOverloadClassProtected; + [overridable] interface test_component.IOverloadClassOverrides; + [overridable] interface test_component.IOverloadClassOverrides2; + } } diff --git a/test/test_component/test_component.vcxproj b/test/test_component/test_component.vcxproj index 15aa24447..3ffdb8f97 100644 --- a/test/test_component/test_component.vcxproj +++ b/test/test_component/test_component.vcxproj @@ -1,10 +1,6 @@ - - Debug - ARM - Debug ARM64 @@ -13,10 +9,6 @@ Debug Win32 - - Release - ARM - Release ARM64 @@ -46,11 +38,6 @@ true x64 - - DynamicLibrary - true - x64 - DynamicLibrary true @@ -62,12 +49,6 @@ true x64 - - DynamicLibrary - false - true - x64 - DynamicLibrary false @@ -93,18 +74,12 @@ - - - - - - @@ -117,35 +92,21 @@ Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - - - Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - - - Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(FxCopDir);$(PATH); @@ -153,6 +114,8 @@ .;$(OutputPath);Generated Files /Zc:threadSafeInit- /we4640 %(AdditionalOptions) MultiThreadedDebug + Level4 + true exports.def @@ -183,61 +146,14 @@ true - - - Disabled - .;$(OutputPath);Generated Files - /Zc:threadSafeInit- /we4640 %(AdditionalOptions) - MultiThreadedDebug - - - exports.def - - - true - - - $(OutputPath)test_component.winmd - - - - - - - - - - - $(OutputPath)test_component.h - - - - - - - - - - - - - - - - - - - /nomidl %(AdditionalOptions) - C:\Windows\System32\WinMetadata - true - - Disabled .;$(OutputPath);Generated Files /Zc:threadSafeInit- /we4640 %(AdditionalOptions) MultiThreadedDebug + Level4 + true exports.def @@ -287,6 +203,8 @@ .;$(OutputPath);Generated Files /Zc:threadSafeInit- /we4640 %(AdditionalOptions) MultiThreadedDebug + Level4 + true exports.def @@ -325,6 +243,8 @@ .;$(OutputPath);Generated Files /Zc:threadSafeInit- /we4640 %(AdditionalOptions) MultiThreaded + Level4 + true true @@ -357,59 +277,6 @@ true - - - MaxSpeed - true - true - .;$(OutputPath);Generated Files - /Zc:threadSafeInit- /we4640 %(AdditionalOptions) - MultiThreaded - - - true - true - exports.def - - - true - - - $(OutputPath)test_component.winmd - - - - - - - - - - - $(OutputPath)test_component.h - - - - - - - - - - - - - - - - - - - /nomidl %(AdditionalOptions) - C:\Windows\System32\WinMetadata - true - - MaxSpeed @@ -418,6 +285,8 @@ .;$(OutputPath);Generated Files /Zc:threadSafeInit- /we4640 %(AdditionalOptions) MultiThreaded + Level4 + true true @@ -471,6 +340,8 @@ .;$(OutputPath);Generated Files /Zc:threadSafeInit- /we4640 %(AdditionalOptions) MultiThreaded + Level4 + true true @@ -519,6 +390,8 @@ + + Create @@ -532,6 +405,7 @@ + diff --git a/test/test_component/test_overload.cpp b/test/test_component/test_overload.cpp new file mode 100644 index 000000000..9c21a06cf --- /dev/null +++ b/test/test_component/test_overload.cpp @@ -0,0 +1,19 @@ +#include "pch.h" +#include "winrt/test_component.h" + +// Simple compile-only test to validate overloads coming from overridable interfaces compile. + +using namespace winrt; +using namespace test_component; + +struct DerivedClass : OverloadClassT +{ + void Foo() + { + // make sure we can actually call the overloads (no ambiguous call errors) + Overload(); + Overload(1); + Overload(1, 2); + Overload(1, 2, 3); + } +}; \ No newline at end of file diff --git a/test/test_component_base/HierarchyA.cpp b/test/test_component_base/HierarchyA.cpp index 887b31bc9..45b3e6098 100644 --- a/test/test_component_base/HierarchyA.cpp +++ b/test/test_component_base/HierarchyA.cpp @@ -3,11 +3,11 @@ namespace winrt::test_component_base::implementation { - HierarchyA::HierarchyA(hstring const& name) + HierarchyA::HierarchyA(hstring const& /*name*/) { throw hresult_not_implemented(); } - HierarchyA::HierarchyA(int32_t dummy, hstring const& name) + HierarchyA::HierarchyA(int32_t /*dummy*/, hstring const& /*name*/) { throw hresult_not_implemented(); } diff --git a/test/test_component_base/HierarchyB.cpp b/test/test_component_base/HierarchyB.cpp index 34c73104f..b56988f73 100644 --- a/test/test_component_base/HierarchyB.cpp +++ b/test/test_component_base/HierarchyB.cpp @@ -1,9 +1,11 @@ #include "pch.h" #include "HierarchyB.h" +#pragma warning(disable: 4702) + namespace winrt::test_component_base::implementation { - HierarchyB::HierarchyB(hstring const& name) + HierarchyB::HierarchyB(hstring const& /*name*/) { throw hresult_not_implemented(); } diff --git a/test/test_component_base/pch.h b/test/test_component_base/pch.h index e5c39a869..a6f43eada 100644 --- a/test/test_component_base/pch.h +++ b/test/test_component_base/pch.h @@ -4,6 +4,6 @@ #include "winrt/base.h" // get_module_lock will always return true if WINRT_NO_MODULE_LOCK is defined. -// This ensures that if the DLL unecessarily exports DllCanUnloadNow that it +// This ensures that if the DLL unnecessarily exports DllCanUnloadNow that it // will in turn return S_FALSE. static_assert(winrt::get_module_lock()); diff --git a/test/test_component_base/test_component_base.vcxproj b/test/test_component_base/test_component_base.vcxproj index d8768de47..90577a2c5 100644 --- a/test/test_component_base/test_component_base.vcxproj +++ b/test/test_component_base/test_component_base.vcxproj @@ -1,10 +1,6 @@ - - Debug - ARM - Debug ARM64 @@ -13,10 +9,6 @@ Debug Win32 - - Release - ARM - Release ARM64 @@ -46,11 +38,6 @@ true x64 - - DynamicLibrary - true - x64 - DynamicLibrary true @@ -62,12 +49,6 @@ true x64 - - DynamicLibrary - false - true - x64 - DynamicLibrary false @@ -93,18 +74,12 @@ - - - - - - @@ -117,35 +92,21 @@ Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - - - Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - - - Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(FxCopDir);$(PATH); @@ -153,6 +114,8 @@ $(ProjectDir);$(OutputPath);Generated Files 4100 MultiThreadedDebug + Level4 + true exports.def @@ -195,74 +158,14 @@ $(OutputPath)test_component_base.winmd - - - Disabled - $(ProjectDir);$(OutputPath);Generated Files - 4100 - MultiThreadedDebug - - - exports.def - - - true - - - $(OutputPath)test_component_base.winmd - - - - - - - - - - - nul - - - - - - - - - - - - - - - - - - - /nomidl %(AdditionalOptions) - C:\Windows\System32\WinMetadata - true - - - $(CppWinRTDir)cppwinrt -input $(OutputPath)test_component_base.winmd -comp $(ProjectDir) -out "$(ProjectDir)Generated Files" -ref sdk -verbose -name test_component_base - - - - - - - Generated Files\module.g.cpp - - - $(OutputPath)test_component_base.winmd - - Disabled $(ProjectDir);$(OutputPath);Generated Files 4100 MultiThreadedDebug + Level4 + true exports.def @@ -325,6 +228,8 @@ $(ProjectDir);$(OutputPath);Generated Files 4100 MultiThreadedDebug + Level4 + true exports.def @@ -375,6 +280,8 @@ $(ProjectDir);$(OutputPath);Generated Files 4100 MultiThreaded + Level4 + true true @@ -419,72 +326,6 @@ $(OutputPath)test_component_base.winmd - - - MaxSpeed - true - true - $(ProjectDir);$(OutputPath);Generated Files - 4100 - MultiThreaded - - - true - true - exports.def - - - true - - - $(OutputPath)test_component_base.winmd - - - - - - - - - - - nul - - - - - - - - - - - - - - - - - - - /nomidl %(AdditionalOptions) - C:\Windows\System32\WinMetadata - true - - - $(CppWinRTDir)cppwinrt -input $(OutputPath)test_component_base.winmd -comp $(ProjectDir) -out "$(ProjectDir)Generated Files" -ref sdk -verbose -name test_component_base - - - - - - - Generated Files\module.g.cpp - - - $(OutputPath)test_component_base.winmd - - MaxSpeed @@ -493,6 +334,8 @@ $(ProjectDir);$(OutputPath);Generated Files 4100 MultiThreaded + Level4 + true true @@ -559,6 +402,8 @@ $(ProjectDir);$(OutputPath);Generated Files 4100 MultiThreaded + Level4 + true true diff --git a/test/test_component_derived/Nested.HierarchyD.cpp b/test/test_component_derived/Nested.HierarchyD.cpp index bad2cf1ce..8011e73e6 100644 --- a/test/test_component_derived/Nested.HierarchyD.cpp +++ b/test/test_component_derived/Nested.HierarchyD.cpp @@ -3,7 +3,7 @@ namespace winrt::test_component_derived::Nested::implementation { - HierarchyD::HierarchyD(hstring const& name) + HierarchyD::HierarchyD(hstring const& /*name*/) { throw hresult_not_implemented(); } diff --git a/test/test_component_derived/test_component_derived.vcxproj b/test/test_component_derived/test_component_derived.vcxproj index e80ab4af1..837d8821e 100644 --- a/test/test_component_derived/test_component_derived.vcxproj +++ b/test/test_component_derived/test_component_derived.vcxproj @@ -1,10 +1,6 @@ - - Debug - ARM - Debug ARM64 @@ -13,10 +9,6 @@ Debug Win32 - - Release - ARM - Release ARM64 @@ -46,11 +38,6 @@ true x64 - - DynamicLibrary - true - x64 - DynamicLibrary true @@ -62,12 +49,6 @@ true x64 - - DynamicLibrary - false - true - x64 - DynamicLibrary false @@ -93,18 +74,12 @@ - - - - - - @@ -117,40 +92,28 @@ Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - - - Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - - - Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(FxCopDir);$(PATH); Disabled $(ProjectDir);$(OutputPath);Generated Files;..\test_component_base\Generated Files + Level4 + true 4100 MultiThreadedDebug @@ -196,73 +159,12 @@ $(OutputPath)test_component_derived.winmd - - - Disabled - $(ProjectDir);$(OutputPath);Generated Files;..\test_component_base\Generated Files - 4100 - MultiThreadedDebug - - - exports.def - - - true - - - $(OutputPath)test_component_derived.winmd - - - - - - - - - - - nul - - - - - - - - - - - - - - - - - - - /nomidl %(AdditionalOptions) - C:\Windows\System32\WinMetadata - true - ..\test_component_base - - - $(CppWinRTDir)cppwinrt -input $(OutputPath)test_component_derived.winmd -ref $(OutputPath)test_component_base.winmd -comp $(ProjectDir) -out "$(ProjectDir)Generated Files" -ref sdk -verbose -name test_component_derived - - - - - - - Generated Files\module.g.cpp - - - $(OutputPath)test_component_derived.winmd - - Disabled $(ProjectDir);$(OutputPath);Generated Files;..\test_component_base\Generated Files + Level4 + true 4100 MultiThreadedDebug @@ -326,6 +228,8 @@ Disabled $(ProjectDir);$(OutputPath);Generated Files;..\test_component_base\Generated Files + Level4 + true 4100 MultiThreadedDebug @@ -377,6 +281,8 @@ true true $(ProjectDir);$(OutputPath);Generated Files;..\test_component_base\Generated Files + Level4 + true 4100 MultiThreaded @@ -424,79 +330,14 @@ $(OutputPath)test_component_derived.winmd - - - MaxSpeed - true - true - $(ProjectDir);$(OutputPath);Generated Files;..\test_component_base\Generated Files - 4100 - MultiThreaded - - - true - true - exports.def - - - true - - - $(OutputPath)test_component_derived.winmd - - - - - - - - - - - nul - - - - - - - - - - - - - - - - - - - /nomidl %(AdditionalOptions) - C:\Windows\System32\WinMetadata - true - ..\test_component_base - - - $(CppWinRTDir)cppwinrt -input $(OutputPath)test_component_derived.winmd -ref $(OutputPath)test_component_base.winmd -comp $(ProjectDir) -out "$(ProjectDir)Generated Files" -ref sdk -verbose -name test_component_derived - - - - - - - Generated Files\module.g.cpp - - - $(OutputPath)test_component_derived.winmd - - MaxSpeed true true $(ProjectDir);$(OutputPath);Generated Files;..\test_component_base\Generated Files + Level4 + true 4100 MultiThreaded @@ -564,6 +405,8 @@ true true $(ProjectDir);$(OutputPath);Generated Files;..\test_component_base\Generated Files + Level4 + true 4100 MultiThreaded diff --git a/test/test_component_fast/test_component_fast.vcxproj b/test/test_component_fast/test_component_fast.vcxproj index b9d54604b..ed5a36222 100644 --- a/test/test_component_fast/test_component_fast.vcxproj +++ b/test/test_component_fast/test_component_fast.vcxproj @@ -1,10 +1,6 @@ - - Debug - ARM - Debug ARM64 @@ -13,10 +9,6 @@ Debug Win32 - - Release - ARM - Release ARM64 @@ -47,11 +39,6 @@ true x64 - - DynamicLibrary - true - x64 - DynamicLibrary true @@ -63,12 +50,6 @@ true x64 - - DynamicLibrary - false - true - x64 - DynamicLibrary false @@ -94,18 +75,12 @@ - - - - - - @@ -118,41 +93,29 @@ Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - - - Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - - - Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(FxCopDir);$(PATH); Disabled $(ProjectDir);$(OutputPath);Generated Files /DWINRT_FAST_ABI_SIZE=50 %(AdditionalOptions) + Level4 + true 4100 MultiThreadedDebug @@ -197,74 +160,13 @@ $(OutputPath)test_component_fast.winmd - - - Disabled - $(ProjectDir);$(OutputPath);Generated Files - /DWINRT_FAST_ABI_SIZE=50 %(AdditionalOptions) - 4100 - MultiThreadedDebug - - - exports.def - - - true - - - $(OutputPath)test_component_fast.winmd - - - - - - - - - - - nul - - - - - - - - - - - - - - - - - - - /nomidl %(AdditionalOptions) - C:\Windows\System32\WinMetadata - true - - - $(CppWinRTDir)cppwinrt -input $(OutputPath)test_component_fast.winmd -comp $(ProjectDir) -out "$(ProjectDir)Generated Files" -ref sdk -verbose -fastabi -prefix -opt -name test_component_fast - - - - - - - Generated Files\module.g.cpp - - - $(OutputPath)test_component_fast.winmd - - Disabled $(ProjectDir);$(OutputPath);Generated Files /DWINRT_FAST_ABI_SIZE=50 %(AdditionalOptions) + Level4 + true 4100 MultiThreadedDebug @@ -328,6 +230,8 @@ Disabled $(ProjectDir);$(OutputPath);Generated Files /DWINRT_FAST_ABI_SIZE=50 %(AdditionalOptions) + Level4 + true 4100 MultiThreadedDebug @@ -379,6 +283,8 @@ true $(ProjectDir);$(OutputPath);Generated Files /DWINRT_FAST_ABI_SIZE=50 %(AdditionalOptions) + Level4 + true 4100 MultiThreaded @@ -425,73 +331,6 @@ $(OutputPath)test_component_fast.winmd - - - MaxSpeed - true - true - $(ProjectDir);$(OutputPath);Generated Files - /DWINRT_FAST_ABI_SIZE=50 %(AdditionalOptions) - 4100 - MultiThreaded - - - true - true - exports.def - - - true - - - $(OutputPath)test_component_fast.winmd - - - - - - - - - - - nul - - - - - - - - - - - - - - - - - - - /nomidl %(AdditionalOptions) - C:\Windows\System32\WinMetadata - true - - - $(CppWinRTDir)cppwinrt -input $(OutputPath)test_component_fast.winmd -comp $(ProjectDir) -out "$(ProjectDir)Generated Files" -ref sdk -verbose -fastabi -prefix -opt -name test_component_fast - - - - - - - Generated Files\module.g.cpp - - - $(OutputPath)test_component_fast.winmd - - MaxSpeed @@ -499,6 +338,8 @@ true $(ProjectDir);$(OutputPath);Generated Files /DWINRT_FAST_ABI_SIZE=50 %(AdditionalOptions) + Level4 + true 4100 MultiThreaded @@ -566,6 +407,8 @@ true $(ProjectDir);$(OutputPath);Generated Files /DWINRT_FAST_ABI_SIZE=50 %(AdditionalOptions) + Level4 + true 4100 MultiThreaded diff --git a/test/test_component_folders/test_component_folders.vcxproj b/test/test_component_folders/test_component_folders.vcxproj index 0270ca257..14c12f8f9 100644 --- a/test/test_component_folders/test_component_folders.vcxproj +++ b/test/test_component_folders/test_component_folders.vcxproj @@ -1,10 +1,6 @@ - - Debug - ARM - Debug ARM64 @@ -13,10 +9,6 @@ Debug Win32 - - Release - ARM - Release ARM64 @@ -46,11 +38,6 @@ true x64 - - DynamicLibrary - true - x64 - DynamicLibrary true @@ -62,12 +49,6 @@ true x64 - - DynamicLibrary - false - true - x64 - DynamicLibrary false @@ -93,18 +74,12 @@ - - - - - - @@ -117,40 +92,28 @@ Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - - - Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - - - Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(FxCopDir);$(PATH); Disabled $(ProjectDir);$(OutputPath);Generated Files + Level4 + true 4100 MultiThreadedDebug @@ -195,72 +158,12 @@ $(OutputPath)test_component_folders.winmd - - - Disabled - $(ProjectDir);$(OutputPath);Generated Files - 4100 - MultiThreadedDebug - - - exports.def - - - true - - - $(OutputPath)test_component_folders.winmd - - - - - - - - - - - nul - - - - - - - - - - - - - - - - - - - /nomidl %(AdditionalOptions) - C:\Windows\System32\WinMetadata - true - - - $(CppWinRTDir)cppwinrt -input $(OutputPath)test_component_folders.winmd -comp -out "$(ProjectDir)Generated Files" -ref sdk -verbose -overwrite -name test_component_folders - - - - - - - Generated Files\module.g.cpp - - - $(OutputPath)test_component_folders.winmd - - Disabled $(ProjectDir);$(OutputPath);Generated Files + Level4 + true 4100 MultiThreadedDebug @@ -323,6 +226,8 @@ Disabled $(ProjectDir);$(OutputPath);Generated Files + Level4 + true 4100 MultiThreadedDebug @@ -373,6 +278,8 @@ true true $(ProjectDir);$(OutputPath);Generated Files + Level4 + true 4100 MultiThreaded @@ -419,78 +326,14 @@ $(OutputPath)test_component_folders.winmd - - - MaxSpeed - true - true - $(ProjectDir);$(OutputPath);Generated Files - 4100 - MultiThreaded - - - true - true - exports.def - - - true - - - $(OutputPath)test_component_folders.winmd - - - - - - - - - - - nul - - - - - - - - - - - - - - - - - - - /nomidl %(AdditionalOptions) - C:\Windows\System32\WinMetadata - true - - - $(CppWinRTDir)cppwinrt -input $(OutputPath)test_component_folders.winmd -comp -out "$(ProjectDir)Generated Files" -ref sdk -verbose -overwrite -name test_component_folders - - - - - - - Generated Files\module.g.cpp - - - $(OutputPath)test_component_folders.winmd - - MaxSpeed true true $(ProjectDir);$(OutputPath);Generated Files + Level4 + true 4100 MultiThreaded @@ -557,6 +400,8 @@ true true $(ProjectDir);$(OutputPath);Generated Files + Level4 + true 4100 MultiThreaded diff --git a/test/test_component_no_pch/test_component_no_pch.vcxproj b/test/test_component_no_pch/test_component_no_pch.vcxproj index 594e85592..117be2d00 100644 --- a/test/test_component_no_pch/test_component_no_pch.vcxproj +++ b/test/test_component_no_pch/test_component_no_pch.vcxproj @@ -1,10 +1,6 @@ - - Debug - ARM - Debug ARM64 @@ -13,10 +9,6 @@ Debug Win32 - - Release - ARM - Release ARM64 @@ -46,11 +38,6 @@ true x64 - - DynamicLibrary - true - x64 - DynamicLibrary true @@ -62,12 +49,6 @@ true x64 - - DynamicLibrary - false - true - x64 - DynamicLibrary false @@ -93,18 +74,12 @@ - - - - - - @@ -117,40 +92,28 @@ Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - - - Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - - - Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(FxCopDir);$(PATH); Disabled $(ProjectDir);$(OutputPath);Generated Files + Level4 + true 4100 NotUsing MultiThreadedDebug @@ -196,73 +159,12 @@ $(OutputPath)test_component_no_pch.winmd - - - Disabled - $(ProjectDir);$(OutputPath);Generated Files - 4100 - NotUsing - MultiThreadedDebug - - - exports.def - - - true - - - $(OutputPath)test_component_no_pch.winmd - - - - - - - - - - - nul - - - - - - - - - - - - - - - - - - - /nomidl %(AdditionalOptions) - C:\Windows\System32\WinMetadata - true - - - $(CppWinRTDir)cppwinrt -input $(OutputPath)test_component_no_pch.winmd -comp -out "$(ProjectDir)Generated Files" -ref sdk -verbose -overwrite -pch . -name test_component_no_pch - - - - - - - Generated Files\module.g.cpp - - - $(OutputPath)test_component_no_pch.winmd - - Disabled $(ProjectDir);$(OutputPath);Generated Files + Level4 + true 4100 NotUsing MultiThreadedDebug @@ -326,6 +228,8 @@ Disabled $(ProjectDir);$(OutputPath);Generated Files + Level4 + true 4100 NotUsing MultiThreadedDebug @@ -377,6 +281,8 @@ true true $(ProjectDir);$(OutputPath);Generated Files + Level4 + true 4100 NotUsing MultiThreaded @@ -424,79 +330,14 @@ $(OutputPath)test_component_no_pch.winmd - - - MaxSpeed - true - true - $(ProjectDir);$(OutputPath);Generated Files - 4100 - NotUsing - MultiThreaded - - - true - true - exports.def - - - true - - - $(OutputPath)test_component_no_pch.winmd - - - - - - - - - - - nul - - - - - - - - - - - - - - - - - - - /nomidl %(AdditionalOptions) - C:\Windows\System32\WinMetadata - true - - - $(CppWinRTDir)cppwinrt -input $(OutputPath)test_component_no_pch.winmd -comp -out "$(ProjectDir)Generated Files" -ref sdk -verbose -overwrite -pch . -name test_component_no_pch - - - - - - - Generated Files\module.g.cpp - - - $(OutputPath)test_component_no_pch.winmd - - MaxSpeed true true $(ProjectDir);$(OutputPath);Generated Files + Level4 + true 4100 NotUsing MultiThreaded @@ -564,6 +405,8 @@ true true $(ProjectDir);$(OutputPath);Generated Files + Level4 + true 4100 NotUsing MultiThreaded diff --git a/test/test_cpp20/array_span.cpp b/test/test_cpp20/array_span.cpp index dff5a2ec5..8cebc4a1e 100644 --- a/test/test_cpp20/array_span.cpp +++ b/test/test_cpp20/array_span.cpp @@ -10,7 +10,7 @@ using namespace Windows::Data::Json; // // This is a helper to create a data reader for use in testing arrays. // -static IAsyncOperation CreateDataReader(std::initializer_list values) +static IAsyncOperation CreateDataReader(std::initializer_list /*values*/) { InMemoryRandomAccessStream stream; DataWriter writer(stream); diff --git a/test/test_cpp20/clang_only.cpp b/test/test_cpp20/clang_only.cpp new file mode 100644 index 000000000..45aa4b380 --- /dev/null +++ b/test/test_cpp20/clang_only.cpp @@ -0,0 +1,23 @@ +#include "pch.h" +#include + +#ifdef __clang__ + +using namespace winrt; +using namespace Windows::Foundation; +using namespace Windows::Storage::Pickers; + +TEST_CASE("clang_lto_visibility") +{ + // A previous bug report (https://github.com/microsoft/cppwinrt/pull/1482) represented a problem when some linker + // options (-O3 -flto -fwhole-program-vtables) were used with cppwinrt generated code. The lack of public annotation + // caused methods to be removed from the binary, leading to a crash. This test case aims to be a regression test for + // that problem. + FileOpenPicker picker{}; + picker.ViewMode(PickerViewMode::Thumbnail); + picker.FileTypeFilter().Append(L".png"); // This line would trigger the crash. + + REQUIRE(true); +} + +#endif // __clang__ \ No newline at end of file diff --git a/test/test_cpp20/custom_error.cpp b/test/test_cpp20/custom_error.cpp index d7b055e47..b925628d9 100644 --- a/test/test_cpp20/custom_error.cpp +++ b/test/test_cpp20/custom_error.cpp @@ -37,9 +37,9 @@ namespace #if defined(_LIBCPP_VERSION) && _LIBCPP_VERSION < 170000 // not available in libc++ before LLVM 16 -TEST_CASE("custom_error_logger", "[!shouldfail]") +TEST_CASE("custom_error_logger_on_throw", "[!shouldfail]") #else -TEST_CASE("custom_error_logger") +TEST_CASE("custom_error_logger_on_throw") #endif { // Set up global handler @@ -72,3 +72,62 @@ TEST_CASE("custom_error_logger") winrt_throw_hresult_handler = nullptr; s_loggerCalled = false; } +template +void HresultOnLine80(Args... args) +{ + // Validate that handler translated on creating an HRESULT +#line 80 // Force next line to be reported as line number 80 + winrt::hresult_canceled(std::forward(args)...); +} + +#if defined(_LIBCPP_VERSION) && _LIBCPP_VERSION < 170000 +// not available in libc++ before LLVM 16 +TEST_CASE("custom_error_logger_on_originate", "[!shouldfail]") +#else +TEST_CASE("custom_error_logger_on_originate") +#endif +{ + // Set up global handler + REQUIRE(!s_loggerCalled); + REQUIRE(!winrt_throw_hresult_handler); + winrt_throw_hresult_handler = logger; + + HresultOnLine80(); + REQUIRE(s_loggerCalled); + // In C++20 these fields should be filled in by std::source_location + REQUIRE(s_loggerArgs.lineNumber == 80); + const auto fileNameSv = std::string_view(s_loggerArgs.fileName); + REQUIRE(!fileNameSv.empty()); + REQUIRE(fileNameSv.find("custom_error.cpp") != std::string::npos); +#ifdef _DEBUG + const auto functionNameSv = std::string_view(s_loggerArgs.functionName); + REQUIRE(!functionNameSv.empty()); + // Every compiler has a slightly different naming approach for this function, and even the same + // compiler can change its mind over time. Instead of matching the entire function name just + // match against the part we care about. + REQUIRE((functionNameSv.find("HresultOnLine80") != std::string_view::npos)); +#else + REQUIRE(s_loggerArgs.functionName == nullptr); +#endif // _DEBUG + + REQUIRE(s_loggerArgs.returnAddress); + REQUIRE(s_loggerArgs.result == HRESULT_FROM_WIN32(ERROR_CANCELLED)); // E_ILLEGAL_DELEGATE_ASSIGNMENT) + + s_loggerCalled = false; + s_loggerArgs.lineNumber = 0; + // verify HRESULT with a custom message + HresultOnLine80(L"with custom message"); + REQUIRE(s_loggerCalled); + REQUIRE(s_loggerArgs.lineNumber == 80); + + s_loggerCalled = false; + s_loggerArgs.lineNumber = 0; + // verify that no_originate does _not_ call the logger. + HresultOnLine80(winrt::hresult_error::no_originate); + REQUIRE(!s_loggerCalled); + REQUIRE(s_loggerArgs.lineNumber == 0); + + // Remove global handler + winrt_throw_hresult_handler = nullptr; + s_loggerCalled = false; +} diff --git a/test/test_cpp20/format.cpp b/test/test_cpp20/format.cpp index 0c40a4113..d16193328 100644 --- a/test/test_cpp20/format.cpp +++ b/test/test_cpp20/format.cpp @@ -17,17 +17,26 @@ TEST_CASE("format") winrt::hstring str = L"World"; REQUIRE(std::format(L"Hello {}", str) == L"Hello World"); } +} +TEST_CASE("format_make") +{ { winrt::Windows::Foundation::IStringable obj = winrt::make(); REQUIRE(std::format(L"This is {}", obj) == L"This is a stringable object"); } +} +TEST_CASE("format_json") +{ { winrt::Windows::Data::Json::JsonArray jsonArray; REQUIRE(std::format(L"The contents of the array are: {}", jsonArray) == L"The contents of the array are: []"); } +} +TEST_CASE("format_wstring") +{ #if __cpp_lib_format >= 202207L { std::wstring str = L"World"; diff --git a/test/test_cpp20/hstring_literal.cpp b/test/test_cpp20/hstring_literal.cpp new file mode 100644 index 000000000..2ba0f3ad7 --- /dev/null +++ b/test/test_cpp20/hstring_literal.cpp @@ -0,0 +1,68 @@ +#include "pch.h" + +using namespace winrt; +using namespace std::literals; + +#if defined(__cpp_nontype_template_args) && __cpp_nontype_template_args >= 201911L + +using namespace winrt::literals; + +namespace +{ + // Exercises the hstring_reference -> param::hstring conversion that projected + // setters rely on, and duplicates into an owning hstring on the way out. + winrt::hstring copy_via_param(winrt::param::hstring const& value) + { + winrt::hstring const& as_hstring = value; + return as_hstring; + } +} + +TEST_CASE("hstring_literal") +{ + // The literal is a genuine constant expression: the fast-pass header is built at + // compile time, so an hstring_reference can be constructed in a constexpr context. + { + constexpr winrt::hstring_reference lit = L"kittens"_hs; + winrt::hstring const& value = lit; + REQUIRE(value == L"kittens"sv); + REQUIRE(value.size() == 7); + } + + // Content and length match the literal. + { + winrt::hstring_reference const lit = L"kittens"_hs; + winrt::hstring const& value = lit; + REQUIRE(value == L"kittens"sv); + REQUIRE(value.size() == 7); + REQUIRE(wcslen(value.c_str()) == 7); + } + + // Built as a fast-pass reference string (no heap allocation). + { + winrt::hstring_reference const lit = L"puppies"_hs; + auto const header = static_cast(winrt::get_abi(lit)); + REQUIRE(header != nullptr); + REQUIRE((header->flags & winrt::impl::hstring_reference_flag) != 0); + REQUIRE(header->length == 7); + } + + // Empty literal projects as the empty (null) HSTRING. + { + winrt::hstring_reference const lit = L""_hs; + winrt::hstring const& value = lit; + REQUIRE(value.empty()); + REQUIRE(value.size() == 0); + REQUIRE(winrt::get_abi(value) == nullptr); + } + + // Binds to a projected setter parameter in a single conversion, and copying + // into an owning hstring duplicates correctly. + { + winrt::hstring const copied = copy_via_param(L"waffles"_hs); + REQUIRE(copied == L"waffles"sv); + REQUIRE(copied.size() == 7); + } +} + +#endif diff --git a/test/test_cpp20/test_cpp20.vcxproj b/test/test_cpp20/test_cpp20.vcxproj index 72d203a37..b13becd23 100644 --- a/test/test_cpp20/test_cpp20.vcxproj +++ b/test/test_cpp20/test_cpp20.vcxproj @@ -1,10 +1,6 @@ - - Debug - ARM - Debug ARM64 @@ -13,10 +9,6 @@ Debug Win32 - - Release - ARM - Release ARM64 @@ -46,10 +38,6 @@ Application true - - Application - true - Application true @@ -59,11 +47,6 @@ false true - - Application - false - true - Application false @@ -86,18 +69,12 @@ - - - - - - @@ -116,6 +93,9 @@ $(OutputPath);Generated Files;..\ NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreaded + Level4 + true + %(AdditionalOptions) -O3 -flto -fwhole-program-vtables Console @@ -137,25 +117,9 @@ $(OutputPath);Generated Files;..\ NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreadedDebug - - - Console - - - - - - - - - - - - - Disabled - $(OutputPath);Generated Files;..\ - NOMINMAX;_MBCS;%(PreprocessorDefinitions) - MultiThreadedDebug + Level4 + true + %(AdditionalOptions) -flto -fwhole-program-vtables Console @@ -175,6 +139,9 @@ $(OutputPath);Generated Files;..\ NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreadedDebug + Level4 + true + %(AdditionalOptions) -flto -fwhole-program-vtables Console @@ -194,6 +161,9 @@ $(OutputPath);Generated Files;..\ NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreadedDebug + Level4 + true + %(AdditionalOptions) -flto -fwhole-program-vtables Console @@ -215,29 +185,9 @@ $(OutputPath);Generated Files;..\ NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreaded - - - Console - true - true - - - - - - - - - - - - - MaxSpeed - true - true - $(OutputPath);Generated Files;..\ - NOMINMAX;_MBCS;%(PreprocessorDefinitions) - MultiThreaded + Level4 + true + %(AdditionalOptions) -O3 -flto -fwhole-program-vtables Console @@ -261,6 +211,9 @@ $(OutputPath);Generated Files;..\ NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreaded + Level4 + true + %(AdditionalOptions) -O3 -flto -fwhole-program-vtables Console @@ -282,9 +235,11 @@ + + NotUsing diff --git a/test/test_cpp20_module/collections.cpp b/test/test_cpp20_module/collections.cpp new file mode 100644 index 000000000..b80e123d2 --- /dev/null +++ b/test/test_cpp20_module/collections.cpp @@ -0,0 +1,57 @@ +#include "pch.h" + +import winrt.Windows.Foundation; + +using namespace winrt; +using namespace Windows::Foundation::Collections; + +TEST_CASE("module_vector") +{ + auto vec = single_threaded_vector(); + vec.Append(10); + vec.Append(20); + vec.Append(30); + REQUIRE(vec.Size() == 3); + REQUIRE(vec.GetAt(0) == 10); + REQUIRE(vec.GetAt(2) == 30); + + vec.RemoveAtEnd(); + REQUIRE(vec.Size() == 2); +} + +TEST_CASE("module_map") +{ + auto map = single_threaded_map(); + map.Insert(L"key1", L"value1"); + map.Insert(L"key2", L"value2"); + REQUIRE(map.Size() == 2); + REQUIRE(map.Lookup(L"key1") == L"value1"); + REQUIRE(map.HasKey(L"key2")); + REQUIRE(!map.HasKey(L"key3")); +} + +TEST_CASE("module_observable_vector") +{ + auto vec = single_threaded_observable_vector(); + int change_count = 0; + auto token = vec.VectorChanged([&](auto&&, auto&&) { ++change_count; }); + vec.Append(1); + vec.Append(2); + REQUIRE(change_count == 2); + vec.VectorChanged(token); +} + +TEST_CASE("module_iterable") +{ + auto vec = single_threaded_vector(); + vec.Append(1); + vec.Append(2); + vec.Append(3); + + int sum = 0; + for (auto v : vec) + { + sum += v; + } + REQUIRE(sum == 6); +} diff --git a/test/test_cpp20_module/com_interop.cpp b/test/test_cpp20_module/com_interop.cpp new file mode 100644 index 000000000..3035d2a05 --- /dev/null +++ b/test/test_cpp20_module/com_interop.cpp @@ -0,0 +1,84 @@ +#include "pch.h" +#include +#include + +import std; +import winrt.Windows.Foundation; + +// +// These tests confirm that COM interop — including legacy (non-WinRT) COM types +// from the Windows SDK — works correctly when consumed via modules. +// +// Note: We avoid 'using namespace Windows::Foundation' here because it brings +// IInspectable/IUnknown into scope and collides with the SDK types of the same name. +// + +using namespace winrt; + +TEST_CASE("module_com_ptr_round_trip") +{ + Windows::Foundation::Uri uri(L"https://example.com"); + + // Detach to raw ABI pointer and re-attach + void* abi = detach_abi(uri); + REQUIRE(abi != nullptr); + + Windows::Foundation::Uri uri2{ nullptr }; + attach_abi(uri2, abi); + REQUIRE(uri2.AbsoluteUri() == L"https://example.com/"); +} + +TEST_CASE("module_sdk_iunknown_interop") +{ + // Interop between winrt projected types and the Windows SDK ::IUnknown + Windows::Foundation::Uri uri(L"https://example.com"); + + // Get the SDK IUnknown pointer from a projected type + ::IUnknown* raw = nullptr; + copy_to_abi(uri, *reinterpret_cast(&raw)); + REQUIRE(raw != nullptr); + + // QI for IInspectable through the raw SDK pointer + ::IInspectable* inspectable = nullptr; + REQUIRE(raw->QueryInterface(IID_IInspectable, reinterpret_cast(&inspectable)) == S_OK); + REQUIRE(inspectable != nullptr); + inspectable->Release(); + + // Round-trip back to a projected type + Windows::Foundation::Uri uri2{ nullptr }; + copy_from_abi(uri2, raw); + REQUIRE(uri2.AbsoluteUri() == L"https://example.com/"); + + raw->Release(); +} + +TEST_CASE("module_com_ptr_sdk_type") +{ + // winrt::com_ptr wrapping a Windows SDK ::IUnknown + Windows::Foundation::Uri uri(L"https://example.com"); + + com_ptr<::IUnknown> unknown; + copy_to_abi(uri, *reinterpret_cast(unknown.put())); + REQUIRE(unknown.get() != nullptr); +} + +TEST_CASE("module_iunknown_identity") +{ + Windows::Foundation::Uri uri(L"https://example.com"); + + auto unknown1 = uri.as(); + auto unknown2 = uri.as(); + REQUIRE(unknown1 == unknown2); +} + +TEST_CASE("module_try_as") +{ + Windows::Foundation::Uri uri(L"https://example.com"); + + auto stringable = uri.try_as(); + REQUIRE(stringable != nullptr); + REQUIRE(!stringable.ToString().empty()); + + auto closable = uri.try_as(); + REQUIRE(closable == nullptr); +} diff --git a/test/test_cpp20_module/coroutines.cpp b/test/test_cpp20_module/coroutines.cpp new file mode 100644 index 000000000..1553b1c6d --- /dev/null +++ b/test/test_cpp20_module/coroutines.cpp @@ -0,0 +1,58 @@ +#include "pch.h" + +import std; +import winrt.Windows.Foundation; + +using namespace winrt; +using namespace Windows::Foundation; + +IAsyncAction do_nothing_async() +{ + co_return; +} + +IAsyncOperation return_42_async() +{ + co_return 42; +} + +IAsyncOperation return_string_async() +{ + co_return L"module coroutine"; +} + +IAsyncAction chain_async() +{ + auto result = co_await return_string_async(); + REQUIRE(!result.empty()); +} + +IAsyncOperation slow_operation() +{ + co_await resume_after(std::chrono::hours(1)); + co_return 0; +} + +TEST_CASE("module_async_action") +{ + auto action = do_nothing_async(); + action.get(); + REQUIRE(action.Status() == AsyncStatus::Completed); +} + +TEST_CASE("module_async_operation") +{ + REQUIRE(return_42_async().get() == 42); +} + +TEST_CASE("module_async_chain") +{ + chain_async().get(); +} + +TEST_CASE("module_async_cancel") +{ + auto op = slow_operation(); + op.Cancel(); + REQUIRE(op.Status() == AsyncStatus::Canceled); +} diff --git a/test/test_cpp20_module/format.cpp b/test/test_cpp20_module/format.cpp new file mode 100644 index 000000000..0c4570300 --- /dev/null +++ b/test/test_cpp20_module/format.cpp @@ -0,0 +1,49 @@ +#include "pch.h" + +#ifdef __cpp_lib_format + +import std; +import winrt.Windows.Foundation; + +// +// These tests confirm that std::format and std::formatter specializations work +// correctly when consumed via modules. Mirrors test/test_cpp20/format.cpp. +// + +using namespace winrt; +using namespace Windows::Foundation; + +TEST_CASE("module_format_hstring") +{ + hstring str = L"World"; + REQUIRE(std::format(L"Hello {}", str) == L"Hello World"); +} + +TEST_CASE("module_format_IStringable") +{ + // Uri implements IStringable — exercises the generated + // std::formatter specialization through modules. + Uri uri(L"https://example.com/path"); + IStringable stringable = uri; + REQUIRE(std::format(L"Visit: {}", stringable) == L"Visit: https://example.com/path"); +} + +TEST_CASE("module_format_projected_class") +{ + // Exercises the generated std::formatter specialization + // (inherits from formatter) through modules. + Uri uri(L"https://example.com"); + REQUIRE(std::format(L"URL: {}", uri) == L"URL: https://example.com/"); +} + +#if __cpp_lib_format >= 202207L +TEST_CASE("module_format_winrt_format") +{ + // winrt::format helper (C++23 formattable concept) + std::wstring str = L"World"; + REQUIRE(winrt::format(L"Hello {}", str) == L"Hello World"); + REQUIRE(winrt::format(L"C++/WinRT #{:d}", 1) == L"C++/WinRT #1"); +} +#endif + +#endif // __cpp_lib_format diff --git a/test/test_cpp20_module/foundation.cpp b/test/test_cpp20_module/foundation.cpp new file mode 100644 index 000000000..d26c55244 --- /dev/null +++ b/test/test_cpp20_module/foundation.cpp @@ -0,0 +1,68 @@ +#include "pch.h" + +import std; +import winrt.Windows.Foundation; + +using namespace winrt; +using namespace Windows::Foundation; + +TEST_CASE("module_uri") +{ + Uri uri(L"https://example.com/path?query=1"); + REQUIRE(!uri.AbsoluteUri().empty()); + REQUIRE(uri.Host() == L"example.com"); + REQUIRE(uri.Path() == L"/path"); +} + +TEST_CASE("module_property_value") +{ + auto pv = PropertyValue::CreateInt32(42); + REQUIRE(pv.as().GetInt32() == 42); + + auto pvs = PropertyValue::CreateString(L"hello"); + REQUIRE(pvs.as().GetString() == L"hello"); +} + +TEST_CASE("module_hstring") +{ + hstring text = L"C++/WinRT modules"; + REQUIRE(!text.empty()); + REQUIRE(text.size() == 17); + + hstring empty; + REQUIRE(empty.empty()); + REQUIRE(empty.size() == 0); +} + +TEST_CASE("module_events") +{ + winrt::event> my_event; + int received = 0; + auto token = my_event.add([&](auto&&, int value) { received = value; }); + my_event(nullptr, 42); + REQUIRE(received == 42); + my_event.remove(token); +} + +TEST_CASE("module_foundation_point") +{ + Point p{ 5.0f, 10.0f }; + REQUIRE(p.X == 5.0f); + REQUIRE(p.Y == 10.0f); +} + +TEST_CASE("module_foundation_size") +{ + Size s{ 800.0f, 600.0f }; + REQUIRE(s.Width == 800.0f); + REQUIRE(s.Height == 600.0f); +} + +TEST_CASE("module_foundation_rect") +{ + Point origin{ 0.0f, 0.0f }; + Size extent{ 100.0f, 200.0f }; + Rect r(origin, extent); + REQUIRE(r.X == 0.0f); + REQUIRE(r.Width == 100.0f); +} diff --git a/test/test_cpp20_module/hash.cpp b/test/test_cpp20_module/hash.cpp new file mode 100644 index 000000000..bb7594104 --- /dev/null +++ b/test/test_cpp20_module/hash.cpp @@ -0,0 +1,73 @@ +#include "pch.h" + +import std; +import winrt.Windows.Foundation; + +// +// These tests confirm that std::hash specializations work correctly +// when consumed via modules, enabling use in unordered containers. +// + +using namespace winrt; +using namespace Windows::Foundation; + +TEST_CASE("module_hash_hstring") +{ + std::unordered_set set; + set.insert(L"hello"); + set.insert(L"world"); + set.insert(L"hello"); // duplicate + REQUIRE(set.size() == 2); + REQUIRE(set.contains(L"hello")); + REQUIRE(set.contains(L"world")); +} + +TEST_CASE("module_hash_IUnknown") +{ + Uri uri(L"https://example.com"); + auto unknown = uri.as(); + + std::unordered_set set; + set.insert(unknown); + set.insert(unknown); // duplicate — same identity + REQUIRE(set.size() == 1); + + // A different object should hash differently (almost certainly) + Uri uri2(L"https://other.com"); + set.insert(uri2.as()); + REQUIRE(set.size() == 2); +} + +TEST_CASE("module_hash_projected_type") +{ + // Projected types like Uri should be hashable via the generated + // std::hash specialization (inherits from hash_base). + std::unordered_set set; + Uri u1(L"https://one.com"); + Uri u2(L"https://two.com"); + set.insert(u1); + set.insert(u2); + set.insert(u1); // duplicate + REQUIRE(set.size() == 2); +} + +TEST_CASE("module_hash_guid") +{ + std::unordered_set set; + guid g1{ 0x01020304, 0x0506, 0x0708, { 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10 } }; + guid g2{ 0x11121314, 0x1516, 0x1718, { 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20 } }; + set.insert(g1); + set.insert(g2); + set.insert(g1); // duplicate + REQUIRE(set.size() == 2); +} + +TEST_CASE("module_hash_map_with_hstring_key") +{ + std::unordered_map map; + map[L"one"] = 1; + map[L"two"] = 2; + map[L"three"] = 3; + REQUIRE(map.size() == 3); + REQUIRE(map[L"two"] == 2); +} diff --git a/test/test_cpp20_module/main.cpp b/test/test_cpp20_module/main.cpp new file mode 100644 index 000000000..415e26f0f --- /dev/null +++ b/test/test_cpp20_module/main.cpp @@ -0,0 +1,24 @@ +#include +#define CATCH_CONFIG_RUNNER +#define CATCH_CONFIG_WINDOWS_SEH +#include "catch.hpp" + +import winrt_base; + +using namespace winrt; + +int main(int const argc, char** argv) +{ + init_apartment(); + std::set_terminate([] { reportFatal("Abnormal termination"); ExitProcess(1); }); + _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE); + (void)_CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR); + _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE); + (void)_CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR); + return Catch::Session().run(argc, argv); +} + +CATCH_TRANSLATE_EXCEPTION(hresult_error const& e) +{ + return to_string(e.message()); +} diff --git a/test/test_cpp20_module/marshal.cpp b/test/test_cpp20_module/marshal.cpp new file mode 100644 index 000000000..d47f8c3cb --- /dev/null +++ b/test/test_cpp20_module/marshal.cpp @@ -0,0 +1,25 @@ +#include "pch.h" +#include +#include + +import std; +import winrt.Windows.Foundation.Collections; + +using namespace winrt; + +struct S : implements +{ + hstring ToString() + { + return L"S"; + } +}; + +// When winrt::impl::get_marshaler was being exported, an MSVC bug caused the marshaler +// object to have a null vtable, which caused a crash when calling any method on the marshaler. +// This test ensures that the marshaler vtable is properly initialized. +TEST_CASE("IMarshal") +{ + auto s = make(); + auto marshal = s.as(); +} diff --git a/test/test_cpp20_module/natvis.cpp b/test/test_cpp20_module/natvis.cpp new file mode 100644 index 000000000..470654d07 --- /dev/null +++ b/test/test_cpp20_module/natvis.cpp @@ -0,0 +1,58 @@ +#include "pch.h" +#include + +import std; +import winrt.Windows.Foundation; + +// +// These tests confirm that the natvis infrastructure (winrt::impl::natvis) +// is reachable through modules, ensuring the debugger visualizer can function. +// natvis is only active in _DEBUG builds. +// + +using namespace winrt; +using namespace Windows::Foundation; + +#ifdef _DEBUG + +TEST_CASE("module_natvis_get_val") +{ + // Verify impl::natvis::get_val is callable through the module. + Uri uri(L"http://example.com/"); + IInspectable inspectable = uri; + + // IStringable IID: {96369F54-8EB6-48F0-ABCE-C1B211E627C3} + // Method index 0 = ToString + auto result = impl::natvis::get_val(&inspectable, L"{96369F54-8EB6-48F0-ABCE-C1B211E627C3}", 0); + + // Compare the natvis result with the direct call + hstring expected = uri.ToString(); + uint32_t expected_len = 0; + auto expected_buf = WindowsGetStringRawBuffer(static_cast(get_abi(expected)), &expected_len); + uint32_t actual_len = 0; + auto actual_buf = WindowsGetStringRawBuffer(static_cast(result.s), &actual_len); + REQUIRE(expected_len == actual_len); + REQUIRE(memcmp(expected_buf, actual_buf, expected_len * sizeof(wchar_t)) == 0); +} + +TEST_CASE("module_natvis_uri_properties") +{ + Uri uri(L"http://moderncpp.com/path"); + IInspectable inspectable = uri; + + // IUriRuntimeClass IID: {9E365E57-48B2-4160-956F-C7385120BBFC} + // Method 5 = Host, Method 7 = Path, Method 11 = SchemeName + auto host_val = impl::natvis::get_val(&inspectable, L"{9E365E57-48B2-4160-956F-C7385120BBFC}", 5); + hstring host_expected = uri.Host(); + REQUIRE(host_expected == hstring{ WindowsGetStringRawBuffer(static_cast(host_val.s), nullptr) }); + + auto path_val = impl::natvis::get_val(&inspectable, L"{9E365E57-48B2-4160-956F-C7385120BBFC}", 7); + hstring path_expected = uri.Path(); + REQUIRE(path_expected == hstring{ WindowsGetStringRawBuffer(static_cast(path_val.s), nullptr) }); + + auto scheme_val = impl::natvis::get_val(&inspectable, L"{9E365E57-48B2-4160-956F-C7385120BBFC}", 11); + hstring scheme_expected = uri.SchemeName(); + REQUIRE(scheme_expected == hstring{ WindowsGetStringRawBuffer(static_cast(scheme_val.s), nullptr) }); +} + +#endif // _DEBUG diff --git a/test/test_cpp20_module/numerics.cpp b/test/test_cpp20_module/numerics.cpp new file mode 100644 index 000000000..0f7dcc7fb --- /dev/null +++ b/test/test_cpp20_module/numerics.cpp @@ -0,0 +1,129 @@ +#include "pch.h" + +#if __has_include() + +import std; +import winrt.Windows.Foundation; +import winrt.Windows.Foundation.Numerics; + +// +// These tests exercise the SDK numerics types (float2, float3, etc.) from +// . These are exported by winrt_numerics and +// transitively available from winrt_base (and thus any namespace module). +// The Point/Size ↔ float2 conversions and name_v/category specializations +// are compiled in winrt_base. +// + +using namespace winrt; +using namespace winrt::Windows::Foundation; +using namespace winrt::Windows::Foundation::Numerics; + +// --- SDK math types (from winrt_numerics, re-exported via winrt_base) --- + +TEST_CASE("module_numerics_float2") +{ + float2 a{ 1.0f, 2.0f }; + float2 b{ 3.0f, 4.0f }; + + auto c = a + b; + REQUIRE(c.x == 4.0f); + REQUIRE(c.y == 6.0f); + + REQUIRE(length(a) > 0.0f); +} + +TEST_CASE("module_numerics_float3") +{ + float3 v{ 1.0f, 0.0f, 0.0f }; + float3 up{ 0.0f, 1.0f, 0.0f }; + + REQUIRE(dot(v, up) == 0.0f); + REQUIRE(cross(v, up).z != 0.0f); +} + +TEST_CASE("module_numerics_float4x4") +{ + auto identity = float4x4::identity(); + REQUIRE(identity.m11 == 1.0f); + REQUIRE(identity.m12 == 0.0f); + + auto t = make_float4x4_translation({ 10.0f, 20.0f, 30.0f }); + REQUIRE(t.m41 == 10.0f); +} + +TEST_CASE("module_numerics_quaternion") +{ + auto identity = quaternion::identity(); + REQUIRE(identity.w == 1.0f); + REQUIRE(length(identity) == 1.0f); +} + +// --- Point/Size ↔ float2 conversions (compiled in winrt_base) --- + +TEST_CASE("module_numerics_point_from_float2") +{ + Point p(float2{ 3.0f, 7.0f }); + REQUIRE(p.X == 3.0f); + REQUIRE(p.Y == 7.0f); +} + +TEST_CASE("module_numerics_point_to_float2") +{ + float2 v = Point{ 10.0f, 20.0f }; + REQUIRE(v.x == 10.0f); + REQUIRE(v.y == 20.0f); +} + +TEST_CASE("module_numerics_size_from_float2") +{ + Size s(float2{ 100.0f, 200.0f }); + REQUIRE(s.Width == 100.0f); + REQUIRE(s.Height == 200.0f); +} + +TEST_CASE("module_numerics_size_to_float2") +{ + float2 v = Size{ 640.0f, 480.0f }; + REQUIRE(v.x == 640.0f); + REQUIRE(v.y == 480.0f); +} + +// --- WinRT projection metadata (name_v/category, compiled in winrt_base) --- +// Verify that the projection machinery produces correct IReference GUIDs +// for numerics types. This exercises name_v, category, and the SHA-1 based +// GUID computation across module boundaries, at compile time. + +namespace +{ + constexpr bool equal(guid const& left, guid const& right) noexcept + { + return left.Data1 == right.Data1 && + left.Data2 == right.Data2 && + left.Data3 == right.Data3 && + left.Data4[0] == right.Data4[0] && + left.Data4[1] == right.Data4[1] && + left.Data4[2] == right.Data4[2] && + left.Data4[3] == right.Data4[3] && + left.Data4[4] == right.Data4[4] && + left.Data4[5] == right.Data4[5] && + left.Data4[6] == right.Data4[6] && + left.Data4[7] == right.Data4[7]; + } +} + +#define REQUIRE_EQUAL_GUID(left, ...) STATIC_REQUIRE(equal(guid(left), guid_of<__VA_ARGS__>())); + +TEST_CASE("module_numerics_ireference_guids") +{ + REQUIRE_EQUAL_GUID("48F6A69E-8465-57AE-9400-9764087F65AD", IReference); + REQUIRE_EQUAL_GUID("1EE770FF-C954-59CA-A754-6199A9BE282C", IReference); + REQUIRE_EQUAL_GUID("A5E843C9-ED20-5339-8F8D-9FE404CF3654", IReference); + REQUIRE_EQUAL_GUID("76358CFD-2CBD-525B-A49E-90EE18247B71", IReference); + REQUIRE_EQUAL_GUID("DACBFFDC-68EF-5FD0-B657-782D0AC9807E", IReference); + REQUIRE_EQUAL_GUID("B27004BB-C014-5DCE-9A21-799C5A3C1461", IReference); + REQUIRE_EQUAL_GUID("46D542A1-52F7-58E7-ACFC-9A6D364DA022", IReference); +} + +#undef REQUIRE_EQUAL_GUID + +#endif // __has_include() diff --git a/test/test_cpp20_module/pch.cpp b/test/test_cpp20_module/pch.cpp new file mode 100644 index 000000000..1d9f38c57 --- /dev/null +++ b/test/test_cpp20_module/pch.cpp @@ -0,0 +1 @@ +#include "pch.h" diff --git a/test/test_cpp20_module/pch.h b/test/test_cpp20_module/pch.h new file mode 100644 index 000000000..d0eb301ac --- /dev/null +++ b/test/test_cpp20_module/pch.h @@ -0,0 +1,3 @@ +#pragma once + +#include "catch.hpp" diff --git a/test/test_cpp20_module/range_for.cpp b/test/test_cpp20_module/range_for.cpp new file mode 100644 index 000000000..962c97179 --- /dev/null +++ b/test/test_cpp20_module/range_for.cpp @@ -0,0 +1,135 @@ +#include "pch.h" + +import std; +import winrt.Windows.Foundation.Collections; + +// +// These tests confirm that C++/WinRT collections support range-based for loop iteration +// and structured bindings when consumed via modules. +// + +using namespace winrt; +using namespace Windows::Foundation::Collections; + +TEST_CASE("module_range_for_IIterable") +{ + IIterable c = single_threaded_vector({ 1, 2, 3 }); + std::vector result; + + for (int i : c) + { + result.push_back(i); + } + + REQUIRE(result.size() == 3); + REQUIRE(result[0] == 1); + REQUIRE(result[1] == 2); + REQUIRE(result[2] == 3); +} + +TEST_CASE("module_range_for_IVector") +{ + IVector c = single_threaded_vector({ 1, 2, 3 }); + std::vector result; + + for (int i : c) + { + result.push_back(i); + } + + REQUIRE(result.size() == 3); + REQUIRE(result[0] == 1); + REQUIRE(result[1] == 2); + REQUIRE(result[2] == 3); +} + +TEST_CASE("module_range_for_IVectorView") +{ + IVectorView c = single_threaded_vector({ 1, 2, 3 }).GetView(); + std::vector result; + + for (int i : c) + { + result.push_back(i); + } + + REQUIRE(result.size() == 3); + REQUIRE(result[0] == 1); + REQUIRE(result[1] == 2); + REQUIRE(result[2] == 3); +} + +TEST_CASE("module_structured_bindings_IKeyValuePair") +{ + std::map values + { + { 1, L"one"}, + { 2, L"two"}, + { 3, L"three"}, + }; + + IIterable> c = single_threaded_map(std::map(values)); + std::map result; + + for (IKeyValuePair i : c) + { + result[i.Key()] = i.Value(); + + // Structured binding on IKeyValuePair + auto const [key, value] = i; + REQUIRE(key == i.Key()); + REQUIRE(value == i.Value()); + } + + REQUIRE(result == values); + + // Range-for with structured bindings + result.clear(); + + for (auto&& [key, value] : c) + { + result[key] = value; + } + + REQUIRE(result == values); +} + +TEST_CASE("module_range_for_IMap") +{ + std::map values + { + { 1, L"one" }, + { 2, L"two" }, + { 3, L"three" }, + }; + + IMap c = single_threaded_map(std::map(values)); + std::map result; + + for (auto&& [key, value] : c) + { + result[key] = value; + } + + REQUIRE(result == values); +} + +TEST_CASE("module_range_for_IMapView") +{ + std::map values + { + { 1, L"one" }, + { 2, L"two" }, + { 3, L"three" }, + }; + + IMapView c = single_threaded_map(std::map(values)).GetView(); + std::map result; + + for (auto&& [key, value] : c) + { + result[key] = value; + } + + REQUIRE(result == values); +} diff --git a/test/test_cpp20_module/source_location.cpp b/test/test_cpp20_module/source_location.cpp new file mode 100644 index 000000000..ebf5139c3 --- /dev/null +++ b/test/test_cpp20_module/source_location.cpp @@ -0,0 +1,13 @@ +#include "pch.h" + +import std; +import winrt.Windows.Foundation; + +TEST_CASE("module_source_location") +{ + // Verify that slim_source_location works across the module boundary + auto loc = winrt::impl::slim_source_location::current(); + REQUIRE(loc.line() > 0); + std::string_view file(loc.file_name()); + REQUIRE(file.find("source_location.cpp") != std::string_view::npos); +} diff --git a/test/test_cpp20_module/test_cpp20_module.vcxproj b/test/test_cpp20_module/test_cpp20_module.vcxproj new file mode 100644 index 000000000..f5c20a35d --- /dev/null +++ b/test/test_cpp20_module/test_cpp20_module.vcxproj @@ -0,0 +1,114 @@ + + + + + Debug + ARM64 + + + Debug + Win32 + + + Release + ARM64 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + {B8E3A5CE-4E91-4F27-9B02-E0CAF7E10D72} + test_cpp20_module + test_cpp20_module + 10.0 + v145 + + + + Application + v145 + + + true + + + false + true + + + + + + + + + $(IntDir)Generated Files\ + + + + Use + pch.h + stdcpplatest + $(CppWinRTGenDir);..\;%(AdditionalIncludeDirectories) + NOMINMAX;%(PreprocessorDefinitions) + Level4 + true + 5311 + /bigobj + true + true + + + Console + ole32.lib;windowsapp.lib;%(AdditionalDependencies) + + + "$(CppWinRTDir)cppwinrt.exe" -in local -out "$(CppWinRTGenDir)." -modules -base -verbose -module_include "Windows.Foundation" -module_exclude "Windows.Foundation.Diagnostics" + + + + + + + CompileAsCppModule + true + NotUsing + + + + + + + + + + Create + + + NotUsing + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/test_cpp20_no_sourcelocation/custom_error.cpp b/test/test_cpp20_no_sourcelocation/custom_error.cpp index 43e5f16d9..d9905ea04 100644 --- a/test/test_cpp20_no_sourcelocation/custom_error.cpp +++ b/test/test_cpp20_no_sourcelocation/custom_error.cpp @@ -53,7 +53,7 @@ TEST_CASE("custom_error_logger") REQUIRE(s_loggerArgs.functionName == nullptr); REQUIRE(s_loggerArgs.returnAddress); - REQUIRE(s_loggerArgs.result == 0x80000018); // E_ILLEGAL_DELEGATE_ASSIGNMENT) + REQUIRE(s_loggerArgs.result == static_cast(0x80000018)); // E_ILLEGAL_DELEGATE_ASSIGNMENT) // Remove global handler winrt_throw_hresult_handler = nullptr; diff --git a/test/test_cpp20_no_sourcelocation/test_cpp20_no_sourcelocation.vcxproj b/test/test_cpp20_no_sourcelocation/test_cpp20_no_sourcelocation.vcxproj index c71cfdc96..85c3e1532 100644 --- a/test/test_cpp20_no_sourcelocation/test_cpp20_no_sourcelocation.vcxproj +++ b/test/test_cpp20_no_sourcelocation/test_cpp20_no_sourcelocation.vcxproj @@ -1,10 +1,6 @@ - - Debug - ARM - Debug ARM64 @@ -13,10 +9,6 @@ Debug Win32 - - Release - ARM - Release ARM64 @@ -46,10 +38,6 @@ Application true - - Application - true - Application true @@ -59,11 +47,6 @@ false true - - Application - false - true - Application false @@ -86,18 +69,12 @@ - - - - - - @@ -112,6 +89,8 @@ WINRT_NO_SOURCE_LOCATION;%(PreprocessorDefinitions) + Level4 + true @@ -156,25 +135,6 @@ - - - Disabled - $(OutputPath);Generated Files;..\ - NOMINMAX;_MBCS;%(PreprocessorDefinitions) - MultiThreadedDebug - - - Console - - - - - - - - - - Disabled @@ -236,29 +196,6 @@ - - - MaxSpeed - true - true - $(OutputPath);Generated Files;..\ - NOMINMAX;_MBCS;%(PreprocessorDefinitions) - MultiThreaded - - - Console - true - true - - - - - - - - - - MaxSpeed diff --git a/test/test_fast/Nomadic.cpp b/test/test_fast/Nomadic.cpp index 98753c06d..c29150e17 100644 --- a/test/test_fast/Nomadic.cpp +++ b/test/test_fast/Nomadic.cpp @@ -11,7 +11,15 @@ hstring invoke_by_interface_vtable_offset(Nomadic const& nomadic, ptrdiff_t offs // that IInspectable has 6 functions in total (including those inherited from IUnknown) auto insp = static_cast<::IInspectable*>(get_abi(nomadic)); auto vtable = *reinterpret_cast(insp); + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wmicrosoft-cast" +#endif auto fn_ptr = static_cast(vtable[6 + offset]); +#ifdef __clang__ +#pragma clang diagnostic pop +#endif HSTRING hstr; check_hresult(fn_ptr(insp, &hstr)); diff --git a/test/test_fast/test_fast.vcxproj b/test/test_fast/test_fast.vcxproj index c256cad6b..c01907348 100644 --- a/test/test_fast/test_fast.vcxproj +++ b/test/test_fast/test_fast.vcxproj @@ -1,10 +1,6 @@ - - Debug - ARM - Debug ARM64 @@ -13,10 +9,6 @@ Debug Win32 - - Release - ARM - Release ARM64 @@ -45,10 +37,6 @@ Application true - - Application - true - Application true @@ -58,11 +46,6 @@ false true - - Application - false - true - Application false @@ -85,18 +68,12 @@ - - - - - - @@ -115,6 +92,8 @@ $(OutputPath);Generated Files;..\; WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreaded + Level4 + true Console @@ -136,25 +115,8 @@ $(OutputPath);Generated Files;..\; WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreadedDebug - - - Console - false - - - $(CppWinRTDir)cppwinrt -in $(OutputPath)test_component_fast.winmd -out "$(ProjectDir)Generated Files" -ref sdk -verbose -fastabi - - - - - - - - - Disabled - $(OutputPath);Generated Files;..\; - WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions) - MultiThreadedDebug + Level4 + true Console @@ -174,6 +136,8 @@ $(OutputPath);Generated Files;..\; WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreadedDebug + Level4 + true Console @@ -193,6 +157,8 @@ $(OutputPath);Generated Files;..\; WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreadedDebug + Level4 + true Console @@ -214,29 +180,8 @@ $(OutputPath);Generated Files;..\; WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreaded - - - Console - true - true - false - - - $(CppWinRTDir)cppwinrt -in $(OutputPath)test_component_fast.winmd -out "$(ProjectDir)Generated Files" -ref sdk -verbose -fastabi - - - - - - - - - MaxSpeed - true - true - $(OutputPath);Generated Files;..\; - WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions) - MultiThreaded + Level4 + true Console @@ -260,6 +205,8 @@ $(OutputPath);Generated Files;..\; WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreaded + Level4 + true Console diff --git a/test/test_fast_fwd/test_fast_fwd.vcxproj b/test/test_fast_fwd/test_fast_fwd.vcxproj index c01406e38..6d049b1a9 100644 --- a/test/test_fast_fwd/test_fast_fwd.vcxproj +++ b/test/test_fast_fwd/test_fast_fwd.vcxproj @@ -1,10 +1,6 @@ - - Debug - ARM - Debug ARM64 @@ -13,10 +9,6 @@ Debug Win32 - - Release - ARM - Release ARM64 @@ -67,6 +59,8 @@ true $(CppWinRTDir);$(OutputPath);Generated Files;..\ WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions) + Level4 + true Console @@ -94,6 +88,8 @@ pch.h true WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions) + Level4 + true Console @@ -114,6 +110,8 @@ Disabled $(CppWinRTDir);$(OutputPath);Generated Files;..\ WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions) + Level4 + true Console @@ -126,35 +124,13 @@ - - - Disabled - true - true - $(CppWinRTDir);$(OutputPath);Generated Files;..\ - stdcpp17 - Use - pch.h - true - WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions) - - - Console - windowsapp.lib - - - $(CppWinRTDir)cppwinrt -in $(CppWinRTDir)test_component_fast.winmd -out "$(ProjectDir)Generated Files" -ref sdk -verbose -fastabi - - - - - - Disabled $(CppWinRTDir);$(OutputPath);Generated Files;..\ WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions) + Level4 + true Console @@ -178,6 +154,8 @@ pch.h true WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions) + Level4 + true Console @@ -198,6 +176,8 @@ true $(CppWinRTDir);$(OutputPath);Generated Files;..\ WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions) + Level4 + true Console @@ -212,34 +192,6 @@ - - - MaxSpeed - true - true - true - true - $(CppWinRTDir);$(OutputPath);Generated Files;..\ - stdcpp17 - Use - pch.h - true - WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions) - - - Console - true - true - windowsapp.lib - - - $(CppWinRTDir)cppwinrt -in $(CppWinRTDir)test_component_fast.winmd -out "$(ProjectDir)Generated Files" -ref sdk -verbose -fastabi - - - - - - @@ -325,18 +277,12 @@ false MultiThreaded - - MultiThreaded - MultiThreaded MultiThreaded - - MultiThreadedDebug - MultiThreadedDebug diff --git a/test/test_module_lock_custom/test_module_lock_custom.vcxproj b/test/test_module_lock_custom/test_module_lock_custom.vcxproj index 6bb40e761..64da0d8bc 100644 --- a/test/test_module_lock_custom/test_module_lock_custom.vcxproj +++ b/test/test_module_lock_custom/test_module_lock_custom.vcxproj @@ -1,10 +1,6 @@ - - Debug - ARM - Debug ARM64 @@ -13,10 +9,6 @@ Debug Win32 - - Release - ARM - Release ARM64 @@ -45,10 +37,6 @@ Application true - - Application - true - Application true @@ -58,11 +46,6 @@ false true - - Application - false - true - Application false @@ -85,18 +68,12 @@ - - - - - - @@ -115,6 +92,8 @@ $(OutputPath);Generated Files;..\; NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreaded + Level4 + true Console @@ -136,25 +115,8 @@ $(OutputPath);Generated Files;..\; NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreadedDebug - - - Console - - - - - - - - - - - - - Disabled - $(OutputPath);Generated Files;..\; - NOMINMAX;_MBCS;%(PreprocessorDefinitions) - MultiThreadedDebug + Level4 + true Console @@ -174,6 +136,8 @@ $(OutputPath);Generated Files;..\; NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreadedDebug + Level4 + true Console @@ -193,6 +157,8 @@ $(OutputPath);Generated Files;..\; NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreadedDebug + Level4 + true Console @@ -214,29 +180,8 @@ $(OutputPath);Generated Files;..\; NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreaded - - - Console - true - true - - - - - - - - - - - - - MaxSpeed - true - true - $(OutputPath);Generated Files;..\; - NOMINMAX;_MBCS;%(PreprocessorDefinitions) - MultiThreaded + Level4 + true Console @@ -260,6 +205,8 @@ $(OutputPath);Generated Files;..\; NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreaded + Level4 + true Console diff --git a/test/test_module_lock_none/main.cpp b/test/test_module_lock_none/main.cpp index ca8eab7ac..9648ad8be 100644 --- a/test/test_module_lock_none/main.cpp +++ b/test/test_module_lock_none/main.cpp @@ -57,11 +57,18 @@ TEST_CASE("module_lock_none") // Validates that test_component_base is pinned by virtue of it defining WINRT_NO_MODULE_LOCK. +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wcast-function-type-mismatch" +#endif auto can_unload = reinterpret_cast(GetProcAddress(LoadLibraryA("test_component_base.dll"), "DllCanUnloadNow")); REQUIRE(can_unload() == S_FALSE); auto cannot_unload = reinterpret_cast(GetProcAddress(LoadLibraryA("test_component_derived.dll"), "DllCanUnloadNow")); REQUIRE(cannot_unload() == S_OK); +#ifdef __clang__ +#pragma clang diagnostic pop +#endif } int main(int const argc, char** argv) diff --git a/test/test_module_lock_none/test_module_lock_none.vcxproj b/test/test_module_lock_none/test_module_lock_none.vcxproj index 7f460c6b2..d9242a281 100644 --- a/test/test_module_lock_none/test_module_lock_none.vcxproj +++ b/test/test_module_lock_none/test_module_lock_none.vcxproj @@ -1,10 +1,6 @@ - - Debug - ARM - Debug ARM64 @@ -13,10 +9,6 @@ Debug Win32 - - Release - ARM - Release ARM64 @@ -45,10 +37,6 @@ Application true - - Application - true - Application true @@ -58,11 +46,6 @@ false true - - Application - false - true - Application false @@ -85,18 +68,12 @@ - - - - - - @@ -115,6 +92,8 @@ $(OutputPath);Generated Files;..\ NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreaded + Level4 + true Console @@ -136,25 +115,8 @@ $(OutputPath);Generated Files;..\ NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreadedDebug - - - Console - - - - - - - - - - - - - Disabled - $(OutputPath);Generated Files;..\ - NOMINMAX;_MBCS;%(PreprocessorDefinitions) - MultiThreadedDebug + Level4 + true Console @@ -174,6 +136,8 @@ $(OutputPath);Generated Files;..\ NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreadedDebug + Level4 + true Console @@ -193,6 +157,8 @@ $(OutputPath);Generated Files;..\ NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreadedDebug + Level4 + true Console @@ -214,29 +180,8 @@ $(OutputPath);Generated Files;..\ NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreaded - - - Console - true - true - - - - - - - - - - - - - MaxSpeed - true - true - $(OutputPath);Generated Files;..\ - NOMINMAX;_MBCS;%(PreprocessorDefinitions) - MultiThreaded + Level4 + true Console @@ -260,6 +205,8 @@ $(OutputPath);Generated Files;..\ NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreaded + Level4 + true Console diff --git a/test/test_nocoro/CMakeLists.txt b/test/test_nocoro/CMakeLists.txt new file mode 100644 index 000000000..ee234f146 --- /dev/null +++ b/test/test_nocoro/CMakeLists.txt @@ -0,0 +1,35 @@ +set(CMAKE_CXX_STANDARD 17) + +file(GLOB TEST_SRCS + LIST_DIRECTORIES false + CONFIGURE_DEPENDS + *.cpp +) +list(FILTER TEST_SRCS EXCLUDE REGEX "/(main|pch)\\.cpp") + + +list(APPEND BROKEN_TESTS + # No broken tests. +) + +# Exclude broken tests +foreach(TEST_SRCS_EXCLUDE_ITEM IN LISTS BROKEN_TESTS) + list(FILTER TEST_SRCS EXCLUDE REGEX "/${TEST_SRCS_EXCLUDE_ITEM}\\.cpp") +endforeach() + +add_executable(test_nocoro main.cpp ${TEST_SRCS}) + +target_compile_definitions(test_nocoro PRIVATE WINRT_NO_SOURCE_LOCATION) + +target_precompile_headers(test_nocoro PRIVATE pch.h) +set_source_files_properties( + main.cpp + PROPERTIES SKIP_PRECOMPILE_HEADERS true +) + +add_dependencies(test_nocoro build-cppwinrt-projection) + +add_test( + NAME test_nocoro + COMMAND "$" ${TEST_COLOR_ARG} +) diff --git a/test/test_nocoro/get.cpp b/test/test_nocoro/get.cpp new file mode 100644 index 000000000..4fd85fe3e --- /dev/null +++ b/test/test_nocoro/get.cpp @@ -0,0 +1,114 @@ +#include "pch.h" + +using namespace winrt; +using namespace Windows::Foundation; +using namespace Windows::Storage; + +template +struct async_completion_source : implements, IAsyncOperation, IAsyncInfo> +{ + void set_result(TResult result) + { + m_result = std::move(result); + m_status = AsyncStatus::Completed; + m_completed(*this, m_status); + } + + void Completed(AsyncOperationCompletedHandler completed) + { + m_completed = completed; + } + + AsyncOperationCompletedHandler Completed() const noexcept + { + return m_completed; + } + + TResult GetResults() + { + return m_result.value(); + } + + uint32_t Id() const + { + return 1; + } + + AsyncStatus Status() const + { + return m_status; + } + + hresult ErrorCode() const + { + return hresult(0); // S_OK + } + + void Cancel() const + { + throw hresult_error(0x80070032); // E_NOT_SUPPORTED + } + + void Close() const + { + } + +private: + AsyncStatus m_status = AsyncStatus::Started; + AsyncOperationCompletedHandler m_completed; + std::optional m_result; +}; + +TEST_CASE("get") +{ + auto acs = winrt::make_self>(); + + std::thread worker([acs] + { + std::this_thread::sleep_for(1s); + acs->set_result(0xDEADBEEF); + }); + + worker.detach(); + + REQUIRE(acs.as>().get() == 0xDEADBEEF); +} + +TEST_CASE("get_unchecked") +{ + // Call a real WinRT async operation from an STA thread. + // This is the scenario the new API is designed for: an STA that is not + // presenting UI, where a synchronous blocking wait is safe. + std::exception_ptr failure{}; + bool content_available = false; + std::thread sta_thread([&failure, &content_available] + { + try + { + winrt::init_apartment(winrt::apartment_type::single_threaded); + struct apartment_guard + { + ~apartment_guard() + { + winrt::uninit_apartment(); + } + } guard; + + auto content = PathIO::ReadTextAsync(L"C:\\Windows\\win.ini").get_unchecked(); + content_available = content.size() > 0; + } + catch (...) + { + failure = std::current_exception(); + } + }); + + sta_thread.join(); + + if (failure) + { + std::rethrow_exception(failure); + } + + REQUIRE(content_available); +} diff --git a/test/test_nocoro/main.cpp b/test/test_nocoro/main.cpp new file mode 100644 index 000000000..7590df7e1 --- /dev/null +++ b/test/test_nocoro/main.cpp @@ -0,0 +1,22 @@ +#include +#define CATCH_CONFIG_RUNNER +#include "catch.hpp" +#include "winrt/base.h" + +using namespace winrt; + +int main(int const argc, char** argv) +{ + init_apartment(); + std::set_terminate([] { reportFatal("Abnormal termination"); ExitProcess(1); }); + _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE); + (void)_CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR); + _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE); + (void)_CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR); + return Catch::Session().run(argc, argv); +} + +CATCH_TRANSLATE_EXCEPTION(hresult_error const& e) +{ + return to_string(e.message()); +} diff --git a/test/test_nocoro/pch.cpp b/test/test_nocoro/pch.cpp new file mode 100644 index 000000000..1d9f38c57 --- /dev/null +++ b/test/test_nocoro/pch.cpp @@ -0,0 +1 @@ +#include "pch.h" diff --git a/test/test_nocoro/pch.h b/test/test_nocoro/pch.h new file mode 100644 index 000000000..30a6d3079 --- /dev/null +++ b/test/test_nocoro/pch.h @@ -0,0 +1,7 @@ +#pragma once + +#include "catch.hpp" +#include "winrt/Windows.Foundation.h" +#include "winrt/Windows.Storage.h" + +using namespace std::literals; diff --git a/test/test_nocoro/test_nocoro.vcxproj b/test/test_nocoro/test_nocoro.vcxproj new file mode 100644 index 000000000..7efc28066 --- /dev/null +++ b/test/test_nocoro/test_nocoro.vcxproj @@ -0,0 +1,241 @@ + + + + + Debug + ARM64 + + + Debug + Win32 + + + Release + ARM64 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + {9E392830-805A-4AAF-932D-C493143EFACA} + unittests + test_nocoro + false + + + + Application + true + + + Application + true + + + Application + false + true + + + Application + false + true + + + Application + true + + + Application + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + MaxSpeed + true + true + $(OutputPath);Generated Files;..\ + NOMINMAX;_MBCS;%(PreprocessorDefinitions) + MultiThreaded + Level4 + true + + + Console + true + true + + + + + + + + + + + + + Disabled + $(OutputPath);Generated Files;..\ + NOMINMAX;_MBCS;%(PreprocessorDefinitions) + MultiThreadedDebug + Level4 + true + + + Console + + + + + + + + + + + + + Disabled + $(OutputPath);Generated Files;..\ + NOMINMAX;_MBCS;%(PreprocessorDefinitions) + MultiThreadedDebug + Level4 + true + + + Console + + + + + + + + + + + + + Disabled + $(OutputPath);Generated Files;..\ + NOMINMAX;_MBCS;%(PreprocessorDefinitions) + MultiThreadedDebug + Level4 + true + + + Console + + + + + + + + + + + + + MaxSpeed + true + true + $(OutputPath);Generated Files;..\ + NOMINMAX;_MBCS;%(PreprocessorDefinitions) + MultiThreaded + Level4 + true + + + Console + true + true + + + + + + + + + + + + + MaxSpeed + true + true + $(OutputPath);Generated Files;..\ + NOMINMAX;_MBCS;%(PreprocessorDefinitions) + MultiThreaded + Level4 + true + + + Console + true + true + + + + + + + + + + + + + + + + + NotUsing + + + Create + + + + + + \ No newline at end of file diff --git a/test/test_slow/test_slow.vcxproj b/test/test_slow/test_slow.vcxproj index 75891b64b..5b753a17a 100644 --- a/test/test_slow/test_slow.vcxproj +++ b/test/test_slow/test_slow.vcxproj @@ -1,10 +1,6 @@ - - Debug - ARM - Debug ARM64 @@ -13,10 +9,6 @@ Debug Win32 - - Release - ARM - Release ARM64 @@ -45,10 +37,6 @@ Application true - - Application - true - Application true @@ -58,11 +46,6 @@ false true - - Application - false - true - Application false @@ -85,18 +68,12 @@ - - - - - - @@ -115,6 +92,8 @@ $(OutputPath);Generated Files;..\ WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreaded + Level4 + true Console @@ -135,24 +114,8 @@ $(OutputPath);Generated Files;..\ WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreadedDebug - - - Console - - - $(CppWinRTDir)cppwinrt -in $(OutputPath)test_component_fast.winmd -out "$(ProjectDir)Generated Files" -ref sdk -verbose - - - - - - - - - Disabled - $(OutputPath);Generated Files;..\ - WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions) - MultiThreadedDebug + Level4 + true Console @@ -171,6 +134,8 @@ $(OutputPath);Generated Files;..\ WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreadedDebug + Level4 + true Console @@ -189,6 +154,8 @@ $(OutputPath);Generated Files;..\ WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreadedDebug + Level4 + true Console @@ -209,28 +176,8 @@ $(OutputPath);Generated Files;..\ WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreaded - - - Console - true - true - - - $(CppWinRTDir)cppwinrt -in $(OutputPath)test_component_fast.winmd -out "$(ProjectDir)Generated Files" -ref sdk -verbose - - - - - - - - - MaxSpeed - true - true - $(OutputPath);Generated Files;..\ - WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions) - MultiThreaded + Level4 + true Console @@ -253,6 +200,8 @@ $(OutputPath);Generated Files;..\ WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreaded + Level4 + true Console diff --git a/vsix/Dev16/Component/source.extension.vsixmanifest b/vsix/Dev16/Component/source.extension.vsixmanifest index afd96cf1f..a7ab21972 100644 --- a/vsix/Dev16/Component/source.extension.vsixmanifest +++ b/vsix/Dev16/Component/source.extension.vsixmanifest @@ -29,7 +29,7 @@ - + diff --git a/vsix/Dev16/Standalone/source.extension.vsixmanifest b/vsix/Dev16/Standalone/source.extension.vsixmanifest index e3c2ac995..b38c06cf8 100644 --- a/vsix/Dev16/Standalone/source.extension.vsixmanifest +++ b/vsix/Dev16/Standalone/source.extension.vsixmanifest @@ -29,7 +29,7 @@ - + diff --git a/vsix/Dev16/vsix.Dev16.csproj b/vsix/Dev16/vsix.Dev16.csproj index e9c5d140e..94a6836c3 100644 --- a/vsix/Dev16/vsix.Dev16.csproj +++ b/vsix/Dev16/vsix.Dev16.csproj @@ -41,8 +41,8 @@ %(Filename)%(Extension) true - - Packages\Microsoft.Windows.CppWinRT.$(CppWinRTVersion).nupkg + + Packages\Microsoft.Windows.CppWinRT.$(NugetPackageVersion).nupkg true @@ -84,14 +84,15 @@ - 16.10.31321.278 + 16.10.31321.278 compile; build; native; contentfiles; analyzers; buildtransitive - 17.3.2093 runtime; build; native; contentfiles; analyzers; buildtransitive all + + diff --git a/vsix/Dev17/Component/source.extension.vsixmanifest b/vsix/Dev17/Component/source.extension.vsixmanifest index bcbfa9c8b..063dfcbc7 100644 --- a/vsix/Dev17/Component/source.extension.vsixmanifest +++ b/vsix/Dev17/Component/source.extension.vsixmanifest @@ -35,7 +35,7 @@ - + diff --git a/vsix/Dev17/Standalone/source.extension.vsixmanifest b/vsix/Dev17/Standalone/source.extension.vsixmanifest index 56ea4b86f..89e178c82 100644 --- a/vsix/Dev17/Standalone/source.extension.vsixmanifest +++ b/vsix/Dev17/Standalone/source.extension.vsixmanifest @@ -35,7 +35,7 @@ - + diff --git a/vsix/Dev17/vsix.Dev17.csproj b/vsix/Dev17/vsix.Dev17.csproj index 3ef30ce63..02f3e0bb8 100644 --- a/vsix/Dev17/vsix.Dev17.csproj +++ b/vsix/Dev17/vsix.Dev17.csproj @@ -44,8 +44,8 @@ %(Filename)%(Extension) true - - Packages\Microsoft.Windows.CppWinRT.$(CppWinRTVersion).nupkg + + Packages\Microsoft.Windows.CppWinRT.$(NugetPackageVersion).nupkg true @@ -87,10 +87,10 @@ - + compile; build; native; contentfiles; analyzers; buildtransitive - + runtime; build; native; contentfiles; analyzers; buildtransitive all @@ -168,6 +168,9 @@ + + + diff --git a/vsix/Extension.targets b/vsix/Extension.targets index 7a7b6c2b8..442f03a53 100644 --- a/vsix/Extension.targets +++ b/vsix/Extension.targets @@ -1,8 +1,10 @@ + + @@ -27,7 +29,7 @@ - + diff --git a/vsix/ItemTemplates/BlankPage/BlankPage.h b/vsix/ItemTemplates/BlankPage/BlankPage.h index 58c0f3648..4f7b2b0dd 100644 --- a/vsix/ItemTemplates/BlankPage/BlankPage.h +++ b/vsix/ItemTemplates/BlankPage/BlankPage.h @@ -9,6 +9,7 @@ namespace winrt::$rootnamespace$::implementation $safeitemname$() { // Xaml objects should not call InitializeComponent during construction. + // If a Xaml object needs to access a Xaml property during initialization, it should override InitializeComponent. // See https://github.com/microsoft/cppwinrt/tree/master/nuget#initializecomponent } diff --git a/vsix/ItemTemplates/BlankUserControl/BlankUserControl.h b/vsix/ItemTemplates/BlankUserControl/BlankUserControl.h index 0ab08377a..210b99659 100644 --- a/vsix/ItemTemplates/BlankUserControl/BlankUserControl.h +++ b/vsix/ItemTemplates/BlankUserControl/BlankUserControl.h @@ -13,6 +13,7 @@ namespace winrt::$rootnamespace$::implementation $safeitemname$() { // Xaml objects should not call InitializeComponent during construction. + // If a Xaml object needs to access a Xaml property during initialization, it should override InitializeComponent. // See https://github.com/microsoft/cppwinrt/tree/master/nuget#initializecomponent } diff --git a/vsix/ProjectTemplates/VC/Windows Desktop/ConsoleApplication/ConsoleApplication.vcxproj b/vsix/ProjectTemplates/VC/Windows Desktop/ConsoleApplication/ConsoleApplication.vcxproj index ad52af212..f205306b8 100644 --- a/vsix/ProjectTemplates/VC/Windows Desktop/ConsoleApplication/ConsoleApplication.vcxproj +++ b/vsix/ProjectTemplates/VC/Windows Desktop/ConsoleApplication/ConsoleApplication.vcxproj @@ -10,7 +10,7 @@ Win32Proj $safeprojectname$ $targetplatformversion$ - 10.0.17134.0 + 10.0.18362.0 @@ -67,6 +67,7 @@ $(IntDir)pch.pch _CONSOLE;WIN32_LEAN_AND_MEAN;WINRT_LEAN_AND_MEAN;%(PreprocessorDefinitions) Level4 + true %(AdditionalOptions) /permissive- /bigobj diff --git a/vsix/ProjectTemplates/VC/Windows Desktop/WindowsApplication/WindowsApplication.vcxproj b/vsix/ProjectTemplates/VC/Windows Desktop/WindowsApplication/WindowsApplication.vcxproj index 8b8cb03ce..e4a05cdc7 100644 --- a/vsix/ProjectTemplates/VC/Windows Desktop/WindowsApplication/WindowsApplication.vcxproj +++ b/vsix/ProjectTemplates/VC/Windows Desktop/WindowsApplication/WindowsApplication.vcxproj @@ -67,6 +67,7 @@ $(IntDir)pch.pch _CONSOLE;WIN32_LEAN_AND_MEAN;WINRT_LEAN_AND_MEAN;%(PreprocessorDefinitions) Level4 + true %(AdditionalOptions) /permissive- /bigobj diff --git a/vsix/ProjectTemplates/VC/Windows Universal/BlankApp/BlankApp.vcxproj b/vsix/ProjectTemplates/VC/Windows Universal/BlankApp/BlankApp.vcxproj index af2b41932..ae3d074f2 100644 --- a/vsix/ProjectTemplates/VC/Windows Universal/BlankApp/BlankApp.vcxproj +++ b/vsix/ProjectTemplates/VC/Windows Universal/BlankApp/BlankApp.vcxproj @@ -14,14 +14,10 @@ Windows Store 10.0 $targetplatformversion$ - 10.0.17134.0 + 10.0.18362.0 - - Debug - ARM - Debug ARM64 @@ -34,10 +30,6 @@ Debug x64 - - Release - ARM - Release ARM64 @@ -84,6 +76,7 @@ pch.h $(IntDir)pch.pch Level4 + true %(AdditionalOptions) /bigobj WIN32_LEAN_AND_MEAN;WINRT_LEAN_AND_MEAN;%(PreprocessorDefinitions) diff --git a/vsix/ProjectTemplates/VC/Windows Universal/BlankApp/MainPage.h b/vsix/ProjectTemplates/VC/Windows Universal/BlankApp/MainPage.h index 92e0a689d..366ef6614 100644 --- a/vsix/ProjectTemplates/VC/Windows Universal/BlankApp/MainPage.h +++ b/vsix/ProjectTemplates/VC/Windows Universal/BlankApp/MainPage.h @@ -9,6 +9,7 @@ namespace winrt::$safeprojectname$::implementation MainPage() { // Xaml objects should not call InitializeComponent during construction. + // If a Xaml object needs to access a Xaml property during initialization, it should override InitializeComponent. // See https://github.com/microsoft/cppwinrt/tree/master/nuget#initializecomponent } diff --git a/vsix/ProjectTemplates/VC/Windows Universal/CoreApp/CoreApp.vcxproj b/vsix/ProjectTemplates/VC/Windows Universal/CoreApp/CoreApp.vcxproj index d2f2b002a..2d891ef11 100644 --- a/vsix/ProjectTemplates/VC/Windows Universal/CoreApp/CoreApp.vcxproj +++ b/vsix/ProjectTemplates/VC/Windows Universal/CoreApp/CoreApp.vcxproj @@ -13,14 +13,10 @@ Windows Store 10.0 $targetplatformversion$ - 10.0.17134.0 + 10.0.18362.0 - - Debug - ARM - Debug ARM64 @@ -33,10 +29,6 @@ Debug x64 - - Release - ARM - Release ARM64 @@ -83,6 +75,7 @@ pch.h $(IntDir)pch.pch Level4 + true %(AdditionalOptions) /bigobj WIN32_LEAN_AND_MEAN;WINRT_LEAN_AND_MEAN;%(PreprocessorDefinitions) diff --git a/vsix/ProjectTemplates/VC/Windows Universal/StaticLibrary/StaticLibrary.vcxproj b/vsix/ProjectTemplates/VC/Windows Universal/StaticLibrary/StaticLibrary.vcxproj index 77cc1e005..2afea1c00 100644 --- a/vsix/ProjectTemplates/VC/Windows Universal/StaticLibrary/StaticLibrary.vcxproj +++ b/vsix/ProjectTemplates/VC/Windows Universal/StaticLibrary/StaticLibrary.vcxproj @@ -15,14 +15,10 @@ Windows Store 10.0 $targetplatformversion$ - 10.0.17134.0 + 10.0.18362.0 - - Debug - ARM - Debug ARM64 @@ -35,10 +31,6 @@ Debug x64 - - Release - ARM - Release ARM64 @@ -89,6 +81,7 @@ pch.h $(IntDir)pch.pch Level4 + true %(AdditionalOptions) /bigobj WIN32_LEAN_AND_MEAN;WINRT_LEAN_AND_MEAN;%(PreprocessorDefinitions) $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) diff --git a/vsix/ProjectTemplates/VC/Windows Universal/WindowsRuntimeComponent/WindowsRuntimeComponent.vcxproj b/vsix/ProjectTemplates/VC/Windows Universal/WindowsRuntimeComponent/WindowsRuntimeComponent.vcxproj index 55a39d0dd..da87bf2fb 100644 --- a/vsix/ProjectTemplates/VC/Windows Universal/WindowsRuntimeComponent/WindowsRuntimeComponent.vcxproj +++ b/vsix/ProjectTemplates/VC/Windows Universal/WindowsRuntimeComponent/WindowsRuntimeComponent.vcxproj @@ -14,14 +14,10 @@ Windows Store 10.0 $targetplatformversion$ - 10.0.17134.0 + 10.0.18362.0 - - Debug - ARM - Debug ARM64 @@ -34,10 +30,6 @@ Debug x64 - - Release - ARM - Release ARM64 @@ -88,6 +80,7 @@ pch.h $(IntDir)pch.pch Level4 + true %(AdditionalOptions) /bigobj _WINRT_DLL;WIN32_LEAN_AND_MEAN;WINRT_LEAN_AND_MEAN;%(PreprocessorDefinitions) $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories)