Merge pull request #1111 from ojwb/empty-arglist-macros

Fix handling of macro with empty argument list
This commit is contained in:
Olly Betts 2017-10-08 15:34:37 +13:00 • committed by GitHub
commit 59ebe27a95
6 changed files with 68 additions and 24 deletions

View file

@ -6,6 +6,11 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/
Version 4.0.0 (in progress) Version 4.0.0 (in progress)
=========================== ===========================
2017-10-07: olly
Fix preprocessor handling of empty macro arguments to match that of
C/C++ compilers. Fixes https://github.com/swig/swig/pull/1111 and
https://sourceforge.net/p/swig/bugs/826/
2017-10-06: wsfulton 2017-10-06: wsfulton
[Python] Issue #1108. Fix platorm inconsistency in Python default argument handling. [Python] Issue #1108. Fix platorm inconsistency in Python default argument handling.
32 bit and 64 bit compiled versions of SWIG generated different Python files 32 bit and 64 bit compiled versions of SWIG generated different Python files

View file

@ -50,9 +50,9 @@
%shared_ptr(Space::Bottom3) %shared_ptr(Space::Bottom3)
%include "swiginterface.i" %include "swiginterface.i"
SWIG_SHARED_PTR_INTERFACE_TYPEMAPS(SWIGEMPTYHACK, Space::ABase1) SWIG_SHARED_PTR_INTERFACE_TYPEMAPS(, Space::ABase1)
SWIG_SHARED_PTR_INTERFACE_TYPEMAPS(SWIGEMPTYHACK, Space::CBase1) SWIG_SHARED_PTR_INTERFACE_TYPEMAPS(, Space::CBase1)
SWIG_SHARED_PTR_INTERFACE_TYPEMAPS(SWIGEMPTYHACK, Space::CBase2) SWIG_SHARED_PTR_INTERFACE_TYPEMAPS(, Space::CBase2)
%interface_impl(Space::ABase1) %interface_impl(Space::ABase1)
%interface_impl(Space::CBase1) %interface_impl(Space::CBase1)
%interface_impl(Space::CBase2) %interface_impl(Space::CBase2)

View file

@ -388,3 +388,42 @@ TCX_PACKED (typedef struct tcxMessageBugImpl
}) tcxMessageBug; }) tcxMessageBug;
%} %}
// Regression tests for https://github.com/swig/swig/pull/1111
%{
static int foo_func(int x) { return x; }
static int foo_func2() { return 0; }
static int bar_func() { return 0; }
static int baz_func(int a, int b, int c) { return a + b - c; }
%}
%inline %{
#define FOO(X) int foo_func(X);
#define FOO2(X) int foo_func2(X);
#define BAR() int bar_func();
#define BAR2() int bar_func2()
#define BAZ(A,B,C) baz_func(A+0,B,C)
#define FOOVAR(...) foo_func(__VA_ARGS__)
#define BARVAR(...) bar_func(__VA_ARGS__)
#define BAZVAR(...) baz_func(__VA_ARGS__)
// This has probably always worked, but make sure that the fix to accept
// an empty X doesn't cause this case to be incorrectly expanded:
const int FOO = 7;
// BAR was incorrectly expanded here, causing:
// Error: Syntax error in input(1).
const int BAR = 6;
// This has probably always worked, but make sure that the fix to accept
// an empty X doesn't stop a non-empty X from working:
FOO(int x)
// FOO() didn't used to get expanded here, causing:
// Syntax error in input(1).
FOO2()
// Check BAR2() still gets expanded here.
BAR2() {
// Regression test - this used to fail with:
// Error: Macro 'BAZ' expects 3 arguments
BAZ(,2,3);
BARVAR();
FOOVAR(1);
BAZVAR(1,2,3);
return 0;
}
%}

View file

@ -44,18 +44,16 @@ struct SWIG_null_deleter {
%#define SWIG_NO_NULL_DELETER_1 %#define SWIG_NO_NULL_DELETER_1
} }
// Workaround empty first macro argument bug
#define SWIGEMPTYHACK
// Main user macro for defining intrusive_ptr typemaps for both const and non-const pointer types // Main user macro for defining intrusive_ptr typemaps for both const and non-const pointer types
%define %intrusive_ptr(TYPE...) %define %intrusive_ptr(TYPE...)
%feature("smartptr", noblock=1) TYPE { SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > } %feature("smartptr", noblock=1) TYPE { SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > }
SWIG_INTRUSIVE_PTR_TYPEMAPS(SWIGEMPTYHACK, TYPE) SWIG_INTRUSIVE_PTR_TYPEMAPS(, TYPE)
SWIG_INTRUSIVE_PTR_TYPEMAPS(const, TYPE) SWIG_INTRUSIVE_PTR_TYPEMAPS(const, TYPE)
%enddef %enddef
%define %intrusive_ptr_no_wrap(TYPE...) %define %intrusive_ptr_no_wrap(TYPE...)
%feature("smartptr", noblock=1) TYPE { SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > } %feature("smartptr", noblock=1) TYPE { SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > }
SWIG_INTRUSIVE_PTR_TYPEMAPS_NO_WRAP(SWIGEMPTYHACK, TYPE) SWIG_INTRUSIVE_PTR_TYPEMAPS_NO_WRAP(, TYPE)
SWIG_INTRUSIVE_PTR_TYPEMAPS_NO_WRAP(const, TYPE) SWIG_INTRUSIVE_PTR_TYPEMAPS_NO_WRAP(const, TYPE)
%enddef %enddef

