From eaa0062cd22477bb03e0c80800eb253b3767b59e Mon Sep 17 00:00:00 2001 From: Marcelo Matus Date: Thu, 15 Jan 2004 03:16:40 +0000 Subject: [PATCH] Fix for friend declarations, and other 'repeated' declarations. Now, this doesn't generate warnings: class A; class B*; int foo(A*, B*); struct A { friend int foo(A*, B*); }; but this generates struct B { friend double foo(A*, B*); }; which is correct, since they have different return types. See the redefined.i file for most cases where repeated (but not redefined) declarations are not generating warnings now, such as: // no warning #define REPEATED 1 #define REPEATED 1 // yes warning #define REDEFINED 1 #define REDEFINED 2 this is following the C, C++ and preprocessor standard behavior. The function 'need_redefined_warn(..)' was added to util.c, if some strange corner appears, and therefore, the parser.y file doesn't need to be changed latter. Also, the redefined warning format in parser.y was changed, so now it respond to William's -Fmicrosoft flag. git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk/SWIG@5633 626c5289-ae23-0410-ae9c-e8d60b6d4f22 --- Examples/test-suite/common.mk | 1 + Examples/test-suite/redefined.i | 93 +++++++++++++++++++++++++++++++++ Source/CParse/cparse.h | 3 ++ Source/CParse/parser.y | 35 +++++++++---- Source/CParse/util.c | 84 +++++++++++++++++++++++++++++ 5 files changed, 205 insertions(+), 11 deletions(-) create mode 100644 Examples/test-suite/redefined.i 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); +}