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)
===========================
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
[Python] Issue #1108. Fix platorm inconsistency in Python default argument handling.
32 bit and 64 bit compiled versions of SWIG generated different Python files

View File

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

View File

@ -388,3 +388,42 @@ TCX_PACKED (typedef struct tcxMessageBugImpl
}) 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
}
// Workaround empty first macro argument bug
#define SWIGEMPTYHACK
// Main user macro for defining intrusive_ptr typemaps for both const and non-const pointer types
%define %intrusive_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)
%enddef
%define %intrusive_ptr_no_wrap(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)
%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
%define %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)
%enddef

View File

@ -640,13 +640,8 @@ static List *find_args(String *s, int ismacro, String *macro_name) {
goto unterm;
}
Chop(str);
if (Len(args) || Len(str))
Append(args, str);
Append(args, str);
Delete(str);
/* if (Len(str) && (c != ')'))
Append(args,str); */
if (c == ')')
return args;
c = Getc(s);
@ -817,11 +812,24 @@ static String *expand_macro(String *name, List *args, String *line_file) {
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 (args && (margs) && (Len(margs) != Len(args))) {
if (Len(margs) > (1 + isvarargs))
if (args && (!margs || Len(margs) != Len(args))) {
if (margs && Len(margs) > (1 + 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);
else
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 (!args && (margs) && Len(margs) > 0) {
if (!args && margs) {
macro_level--;
return NewString(name);
}
@ -1156,10 +1164,6 @@ static DOH *Preprocessor_replace(DOH *s) {
args = find_args(s, 1, id);
macro_additional_lines = Getline(s) - line;
assert(macro_additional_lines >= 0);
if (!Len(args)) {
Delete(args);
args = 0;
}
} else {
args = 0;
}