diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index cf32a7e0c..5672081c0 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -174,6 +174,7 @@ CPP_TEST_CASES += \ private_assign \ protected_rename \ pure_virtual \ + redefined \ reference_global_vars \ rename_default \ rename_default \ diff --git a/Examples/test-suite/redefined.i b/Examples/test-suite/redefined.i new file mode 100644 index 000000000..c8f17569b --- /dev/null +++ b/Examples/test-suite/redefined.i @@ -0,0 +1,93 @@ +%module redefined + +#if 1 + // + // All these repeated declarations are not redefinitions, + // and they are valid C++ code, therefore, we skip + // swig redefined warnings. + // +%define uja + aju; +%enddef + +%define uja + aju; +%enddef + +%constant int agua = 0; +%constant int agua = 0; + +%inline %{ + +#define REPEATED 1 +#define REPEATED 1 + +#define MACROREP(x) x +#define MACROREP(x) x + + typedef int Int; + typedef int Int; + + int hello(int); + inline int hello(int) { return 0; }; + + struct Hello + { + typedef int Int; + typedef int Int; + friend int hello(int); + }; + + struct Hello2 + { + typedef int Int; + typedef int Int; + friend int hello(int); + }; + +%} + + +#else + +// +// the %extend directive ALWAYS emits redefined warnings, +// since it is not only introducing a declaration, but a redefinition. +// +%extend Hello { + int hi(int) { return 0; }; +} + +// +// All these repeated declarations are really redefinitions, +// therefore, swig must produce a redefined warning +// + +%constant int agua = 0; +%constant int agua = 1; + + +%inline %{ + +#define REPEATED 1 +#define REPEATED 2 + +#define MACROREP(x) x +#define MACROREP(x) x*2 + + typedef int Int; + typedef double Int; + + int hello(int); + inline double hello(int) { return 0; }; + + struct Hello + { + typedef int Int; + typedef double Int; + friend short hello(int); + int hi(int) { return 0; }; + }; + +%} +#endif diff --git a/Source/CParse/cparse.h b/Source/CParse/cparse.h index a1d217ae8..9c3fd8e80 100644 --- a/Source/CParse/cparse.h +++ b/Source/CParse/cparse.h @@ -49,6 +49,9 @@ extern void Swig_cparse_replace_descriptor(String *s); extern void cparse_normalize_void(Node *); extern int need_protected(Node *n, int dirprot_mode); extern Parm *Swig_cparse_parm(String *s); +extern int need_name_warning(Node *n); +extern int need_redefined_warn(Node* a, Node* b, int InClass); + /* templ.c */ extern int Swig_cparse_template_expand(Node *n, String *rname, ParmList *tparms); diff --git a/Source/CParse/parser.y b/Source/CParse/parser.y index bcf973860..afe2457db 100644 --- a/Source/CParse/parser.y +++ b/Source/CParse/parser.y @@ -271,7 +271,6 @@ static String *make_unnamed() { } /* Return the node name when it requires to emit a name warning */ -extern int need_name_warning(Node *n); static String *name_warning(Node *n,String *name,SwigType *decl) { /* Return in the obvious cases */ if (!namewarn_hash || !name || !need_name_warning(n)) return 0; @@ -375,18 +374,26 @@ static void add_symbols(Node *n) { Setattr(n,"sym:name",symname); } else { String *e = NewString(""); - Printf(e,"Identifier '%s' redeclared (ignored).", symname); + String *en = NewString(""); + String *ec = NewString(""); + Printf(en,"Identifier '%s' redeclared (ignored)", symname); if (Cmp(symname,Getattr(n,"name"))) { - Printf(e," (Renamed from '%s')", SwigType_namestr(Getattr(n,"name"))); + Printf(en," (Renamed from '%s')", SwigType_namestr(Getattr(n,"name"))); } - Printf(e,"\n%s:%d: Previous declaration of '%s'", Getfile(c),Getline(c),symname); + Printf(en,","); + Printf(ec," previous declaration of '%s'", symname); if (Cmp(symname,Getattr(c,"name"))) { - Printf(e," (Renamed from '%s')", SwigType_namestr(Getattr(c,"name"))); + Printf(ec," (Renamed from '%s')", SwigType_namestr(Getattr(c,"name"))); } - /* avoid warning for friend declarations */ - if (!is_friend(n) && !is_friend(c)) - Swig_warning(WARN_PARSE_REDEFINED,Getfile(n), Getline(n),"%s\n", e); + Printf(ec,"."); + if (need_redefined_warn(n, c, inclass)) { + Swig_warning(WARN_PARSE_REDEFINED,Getfile(n),Getline(n),"%s\n",en); + Swig_warning(WARN_PARSE_REDEFINED,Getfile(c),Getline(c),"%s\n",ec); + } + Printf(e,"%s\n%s:%d:%s\n", en, Getfile(c), Getline(c), ec); Setattr(n,"error",e); + Delete(en); + Delete(ec); } } } else { @@ -526,10 +533,16 @@ static void merge_extensions(Node *cls, Node *am) { if (csym != n) { /* Conflict with previous definition. Nuke previous definition */ String *e = NewString(""); - Printf(e,"Identifier '%s' redeclared (ignored).\n", symname); - Printf(e,"%s:%d: Previous definition of tag '%s'", Getfile(n),Getline(n), symname); - Swig_warning(WARN_PARSE_REDEFINED,Getfile(csym), Getline(csym), "%s\n", e); + String *en = NewString(""); + String *ec = NewString(""); + Printf(ec,"Identifier '%s' redeclared (ignored),\n", symname); + Printf(en," %%extend definition of '%s'.", symname); + Swig_warning(WARN_PARSE_REDEFINED,Getfile(csym), Getline(csym), "%s\n", ec); + Swig_warning(WARN_PARSE_REDEFINED,Getfile(n), Getline(n), "%s\n", en); + Printf(e,"%s\n%s:%d:%s\n", ec, Getfile(n), Getline(n), en); Setattr(csym,"error",e); + Delete(en); + Delete(ec); Swig_symbol_remove(csym); /* Remove class definition */ Swig_symbol_add(symname,n); /* Insert extend definition */ } diff --git a/Source/CParse/util.c b/Source/CParse/util.c index ef206f40c..692325130 100644 --- a/Source/CParse/util.c +++ b/Source/CParse/util.c @@ -137,3 +137,87 @@ int need_name_warning(Node *n) } return need; } + + +int are_equivalent_nodes(Node* a, Node* b, int a_inclass) +{ + /* they must have the same type */ + SwigType *ta = nodeType(a); + SwigType *tb = nodeType(b); + if (Cmp(ta, tb) != 0) return 0; + + /* cdecl case */ + if (Cmp(ta, "cdecl") == 0) { + /* typedef */ + String *a_storage = Getattr(a,"storage"); + String *b_storage = Getattr(b,"storage"); + + if ((Cmp(a_storage,"typedef") == 0) + || (Cmp(b_storage,"typedef") == 0)) { + if (Cmp(a_storage, b_storage) == 0) { + String *a_type = (Getattr(a,"type")); + String *b_type = (Getattr(b,"type")); + if (Cmp(a_type, b_type) == 0) return 1; + } + return 0; + } + + /* static functions */ + if ((Cmp(a_storage, "static") == 0) + || (Cmp(b_storage, "static") == 0)) { + if (Cmp(a_storage, b_storage) != 0) return 0; + } + + if (!a_inclass || (Cmp(a_storage,"friend") == 0)) { + /* check declaration */ + String *a_decl = (Getattr(a,"decl")); + String *b_decl = (Getattr(b,"decl")); + if (Cmp(a_decl, b_decl) == 0) { + /* check return type */ + String *a_type = (Getattr(a,"type")); + String *b_type = (Getattr(b,"type")); + if (Cmp(a_type, b_type) == 0) { + /* check parameters */ + Parm *ap = (Getattr(a,"parms")); + Parm *bp = (Getattr(b,"parms")); + int la = Len(ap); + int lb = Len(bp); + + if (la != lb) return 0; + while (ap && bp) { + SwigType *at = Getattr(ap,"type"); + SwigType *bt = Getattr(bp,"type"); + if (Cmp(at, bt) != 0) return 0; + ap = nextSibling(ap); + bp = nextSibling(bp); + } + return 1; + } + } + } + } else { + /* %constant case */ + String *a_storage = Getattr(a,"storage"); + String *b_storage = Getattr(b,"storage"); + if ((Cmp(a_storage, "%constant") == 0) + || (Cmp(b_storage, "%constant") == 0)) { + if (Cmp(a_storage, b_storage) == 0) { + String *a_type = (Getattr(a,"type")); + String *b_type = (Getattr(b,"type")); + if ((Cmp(a_type, b_type) == 0) + && (Cmp(Getattr(a,"value"), Getattr(b,"value")) == 0)) + return 1; + } + return 0; + } + } + return 0; +} + +int need_redefined_warn(Node* a, Node* b, int InClass) +{ + String *a_storage = Getattr(a,"storage"); + String *b_storage = Getattr(b,"storage"); + + return !are_equivalent_nodes(a, b, InClass); +}