diff --git a/CHANGES.current b/CHANGES.current index 76180b9ae..7e9ecfdca 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -1,6 +1,59 @@ Version 1.3.23 (in progress) ============================ +10/31/2004: mmatus + - Solve namespace + class declarations, as in + + namespace foo { + struct Bar; + struct Foo { + }; + } + + struct foo::Bar : Foo { + }; + + see namespace_class.i for more examples. + + - Fix %template directive to properly use namespaces, + including the case: + + namespace one + { + template + struct Ptr {}; + } + + namespace one + { + struct Obj1 {}; + typedef Ptr Obj1_ptr; + %template(Obj1_ptr) Ptr; + } + + namespace two + { + struct Obj2 {}; + typedef one::Ptr Obj2_ptr; + %template(Obj2_ptr) one::Ptr; + } + + this is done by using the namespace name 'one' to create + a namespace node to emit the template instantiation, + just as before, but the template parameters are resolved + and qualified in the current namespace ('one' or 'two'). + This is same way that typedef works. + + This resolve the smart_pointer_namespace2.i case, and at + the same time, several other ones where before swig was + generating the + + "Can't instantiate template 'xx' inside namespace 'yy'" + + error message. In fact, that error doesn't exist + anymore. You can only get an error if you use a bad + namespace name or so. + 10/30/2004: mmatus - [ruby] Directors fixes: - enums and std::strings are working now (several diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index db269e4cd..97828f3ce 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -46,8 +46,7 @@ LIBPREFIX = lib # Broken C++ test cases. (Can be run individually using make testcase.cpptest.) CPP_TEST_BROKEN += \ namespace_union \ - overload_complicated \ - smart_pointer_namespace2 + overload_complicated # Broken C test cases. (Can be run individually using make testcase.ctest.) C_TEST_BROKEN += \ @@ -157,6 +156,7 @@ CPP_TEST_CASES += \ name_cxx \ name_inherit \ name_warnings \ + namespace_class \ namespace_enum \ namespace_extend \ namespace_nested \ @@ -187,6 +187,7 @@ CPP_TEST_CASES += \ smart_pointer_multi \ smart_pointer_multi_typedef \ smart_pointer_namespace \ + smart_pointer_namespace2 \ smart_pointer_not \ smart_pointer_overload \ smart_pointer_protected \ diff --git a/Examples/test-suite/namespace_class.i b/Examples/test-suite/namespace_class.i new file mode 100644 index 000000000..77b6a8b9d --- /dev/null +++ b/Examples/test-suite/namespace_class.i @@ -0,0 +1,150 @@ +%module namespace_class + +%inline %{ + template void foobar(T t) {} + namespace test { + template void barfoo(T t) {} + } +%} + +%template(FooBarInt) ::foobar; +%template(BarFooInt) test::barfoo; + + +%inline %{ + + namespace test { + enum Hello { + Hi + }; + + struct Test; + + struct Bar { + Hello foo(Hello h) { + return h; + } + }; + + namespace hola { + struct Bor; + struct Foo; + struct Foobar; + template struct BarT { + }; + + template class FooT; + } + + template + class hola::FooT { + public: + Hello foo(Hello h) { + return h; + } + + T bar(T h) { + return h; + } + }; + + namespace hola { + template <> class FooT; + template <> class FooT; + } + + template <> + class hola::FooT { + public: + double moo(double h) { + return h; + } + }; + + int a; + + struct hola::Foo : Bar { + Hello bar(Hello h) { + return h; + } + }; + } + + struct test::Test { + Hello foo(Hello h) { + return h; + } + }; + + struct test::hola::Bor { + Hello foo(Hello h) { + return h; + } + }; + + namespace test { + struct hola::Foobar : Bar { + Hello bar(Hello h) { + return h; + } + }; + } + + template <> + class test::hola::FooT { + public: + int quack(int h) { + return h; + } + }; + +%} + + +namespace test +{ + namespace hola { + %template(FooT_i) FooT; + } + + %template(FooT_H) hola::FooT; +} + +%template(FooT_d) test::hola::FooT; +%template(BarT_H) test::hola::BarT; + +%inline %{ + + namespace hi { + namespace hello { + template struct PooT; + } + + namespace hello { + template struct PooT + { + }; + } + } +%} + +%template(Poo_i) hi::hello::PooT; + +%inline %{ + + template struct BooT { + }; + + namespace test { + + typedef ::BooT BooT_H; + } + +%} + +namespace test { + + %template(BooT_H) ::BooT; +} +%template(BooT_i) ::BooT; + diff --git a/Source/CParse/cparse.h b/Source/CParse/cparse.h index fdc997056..758f65a83 100644 --- a/Source/CParse/cparse.h +++ b/Source/CParse/cparse.h @@ -57,9 +57,9 @@ extern int need_redefined_warn(Node* a, Node* b, int InClass); /* templ.c */ -extern void Swig_cparse_template_defargs(Parm *parms, Parm *targs); -extern int Swig_cparse_template_expand(Node *n, String *rname, ParmList *tparms); -extern Node *Swig_cparse_template_locate(String *name, ParmList *tparms); +extern void Swig_cparse_template_defargs(Parm *parms, Parm *targs, Symtab *tscope); +extern int Swig_cparse_template_expand(Node *n, String *rname, ParmList *tparms, Symtab *tscope); +extern Node *Swig_cparse_template_locate(String *name, ParmList *tparms, Symtab *tscope); extern void Swig_cparse_debug_templates(int); #ifdef __cplusplus diff --git a/Source/CParse/parser.y b/Source/CParse/parser.y index b9a509958..e37814f92 100644 --- a/Source/CParse/parser.y +++ b/Source/CParse/parser.y @@ -713,6 +713,102 @@ static void merge_extensions(Node *cls, Node *am) { return bases; } + /* If the class name is qualified. We need to create or lookup namespace entries */ +static Node *nspace = 0; +static Node *nspace_inner = 0; +static String *resolve_namespace_class(String *cname) { + nspace = 0; + nspace_inner = 0; + if (Swig_scopename_check(cname)) { + Node *ns; + String *prefix = Swig_scopename_prefix(cname); + String *base = Swig_scopename_last(cname); + if (!prefix) { + /* Use the global scope */ + Symtab *symtab = Swig_symbol_current(); + Node *pn = parentNode(symtab); + while (pn) { + symtab = pn; + pn = parentNode(symtab); + if (!pn) break; + } + Swig_symbol_setscope(symtab); + Namespaceprefix = 0; + nspace = new_node("namespace"); + Setattr(nspace,"symtab", symtab); + nspace_inner = nspace; + return base; + } + /* Try to locate the scope */ + ns = Swig_symbol_clookup(prefix,0); + if (!ns) { + Swig_error(cparse_file,cparse_line,"Undefined scope '%s'\n", prefix); + } else { + if (Strcmp(nodeType(ns),"namespace") != 0) { + Swig_error(cparse_file,cparse_line,"'%s' is not defined as namespace.\n", prefix); + ns = 0; + } else { + Symtab *nscope = Getattr(ns,"symtab"); + String *tname = Swig_symbol_qualifiedscopename(0); + String *nname = Swig_symbol_qualifiedscopename(nscope); + if (tname && (Strcmp(tname,nname) == 0)) { + ns = 0; + cname = base; + } + Delete(tname); + Delete(nname); + } + if (ns) { + List *scopes; + String *sname; + Iterator si; + String *name = NewString(prefix); + scopes = NewList(); + while (name) { + String *base = Swig_scopename_last(name); + String *tprefix = Swig_scopename_prefix(name); + Insert(scopes,0,base); + Delete(name); + name = tprefix; + } + for (si = First(scopes); si.item; si = Next(si)) { + Node *ns1,*ns2; + sname = si.item; + ns1 = Swig_symbol_clookup(sname,0); + assert(ns1); + if (Strcmp(nodeType(ns1),"namespace") == 0) { + if (Getattr(ns1,"alias")) { + ns1 = Getattr(ns1,"namespace"); + } + } else { + assert(0); + } + ns2 = new_node("namespace"); + Setattr(ns2,"name",sname); + Setattr(ns2,"symtab", Getattr(ns1,"symtab")); + add_symbols(ns2); + Swig_symbol_setscope(Getattr(ns1,"symtab")); + Namespaceprefix = Swig_symbol_qualifiedscopename(0); + if (nspace_inner) { + if (Getattr(nspace_inner,"symtab") != Getattr(ns2,"symtab")) { + appendChild(nspace_inner,ns2); + } + } + nspace_inner = ns2; + if (!nspace) nspace = ns2; + } + cname = base; + } + } + Delete(prefix); + } + return cname; +} + + + + + /* Structures for handling code fragments built for nested classes */ typedef struct Nested { @@ -2049,7 +2145,6 @@ types_directive : TYPES LPAREN parms RPAREN SEMI { template_directive: SWIGTEMPLATE LPAREN idstringopt RPAREN idcolonnt LESSTHAN valparms GREATERTHAN SEMI { Parm *p, *tp; Node *n; - Node *nspace = 0, *nspace_inner = 0; Node *tnode = 0; Symtab *tscope = 0; int specialized = 0; @@ -2058,78 +2153,17 @@ template_directive: SWIGTEMPLATE LPAREN idstringopt RPAREN idcolonnt LESSTHAN va tscope = Swig_symbol_current(); /* Get the current scope */ - /* If the template name is qualified. We need to create or lookup namespace entries */ - if (Swig_scopename_check($5)) { - String *prefix, *base; - Node *ns; - prefix = Swig_scopename_prefix($5); - base = Swig_scopename_last($5); + /* If the class name is qualified. We need to create or lookup namespace entries */ + $5 = resolve_namespace_class($5); + + /* + we use the new namespace entry 'nspace' only to + emit the template node. The template parameters are + resolved in the current 'tscope'. - /* Try to locate the scope */ - ns = Swig_symbol_clookup(prefix,0); - if (!ns) { - Swig_error(cparse_file,cparse_line,"Undefined scope '%s'\n", prefix); - } else { - if (Strcmp(nodeType(ns),"namespace") != 0) { - Swig_error(cparse_file,cparse_line,"'%s' is not defined as namespace.\n", prefix); - ns = 0; - } else { - /* Swig_symbol_setscope(Getattr(ns,"symtab")); - Namespaceprefix = Swig_symbol_qualifiedscopename(0); */ - } - } - - if (ns && Namespaceprefix) { - Swig_error(cparse_file,cparse_line, - "Can't instantiate template '%s' inside namespace '%s'.\n" - "Suggest moving %%template outside the namespace.\n", $5, Namespaceprefix); - - } - - /* Create namespace nodes to enclose the template declaration */ - if (ns) { - List *scopes; - String *sname; - Iterator si; - String *name = NewString(prefix); - scopes = NewList(); - while (name) { - String *tprefix; - String *base = Swig_scopename_last(name); - Insert(scopes,0,base); - tprefix = Swig_scopename_prefix(name); - Delete(name); - name = tprefix; - } - for (si = First(scopes); si.item; si = Next(si)) { - Node *ns1,*ns2; - sname = si.item; - ns1 = Swig_symbol_clookup(sname,0); - assert(ns1); - if (Strcmp(nodeType(ns1),"namespace") == 0) { - if (Getattr(ns1,"alias")) { - ns1 = Getattr(ns1,"namespace"); - } - } else { - assert(0); - } - ns2 = new_node("namespace"); - Setattr(ns2,"name",sname); - Setattr(ns2,"symtab", Getattr(ns1,"symtab")); - add_symbols(ns2); - Swig_symbol_setscope(Getattr(ns1,"symtab")); - Namespaceprefix = Swig_symbol_qualifiedscopename(0); - if (nspace_inner) { - appendChild(nspace_inner,ns2); - } - nspace_inner = ns2; - if (!nspace) nspace = ns2; - } - $5 = base; - } - } - - n = Swig_cparse_template_locate($5,$7); + this is closer to the C++ (typedef) behavior. + */ + n = Swig_cparse_template_locate($5,$7,tscope); /* Patch the argument types to respect namespaces */ p = $7; @@ -2139,17 +2173,17 @@ template_directive: SWIGTEMPLATE LPAREN idstringopt RPAREN idcolonnt LESSTHAN va SwigType *ty = Getattr(p,"type"); if (ty) { if (template_reduce) { - SwigType *rty = Swig_symbol_typedef_reduce(ty,0); - ty = Swig_symbol_type_qualify(rty,0); + SwigType *rty = Swig_symbol_typedef_reduce(ty,tscope); + ty = Swig_symbol_type_qualify(rty,tscope); Setattr(p,"type",ty); Delete(rty); } else { - ty = Swig_symbol_type_qualify(ty,0); + ty = Swig_symbol_type_qualify(ty,tscope); Setattr(p,"type",ty); } } } else { - value = Swig_symbol_type_qualify(value,0); + value = Swig_symbol_type_qualify(value,tscope); Setattr(p,"value",value); } @@ -2217,12 +2251,12 @@ template_directive: SWIGTEMPLATE LPAREN idstringopt RPAREN idcolonnt LESSTHAN va Setattr(templnode,"sym:typename","1"); } if ($3) { - Swig_cparse_template_expand(templnode,$3,temparms); + Swig_cparse_template_expand(templnode,$3,temparms,tscope); Setattr(templnode,"sym:name",$3); } else { static int cnt = 0; String *nname = NewStringf("__dummy_%d__", cnt++); - Swig_cparse_template_expand(templnode,nname,temparms); + Swig_cparse_template_expand(templnode,nname,temparms,tscope); Setattr(templnode,"sym:name",nname); if (!Swig_template_extmode()) { Setattr(templnode,"feature:ignore","1"); @@ -2644,6 +2678,13 @@ cpp_class_decl : /* A simple class/struct/union definition */ storage_class cpptype idcolon inherit LBRACE { List *bases = 0; + + /* preserve the current scope */ + prev_symtab = Swig_symbol_current(); + + /* If the class name is qualified. We need to create or lookup namespace entries */ + $3 = resolve_namespace_class($3); + class_rename = make_name($3,0); Classprefix = NewString($3); /* Deal with inheritance */ @@ -2700,6 +2741,7 @@ cpp_class_decl : } cpp_members RBRACE cpp_opt_declarators { Node *p; SwigType *ty; + Symtab *cscope = prev_symtab; Node *am = 0; inclass = 0; $$ = new_node("class"); @@ -2768,12 +2810,23 @@ cpp_class_decl : } Setattr($$,"symtab",Swig_symbol_popscope()); - yyrename = NewString(class_rename); Classprefix = 0; - Namespaceprefix = Swig_symbol_qualifiedscopename(0); + if (nspace) { + appendChild(nspace_inner,$$); + Swig_symbol_setscope(Getattr(nspace_inner,"symtab")); + Namespaceprefix = Swig_symbol_qualifiedscopename(0); + add_symbols($$); + $$ = nspace; + Swig_symbol_setscope(cscope); + Namespaceprefix = Swig_symbol_qualifiedscopename(0); + add_symbols($9); + } else { + yyrename = NewString(class_rename); + Namespaceprefix = Swig_symbol_qualifiedscopename(0); - add_symbols($$); - add_symbols($9); + add_symbols($$); + add_symbols($9); + } } /* An unnamed struct, possibly with a typedef */ @@ -2908,6 +2961,23 @@ cpp_template_decl : TEMPLATE LESSTHAN template_parms GREATERTHAN { template_para String *tname = 0; int error = 0; + /* check if we get a namespace node with a class declaration, and retrieve the class */ + Symtab *cscope = Swig_symbol_current(); + Symtab *sti = 0; + Node *ntop = $6; + Node *ni = ntop; + SwigType *ntype = ni ? nodeType(ni) : 0; + while (ni && Strcmp(ntype,"namespace") == 0) { + sti = Getattr(ni,"symtab"); + ni = firstChild(ni); + ntype = nodeType(ni); + } + if (sti) { + Swig_symbol_setscope(sti); + Namespaceprefix = Swig_symbol_qualifiedscopename(0); + $6 = ni; + } + template_parameters = 0; $$ = $6; if ($$) tname = Getattr($$,"name"); @@ -3085,7 +3155,7 @@ cpp_template_decl : TEMPLATE LESSTHAN template_parms GREATERTHAN { template_para fname = SwigType_templateprefix(tname); tparms = SwigType_function_parms(tname); /* add default args from generic template */ - Swig_cparse_template_defargs(tparms, Getattr(tempn,"templateparms")); + Swig_cparse_template_defargs(tparms, Getattr(tempn,"templateparms"),0); Append(fname,"<("); p = tparms; while (p){ @@ -3124,6 +3194,9 @@ cpp_template_decl : TEMPLATE LESSTHAN template_parms GREATERTHAN { template_para Swig_symbol_cadd(fname,$$); } } + $$ = ntop; + Swig_symbol_setscope(cscope); + Namespaceprefix = Swig_symbol_qualifiedscopename(0); if (error) $$ = 0; } | TEMPLATE cpptype idcolon { diff --git a/Source/CParse/templ.c b/Source/CParse/templ.c index c239874b8..7abdeb8bb 100644 --- a/Source/CParse/templ.c +++ b/Source/CParse/templ.c @@ -210,7 +210,7 @@ String *partial_arg(String *s, String *p) { } int -Swig_cparse_template_expand(Node *n, String *rname, ParmList *tparms) { +Swig_cparse_template_expand(Node *n, String *rname, ParmList *tparms, Symtab *tscope) { List *patchlist, *cpatchlist, *typelist; String *templateargs; String *tname; @@ -364,7 +364,7 @@ Swig_cparse_template_expand(Node *n, String *rname, ParmList *tparms) { if (bases) { Iterator b; for (b = First(bases); b.item; b = Next(b)) { - String *qn = Swig_symbol_type_qualify(b.item,0); + String *qn = Swig_symbol_type_qualify(b.item,tscope); Clear(b.item); Append(b.item,qn); } @@ -387,7 +387,7 @@ Swig_cparse_template_expand(Node *n, String *rname, ParmList *tparms) { void -Swig_cparse_template_defargs(Parm *parms, Parm *targs) { +Swig_cparse_template_defargs(Parm *parms, Parm *targs, Symtab *tscope) { if (Len(parms) < Len(targs)) { Parm *lp = parms; Parm *p = lp; @@ -403,7 +403,7 @@ Swig_cparse_template_defargs(Parm *parms, Parm *targs) { Parm *cp; Parm *ta = targs; Parm *p = parms; - SwigType *nt = Swig_symbol_typedef_reduce(value,0); + SwigType *nt = Swig_symbol_typedef_reduce(value,tscope); while(p && ta) { String *name = Getattr(ta,"name"); String *value = Getattr(p,"value"); @@ -412,7 +412,7 @@ Swig_cparse_template_defargs(Parm *parms, Parm *targs) { p = nextSibling(p); ta = nextSibling(ta); } - cp = NewParm(Swig_symbol_type_qualify(nt,0),0); + cp = NewParm(Swig_symbol_type_qualify(nt,tscope),0); set_nextSibling(lp,cp); lp = cp; tp = nextSibling(tp); @@ -432,7 +432,7 @@ Swig_cparse_template_defargs(Parm *parms, Parm *targs) { * ----------------------------------------------------------------------------- */ static Node * -template_locate(String *name, Parm *tparms) { +template_locate(String *name, Parm *tparms, Symtab *tscope) { Node *n; String *tname, *rname = 0; Node *templ; @@ -445,12 +445,12 @@ template_locate(String *name, Parm *tparms) { parms = CopyParmList(tparms); /* Search for generic template */ - templ = Swig_symbol_clookup_local(name,0); + templ = Swig_symbol_clookup(name,0); /* Add default values from generic template */ if (templ) { targs = Getattr(templ,"templateparms"); - Swig_cparse_template_defargs(parms, targs); + Swig_cparse_template_defargs(parms, targs, tscope); } @@ -459,8 +459,8 @@ template_locate(String *name, Parm *tparms) { while (p) { SwigType *ty = Getattr(p,"type"); if (ty) { - SwigType *rt = Swig_symbol_typedef_reduce(ty,0); - SwigType *nt = Swig_symbol_type_qualify(rt,0); + SwigType *rt = Swig_symbol_typedef_reduce(ty,tscope); + SwigType *nt = Swig_symbol_type_qualify(rt,tscope); Setattr(p,"type",nt); Delete(rt); } @@ -616,9 +616,9 @@ template_locate(String *name, Parm *tparms) { * ----------------------------------------------------------------------------- */ Node * -Swig_cparse_template_locate(String *name, Parm *tparms) { +Swig_cparse_template_locate(String *name, Parm *tparms, Symtab *tscope) { Node *n = 0; - n = template_locate(name, tparms); /* this function does what we want for templated classes */ + n = template_locate(name, tparms, tscope); /* this function does what we want for templated classes */ if (n) { int isclass = 0;