Commit Graph

1 Commits

Author SHA1 Message Date
William S Fulton d3a20504be Fix multicharacter constants to have type int, not char
A character constant containing more than one character, e.g. 'ab', has
type int per both the C standard (6.4.4.4p10) and the C++ standard
([lex.ccon], which describes it as a "multicharacter literal"). SWIG
previously classified every character constant as char regardless of
length, which caused the generated wrapper accessor for a constant such
as #define X 'ab' to be declared char instead of int, silently
truncating the value.

The literal text is left untouched (SWIG does not evaluate constant
expressions), only the internal type tag changes, so the real compiler
that builds the generated wrapper still computes the (implementation
defined) value, exactly as it would for hand written C/C++ code.

Add a new C-only multichar_constant.i test case with per-language runme
files, and keep the new csharp/java char_constant runme files (which
had no coverage before) for the existing, unrelated character constant
checks.

Compiling a real multicharacter constant always triggers GCC's
-Wmultichar warning. #pragma GCC diagnostic ignored "-Wmultichar" does
not suppress it: this is a known, longstanding GCC C++ front-end bug
(gcc.gnu.org PR57241/PR53431, fixed in GCC 13) - verified locally that
it fails identically on GCC 11 and 12 regardless of file- or
function-level pragma scope, while working fine in C or with GCC 13+
or Clang (which also defines __GNUC__ but doesn't have this bug).

The new testcase avoids the warning entirely, with no build system
changes needed:

- The %inline global variable imulti_ab uses the real literal (guarded
  by the pragma) wherever that's known to work, and otherwise falls
  back to reconstructing the identical value GCC's own packing of
  'ab' produces (most significant byte first) without writing a
  multicharacter literal at all - the same symbol name and type either
  way, so the generated accessor links correctly regardless of which
  branch was compiled.
- The #define-driven MULTICHAR_AB constant (whose registration code is
  auto-generated per target language, so a similar fallback isn't
  portable to hand-write once for every language) is skipped entirely
  for octave and javascript's node/napi/v8 engines, the only
  configurations that always compile the generated wrapper as C++
  regardless of SWIG's own -c/-c++ mode (their runtime APIs require
  it) and so would otherwise still hit the GCC bug above.

Verified against both GCC 13 (default) and GCC 11 (matching the actual
CI toolchain that originally failed) across all configured languages.

Assisted-by: Claude Code (Sonnet 5)
2026-07-29 19:46:45 +01:00