Remove the -rename option in the Go language support. Do a much

better job of checking for name conflicts.  Ignore conflicting names
with a warning.  Adjust the testsuite accordingly.


git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@12135 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
Ian Lance Taylor 2010-06-17 18:59:26 +00:00
parent 683dafb6d3
commit 2970f53c21
18 changed files with 232 additions and 94 deletions

View File

@ -116,15 +116,6 @@ swig -go -help
or <tt>int64</tt>. The &lt;s&gt; argument should be 32 or 64.</td>
</tr>
<tr>
<td>-rename &lt;old&gt;=&lt;new&gt;</td>
<td>Rename &lt;old%gt; to &lt;new&gt; when processing the C/C++ code
and also the SWIG input file. This is a convenient way to rename
names in the C/C++ code which are the same expect for the first
letter, to avoid conflicts when applying the Go renaming rules
described below.</td>
</tr>
</table>
<H3><a name="Go_outputs"></a>20.2.2 Go Output Files</H3>

View File

@ -5,6 +5,7 @@ This testcase primarily test constant pointers, eg int* const. Only a getter is
%module constant_pointers
%warnfilter(SWIGWARN_TYPEMAP_SWIGTYPELEAK); /* memory leak when setting a ptr/ref variable */
%warnfilter(SWIGWARN_GO_NAME_CONFLICT); /* Ignoring 'Foo' due to Go name ('Foo') conflict with 'foo' */
%inline %{

View File

@ -1,4 +1,7 @@
%module(directors="1") director_finalizer
%warnfilter(SWIGWARN_GO_NAME_CONFLICT); /* Ignoring 'deleteFoo' due to Go name ('DeleteFoo') conflict with '~Foo' */
%{
int status = 0;

View File

@ -43,6 +43,8 @@
%warnfilter(SWIGWARN_RUBY_WRONG_NAME) Instances::memberinstance2;
%warnfilter(SWIGWARN_RUBY_WRONG_NAME) Instances::memberinstance3;
%warnfilter(SWIGWARN_GO_NAME_CONFLICT); /* Ignoring 'one' due to Go name ('ObscureOne') conflict with 'Obscure::One' */
%inline %{
enum { AnonEnum1, AnonEnum2 = 100 };

View File

@ -21,22 +21,6 @@ top_builddir = @top_builddir@
include $(srcdir)/../common.mk
# Custom tests - tests with additional commandline options
constant_pointers.cpptest: SWIGOPT += -rename foo=foofn
director_enum.cpptest: SWIGOPT += -rename Hello=Helloe
director_finalizer.cpptest: SWIGOPT += -rename deleteFoo=deleteFooFn
enum_thorough.cpptest: SWIGOPT += -rename One=Onee -rename Two=Twoe
mixed_types.cpptest: SWIGOPT += -rename Hello=Helloe
overload_simple.cpptest: SWIGOPT += -rename foo=foofn
smart_pointer_extend.cpptest: SWIGOPT += -rename CPtrFoo=CPtrFoos
smart_pointer_member.cpptest: SWIGOPT += -rename Foo=Foos
special_variable_macros.cpptest: SWIGOPT += -rename Name=Names
template_partial_specialization.cpptest: SWIGOPT += -rename b=bfn
template_partial_specialization_typedef.cpptest: SWIGOPT += -rename b=bfn
template_specialization_enum.cpptest: SWIGOPT += -rename Hello=Helloe
preproc.ctest: SWIGOPT += -rename a5=a5c -rename a6=a6c
mod.multicpptest: SWIGOPT += -rename GetC=GetCFn
.SUFFIXES: .cpptest .ctest .multicpptest
# Rules for the different types of tests

View File

@ -3,7 +3,7 @@ package main
import "./director_enum"
type MyFoo struct{} // From director_enum.Foo
func (p *MyFoo) Say_hi(val director_enum.EnumDirectorHelloe) director_enum.EnumDirectorHelloe {
func (p *MyFoo) Say_hi(val director_enum.EnumDirectorHello) director_enum.EnumDirectorHello {
return val
}

View File

@ -3,57 +3,57 @@ package main
import . "./overload_simple"
func main() {
if Foofn(3) != "foo:int" {
if Foo(3) != "foo:int" {
panic("foo(int)")
}
if Foofn(float64(3.0)) != "foo:double" {
if Foo(float64(3.0)) != "foo:double" {
panic("foo(double)")
}
if Foofn("hello") != "foo:char *" {
if Foo("hello") != "foo:char *" {
panic("foo(char *)")
}
f := NewFoo()
f := NewFoos()
b := NewBar()
if Foofn(f) != "foo:Foo *" {
if Foo(f) != "foo:Foo *" {
panic("foo(Foo *)")
}
if Foofn(b) != "foo:Bar *" {
if Foo(b) != "foo:Bar *" {
panic("foo(Bar *)")
}
v := Malloc_void(32)
if Foofn(v) != "foo:void *" {
if Foo(v) != "foo:void *" {
panic("foo(void *)")
}
s := NewSpam()
if s.Foofn(3) != "foo:int" {
if s.Foo(3) != "foo:int" {
panic("Spam::foo(int)")
}
if s.Foofn(float64(3.0)) != "foo:double" {
if s.Foo(float64(3.0)) != "foo:double" {
panic("Spam::foo(double)")
}
if s.Foofn("hello") != "foo:char *" {
if s.Foo("hello") != "foo:char *" {
panic("Spam::foo(char *)")
}
if s.Foofn(f) != "foo:Foo *" {
if s.Foo(f) != "foo:Foo *" {
panic("Spam::foo(Foo *)")
}
if s.Foofn(b) != "foo:Bar *" {
if s.Foo(b) != "foo:Bar *" {
panic("Spam::foo(Bar *)")
}
if s.Foofn(v) != "foo:void *" {
if s.Foo(v) != "foo:void *" {
panic("Spam::foo(void *)")
}

View File

@ -4,7 +4,7 @@ import "fmt"
import . "./smart_pointer_member"
func main() {
f := NewFoos()
f := NewFoo()
f.SetY(1)
if f.GetY() != 1 {
@ -24,7 +24,7 @@ func main() {
panic(0)
}
if b.GetZ() != GetFoosZ() {
if b.GetZ() != GetFooZ() {
panic(0)
}
}

View File

@ -3,7 +3,7 @@ package main
import "./special_variable_macros"
func main() {
name := special_variable_macros.NewNames()
name := special_variable_macros.NewName()
if special_variable_macros.TestFred(name) != "none" {
panic("test failed")
}

View File

@ -3,6 +3,8 @@
%warnfilter(SWIGWARN_RUBY_WRONG_NAME) hi; /* Ruby, wrong constant name */
%warnfilter(SWIGWARN_RUBY_WRONG_NAME) hello; /* Ruby, wrong constant name */
%warnfilter(SWIGWARN_GO_NAME_CONFLICT); /* Ignoring 'hello' due to Go name ('Hello') conflict with 'Hello' */
%inline
{
const void* ref_pointer(const void*& a) {

View File

@ -14,7 +14,10 @@
%warnfilter(SWIGWARN_LANG_OVERLOAD_SHADOW) fid;
#endif
#ifdef SWIGGO
%warnfilter(SWIGWARN_PARSE_KEYWORD) type; // 'type' is a Go keyword, renamed as 'Xtype'
%rename(Foos) Foo;
#endif
#ifndef SWIG_NO_OVERLOAD
%immutable Spam::type;

View File

@ -7,6 +7,8 @@
%warnfilter(SWIGWARN_RUBY_WRONG_NAME) __GMP_HAVE_PROTOTYPES; /* Ruby, wrong constant name */
%warnfilter(SWIGWARN_RUBY_WRONG_NAME) __GMP_HAVE_TOKEN_PASTE; /* Ruby, wrong constant name */
#pragma SWIG nowarn=890 /* lots of Go name conflicts */
/* check __cplusplus case */
%header
%{

View File

@ -1,6 +1,6 @@
%module smart_pointer_member
%warnfilter(SWIGWARN_GO_NAME_CONFLICT); /* Ignoring 'foo' due to Go name ('Foo') conflict with 'Foo' */
%inline %{

View File

@ -3,6 +3,8 @@
// test $typemap() special variable function
// these tests are not typical of how $typemap() should be used, but it checks that it is mostly working
%warnfilter(SWIGWARN_GO_NAME_CONFLICT); /* Ignoring 'NewName' due to Go name ('NewName') conflict with 'Name' */
%inline %{
struct Name {
Name(const char *n="none") : name(n) {}

View File

@ -3,6 +3,7 @@
%warnfilter(SWIGWARN_RUBY_WRONG_NAME) Hello; /* Ruby, wrong class name */
%warnfilter(SWIGWARN_RUBY_WRONG_NAME) Hi; /* Ruby, wrong class name */
%warnfilter(SWIGWARN_GO_NAME_CONFLICT); /* Ignoring 'hello due to Go name ('Hello) conflict with 'Hello' */
%inline %{

View File

@ -258,6 +258,9 @@
/* please leave 870-889 free for PHP */
#define WARN_GO_NAME_CONFLICT 890
/* please leave 890-899 free for Go */
/* Feel free to claim any number in this space that's not currently being used. Just make sure you
add an entry here */

View File

@ -27,8 +27,6 @@ class GO:public Language {
String *soname;
// Size in bits of the C type "long".
int long_type_size;
// Rename directives.
String *renames;
/* Output files */
File *f_c_begin;
@ -90,7 +88,6 @@ public:
go_prefix(NULL),
soname(NULL),
long_type_size(32),
renames(NULL),
f_c_begin(NULL),
f_go_begin(NULL),
f_gc_begin(NULL),
@ -176,26 +173,6 @@ private:
} else {
Swig_arg_error();
}
} else if (strcmp(argv[i], "-rename") == 0) {
if (argv[i + 1] != NULL) {
String *d = NewString(argv[i + 1]);
Replace(d, "=", " ", DOH_REPLACE_FIRST);
Preprocessor_define(d, 0);
if (renames == NULL) {
renames = NewString("");
}
Printv(renames, "#define ", d, "\n", NULL);
Delete(d);
Swig_mark_arg(i);
Swig_mark_arg(i + 1);
++i;
// Prevent SWIG from trying to define this for the
// preprocessor, which breaks if there are multiple
// -rename options.
argv[i] = NULL;
} else {
Swig_arg_error();
}
} else if (strcmp(argv[i], "-help") == 0) {
Printf(stdout, "%s\n", usage);
}
@ -355,9 +332,6 @@ private:
}
Swig_banner(f_c_begin);
if (renames != NULL) {
Printf(f_c_begin, "%s\n", renames);
}
if (directorsEnabled()) {
Printf(f_c_runtime, "#define SWIG_DIRECTORS\n");
@ -560,6 +534,11 @@ private:
}
Delete(c2);
Delete(c1);
if (!checkIgnoredParameters(n, go_name)) {
Delete(go_name);
return SWIG_NOWRAP;
}
} else if (Cmp(nodetype, "constructor") == 0) {
is_ctor_dtor = true;
@ -612,23 +591,28 @@ private:
}
go_name = buildGoName(name, is_static, is_friend);
if (!checkIgnoredParameters(n, go_name)) {
Delete(go_name);
return SWIG_NOWRAP;
}
}
String *overname = NULL;
if (Getattr(n, "sym:overloaded")) {
overname = Getattr(n, "sym:overname");
} else if (class_name == NULL || is_static) {
if (!addSymbol(go_name, n)) {
return SWIG_ERROR;
}
} else {
String *c = Copy(class_name);
Putc('+', c);
Append(c, go_name);
if (!addSymbol(c, n)) {
return SWIG_ERROR;
String *scope;
if (class_name == NULL || is_static || is_ctor_dtor) {
scope = NULL;
} else {
scope = NewString("swiggoscope.");
Append(scope, class_name);
}
if (!checkNameConflict(go_name, n, scope)) {
Delete(go_name);
return SWIG_NOWRAP;
}
Delete(c);
}
String *wname = Swig_name_wrapper(name);
@ -646,6 +630,18 @@ private:
}
if (Getattr(n, "sym:overloaded") && Getattr(n, "sym:nextSibling") == NULL) {
String *scope ;
if (class_name == NULL || is_static || is_ctor_dtor) {
scope = NULL;
} else {
scope = NewString("swiggoscope.");
Append(scope, class_name);
}
if (!checkNameConflict(go_name, n, scope)) {
Delete(go_name);
return SWIG_NOWRAP;
}
String *receiver = class_receiver;
if (is_static || is_ctor_dtor) {
receiver = NULL;
@ -1563,11 +1559,6 @@ private:
String *go_name = buildGoName(Getattr(n, "sym:name"), false, false);
if (!addSymbol(go_name, n)) {
Delete(go_name);
return SWIG_ERROR;
}
String *tm = goType(n, type);
String *value = Getattr(n, "value");
@ -1625,6 +1616,15 @@ private:
}
}
if (!checkNameConflict(go_name, n, NULL)) {
Delete(tm);
Delete(go_name);
if (copy != NULL) {
Delete(copy);
}
return SWIG_NOWRAP;
}
Printv(f_go_wrappers, "const ", go_name, " ", tm, " = ", NULL);
if (SwigType_type(type) == T_STRING) {
Printv(f_go_wrappers, "\"", value, "\"", NULL);
@ -1655,6 +1655,10 @@ private:
String *name = goEnumName(n);
if (Strcmp(name, "int") != 0) {
if (!ImportMode || imported_package == NULL) {
if (!checkNameConflict(name, n, NULL)) {
Delete(name);
return SWIG_NOWRAP;
}
Printv(f_go_wrappers, "type ", name, " int\n", NULL);
} else {
String *nw = NewString("");
@ -1693,6 +1697,18 @@ private:
* ------------------------------------------------------------------------ */
int goComplexConstant(Node *n, SwigType *type) {
String *symname = Getattr(n, "sym:name");
if (symname == NULL) {
symname = Getattr(n, "name");
}
String *varname = buildGoName(symname, true, false);
if (!checkNameConflict(varname, n, NULL)) {
Delete(varname);
return SWIG_NOWRAP;
}
String *get = NewString("");
Printv(get, "result = ", NULL);
@ -1720,11 +1736,6 @@ private:
Printv(get, ";\n", NULL);
Setattr(n, "wrap:action", get);
String *symname = Getattr(n, "sym:name");
if (symname == NULL) {
symname = Getattr(n, "name");
}
String *sname = Copy(symname);
if (class_name != NULL) {
Append(sname, "_");
@ -1747,7 +1758,6 @@ private:
return r;
}
String *varname = buildGoName(symname, true, false);
String *t = goType(n, type);
Printv(f_go_wrappers, "var ", varname, " ", t, " = ", go_name, "()\n", NULL);
@ -1779,6 +1789,12 @@ private:
String *go_name = exportedName(name);
if (!checkNameConflict(go_name, n, NULL)) {
Delete(go_name);
SetFlag(n, "go:conflict");
return SWIG_NOWRAP;
}
String *go_type_name = goCPointerType(Getattr(n, "classtypeobj"), true);
class_name = name;
@ -2452,8 +2468,8 @@ private:
Append(fn_name, go_name);
if (overname == NULL && !is_ignored) {
if (!addSymbol(fn_name, n)) {
return SWIG_ERROR;
if (!checkNameConflict(fn_name, n, NULL)) {
return SWIG_NOWRAP;
}
}
@ -4117,6 +4133,132 @@ private:
return s2;
}
/* ----------------------------------------------------------------------
* checkNameConflict()
*
* Check for a name conflict on the name we are going to use in Go.
* These conflicts are likely because of the enforced
* capitalization. When we find one, issue a warning and return
* false. If the name is OK, return true.
* ---------------------------------------------------------------------- */
bool checkNameConflict(String* name, Node* n, const_String_or_char_ptr scope) {
Node *lk = symbolLookup(name, scope);
if (lk != NULL) {
String *n1 = Getattr(n, "sym:name");
if (n1 == NULL) {
n1 = Getattr(n, "name");
}
String *n2 = Getattr(lk, "sym:name");
if (n2 == NULL) {
n2 = Getattr(lk, "name");
}
Swig_warning(WARN_GO_NAME_CONFLICT, input_file, line_number,
"Ignoring '%s' due to Go name ('%s') conflict with '%s'\n",
n1, name, n2);
return false;
}
bool r = addSymbol(name, n, scope);
assert(r);
return true;
}
/* ----------------------------------------------------------------------
* checkIgnoredParameters()
*
* If any of the parameters of this function, or the return type,
* are ignored due to a name conflict, give a warning and return
* false.
* ---------------------------------------------------------------------- */
bool checkIgnoredParameters(Node *n, String *go_name) {
ParmList *parms = Getattr(n, "parms");
if (parms != NULL) {
Wrapper *dummy = NewWrapper();
emit_attach_parmmaps(parms, dummy);
int parm_count = emit_num_arguments(parms);
Parm *p = parms;
for (int i = 0; i < parm_count; ++i) {
p = getParm(p);
if (!checkIgnoredType(n, go_name, Getattr(p, "type"))) {
DelWrapper(dummy);
return false;
}
p = nextParm(p);
}
DelWrapper(dummy);
}
if (!checkIgnoredType(n, go_name, Getattr(n, "type"))) {
return false;
}
return true;
}
/* ----------------------------------------------------------------------
* checkIgnoredType()
*
* If this type is being ignored due to a name conflict, give a
* warning and return false.
* ---------------------------------------------------------------------- */
bool checkIgnoredType(Node *n, String *go_name, SwigType *type) {
if (hasGoTypemap(type)) {
return true;
}
SwigType *t = SwigType_typedef_resolve_all(type);
bool ret = true;
bool is_conflict = false;
Node *e = Language::enumLookup(t);
if (e != NULL) {
if (GetFlag(e, "go:conflict")) {
is_conflict = true;
}
} else if (SwigType_issimple(t)) {
Node *cn = classLookup(t);
if (cn != NULL) {
if (GetFlag(cn, "go:conflict")) {
is_conflict = true;
}
}
} else if (SwigType_ispointer(t) || SwigType_isarray(t) || SwigType_isqualifier(t) || SwigType_isreference(t)) {
SwigType *r = Copy(t);
if (SwigType_ispointer(r)) {
SwigType_del_pointer(r);
} else if (SwigType_isarray(r)) {
SwigType_del_array(r);
} else if (SwigType_isqualifier(r)) {
SwigType_del_qualifier(r);
} else {
SwigType_del_reference(r);
}
if (!checkIgnoredType(n, go_name, r)) {
ret = false;
}
Delete(r);
}
if (is_conflict) {
String *s = SwigType_str(t, NULL);
Swig_warning(WARN_GO_NAME_CONFLICT, input_file, line_number,
"Ignoring '%s' (Go name '%s') due to Go name conflict for parameter or result type '%s'\n",
Getattr(n, "name"), go_name, s);
Delete(s);
ret = false;
}
Delete(t);
return ret;
}
/* ----------------------------------------------------------------------
* goType()
*
@ -4631,5 +4773,4 @@ Go Options (available with -go)\n\
-go-prefix <p> - Like gccgo -fgo-prefix option\n\
-soname <name> - Set shared library holding C/C++ code to <name>\n\
-longsize <s> - Set size of C/C++ long type--32 or 64 bits\n\
-rename <new>=<old> - Rename symbols from <new> to <old>\n\
\n";

View File

@ -2995,7 +2995,10 @@ void Language::dumpSymbols() {
* ----------------------------------------------------------------------------- */
Node *Language::symbolLookup(String *s, const_String_or_char_ptr scope) {
Hash *symbols = Getattr(symtabs, scope);
Hash *symbols = Getattr(symtabs, scope ? scope : "");
if (symbols == NULL) {
return NULL;
}
return Getattr(symbols, s);
}