fixes for namespaces + class declarations + %template directive

git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk/SWIG@6576 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
Marcelo Matus 2004-11-01 08:38:21 +00:00
commit 3fc7b773d9
6 changed files with 377 additions and 100 deletions

View file

@ -1,6 +1,59 @@
Version 1.3.23 (in progress) 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 <typename T>
struct Ptr {};
}
namespace one
{
struct Obj1 {};
typedef Ptr<Obj1> Obj1_ptr;
%template(Obj1_ptr) Ptr<Obj1>;
}
namespace two
{
struct Obj2 {};
typedef one::Ptr<Obj2> Obj2_ptr;
%template(Obj2_ptr) one::Ptr<Obj2>;
}
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 10/30/2004: mmatus
- [ruby] Directors fixes: - [ruby] Directors fixes:
- enums and std::strings are working now (several - enums and std::strings are working now (several

View file

@ -46,8 +46,7 @@ LIBPREFIX = lib
# Broken C++ test cases. (Can be run individually using make testcase.cpptest.) # Broken C++ test cases. (Can be run individually using make testcase.cpptest.)
CPP_TEST_BROKEN += \ CPP_TEST_BROKEN += \
namespace_union \ namespace_union \
overload_complicated \ overload_complicated
smart_pointer_namespace2
# Broken C test cases. (Can be run individually using make testcase.ctest.) # Broken C test cases. (Can be run individually using make testcase.ctest.)
C_TEST_BROKEN += \ C_TEST_BROKEN += \
@ -157,6 +156,7 @@ CPP_TEST_CASES += \
name_cxx \ name_cxx \
name_inherit \ name_inherit \
name_warnings \ name_warnings \
namespace_class \
namespace_enum \ namespace_enum \
namespace_extend \ namespace_extend \
namespace_nested \ namespace_nested \
@ -187,6 +187,7 @@ CPP_TEST_CASES += \
smart_pointer_multi \ smart_pointer_multi \
smart_pointer_multi_typedef \ smart_pointer_multi_typedef \
smart_pointer_namespace \ smart_pointer_namespace \
smart_pointer_namespace2 \
smart_pointer_not \ smart_pointer_not \
smart_pointer_overload \ smart_pointer_overload \
smart_pointer_protected \ smart_pointer_protected \

View file

@ -0,0 +1,150 @@
%module namespace_class
%inline %{
template<class T> void foobar(T t) {}
namespace test {
template<class T> void barfoo(T t) {}
}
%}
%template(FooBarInt) ::foobar<int>;
%template(BarFooInt) test::barfoo<int>;
%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 <class T> struct BarT {
};
template <class T> class FooT;
}
template <class T>
class hola::FooT {
public:
Hello foo(Hello h) {
return h;
}
T bar(T h) {
return h;
}
};
namespace hola {
template <> class FooT<double>;
template <> class FooT<int>;
}
template <>
class hola::FooT<double> {
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<int> {
public:
int quack(int h) {
return h;
}
};
%}
namespace test
{
namespace hola {
%template(FooT_i) FooT<int>;
}
%template(FooT_H) hola::FooT<Hello>;
}
%template(FooT_d) test::hola::FooT<double>;
%template(BarT_H) test::hola::BarT<test::Hello>;
%inline %{
namespace hi {
namespace hello {
template <class T> struct PooT;
}
namespace hello {
template <class T> struct PooT
{
};
}
}
%}
%template(Poo_i) hi::hello::PooT<int>;
%inline %{
template <class T> struct BooT {
};
namespace test {
typedef ::BooT<Hello> BooT_H;
}
%}
namespace test {
%template(BooT_H) ::BooT<Hello>;
}
%template(BooT_i) ::BooT<int>;

View file

@ -57,9 +57,9 @@ extern int need_redefined_warn(Node* a, Node* b, int InClass);
/* templ.c */ /* templ.c */
extern void Swig_cparse_template_defargs(Parm *parms, Parm *targs); extern void Swig_cparse_template_defargs(Parm *parms, Parm *targs, Symtab *tscope);
extern int Swig_cparse_template_expand(Node *n, String *rname, ParmList *tparms); extern int Swig_cparse_template_expand(Node *n, String *rname, ParmList *tparms, Symtab *tscope);
extern Node *Swig_cparse_template_locate(String *name, ParmList *tparms); extern Node *Swig_cparse_template_locate(String *name, ParmList *tparms, Symtab *tscope);
extern void Swig_cparse_debug_templates(int); extern void Swig_cparse_debug_templates(int);
#ifdef __cplusplus #ifdef __cplusplus

View file

@ -713,6 +713,102 @@ static void merge_extensions(Node *cls, Node *am) {
return bases; 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 */ /* Structures for handling code fragments built for nested classes */
typedef struct Nested { 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 { template_directive: SWIGTEMPLATE LPAREN idstringopt RPAREN idcolonnt LESSTHAN valparms GREATERTHAN SEMI {
Parm *p, *tp; Parm *p, *tp;
Node *n; Node *n;
Node *nspace = 0, *nspace_inner = 0;
Node *tnode = 0; Node *tnode = 0;
Symtab *tscope = 0; Symtab *tscope = 0;
int specialized = 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 */ tscope = Swig_symbol_current(); /* Get the current scope */
/* If the template name is qualified. We need to create or lookup namespace entries */ /* If the class name is qualified. We need to create or lookup namespace entries */
if (Swig_scopename_check($5)) { $5 = resolve_namespace_class($5);
String *prefix, *base;
Node *ns;
prefix = Swig_scopename_prefix($5);
base = Swig_scopename_last($5);
/* Try to locate the scope */ /*
ns = Swig_symbol_clookup(prefix,0); we use the new namespace entry 'nspace' only to
if (!ns) { emit the template node. The template parameters are
Swig_error(cparse_file,cparse_line,"Undefined scope '%s'\n", prefix); resolved in the current 'tscope'.
} 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) { this is closer to the C++ (typedef) behavior.
Swig_error(cparse_file,cparse_line, */
"Can't instantiate template '%s' inside namespace '%s'.\n" n = Swig_cparse_template_locate($5,$7,tscope);
"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);
/* Patch the argument types to respect namespaces */ /* Patch the argument types to respect namespaces */
p = $7; p = $7;
@ -2139,17 +2173,17 @@ template_directive: SWIGTEMPLATE LPAREN idstringopt RPAREN idcolonnt LESSTHAN va
SwigType *ty = Getattr(p,"type"); SwigType *ty = Getattr(p,"type");
if (ty) { if (ty) {
if (template_reduce) { if (template_reduce) {
SwigType *rty = Swig_symbol_typedef_reduce(ty,0); SwigType *rty = Swig_symbol_typedef_reduce(ty,tscope);
ty = Swig_symbol_type_qualify(rty,0); ty = Swig_symbol_type_qualify(rty,tscope);
Setattr(p,"type",ty); Setattr(p,"type",ty);
Delete(rty); Delete(rty);
} else { } else {
ty = Swig_symbol_type_qualify(ty,0); ty = Swig_symbol_type_qualify(ty,tscope);
Setattr(p,"type",ty); Setattr(p,"type",ty);
} }
} }
} else { } else {
value = Swig_symbol_type_qualify(value,0); value = Swig_symbol_type_qualify(value,tscope);
Setattr(p,"value",value); Setattr(p,"value",value);
} }
@ -2217,12 +2251,12 @@ template_directive: SWIGTEMPLATE LPAREN idstringopt RPAREN idcolonnt LESSTHAN va
Setattr(templnode,"sym:typename","1"); Setattr(templnode,"sym:typename","1");
} }
if ($3) { if ($3) {
Swig_cparse_template_expand(templnode,$3,temparms); Swig_cparse_template_expand(templnode,$3,temparms,tscope);
Setattr(templnode,"sym:name",$3); Setattr(templnode,"sym:name",$3);
} else { } else {
static int cnt = 0; static int cnt = 0;
String *nname = NewStringf("__dummy_%d__", cnt++); 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); Setattr(templnode,"sym:name",nname);
if (!Swig_template_extmode()) { if (!Swig_template_extmode()) {
Setattr(templnode,"feature:ignore","1"); Setattr(templnode,"feature:ignore","1");
@ -2644,6 +2678,13 @@ cpp_class_decl :
/* A simple class/struct/union definition */ /* A simple class/struct/union definition */
storage_class cpptype idcolon inherit LBRACE { storage_class cpptype idcolon inherit LBRACE {
List *bases = 0; 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); class_rename = make_name($3,0);
Classprefix = NewString($3); Classprefix = NewString($3);
/* Deal with inheritance */ /* Deal with inheritance */
@ -2700,6 +2741,7 @@ cpp_class_decl :
} cpp_members RBRACE cpp_opt_declarators { } cpp_members RBRACE cpp_opt_declarators {
Node *p; Node *p;
SwigType *ty; SwigType *ty;
Symtab *cscope = prev_symtab;
Node *am = 0; Node *am = 0;
inclass = 0; inclass = 0;
$$ = new_node("class"); $$ = new_node("class");
@ -2768,12 +2810,23 @@ cpp_class_decl :
} }
Setattr($$,"symtab",Swig_symbol_popscope()); Setattr($$,"symtab",Swig_symbol_popscope());
yyrename = NewString(class_rename);
Classprefix = 0; 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($$);
add_symbols($9); add_symbols($9);
}
} }
/* An unnamed struct, possibly with a typedef */ /* An unnamed struct, possibly with a typedef */
@ -2908,6 +2961,23 @@ cpp_template_decl : TEMPLATE LESSTHAN template_parms GREATERTHAN { template_para
String *tname = 0; String *tname = 0;
int error = 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; template_parameters = 0;
$$ = $6; $$ = $6;
if ($$) tname = Getattr($$,"name"); if ($$) tname = Getattr($$,"name");
@ -3085,7 +3155,7 @@ cpp_template_decl : TEMPLATE LESSTHAN template_parms GREATERTHAN { template_para
fname = SwigType_templateprefix(tname); fname = SwigType_templateprefix(tname);
tparms = SwigType_function_parms(tname); tparms = SwigType_function_parms(tname);
/* add default args from generic template */ /* 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,"<("); Append(fname,"<(");
p = tparms; p = tparms;
while (p){ while (p){
@ -3124,6 +3194,9 @@ cpp_template_decl : TEMPLATE LESSTHAN template_parms GREATERTHAN { template_para
Swig_symbol_cadd(fname,$$); Swig_symbol_cadd(fname,$$);
} }
} }
$$ = ntop;
Swig_symbol_setscope(cscope);
Namespaceprefix = Swig_symbol_qualifiedscopename(0);
if (error) $$ = 0; if (error) $$ = 0;
} }
| TEMPLATE cpptype idcolon { | TEMPLATE cpptype idcolon {

View file

@ -210,7 +210,7 @@ String *partial_arg(String *s, String *p) {
} }
int 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; List *patchlist, *cpatchlist, *typelist;
String *templateargs; String *templateargs;
String *tname; String *tname;
@ -364,7 +364,7 @@ Swig_cparse_template_expand(Node *n, String *rname, ParmList *tparms) {
if (bases) { if (bases) {
Iterator b; Iterator b;
for (b = First(bases); b.item; b = Next(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); Clear(b.item);
Append(b.item,qn); Append(b.item,qn);
} }
@ -387,7 +387,7 @@ Swig_cparse_template_expand(Node *n, String *rname, ParmList *tparms) {
void void
Swig_cparse_template_defargs(Parm *parms, Parm *targs) { Swig_cparse_template_defargs(Parm *parms, Parm *targs, Symtab *tscope) {
if (Len(parms) < Len(targs)) { if (Len(parms) < Len(targs)) {
Parm *lp = parms; Parm *lp = parms;
Parm *p = lp; Parm *p = lp;
@ -403,7 +403,7 @@ Swig_cparse_template_defargs(Parm *parms, Parm *targs) {
Parm *cp; Parm *cp;
Parm *ta = targs; Parm *ta = targs;
Parm *p = parms; Parm *p = parms;
SwigType *nt = Swig_symbol_typedef_reduce(value,0); SwigType *nt = Swig_symbol_typedef_reduce(value,tscope);
while(p && ta) { while(p && ta) {
String *name = Getattr(ta,"name"); String *name = Getattr(ta,"name");
String *value = Getattr(p,"value"); String *value = Getattr(p,"value");
@ -412,7 +412,7 @@ Swig_cparse_template_defargs(Parm *parms, Parm *targs) {
p = nextSibling(p); p = nextSibling(p);
ta = nextSibling(ta); 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); set_nextSibling(lp,cp);
lp = cp; lp = cp;
tp = nextSibling(tp); tp = nextSibling(tp);
@ -432,7 +432,7 @@ Swig_cparse_template_defargs(Parm *parms, Parm *targs) {
* ----------------------------------------------------------------------------- */ * ----------------------------------------------------------------------------- */
static Node * static Node *
template_locate(String *name, Parm *tparms) { template_locate(String *name, Parm *tparms, Symtab *tscope) {
Node *n; Node *n;
String *tname, *rname = 0; String *tname, *rname = 0;
Node *templ; Node *templ;
@ -445,12 +445,12 @@ template_locate(String *name, Parm *tparms) {
parms = CopyParmList(tparms); parms = CopyParmList(tparms);
/* Search for generic template */ /* Search for generic template */
templ = Swig_symbol_clookup_local(name,0); templ = Swig_symbol_clookup(name,0);
/* Add default values from generic template */ /* Add default values from generic template */
if (templ) { if (templ) {
targs = Getattr(templ,"templateparms"); 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) { while (p) {
SwigType *ty = Getattr(p,"type"); SwigType *ty = Getattr(p,"type");
if (ty) { if (ty) {
SwigType *rt = Swig_symbol_typedef_reduce(ty,0); SwigType *rt = Swig_symbol_typedef_reduce(ty,tscope);
SwigType *nt = Swig_symbol_type_qualify(rt,0); SwigType *nt = Swig_symbol_type_qualify(rt,tscope);
Setattr(p,"type",nt); Setattr(p,"type",nt);
Delete(rt); Delete(rt);
} }
@ -616,9 +616,9 @@ template_locate(String *name, Parm *tparms) {
* ----------------------------------------------------------------------------- */ * ----------------------------------------------------------------------------- */
Node * Node *
Swig_cparse_template_locate(String *name, Parm *tparms) { Swig_cparse_template_locate(String *name, Parm *tparms, Symtab *tscope) {
Node *n = 0; 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) { if (n) {
int isclass = 0; int isclass = 0;