Skip to content

COMP: Pass /Zc:__cplusplus when compiling SWIG wrappers with MSVC - #6822

Merged
hjmjohnson merged 1 commit into
InsightSoftwareConsortium:mainfrom
hjmjohnson:comp-msvc-zc-cplusplus-swig
Sep 1, 2026
Merged

COMP: Pass /Zc:__cplusplus when compiling SWIG wrappers with MSVC#6822
hjmjohnson merged 1 commit into
InsightSoftwareConsortium:mainfrom
hjmjohnson:comp-msvc-zc-cplusplus-swig

Conversation

@hjmjohnson

@hjmjohnson hjmjohnson commented Aug 31, 2026

Copy link
Copy Markdown
Member

Problem

The Windows Python wrapping build fails with five C2280 errors, all from one root cause:

itkGradientImageFilterPython.cpp: error C2280:
  'std::unique_ptr<itk::ImageBoundaryCondition<TInputImage,TInputImage>,...>::unique_ptr(const unique_ptr &)':
  attempting to reference a deleted function

Root cause

Not the wrapping declarations. SWIG generates correct code:

std::unique_ptr< itkImageBoundaryConditionIF2 > arg2 ;
...
(&arg2)->reset((itkImageBoundaryConditionIF2 *)argp2);
(arg1)->SetBoundaryCondition(SWIG_STD_MOVE(arg2));

The %unique_ptr(...) typemap applies as intended and the one-argument mangled name resolves against
ImageBoundaryCondition<TInputImage, TInputImage> without trouble, since the default template argument
collapses for SWIG just as it does for C++.

The failure is in SWIG's move guard:

#if __cplusplus >= 201103L
# define SWIG_STD_MOVE(OBJ) std::move(OBJ)
#else
# define SWIG_STD_MOVE(OBJ) OBJ
#endif

MSVC reports __cplusplus as 199711L regardless of /std:c++NN unless /Zc:__cplusplus is given.
ITK passes /std:c++17 but never /Zc:__cplusplus. On MSVC the #else branch therefore wins,
SWIG_STD_MOVE(arg2) degrades from std::move(arg2) to plain arg2, and the by-value std::unique_ptr
parameter is copied.

Measured on the CI toolchain (MSVC 19.38.33145):

Flags __cplusplus SWIG emits
/std:c++17 199711L a copy → C2280
/std:c++17 /Zc:__cplusplus 201703L std::move

GCC and Clang report __cplusplus truthfully and emit std::move, which is why only the MSVC Python
wrapping build is affected. It is not that other platforms wrap a different instantiation set.

GradientImageFilter::SetBoundaryCondition (added in 6203371) is simply the first wrapped method to take
a std::unique_ptr by value, so it is the first to trip a pre-existing gap in the MSVC wrapper flags rather
than the cause of it.

Fix

Add /Zc:__cplusplus to the MSVC wrapper compile flags, alongside the /wd4244 /wd4996 already there. This
is scoped to the SWIG-generated wrapper sources, so it does not change how ITK itself is compiled, and it
covers any other SWIG feature gated on __cplusplus rather than only this call site.

No .wrap file or header change is required; the generated .cpp is unchanged by this fix.

Verification

Reproduced and fixed on Windows, MSVC 19.38.33145 (VS 2022, toolset 14.38), Ninja, Release x64, against
main at 2bdb783.

Before:

itkGradientImageFilterPython.cpp(4512): error C2280: ... attempting to reference a deleted function

After: ITKImageGradientPython builds and links clean — 0 errors, 0 C2280, producing
_ITKImageGradientPython.pyd. SWIG did not regenerate the .cpp; only the compile flags changed, confirming
this is purely a flag defect.

Scope of verification: the reproduction used a reduced wrapping configuration
(Module_ITKImageGradient only, ITK_WRAP_float=ON, ITK_WRAP_IMAGE_DIMS=2;3) to keep the turnaround short.
The flag applies to every wrapper target, so a full ITK_WRAP_PYTHON build is the appropriate regression
check before merging; that has not been run here.

AI assistance
  • Tool: Claude Code (claude-opus-5)
  • Role: root-cause analysis, hypothesis testing
  • Contribution: traced the C2280 past the wrapping declarations to
    SWIG's SWIG_STD_MOVE guard, and measured __cplusplus with and
    without /Zc:__cplusplus on the CI toolchain to confirm
  • Reproduced and verified locally on Windows/MSVC before committing

@github-actions github-actions Bot added type:Compiler Compiler support or related warnings area:Python wrapping Python bindings for a class labels Aug 31, 2026
@hjmjohnson
hjmjohnson force-pushed the comp-msvc-zc-cplusplus-swig branch from a19985b to 8b09530 Compare August 31, 2026 14:22
@hjmjohnson
hjmjohnson marked this pull request as ready for review August 31, 2026 14:55
@greptile-apps

greptile-apps Bot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The MSVC Python wrapper build flags now include /Zc:__cplusplus, allowing generated wrappers to report the configured C++ language version correctly while retaining the existing generated-code warning suppressions.

Confidence Score: 5/5

No blocking failure remains.

The focused CMake check exercised the MSVC wrapper-target configuration and confirmed that the generated target retains both existing warning suppressions and receives the new C++ conformance option.

T-Rex T-Rex Logs

What T-Rex did

  • Reviewed the focused MSVC wrapper target property harness used for both captures.
  • Validated the baseline wrapper target flags before the added C++ conformance option, confirming exit code 0 and the baseline flags.
  • Validated the PR-path wrapper target flags after the added C++ conformance option, confirming exit code 0 and all three expected flags.
  • Confirmed the harness executable used for the captures was the exact focused harness and that no repository-tracked file was modified.

View all artifacts

T-Rex Ran code and verified through T-Rex

Reviews (2): Last reviewed commit: "COMP: Pass /Zc:__cplusplus when compilin..." | Re-trigger Greptile

Comment thread Wrapping/macro_files/itk_end_wrap_module.cmake Outdated

@dzenanz dzenanz left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Greptile is right. This comment does not need to be that long. The full explanation is in the commit message. A suggested solution is provided inline. Otherwise seems like a good fix.

Comment thread Wrapping/macro_files/itk_end_wrap_module.cmake Outdated
MSVC reports __cplusplus as 199711L regardless of /std:c++NN unless
/Zc:__cplusplus is given. SWIG guards its move support on
__cplusplus >= 201103L, so SWIG_STD_MOVE(x) silently degraded from
std::move(x) to x, and every wrapped method taking a std::unique_ptr
by value failed to compile.

GradientImageFilter::SetBoundaryCondition is the first such method, so
the Windows Python wrapping build broke with

  itkGradientImageFilterPython.cpp: error C2280:
    'std::unique_ptr<itk::ImageBoundaryCondition<...>>::unique_ptr(
    const unique_ptr &)': attempting to reference a deleted function

GCC and Clang report __cplusplus truthfully and emit std::move, which
is why only the MSVC Python wrapping build was affected.

The flag joins the existing MSVC wrapper flags, so it is scoped to the
generated wrapper sources and does not change how ITK itself is built.
It also covers any other SWIG feature gated on __cplusplus.
@hjmjohnson
hjmjohnson force-pushed the comp-msvc-zc-cplusplus-swig branch from 8b09530 to 9ceb493 Compare September 1, 2026 00:34
@hjmjohnson
hjmjohnson merged commit 445b19d into InsightSoftwareConsortium:main Sep 1, 2026
15 of 17 checks passed
@hjmjohnson

Copy link
Copy Markdown
Member Author

@greptileai review

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:Python wrapping Python bindings for a class type:Compiler Compiler support or related warnings

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants