diff --git a/CHANGES.current b/CHANGES.current index c8b0aa184..6a3089efe 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,26 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.2.0 (in progress) =========================== +2023-11-09: olly + #2591 SWIG now supports command line options -std=cXX and + -std=c++XX to specify the C/C++ standards version. The only effect + of these options is to set appropriate values for __STDC_VERSION__ + and __cplusplus respectively, which is useful if you're wrapping + headers which have preprocessor checks based on their values. + +2023-11-09: olly + SWIG now defines __STDC__ to 1 to match the behaviour of ISO C/C++ + compilers - previously it had an empty value. + + *** POTENTIAL INCOMPATIBILITY *** + +2023-11-09: olly + When -c++ is used, SWIG now defines __cplusplus to be 199711L (the + value for C++98) by default - previously its value was set to + __cplusplus. + + *** POTENTIAL INCOMPATIBILITY *** + 2023-11-08: emmenlau #2480 [C#] Add std_unordered_map.i for wrapping std::std_unordered_map, implementing C# System.Collections.Generic.IDictionary<>. @@ -555,22 +575,6 @@ Version 4.2.0 (in progress) purpose in over 20 years, and has never been documented outside of CHANGES. -2023-05-18: olly - SWIG now defines __STDC__ to 1 to match the behaviour of ISO C/C++ - compilers, rather than to have an empty value. - - *** POTENTIAL INCOMPATIBILITY *** - -2023-05-18: olly - #2591 The value of __cplusplus SWIG defines can now be overridden - on the command line, e.g. using -D__cplusplus=201103L which is - useful if you're wrapping headers which have preprocessor checks - based on its value. By default SWIG now defines __cplusplus to - 199711L (the value for C++98) rather than setting its value to - be __cplusplus. - - *** POTENTIAL INCOMPATIBILITY *** - 2023-05-18: olly #2591 Add new -U command line option to undefine a preprocessor symbol. diff --git a/Doc/Manual/Preprocessor.html b/Doc/Manual/Preprocessor.html index e04cbe82d..ac61bf8e7 100644 --- a/Doc/Manual/Preprocessor.html +++ b/Doc/Manual/Preprocessor.html @@ -164,8 +164,9 @@ In addition, SWIG defines the following set of standard C/C++ macros:
__LINE__ Current line number __FILE__ Current file name -__STDC__ Defined to indicate ISO C -__cplusplus Defined when -c++ option used +__STDC__ Defined to indicate ISO C/C++ +__cplusplus Defined when -c++ option used, value controlled by -std=c++NN +__STDC_VERSION__ May be defined when -c++ option is not used, value controlled by -std=cNN@@ -177,13 +178,16 @@ have an empty value.
Since SWIG 4.2.0, __cplusplus is defined to 199711L -(the value for C++98) but you can override this by defining it -explicitly on the SWIG command line if you are wrapping headers -which have preprocessor checks based on its value (e.g. use --D__cplusplus=201103L to set it to the value for C++11). -Before this SWIG always defined it to have the value -__cplusplus and attempting to use -D__cplusplus -to change this gave an error. +(the value for C++98) by default. Before this SWIG always defined it to have +the value __cplusplus. +
+ ++Since SWIG 4.2.0, SWIG supports command line options -std=cXX and +-std=c++XX to specify the C/C++ standards version. The only effect of +these options is to set appropriate values for __STDC_VERSION__ and +__cplusplus respectively, which is useful if you're wrapping +headers which have preprocessor checks based on their values.
diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index 9fa50e492..9946fbc3e 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -375,6 +375,7 @@ CPP_TEST_CASES += \ pointer_reference \ preproc_constants \ preproc_cpp \ + preproc_predefined_stdcpp \ primitive_ref \ private_assign \ proxycode \ @@ -824,6 +825,7 @@ C_TEST_CASES += \ preproc_include \ preproc_line_file \ preproc_predefined \ + preproc_predefined_stdc \ register_par \ ret_by_value \ simple_array \ @@ -853,6 +855,8 @@ MULTI_CPP_TEST_CASES += \ wallkw.cpptest: SWIGOPT += -Wallkw preproc_include.ctest: SWIGOPT += -includeall command_line_define.ctest: SWIGOPT += -DFOO -DBAR=123 -DBAZ -UBAZ -UNOTSET +preproc_predefined_stdc.ctest: SWIGOPT += -std=c23 +preproc_predefined_stdcpp.cpptest: SWIGOPT += -std=c++23 # Allow modules to define temporarily failing tests. C_TEST_CASES := $(filter-out $(FAILING_C_TESTS),$(C_TEST_CASES)) diff --git a/Examples/test-suite/preproc_predefined_stdc.i b/Examples/test-suite/preproc_predefined_stdc.i new file mode 100644 index 000000000..4149611a9 --- /dev/null +++ b/Examples/test-suite/preproc_predefined_stdc.i @@ -0,0 +1,24 @@ +%module preproc_predefined_stdc + +// Test handling of -std=c23 + +// __STDC__ should still have value 1. +#ifndef __STDC__ +# error __STDC__ not defined at SWIG-time +#endif +#if __STDC__-0 != 1 +# error __STDC__ value not 1 at SWIG-time +#endif + +// __cplusplus should not be defined. +#ifdef __cplusplus +# error __cplusplus defined at SWIG-time but should not be +#endif + +// __STDC_VERSION__ should be suitably defined. +#ifndef __STDC_VERSION__ +# error __STDC_VERSION__ not defined at SWIG-time +#endif +#if __STDC_VERSION__ != 202311L +# error __STDC_VERSION__ value not 202311L at SWIG-time +#endif diff --git a/Examples/test-suite/preproc_predefined_stdcpp.i b/Examples/test-suite/preproc_predefined_stdcpp.i new file mode 100644 index 000000000..41aa06114 --- /dev/null +++ b/Examples/test-suite/preproc_predefined_stdcpp.i @@ -0,0 +1,24 @@ +%module preproc_predefined_stdcpp + +// Test handling of -std=c++23 + +// __STDC__ should still have value 1. +#ifndef __STDC__ +# error __STDC__ not defined at SWIG-time +#endif +#if __STDC__-0 != 1 +# error __STDC__ value not 1 at SWIG-time +#endif + +// __STDC_VERSION__ should not be defined. +#ifdef __STDC_VERSION__ +# error __STDC_VERSION__ defined at SWIG-time but should not be +#endif + +// __cplusplus should be suitably defined. +#ifndef __cplusplus +# error __cplusplus not defined at SWIG-time +#endif +#if __cplusplus != 202302L +# error __cplusplus value not 202302L at SWIG-time +#endif diff --git a/Source/Modules/main.cxx b/Source/Modules/main.cxx index b1cecbd81..b72558c48 100644 --- a/Source/Modules/main.cxx +++ b/Source/Modules/main.cxx @@ -210,6 +210,8 @@ static String *external_runtime_name = 0; enum { STAGE1=1, STAGE2=2, STAGE3=4, STAGE4=8, STAGEOVERFLOW=16 }; static List *libfiles = 0; static List *all_output_files = 0; +static const char *stdcpp_define = NULL; +static const char *stdc_define = NULL; /* ----------------------------------------------------------------------------- * check_extension() @@ -463,6 +465,46 @@ static void getoptions(int argc, char *argv[]) { // Undocumented Swig_cparse_cplusplusout(1); Swig_mark_arg(i); + } else if (strncmp(argv[i], "-std=c", 6) == 0) { + const char *std = argv[i] + 6; + if (strncmp(std, "++", 2) == 0) { + std += 2; + if (strcmp(std, "98") == 0 || strcmp(std, "03") == 0) { + stdcpp_define = "__cplusplus 199711L"; + } else if (strcmp(std, "11") == 0) { + stdcpp_define = "__cplusplus 201103L"; + } else if (strcmp(std, "14") == 0) { + stdcpp_define = "__cplusplus 201402L"; + } else if (strcmp(std, "17") == 0) { + stdcpp_define = "__cplusplus 201703L"; + } else if (strcmp(std, "20") == 0) { + stdcpp_define = "__cplusplus 202002L"; + } else if (strcmp(std, "23") == 0) { + stdcpp_define = "__cplusplus 202302L"; + } else { + Printf(stderr, "Unrecognised C++ standard version in option '%s'\n", argv[i]); + Exit(EXIT_FAILURE); + } + } else { + if (strcmp(std, "89") == 0 || strcmp(std, "90") == 0) { + stdc_define = NULL; + } else if (strcmp(std, "95") == 0) { + stdc_define = "__STDC_VERSION__ 199409L"; + } else if (strcmp(std, "99") == 0) { + stdc_define = "__STDC_VERSION__ 199901L"; + } else if (strcmp(std, "11") == 0) { + stdc_define = "__STDC_VERSION__ 201112L"; + } else if (strcmp(std, "17") == 0 || strcmp(std, "18") == 0) { + // Both GCC and clang accept -std=c18 as well as -std=c17. + stdc_define = "__STDC_VERSION__ 201710L"; + } else if (strcmp(std, "23") == 0) { + stdc_define = "__STDC_VERSION__ 202311L"; + } else { + Printf(stderr, "Unrecognised C standard version in option '%s'\n", argv[i]); + Exit(EXIT_FAILURE); + } + } + Swig_mark_arg(i); } else if (strcmp(argv[i], "-fcompact") == 0) { Wrapper_compact_print_mode_set(1); Swig_mark_arg(i); @@ -890,10 +932,28 @@ int SWIG_main(int argc, char *argv[], const TargetLanguageModule *tlm) { Preprocessor_define("SWIG 1", 0); Preprocessor_define("__STDC__ 1", 0); - // Define __cplusplus to the C++98 value, but only if it's not already - // defined so the user to override with e.g. -D__cplusplus=202002L - if (CPlusPlus && !Preprocessor_defined("__cplusplus")) - Preprocessor_define("__cplusplus 199711L", 0); + if (CPlusPlus) { + // Default to C++98. + if (!stdcpp_define) stdcpp_define = "__cplusplus 199711L"; + Preprocessor_define(stdcpp_define, 0); + } else { + if (stdcpp_define) { + Printf(stderr, "Option -std=c++XX was used without -c++\n"); + Exit(EXIT_FAILURE); + } + } + + if (!CPlusPlus) { + // Default to C90 which didn't define __STDC_VERSION__. + if (stdc_define) { + Preprocessor_define(stdc_define, 0); + } + } else { + if (stdc_define) { + Printf(stderr, "Option -std=cXX was used with -c++\n"); + Exit(EXIT_FAILURE); + } + } String *vers = Swig_package_version_hex(); Preprocessor_define(vers, 0);