Skip to content

Do not use I as a variable name, since <complex.h> defines it as a macro - #2752

Merged
willend merged 1 commit into
mccode-dev:mainfrom
tkittel:avoid-I-identifier
Oct 5, 2026
Merged

willend merged 1 commit into
mccode-dev:mainfrom
tkittel:avoid-I-identifier

Conversation

@tkittel

@tkittel tkittel commented Oct 5, 2026

Copy link
Copy Markdown
Contributor

Related to compilation failures in the SKADI instrument (which uses both SasView and Union), this PR avoids a temporary workaround with compilation flags that anyway did not work on all platforms. The least intrusive (and only really) solution is to stop using variables named I in components that might be used alongside SasView. I asked Claude to also look elsewhere for I usage, so we are getting fixes in a few contrib components as well just to be sure.

Claude will

Free-form text area

Please describe what your PR is adding in terms of features or bugfixes:

This fixes #2546: instruments combining a SasView sample with Union_master (or Refractor, Mirror_Curved_Bispectral or Mirror_Elliptic_Bispectral) did not compile.

The cause is a clash with a system header. The SasView components include <tgmath.h>, and thereby <complex.h>, which defines I as a macro for the imaginary unit. Every component later in the generated C file which uses I as an identifier then breaks, e.g. Coords I = coords_scale (V, 1 / v_length); in Union_master gives error: expected identifier or '(' before '__extension__'. The workaround used so far, -D__COMPLEX_H__, only works on macOS. It can also change the results of SasView models which use complex numbers, so it shouldn't be used.

The fix: these components no longer use I as a variable name. I searched all McStas and McXtrace components and libraries for declarations of I, and found four:

  • Union_master and Refractor: the local Coords I (the normalised incident direction) is renamed to I_in, next to the existing I_reflect and I_refract. The two comments with the formulas are updated accordingly.
  • Mirror_Curved_Bispectral and Mirror_Elliptic_Bispectral (contrib): I, one of the roots I, J, K of the polynomial, is renamed to I_root.

The changed files are formatted with mccode-clangformat, which only realigns some trailing comments and wraps one line.

Using I as an identifier can not in general be supported or recommended, since it clashes with a system header which McCode does not control. It is not possible to fix this on the SasView side instead, e.g. with #undef I after the include: SasView's own complex number code (cl_complex.h) uses I. So AGENTS.md (section "Complex numbers") now says not to use I as an identifier.

Test results, with McStas 3.9.0 from conda-forge on Linux, and the changed components copied next to the instruments:

  • A test instrument with a SasView sample (SasView_barbell), a minimal Union setup with Union_master, a Refractor, and both mirrors (attached in the comments):
    • with the components of main: 26 compile errors (the I macro);
    • with this PR: it compiles and runs.
  • The SKADI model (ESS), with its SasView frontend and the Union detector model, which hit this problem: it compiles with this PR, without -D__COMPLEX_H__.
  • No change in behaviour:
    • the C code generated for the test instrument without the SasView sample is identical with and without this PR, apart from the renamed variables and one wrapped line;
    • with the same seed, PSI_ICON (the only example using Refractor) and 10 examples using Union_master (ILL_SALSA, Union_NCrystal_example and 8 tests from Tests_union) give identical output with and without this PR. The only exception is the neutron column of the event list of Union_abs_logger_nD_scintillator, which holds uninitialised memory in any run (an unrelated bug in that component).
    • The two mirrors have no example instruments.

Declaration of use of AI-tools

  • Please add a checkmark here if you used AI-tools during the work for this contribution

  • Furter, please describe how / where and for what the tools were used:

    Claude Code (Anthropic, model Claude Opus 5.5) was used, under my direction, to find the cause of the compile errors, to search the components for the identifier, to write the patch, and to run the tests described above.


Development OS / boundary conditions

Please describe what OS you developed and tested your additions on, and if any special dependencies are required:

Developed and tested on Linux (Ubuntu, x86_64) with McStas 3.9.0 from conda-forge. The change only renames variables, so it should behave the same on other platforms, but it has not been tested on Windows or macOS. No new dependencies.


PR Checklist for contributing to McStas/McXtrace

For a coherent and useful contribution to McStas/McXtrace, please fill in relevant parts of the checklist:

  • My contribution includes patches to an existing component file

    • I have used the mcdoc utility and rendered a reasonable documentation page for the component (please attach as screenshot in comments!)

      Not done: the documentation headers are unchanged.

    • I have ensured that basic use of the component is OK (e.g. an instrument using it compiles?)

    • I have used the mctest utility to test one or more instruments making use of the component (please attach mcviewtest report as screenshot in comments)

      Not with mctest, but by comparing the outputs of 11 example instruments with and without this PR (see above).

    • I have used the mccode-clangformat tool to apply the standard McCode component indentation scheme

    • I have used the mcrun --c-lint "linter" and followed advice to remove most / all warnings that are raised

      Not done: the change only renames variables.

  • My contribution includes patches to an existing instrument file

    • Not relevant.
  • My contribution includes a new component file

    • Not relevant.
  • My contribution includes a new instrument file

    • Not relevant.
  • My work touches the code-generator in mccode/src

    • Not relevant.
  • My work touches / adds to the runtime lib code (.c,.h etc in multiple locations

    • Not relevant.
  • My PR is meant to fix a specific, existing issue

  • My contribution contains something else

    • Not relevant.

🤖 Generated with Claude Code

The SasView components include <tgmath.h>, and thereby <complex.h>, which
defines I as a macro for the imaginary unit. So instruments combining a
SasView sample with Union_master, Refractor, Mirror_Curved_Bispectral or
Mirror_Elliptic_Bispectral did not compile, since these declare a variable
called I (issue mccode-dev#2546). The variable is renamed to I_in (the incident
direction, next to I_reflect and I_refract) in Union_master and Refractor,
and to I_root (a root of the polynomial, next to J and K) in the two
mirrors. The changed files are formatted with mccode-clangformat.

Using I as an identifier clashes with a system header, so it can not in
general be supported by McCode; AGENTS.md now says to avoid it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@willend

willend commented Oct 5, 2026

Copy link
Copy Markdown
Contributor

Cool. Merging.

@willend
willend merged commit c2be8e0 into mccode-dev:main Oct 5, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG]: MacOS Compilation Error: Name collision between <complex.h> 's I macro and Coords I variables in components ( Union_master , Refractor )

2 participants