From bcba55e6f07cb6662a0e442497c99ffa52fdbd28 Mon Sep 17 00:00:00 2001 From: Dave Beazley Date: Tue, 25 Feb 2003 03:26:01 +0000 Subject: [PATCH] Experimental patch for abstract methods git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@4385 626c5289-ae23-0410-ae9c-e8d60b6d4f22 --- SWIG/Source/Modules/allocate.cxx | 42 +++++++- SWIG/Source/Swig/swig.h | 2 + SWIG/Source/Swig/symbol.c | 159 +++++++++++++++++++++++++++---- 3 files changed, 184 insertions(+), 19 deletions(-) diff --git a/SWIG/Source/Modules/allocate.cxx b/SWIG/Source/Modules/allocate.cxx index 4353a107a..f0a00cac4 100644 --- a/SWIG/Source/Modules/allocate.cxx +++ b/SWIG/Source/Modules/allocate.cxx @@ -26,6 +26,31 @@ void Wrapper_virtual_elimination_mode_set(int flag) { virtual_elimination_mode = flag; } +/* Helper function to assist with abstract class checking. + This is a major hack. Sorry. */ + +static String *search_decl = 0; /* Declarator being searched */ +static int check_implemented(Node *n) { + String *local_decl; + if (!n) return 0; + while (n) { + if (Strcmp(nodeType(n), "cdecl") == 0) { + local_decl = Getattr(n,"decl"); + if (local_decl) local_decl = SwigType_typedef_resolve_all(local_decl); + if (local_decl && (Strcmp(local_decl, search_decl) == 0)) { + if (!Getattr(n,"abstract")) { + Delete(local_decl); + return 1; + } + } + Delete(local_decl); + } + n = Getattr(n,"csym:nextSibling"); + } + return 0; +} + + class Allocate : public Dispatcher { Node *inclass; enum AccessMode { PUBLIC, PRIVATE, PROTECTED }; @@ -143,11 +168,16 @@ class Allocate : public Dispatcher { if (base_decl) base_decl = SwigType_typedef_resolve_all(base_decl); if (Strstr(name,"~")) continue; /* Don't care about destructors */ int implemented = 0; - Node *dn = Swig_symbol_clookup(name,0); + /* Node *dn = Swig_symbol_clookup_local(name,0); if (!dn) { Printf(stdout,"node: %x '%s'. base: %x '%s'. member '%s'\n", n, Getattr(n,"name"), base, Getattr(base,"name"), name); } assert(dn != 0); // Assertion of doom + */ + search_decl = base_decl; + Node *dn = Swig_symbol_clookup_local_check(name,0,check_implemented); + + /* while (dn && !implemented) { String *local_decl = Getattr(dn,"decl"); if (local_decl) local_decl = SwigType_typedef_resolve_all(local_decl); @@ -158,10 +188,16 @@ class Allocate : public Dispatcher { Delete(local_decl); dn = Getattr(dn,"csym:nextSibling"); } - if (!implemented && (Getattr(nn,"abstract"))) { + */ + + Delete(base_decl); + + /* if (!implemented && (Getattr(nn,"abstract"))) { return 1; } - Delete(base_decl); + */ + + if (!dn) return 1; /* if (dn && (Getattr(dn,"abstract"))) { return 1; diff --git a/SWIG/Source/Swig/swig.h b/SWIG/Source/Swig/swig.h index 0ab83536e..9ba11f118 100644 --- a/SWIG/Source/Swig/swig.h +++ b/SWIG/Source/Swig/swig.h @@ -281,8 +281,10 @@ extern Symtab *Swig_symbol_popscope(); extern Node *Swig_symbol_add(String_or_char *symname, Node *node); extern void Swig_symbol_cadd(String_or_char *symname, Node *node); extern Node *Swig_symbol_clookup(String_or_char *symname, Symtab *tab); +extern Node *Swig_symbol_clookup_check(String_or_char *symname, Symtab *tab, int (*check)(Node *)); extern Symtab *Swig_symbol_cscope(String_or_char *symname, Symtab *tab); extern Node *Swig_symbol_clookup_local(String_or_char *symname, Symtab *tab); +extern Node *Swig_symbol_clookup_local_check(String_or_char *symname, Symtab *tab, int (*check)(Node *)); extern String *Swig_symbol_qualified(Node *node); extern Node *Swig_symbol_isoverloaded(Node *node); extern void Swig_symbol_remove(Node *node); diff --git a/SWIG/Source/Swig/symbol.c b/SWIG/Source/Swig/symbol.c index 31a6016c3..a92a1d114 100644 --- a/SWIG/Source/Swig/symbol.c +++ b/SWIG/Source/Swig/symbol.c @@ -648,10 +648,14 @@ Swig_symbol_add(String_or_char *symname, Node *n) { * towards the global scope. * * This function operates in the C namespace, not the target namespace. + * + * The check function is an optional callback that can be used to verify a particular + * symbol match. This is only used in some of the more exotic parts of SWIG. For instance, + * verifying that a class hierarchy implements all pure virtual methods. * ----------------------------------------------------------------------------- */ static Node * -symbol_lookup(String_or_char *name, Symtab *symtab) { +symbol_lookup(String_or_char *name, Symtab *symtab, int (*check)(Node *n)) { Node *n; List *inherit; Hash *sym = Getattr(symtab,"csymtab"); @@ -661,15 +665,30 @@ symbol_lookup(String_or_char *name, Symtab *symtab) { n = Getattr(sym,name); if (n) { - Setmark(symtab,0); - return n; + /* if a check-function is defined. Call it to determine a match */ + if (check) { + int c = check(n); + if (c == 1) { + Setmark(symtab,0); + return n; + } + if (c < 0) { + /* Terminate the search right away */ + Setmark(symtab,0); + return 0; + } + } else { + Setmark(symtab,0); + return n; + } } + inherit = Getattr(symtab,"inherit"); if (inherit) { int i,len; len = Len(inherit); for (i = 0; i < len; i++) { - n = symbol_lookup(name, Getitem(inherit,i)); + n = symbol_lookup(name, Getitem(inherit,i),check); if (n) { Setmark(symtab,0); return n; @@ -681,7 +700,7 @@ symbol_lookup(String_or_char *name, Symtab *symtab) { } static Node * -symbol_lookup_qualified(String_or_char *name, Symtab *symtab, String *prefix, int local) { +symbol_lookup_qualified(String_or_char *name, Symtab *symtab, String *prefix, int local, int (*checkfunc)(Node *n)) { /* This is a little funky, we search by fully qualified names */ if (!symtab) return 0; @@ -691,7 +710,7 @@ symbol_lookup_qualified(String_or_char *name, Symtab *symtab, String *prefix, in String *prefix; bname = Swig_scopename_last(name); prefix = Swig_scopename_prefix(name); - n = symbol_lookup_qualified(bname,symtab,prefix,local); + n = symbol_lookup_qualified(bname,symtab,prefix,local,checkfunc); Delete(bname); Delete(prefix); return n; @@ -713,13 +732,13 @@ symbol_lookup_qualified(String_or_char *name, Symtab *symtab, String *prefix, in /* Found a scope match */ if (st) { if (!name) return st; - n = symbol_lookup(name, st); + n = symbol_lookup(name, st,checkfunc); } Delete(qname); if (!n) { if (!local) { Node *pn = parentNode(symtab); - if (pn) n = symbol_lookup_qualified(name,pn, prefix, local); + if (pn) n = symbol_lookup_qualified(name,pn, prefix, local,checkfunc); } else { n = 0; } @@ -757,12 +776,12 @@ Swig_symbol_clookup(String_or_char *name, Symtab *n) { if (Strncmp(name,"::",2) == 0) { String *nname = NewString(Char(name)+2); if (Swig_scopename_check(nname)) { - s = symbol_lookup_qualified(nname,global_scope,0,0); + s = symbol_lookup_qualified(nname,global_scope,0,0,0); } } else { String *prefix = Swig_scopename_prefix(name); if (prefix) { - s = symbol_lookup_qualified(name,hsym,0,0); + s = symbol_lookup_qualified(name,hsym,0,0,0); Delete(prefix); if (!s) { return 0; @@ -772,7 +791,7 @@ Swig_symbol_clookup(String_or_char *name, Symtab *n) { } if (!s) { while (hsym) { - s = symbol_lookup(name,hsym); + s = symbol_lookup(name,hsym,0); if (s) break; hsym = parentNode(hsym); if (!hsym) break; @@ -793,6 +812,73 @@ Swig_symbol_clookup(String_or_char *name, Symtab *n) { return s; } +/* ----------------------------------------------------------------------------- + * Swig_symbol_clookup_check() + * + * This function is identical to Swig_symbol_clookup() except that it + * accepts a callback function that is invoked to determine a symbol match. + * The purpose of this function is to support complicated algorithms that need + * to examine multiple definitions of the same symbol that might appear in an + * inheritance hierarchy. + * ----------------------------------------------------------------------------- */ + +Node * +Swig_symbol_clookup_check(String_or_char *name, Symtab *n, int (*checkfunc)(Node *n)) { + Hash *hsym; + Node *s = 0; + + if (!n) { + hsym = current_symtab; + } else { + if (Strcmp(nodeType(n),"symboltable")) { + n = Getattr(n,"sym:symtab"); + } + assert(n); + if (n) { + hsym = n; + } + } + + if (Swig_scopename_check(name)) { + if (Strncmp(name,"::",2) == 0) { + String *nname = NewString(Char(name)+2); + if (Swig_scopename_check(nname)) { + s = symbol_lookup_qualified(nname,global_scope,0,0,checkfunc); + } + } else { + String *prefix = Swig_scopename_prefix(name); + if (prefix) { + s = symbol_lookup_qualified(name,hsym,0,0,checkfunc); + Delete(prefix); + if (!s) { + return 0; + } + } + } + } + if (!s) { + while (hsym) { + s = symbol_lookup(name,hsym,checkfunc); + if (s) break; + hsym = parentNode(hsym); + if (!hsym) break; + } + } + if (!s) { + return 0; + } + /* Check if s is a 'using' node */ + while (s && Strcmp(nodeType(s),"using") == 0) { + Node *ss; + ss = Swig_symbol_clookup(Getattr(s,"uname"), Getattr(s,"sym:symtab")); + if (!ss && !checkfunc) { + Swig_warning(WARN_PARSE_USING_UNDEF, Getfile(s), Getline(s), "Nothing known about '%s'.\n", Getattr(s,"uname")); + } + s = ss; + } + return s; +} + Node * Swig_symbol_clookup_local(String_or_char *name, Symtab *n) { Hash *h, *hsym; @@ -812,13 +898,13 @@ Swig_symbol_clookup_local(String_or_char *name, Symtab *n) { if (Swig_scopename_check(name)) { if (Strncmp(name,"::",2) == 0) { - s = symbol_lookup_qualified(Char(name)+2,global_scope,0,0); + s = symbol_lookup_qualified(Char(name)+2,global_scope,0,0,0); } else { - s = symbol_lookup_qualified(name,hsym,0,0); + s = symbol_lookup_qualified(name,hsym,0,0,0); } } if (!s) { - s = symbol_lookup(name,hsym); + s = symbol_lookup(name,hsym,0); } if (!s) return 0; /* Check if s is a 'using' node */ @@ -832,6 +918,47 @@ Swig_symbol_clookup_local(String_or_char *name, Symtab *n) { return s; } + +Node * +Swig_symbol_clookup_local_check(String_or_char *name, Symtab *n, int (*checkfunc)(Node *)) { + Hash *h, *hsym; + Node *s = 0; + + if (!n) { + hsym = current_symtab; + h = ccurrent; + } else { + if (Strcmp(nodeType(n),"symboltable")) { + n = Getattr(n,"sym:symtab"); + } + assert(n); + hsym = n; + h = Getattr(n,"csymtab"); + } + + if (Swig_scopename_check(name)) { + if (Strncmp(name,"::",2) == 0) { + s = symbol_lookup_qualified(Char(name)+2,global_scope,0,0,checkfunc); + } else { + s = symbol_lookup_qualified(name,hsym,0,0,checkfunc); + } + } + if (!s) { + s = symbol_lookup(name,hsym,checkfunc); + } + if (!s) return 0; + /* Check if s is a 'using' node */ + while (s && Strcmp(nodeType(s),"using") == 0) { + Node *ss = Swig_symbol_clookup_local_check(Getattr(s,"uname"), Getattr(s,"sym:symtab"),checkfunc); + if (!ss && !checkfunc) { + Swig_warning(WARN_PARSE_USING_UNDEF, Getfile(s), Getline(s), "Nothing known about '%s'.\n", Getattr(s,"uname")); + } + s = ss; + } + return s; +} + + /* ----------------------------------------------------------------------------- * Swig_symbol_cscope() * @@ -840,8 +967,8 @@ Swig_symbol_clookup_local(String_or_char *name, Symtab *n) { Symtab * Swig_symbol_cscope(String_or_char *name, Symtab *symtab) { - if (Strncmp(name,"::",2) == 0) return symbol_lookup_qualified(0, global_scope, name, 0); - return symbol_lookup_qualified(0,symtab,name,0); + if (Strncmp(name,"::",2) == 0) return symbol_lookup_qualified(0, global_scope, name, 0,0); + return symbol_lookup_qualified(0,symtab,name,0,0); } /* -----------------------------------------------------------------------------