fixes for namespaces + class declarations + %template directive

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

View file

@ -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 <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
- [ruby] Directors fixes:
- 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.)
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 \

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 */
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

View file

@ -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 {

View file

@ -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;