View file

@ -49,12 +49,10 @@ struct SWIG_null_deleter {
} }
// Workaround empty first macro argument bug
#define SWIGEMPTYHACK
// Main user macro for defining shared_ptr typemaps for both const and non-const pointer types // Main user macro for defining shared_ptr typemaps for both const and non-const pointer types
%define %shared_ptr(TYPE...) %define %shared_ptr(TYPE...)
%feature("smartptr", noblock=1) TYPE { SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > } %feature("smartptr", noblock=1) TYPE { SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > }
SWIG_SHARED_PTR_TYPEMAPS(SWIGEMPTYHACK, TYPE) SWIG_SHARED_PTR_TYPEMAPS(, TYPE)
SWIG_SHARED_PTR_TYPEMAPS(const, TYPE) SWIG_SHARED_PTR_TYPEMAPS(const, TYPE)
%enddef %enddef

View file

@ -640,13 +640,8 @@ static List *find_args(String *s, int ismacro, String *macro_name) {
goto unterm; goto unterm;
} }
Chop(str); Chop(str);
if (Len(args) || Len(str))
Append(args, str); Append(args, str);
Delete(str); Delete(str);
/* if (Len(str) && (c != ')'))
Append(args,str); */
if (c == ')') if (c == ')')
return args; return args;
c = Getc(s); c = Getc(s);
@ -817,11 +812,24 @@ static String *expand_macro(String *name, List *args, String *line_file) {
Delete(vararg); Delete(vararg);
} }
} }
if (args && margs && Len(margs) == 0 && Len(args) == 1 && Len(Getitem(args, 0)) == 0) {
/* FOO() can invoke a macro defined as FOO(X) as well as one defined FOO().
*
* Handle this by removing the only argument if it's empty and the macro
* expects no arguments.
*
* We don't need to worry about varargs here - a varargs macro will always have
* Len(margs) >= 1, since the varargs are put in the final macro argument.
*/
Delitem(args, 0);
}
/* If there are arguments, see if they match what we were given */ /* If there are arguments, see if they match what we were given */
if (args && (margs) && (Len(margs) != Len(args))) { if (args && (!margs || Len(margs) != Len(args))) {
if (Len(margs) > (1 + isvarargs)) if (margs && Len(margs) > (1 + isvarargs))
Swig_error(macro_start_file, macro_start_line, "Macro '%s' expects %d arguments\n", name, Len(margs) - isvarargs); Swig_error(macro_start_file, macro_start_line, "Macro '%s' expects %d arguments\n", name, Len(margs) - isvarargs);
else if (Len(margs) == (1 + isvarargs)) else if (margs && Len(margs) == (1 + isvarargs))
Swig_error(macro_start_file, macro_start_line, "Macro '%s' expects 1 argument\n", name); Swig_error(macro_start_file, macro_start_line, "Macro '%s' expects 1 argument\n", name);
else else
Swig_error(macro_start_file, macro_start_line, "Macro '%s' expects no arguments\n", name); Swig_error(macro_start_file, macro_start_line, "Macro '%s' expects no arguments\n", name);
@ -830,7 +838,7 @@ static String *expand_macro(String *name, List *args, String *line_file) {
} }
/* If the macro expects arguments, but none were supplied, we leave it in place */ /* If the macro expects arguments, but none were supplied, we leave it in place */
if (!args && (margs) && Len(margs) > 0) { if (!args && margs) {
macro_level--; macro_level--;
return NewString(name); return NewString(name);
} }
@ -1156,10 +1164,6 @@ static DOH *Preprocessor_replace(DOH *s) {
args = find_args(s, 1, id); args = find_args(s, 1, id);
macro_additional_lines = Getline(s) - line; macro_additional_lines = Getline(s) - line;
assert(macro_additional_lines >= 0); assert(macro_additional_lines >= 0);
if (!Len(args)) {
Delete(args);
args = 0;
}
} else { } else {
args = 0; args = 0;
} }