Support -std= command line option

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.

Closes #2591
This commit is contained in:
Olly Betts 2023-11-09 11:53:37 +13:00
parent 432daea78c
commit 13eca97013
6 changed files with 149 additions and 29 deletions

View File

@ -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.

View File

@ -164,8 +164,9 @@ In addition, SWIG defines the following set of standard C/C++ macros:
<pre>
__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 <tt>-std=c++NN</tt>
__STDC_VERSION__ May be defined when -c++ option is not used, value controlled by <tt>-std=cNN</tt>
</pre>
</div>
@ -177,13 +178,16 @@ have an empty value.
<p>
Since SWIG 4.2.0, <tt>__cplusplus</tt> is defined to <tt>199711L</tt>
(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
<tt>-D__cplusplus=201103L</tt> to set it to the value for C++11).
Before this SWIG always defined it to have the <b>value</b>
<tt>__cplusplus</tt> and attempting to use <tt>-D__cplusplus</tt>
to change this gave an error.
(the value for C++98) by default. Before this SWIG always defined it to have
the <b>value</b> <tt>__cplusplus</tt>.
</p>
<p>
Since SWIG 4.2.0, SWIG supports command line options <tt>-std=cXX</tt> and
<tt>-std=c++XX</tt> to specify the C/C++ standards version. The only effect of
these options is to set appropriate values for <tt>__STDC_VERSION__</tt> and
<tt>__cplusplus</tt> respectively, which is useful if you're wrapping
headers which have preprocessor checks based on their values.
</p>
<p>

View File

@ -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))

View File

@ -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

View File

@ -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

View File

@ -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);