Merge branch 'master' into gsoc2017-php7-classes-via-c-api

This commit is contained in:
Olly Betts 2017-09-14 09:01:37 +12:00
commit f72d9c1f21
103 changed files with 2332 additions and 853 deletions

View file

@ -209,7 +209,7 @@ static String *yyrename = 0;
/* Forward renaming operator */
static String *resolve_create_node_scope(String *cname);
static String *resolve_create_node_scope(String *cname, int is_class_definition);
Hash *Swig_cparse_features(void) {
@ -815,32 +815,53 @@ static String *remove_block(Node *kw, const String *inputcode) {
return modified_code;
}
/*
#define RESOLVE_DEBUG 1
*/
static Node *nscope = 0;
static Node *nscope_inner = 0;
/* Remove the scope prefix from cname and return the base name without the prefix.
* The scopes required for the symbol name are resolved and/or created, if required.
* For example AA::BB::CC as input returns CC and creates the namespace AA then inner
* namespace BB in the current scope. If cname is found to already exist as a weak symbol
* (forward reference) then the scope might be changed to match, such as when a symbol match
* is made via a using reference. */
static String *resolve_create_node_scope(String *cname) {
* namespace BB in the current scope. */
static String *resolve_create_node_scope(String *cname, int is_class_definition) {
Symtab *gscope = 0;
Node *cname_node = 0;
int skip_lookup = 0;
String *last = Swig_scopename_last(cname);
nscope = 0;
nscope_inner = 0;
if (Strncmp(cname,"::",2) == 0)
skip_lookup = 1;
cname_node = skip_lookup ? 0 : Swig_symbol_clookup_no_inherit(cname, 0);
if (Strncmp(cname,"::" ,2) != 0) {
if (is_class_definition) {
/* Only lookup symbols which are in scope via a using declaration but not via a using directive.
For example find y via 'using x::y' but not y via a 'using namespace x'. */
cname_node = Swig_symbol_clookup_no_inherit(cname, 0);
if (!cname_node) {
Node *full_lookup_node = Swig_symbol_clookup(cname, 0);
if (full_lookup_node) {
/* This finds a symbol brought into scope via both a using directive and a using declaration. */
Node *last_node = Swig_symbol_clookup_no_inherit(last, 0);
if (last_node == full_lookup_node)
cname_node = last_node;
}
}
} else {
/* For %template, the template needs to be in scope via any means. */
cname_node = Swig_symbol_clookup(cname, 0);
}
}
#if RESOLVE_DEBUG
if (!cname_node)
Printf(stdout, "symbol does not yet exist (%d): [%s]\n", is_class_definition, cname);
else
Printf(stdout, "symbol does exist (%d): [%s]\n", is_class_definition, cname);
#endif
if (cname_node) {
/* The symbol has been defined already or is in another scope.
If it is a weak symbol, it needs replacing and if it was brought into the current scope
via a using declaration, the scope needs adjusting appropriately for the new symbol.
If it is a weak symbol, it needs replacing and if it was brought into the current scope,
the scope needs adjusting appropriately for the new symbol.
Similarly for defined templates. */
Symtab *symtab = Getattr(cname_node, "sym:symtab");
Node *sym_weak = Getattr(cname_node, "sym:weak");
@ -848,48 +869,92 @@ static String *resolve_create_node_scope(String *cname) {
/* Check if the scope is the current scope */
String *current_scopename = Swig_symbol_qualifiedscopename(0);
String *found_scopename = Swig_symbol_qualifiedscopename(symtab);
int len;
if (!current_scopename)
current_scopename = NewString("");
if (!found_scopename)
found_scopename = NewString("");
len = Len(current_scopename);
if ((len > 0) && (Strncmp(current_scopename, found_scopename, len) == 0)) {
if (Len(found_scopename) > len + 2) {
/* A matching weak symbol was found in non-global scope, some scope adjustment may be required */
String *new_cname = NewString(Char(found_scopename) + len + 2); /* skip over "::" prefix */
String *base = Swig_scopename_last(cname);
Printf(new_cname, "::%s", base);
cname = new_cname;
Delete(base);
} else {
/* A matching weak symbol was found in the same non-global local scope, no scope adjustment required */
assert(len == Len(found_scopename));
{
int fail = 1;
List *current_scopes = Swig_scopename_tolist(current_scopename);
List *found_scopes = Swig_scopename_tolist(found_scopename);
Iterator cit = First(current_scopes);
Iterator fit = First(found_scopes);
#if RESOLVE_DEBUG
Printf(stdout, "comparing current: [%s] found: [%s]\n", current_scopename, found_scopename);
#endif
for (; fit.item && cit.item; fit = Next(fit), cit = Next(cit)) {
String *current = cit.item;
String *found = fit.item;
#if RESOLVE_DEBUG
Printf(stdout, " looping %s %s\n", current, found);
#endif
if (Strcmp(current, found) != 0)
break;
}
} else {
String *base = Swig_scopename_last(cname);
if (Len(found_scopename) > 0) {
/* A matching weak symbol was found in a different scope to the local scope - probably via a using declaration */
cname = NewStringf("%s::%s", found_scopename, base);
if (!cit.item) {
String *subscope = NewString("");
for (; fit.item; fit = Next(fit)) {
if (Len(subscope) > 0)
Append(subscope, "::");
Append(subscope, fit.item);
}
if (Len(subscope) > 0)
cname = NewStringf("%s::%s", subscope, last);
else
cname = Copy(last);
#if RESOLVE_DEBUG
Printf(stdout, "subscope to create: [%s] cname: [%s]\n", subscope, cname);
#endif
fail = 0;
Delete(subscope);
} else {
/* Either:
1) A matching weak symbol was found in a different scope to the local scope - this is actually a
symbol with the same name in a different scope which we don't want, so no adjustment required.
2) A matching weak symbol was found in the global scope - no adjustment required.
*/
cname = Copy(base);
if (is_class_definition) {
if (!fit.item) {
/* It is valid to define a new class with the same name as one forward declared in a parent scope */
fail = 0;
} else if (Swig_scopename_check(cname)) {
/* Classes defined with scope qualifiers must have a matching forward declaration in matching scope */
fail = 1;
} else {
/* This may let through some invalid cases */
fail = 0;
}
#if RESOLVE_DEBUG
Printf(stdout, "scope for class definition, fail: %d\n", fail);
#endif
} else {
#if RESOLVE_DEBUG
Printf(stdout, "no matching base scope for template\n");
#endif
fail = 1;
}
}
Delete(found_scopes);
Delete(current_scopes);
if (fail) {
String *cname_resolved = NewStringf("%s::%s", found_scopename, last);
Swig_error(cparse_file, cparse_line, "'%s' resolves to '%s' and was incorrectly instantiated in scope '%s' instead of within scope '%s'.\n", cname, cname_resolved, current_scopename, found_scopename);
cname = Copy(last);
Delete(cname_resolved);
}
Delete(base);
}
Delete(current_scopename);
Delete(found_scopename);
}
} else if (!is_class_definition) {
/* A template instantiation requires a template to be found in scope... fail here too?
Swig_error(cparse_file, cparse_line, "No template found to instantiate '%s' with %%template.\n", cname);
*/
}
if (Swig_scopename_check(cname)) {
Node *ns;
String *prefix = Swig_scopename_prefix(cname);
String *base = Swig_scopename_last(cname);
if (prefix && (Strncmp(prefix,"::",2) == 0)) {
/* I don't think we can use :: global scope to declare classes and hence neither %template. - consider reporting error instead - wsfulton. */
/* Use the global scope */
@ -899,6 +964,7 @@ static String *resolve_create_node_scope(String *cname) {
gscope = set_scope_to_global();
}
if (Len(prefix) == 0) {
String *base = Copy(last);
/* Use the global scope, but we need to add a 'global' namespace. */
if (!gscope) gscope = set_scope_to_global();
/* note that this namespace is not the "unnamed" one,
@ -907,6 +973,7 @@ static String *resolve_create_node_scope(String *cname) {
nscope = new_node("namespace");
Setattr(nscope,"symtab", gscope);;
nscope_inner = nscope;
Delete(last);
return base;
}
/* Try to locate the scope */
@ -924,7 +991,7 @@ static String *resolve_create_node_scope(String *cname) {
String *nname = Swig_symbol_qualifiedscopename(nstab);
if (tname && (Strcmp(tname,nname) == 0)) {
ns = 0;
cname = base;
cname = Copy(last);
}
Delete(tname);
Delete(nname);
@ -932,19 +999,10 @@ static String *resolve_create_node_scope(String *cname) {
if (ns) {
/* we will try to create a new node using the namespaces we
can find in the scope name */
List *scopes;
List *scopes = Swig_scopename_tolist(prefix);
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(base);
Delete(name);
name = tprefix;
}
for (si = First(scopes); si.item; si = Next(si)) {
Node *ns1,*ns2;
sname = si.item;
@ -990,12 +1048,13 @@ static String *resolve_create_node_scope(String *cname) {
nscope_inner = ns2;
if (!nscope) nscope = ns2;
}
cname = base;
cname = Copy(last);
Delete(scopes);
}
}
Delete(prefix);
}
Delete(last);
return cname;
}
@ -2631,9 +2690,8 @@ template_directive: SWIGTEMPLATE LPAREN idstringopt RPAREN idcolonnt LESSTHAN va
tscope = Swig_symbol_current(); /* Get the current scope */
/* If the class name is qualified, we need to create or lookup namespace entries */
if (!inclass) {
$5 = resolve_create_node_scope($5);
}
$5 = resolve_create_node_scope($5, 0);
if (nscope_inner && Strcmp(nodeType(nscope_inner), "class") == 0) {
outer_class = nscope_inner;
}
@ -2991,6 +3049,9 @@ c_declaration : c_decl {
SetFlag($$,"aliastemplate");
add_symbols($$);
}
| cpp_static_assert {
$$ = $1;
}
;
/* ------------------------------------------------------------
@ -3520,7 +3581,7 @@ cpp_class_decl : storage_class cpptype idcolon inherit LBRACE {
Setattr($<node>$,"prev_symtab",Swig_symbol_current());
/* If the class name is qualified. We need to create or lookup namespace/scope entries */
scope = resolve_create_node_scope($3);
scope = resolve_create_node_scope($3, 1);
/* save nscope_inner to the class - it may be overwritten in nested classes*/
Setattr($<node>$, "nested:innerscope", nscope_inner);
Setattr($<node>$, "nested:nscope", nscope);
@ -4209,9 +4270,6 @@ cpp_temp_possible: c_decl {
| cpp_constructor_decl {
$$ = $1;
}
| cpp_static_assert {
$$ = $1;
}
| cpp_template_decl {
$$ = 0;
}
@ -4469,7 +4527,6 @@ cpp_member : c_declaration { $$ = $1; }
default_arguments($$);
}
| cpp_destructor_decl { $$ = $1; }
| cpp_static_assert { $$ = $1; }
| cpp_protection_decl { $$ = $1; }
| cpp_swig_directive { $$ = $1; }
| cpp_conversion_operator { $$ = $1; }
@ -4673,7 +4730,8 @@ cpp_catch_decl : CATCH LPAREN parms RPAREN LBRACE {
}
;
/* static_assert(bool, const char*); */
/* static_assert(bool, const char*); (C++11)
* static_assert(bool); (C++17) */
cpp_static_assert : STATIC_ASSERT LPAREN {
skip_balanced('(',')');
$$ = 0;

View file

@ -990,7 +990,7 @@ private:
* overname: The overload string for overloaded function.
* wname: The SWIG wrapped name--the name of the C function.
* base: A list of the names of base classes, in the case where this
* is is a vritual method not defined in the current class.
* is a virtual method not defined in the current class.
* parms: The parameters.
* result: The result type.
* is_static: Whether this is a static method or member.

View file

@ -1949,7 +1949,7 @@ int Language::unrollVirtualMethods(Node *n, Node *parent, List *vm, int default_
generation of 'empty' director classes.
But this has to be done outside the previous 'for'
an the recursive loop!.
and the recursive loop!.
*/
if (n == parent) {
int len = Len(vm);
@ -2078,7 +2078,7 @@ int Language::classDirectorConstructors(Node *n) {
needed, since there is a public constructor already defined.
(scottm) This code is needed here to make the director_abstract +
test generate compilable code (Example2 in director_abastract.i).
test generate compilable code (Example2 in director_abstract.i).
(mmatus) This is very strange, since swig compiled with gcc3.2.3
doesn't need it here....
@ -3308,7 +3308,7 @@ Node *Language::classLookup(const SwigType *s) const {
}
if (n) {
/* Found a match. Look at the prefix. We only allow
the cases where where we want a proxy class for the particular type */
the cases where we want a proxy class for the particular type */
bool acceptable_prefix =
(Len(prefix) == 0) || // simple type (pass by value)
(Strcmp(prefix, "p.") == 0) || // pointer

View file

@ -1755,7 +1755,7 @@ public:
*
* This is to convert the string of Lua code into a proper string, which can then be
* emitted into the C/C++ code.
* Basically is is a lot of search & replacing of odd sequences
* Basically it is a lot of search & replacing of odd sequences
* ---------------------------------------------------------------------------- */
void escapeCode(String *str) {
@ -1770,7 +1770,7 @@ public:
/* -----------------------------------------------------------------------------
* rawGetCArraysHash(String *name)
*
* A small helper to hide impelementation of how CArrays hashes are stored
* A small helper to hide implementation of how CArrays hashes are stored
* ---------------------------------------------------------------------------- */
Hash *rawGetCArraysHash(const_String_or_char_ptr name) {

View file

@ -718,7 +718,7 @@ String * R::createFunctionPointerHandler(SwigType *t, Node *n, int *numArgs) {
function that handles the scoerceout.
We need to check if any of the argument types have an entry in
that map. If none do, the ignore and call the function straight.
Otherwise, generate the a marshalling function.
Otherwise, generate a marshalling function.
Need to be able to find it in S. Or use an entirely generic one
that evaluates the expressions.
Handle errors in the evaluation of the function by restoring

View file

@ -187,8 +187,10 @@ class TypePass:private Dispatcher {
ilist = alist = NewList();
Append(ilist, bcls);
} else {
Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bname), Getline(bname), "Base class '%s' has no name as it is an empty template instantiated with '%%template()'. Ignored.\n", SwigType_namestr(bname));
Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bcls), Getline(bcls), "The %%template directive must be written before '%s' is used as a base class and be declared with a name.\n", SwigType_namestr(bname));
if (!GetFlag(bcls, "feature:ignore")) {
Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bname), Getline(bname), "Base class '%s' has no name as it is an empty template instantiated with '%%template()'. Ignored.\n", SwigType_namestr(bname));
Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bcls), Getline(bcls), "The %%template directive must be written before '%s' is used as a base class and be declared with a name.\n", SwigType_namestr(bname));
}
}
}
break;
@ -209,8 +211,10 @@ class TypePass:private Dispatcher {
ilist = alist = NewList();
Append(ilist, bcls);
} else {
Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bname), Getline(bname), "Base class '%s' has no name as it is an empty template instantiated with '%%template()'. Ignored.\n", SwigType_namestr(bname));
Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bcls), Getline(bcls), "The %%template directive must be written before '%s' is used as a base class and be declared with a name.\n", SwigType_namestr(bname));
if (!GetFlag(bcls, "feature:ignore")) {
Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bname), Getline(bname), "Base class '%s' has no name as it is an empty template instantiated with '%%template()'. Ignored.\n", SwigType_namestr(bname));
Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bcls), Getline(bcls), "The %%template directive must be written before '%s' is used as a base class and be declared with a name.\n", SwigType_namestr(bname));
}
}
} else {
Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bname), Getline(bname), "Base class '%s' undefined.\n", SwigType_namestr(bname));
@ -1199,10 +1203,7 @@ class TypePass:private Dispatcher {
} else if (Strcmp(ntype, "enum") == 0) {
SwigType_typedef_using(Getattr(n, "uname"));
} else if (Strcmp(ntype, "template") == 0) {
/*
Printf(stdout, "usingDeclaration template %s --- %s\n", Getattr(n, "name"), Getattr(n, "uname"));
SwigType_typedef_using(Getattr(n, "uname"));
*/
}
}
}

View file

@ -59,7 +59,7 @@ int is_non_virtual_protected_access(Node *n) {
// When vtable is empty, the director class does not get emitted, so a check for an empty vtable should be done.
// However, vtable is set in Language and so is not yet set when methods in Typepass call clean_overloaded()
// which calls is_non_virtual_protected_access. So commented out below.
// Moving the director vtable creation into into Typepass should solve this problem.
// Moving the director vtable creation into Typepass should solve this problem.
if (is_member_director_helper(parentNode, n) /* && Getattr(parentNode, "vtable")*/)
result = 1;
}

View file

@ -277,7 +277,7 @@ int Swig_cargs(Wrapper *w, ParmList *p) {
SwigType_del_rvalue_reference(tvalue);
tycode = SwigType_type(tvalue);
if (tycode != T_USER) {
/* plain primitive type, we copy the the def value */
/* plain primitive type, we copy the def value */
String *lstr = SwigType_lstr(tvalue, defname);
defvalue = NewStringf("%s = %s", lstr, qvalue);
Delete(lstr);

View file

@ -823,10 +823,11 @@ String *Swig_string_emangle(String *s) {
/* -----------------------------------------------------------------------------
* Swig_scopename_prefix()
* Swig_scopename_split()
*
* Take a qualified name like "A::B::C" and return the scope name.
* In this case, "A::B". Returns NULL if there is no base.
* Take a qualified name like "A::B::C" and splits off the last name.
* In this case, returns "C" as last and "A::B" as prefix.
* Always returns non NULL for last, but prefix may be NULL if there is no prefix.
* ----------------------------------------------------------------------------- */
void Swig_scopename_split(const String *s, String **rprefix, String **rlast) {
@ -882,6 +883,12 @@ void Swig_scopename_split(const String *s, String **rprefix, String **rlast) {
}
}
/* -----------------------------------------------------------------------------
* Swig_scopename_prefix()
*
* Take a qualified name like "A::B::C" and return the scope name.
* In this case, "A::B". Returns NULL if there is no base.
* ----------------------------------------------------------------------------- */
String *Swig_scopename_prefix(const String *s) {
char *tmp = Char(s);
@ -1067,6 +1074,31 @@ String *Swig_scopename_suffix(const String *s) {
}
}
/* -----------------------------------------------------------------------------
* Swig_scopename_tolist()
*
* Take a qualified scope name like "A::B::C" and convert it to a list.
* In this case, return a list of 3 elements "A", "B", "C".
* Returns an empty list if the input is empty.
* ----------------------------------------------------------------------------- */
List *Swig_scopename_tolist(const String *s) {
List *scopes = NewList();
String *name = Len(s) == 0 ? 0 : NewString(s);
while (name) {
String *last = 0;
String *prefix = 0;
Swig_scopename_split(name, &prefix, &last);
Insert(scopes, 0, last);
Delete(last);
Delete(name);
name = prefix;
}
Delete(name);
return scopes;
}
/* -----------------------------------------------------------------------------
* Swig_scopename_check()
*

View file

@ -326,6 +326,7 @@ extern int ParmList_is_compactdefargs(ParmList *p);
extern String *Swig_scopename_last(const String *s);
extern String *Swig_scopename_first(const String *s);
extern String *Swig_scopename_suffix(const String *s);
extern List *Swig_scopename_tolist(const String *s);
extern int Swig_scopename_check(const String *s);
extern String *Swig_string_lower(String *s);
extern String *Swig_string_upper(String *s);

View file

@ -599,7 +599,7 @@ void Swig_symbol_cadd(const_String_or_char_ptr name, Node *n) {
Setattr(ccurrent, name, n);
}
/* Multiple entries in the C symbol table. We append to to the symbol table */
/* Multiple entries in the C symbol table. We append to the symbol table */
if (append) {
Node *fn, *pn = 0;
cn = Getattr(ccurrent, name);

View file

@ -61,13 +61,44 @@ static void replace_embedded_typemap(String *s, ParmList *parm_sublist, Wrapper
static Hash *typemaps;
/* -----------------------------------------------------------------------------
* typemap_identifier_fix()
*
* Create a type that can be used as a hash key lookup independent of the various
* ways a template parameter list can be defined. This is achieved by fully
* resolving the template parameters.
*
* This is a copy and modification of feature_identifier_fix in parser.y.
* ----------------------------------------------------------------------------- */
static SwigType *typemap_identifier_fix(const SwigType *s) {
String *tp = SwigType_istemplate_templateprefix(s);
if (tp) {
String *ts, *ta, *tq, *tr;
ts = SwigType_templatesuffix(s);
ta = SwigType_templateargs(s);
tq = Swig_symbol_type_qualify(ta, 0);
tr = SwigType_typedef_resolve_all(ta);
Append(tp,tr);
Append(tp,ts);
Delete(ts);
Delete(ta);
Delete(tq);
Delete(tr);
return tp;
} else {
return NewString(s);
}
}
static Hash *get_typemap(const SwigType *type) {
Hash *tm = 0;
SwigType *dtype = 0;
SwigType *hashtype;
if (SwigType_istemplate(type)) {
String *ty = Swig_symbol_template_deftype(type, 0);
SwigType *rty = typemap_identifier_fix(type);
String *ty = Swig_symbol_template_deftype(rty, 0);
dtype = Swig_symbol_type_qualify(ty, 0);
type = dtype;
Delete(ty);
@ -88,7 +119,7 @@ static void set_typemap(const SwigType *type, Hash **tmhash) {
Hash *new_tm = 0;
assert(*tmhash == 0);
if (SwigType_istemplate(type)) {
SwigType *rty = SwigType_typedef_resolve_all(type);
SwigType *rty = typemap_identifier_fix(type);
String *ty = Swig_symbol_template_deftype(rty, 0);
String *tyq = Swig_symbol_type_qualify(ty, 0);
hashtype = SwigType_remove_global_scope_prefix(tyq);
@ -733,6 +764,7 @@ static Hash *typemap_search(const_String_or_char_ptr tmap_method, SwigType *type
SwigType *oldctype = ctype;
ctype = SwigType_typedef_resolve(ctype_unstripped);
Delete(oldctype);
Delete(ctype_unstripped);
ctype_unstripped = Copy(ctype);
}
}

View file

@ -42,10 +42,15 @@
* "name" - Scope name
* "qname" - Fully qualified typename
* "typetab" - Type table containing typenames and typedef information
* For a given key in the typetab table, the value is a fully
* qualified name if not pointing to itself.
* "symtab" - Hash table of symbols defined in a scope
* "inherit" - List of inherited scopes
* "parent" - Parent scope
*
* The contents of these tables can be viewed for debugging using the -debug-typedef
* option which calls SwigType_print_scope().
*
* Typedef information is stored in the "typetab" hash table. For example,
* if you have these declarations:
*
@ -53,8 +58,7 @@
* typedef A B;
* typedef B *C;
*
* typetab is built as follows:
*
* typetab in scope '' contains:
* "A" : "int"
* "B" : "A"
* "C" : "p.B"
@ -67,31 +71,76 @@
* ---> a(40).p.p.A (B --> A)
* ---> a(40).p.p.int (A --> int)
*
*
* Using declarations are stored in the "typetab" hash table. For example,
*
* namespace NN {
* struct SS {};
* }
* namespace N {
* struct S {};
* using NN::SS;
* }
* using N::S;
*
* typetab in scope '' contains:
* "S" : "N::S"
*
* and typetab in scope 'N' contains:
* "SS" : "NN::SS"
* "S" : "S"
*
*
* For inheritance, SWIG tries to resolve types back to the base class. For instance, if
* you have this:
*
* class Foo {
* public:
* typedef int Integer;
* };
* class Foo {
* public:
* typedef int Integer;
* };
* struct Bar : public Foo {
* void blah(Integer x);
* };
*
* class Bar : public Foo {
* void blah(Integer x);
* };
* In this case typetab in scope '' contains:
* "Foo" : "Foo"
* "Bar" : "Bar"
* and scope 'Foo' contains:
* "Integer" : "int"
* and scope 'Bar' inherits from 'Foo' but is empty (observe that blah is not a scope or typedef)
*
* The argument type of Bar::blah will be set to Foo::Integer.
*
*
* The scope-inheritance mechanism is used to manage C++ using directives.
*
* namespace XX {
* class CC {};
* }
* namespace X {
* class C {};
* using namespace XX;
* }
* using namespace X;
*
* typetab in scope '' inherits from 'X'
* typetab in scope 'X' inherits from 'XX' and contains:
* "C" : "C"
* typetab in scope 'XX' contains:
* "CC" : "CC"
*
*
* The scope-inheritance mechanism is used to manage C++ namespace aliases.
* For example, if you have this:
*
* namespace Foo {
* typedef int Integer;
* }
* namespace Foo {
* typedef int Integer;
* }
*
* namespace F = Foo;
* namespace F = Foo;
*
* In this case, "F::" is defined as a scope that "inherits" from Foo. Internally,
* "F::" will merely be an empty scope that refers to Foo. SWIG will never
* In this case, F is defined as a scope that "inherits" from Foo. Internally,
* F will merely be an empty scope that points to Foo. SWIG will never
* place new type information into a namespace alias---attempts to do so
* will generate a warning message (in the parser) and will place information into
* Foo instead.
@ -166,6 +215,7 @@ void SwigType_typesystem_init() {
* ----------------------------------------------------------------------------- */
int SwigType_typedef(const SwigType *type, const_String_or_char_ptr name) {
/* Printf(stdout, "typedef %s %s\n", type, name); */
if (Getattr(current_typetab, name))
return -1; /* Already defined */
if (Strcmp(type, name) == 0) { /* Can't typedef a name to itself */
@ -248,10 +298,26 @@ void SwigType_new_scope(const_String_or_char_ptr name) {
ttab = NewHash();
Setattr(s, "typetab", ttab);
/* Build fully qualified name and */
/* Build fully qualified name */
qname = SwigType_scope_name(s);
#if 1
{
/* TODO: only do with templates? What happens with non-templates with code below? */
String *stripped_qname;
stripped_qname = SwigType_remove_global_scope_prefix(qname);
/* Use fully qualified name for hash key without unary scope prefix, qname may contain unary scope */
Setattr(scopes, stripped_qname, s);
Setattr(s, "qname", qname);
/*
Printf(stdout, "SwigType_new_scope stripped %s %s\n", qname, stripped_qname);
*/
Delete(stripped_qname);
}
#else
Printf(stdout, "SwigType_new_scope %s\n", qname);
Setattr(scopes, qname, s);
Setattr(s, "qname", qname);
#endif
Delete(qname);
current_scope = s;
@ -418,12 +484,14 @@ static Typetab *SwigType_find_scope(Typetab *s, const SwigType *nameprefix) {
Typetab *s_orig = s;
String *nnameprefix = 0;
static int check_parent = 1;
int is_template = 0;
if (Getmark(s))
return 0;
Setmark(s, 1);
if (SwigType_istemplate(nameprefix)) {
is_template = SwigType_istemplate(nameprefix);
if (is_template) {
nnameprefix = SwigType_typedef_resolve_all(nameprefix);
nameprefix = nnameprefix;
}
@ -437,10 +505,12 @@ static Typetab *SwigType_find_scope(Typetab *s, const SwigType *nameprefix) {
} else {
full = NewString(nameprefix);
}
if (Getattr(scopes, full)) {
s = Getattr(scopes, full);
} else {
s = 0;
s = Getattr(scopes, full);
if (!s && is_template) {
/* try look up scope with all the unary scope operators within the template parameter list removed */
SwigType *full_stripped = SwigType_remove_global_scope_prefix(full);
s = Getattr(scopes, full_stripped);
Delete(full_stripped);
}
Delete(full);
if (s) {
@ -541,8 +611,11 @@ static SwigType *_typedef_resolve(Typetab *s, String *base, int look_parent) {
/* -----------------------------------------------------------------------------
* template_parameters_resolve()
*
* For use with templates only. The template parameters are resolved. If none
* of the parameters can be resolved, zero is returned.
* For use with templates only. Attempts to resolve one template parameter.
*
* If one of the template parameters can be resolved, the type is returned with
* just the one parameter resolved and the remaining parameters left as is.
* If none of the template parameters can be resolved, zero is returned.
* ----------------------------------------------------------------------------- */
static String *template_parameters_resolve(const String *base) {
@ -574,14 +647,15 @@ static String *template_parameters_resolve(const String *base) {
if ((i + 1) < sz)
Append(type, ",");
}
Append(type, ")>");
Append(type, suffix);
Delete(suffix);
Delete(tparms);
if (!rep) {
if (rep) {
Append(type, ")>");
Append(type, suffix);
} else {
Delete(type);
type = 0;
}
Delete(suffix);
Delete(tparms);
return type;
}
@ -592,6 +666,17 @@ static SwigType *typedef_resolve(Typetab *s, String *base) {
/* -----------------------------------------------------------------------------
* SwigType_typedef_resolve()
*
* Given a type declaration, this function looks to reduce/resolve the type via a
* typedef (including via C++ using declarations).
*
* If it is able to find a typedef, the resolved type is returned. If no typedef
* is found NULL is returned. The type name is resolved in the current scope.
* The type returned is not always fully qualified for the global scope, it is
* valid for use in the current scope. If the current scope is global scope, a
* fully qualified type should be returned.
*
* Some additional notes are in Doc/Manual/Extending.html.
* ----------------------------------------------------------------------------- */
/* #define SWIG_DEBUG */
@ -718,6 +803,25 @@ SwigType *SwigType_typedef_resolve(const SwigType *t) {
}
}
if (!type && SwigType_istemplate(base)) {
String *tprefix = SwigType_templateprefix(base);
String *rtprefix = SwigType_typedef_resolve(tprefix);
/* We're looking for a using declaration on the template prefix to resolve the template prefix
* in another scope. Using declaration do not have template parameters. */
if (rtprefix && !SwigType_istemplate(rtprefix)) {
String *tsuffix = SwigType_templatesuffix(base);
String *targs = SwigType_templateargs(base);
type = NewString(rtprefix);
newtype = 1;
Append(type, targs);
Append(type, tsuffix);
Delete(targs);
Delete(tsuffix);
Delete(rtprefix);
}
Delete(tprefix);
}
if (type && (Equal(base, type))) {
if (newtype)
Delete(type);
@ -911,6 +1015,9 @@ SwigType *SwigType_typedef_resolve_all(const SwigType *t) {
return Copy(r);
}
#ifdef SWIG_DEBUG
Printf(stdout, "SwigType_typedef_resolve_all start ... %s\n", t);
#endif
/* Recursively resolve the typedef */
r = NewString(t);
while ((n = SwigType_typedef_resolve(r))) {
@ -931,6 +1038,9 @@ SwigType *SwigType_typedef_resolve_all(const SwigType *t) {
Delete(key);
Delete(rr);
}
#ifdef SWIG_DEBUG
Printf(stdout, "SwigType_typedef_resolve_all end === %s => %s\n", t, r);
#endif
return r;
}
@ -938,8 +1048,17 @@ SwigType *SwigType_typedef_resolve_all(const SwigType *t) {
/* -----------------------------------------------------------------------------
* SwigType_typedef_qualified()
*
* Given a type declaration, this function tries to fully qualify it according to
* typedef scope rules.
* Given a type declaration, this function tries to fully qualify it so that the
* resulting type can be used in the global scope. The type name is resolved in
* the current scope.
*
* It provides a fully qualified name, not necessarily a fully expanded name.
* When a using declaration or using directive is found the type may not be fully
* expanded, but it will be resolved and fully qualified for use in the global scope.
*
* This function is for looking up scopes to qualify a type. It does not resolve
* C typedefs, it just qualifies them. See SwigType_typedef_resolve for resolving.
*
* If the unary scope operator (::) is used as a prefix to the type to denote global
* scope, it is left in place.
* ----------------------------------------------------------------------------- */
@ -1000,20 +1119,14 @@ SwigType *SwigType_typedef_qualified(const SwigType *t) {
out of the current scope */
Typetab *cs = current_scope;
while (cs) {
String *qs = SwigType_scope_name(cs);
if (Len(qs)) {
Append(qs, "::");
}
Append(qs, e);
if (Getattr(scopes, qs)) {
if (cs) {
Typetab *found_scope = SwigType_find_scope(cs, e);
if (found_scope) {
String *qs = SwigType_scope_name(found_scope);
Clear(e);
Append(e, qs);
Delete(qs);
break;
}
Delete(qs);
cs = Getattr(cs, "parent");
}
}
}
@ -1029,10 +1142,6 @@ SwigType *SwigType_typedef_qualified(const SwigType *t) {
Parm *p;
List *parms;
ty = Swig_symbol_template_deftype(e, current_symtab);
/*
String *dt = Swig_symbol_template_deftype(e, current_symtab);
ty = Swig_symbol_type_qualify(dt, 0);
*/
e = ty;
parms = SwigType_parmlist(e);
tprefix = SwigType_templateprefix(e);
@ -1099,9 +1208,6 @@ SwigType *SwigType_typedef_qualified(const SwigType *t) {
Delete(tprefix);
Delete(qprefix);
Delete(parms);
/*
Delete(dt);
*/
}
Append(result, e);
Delete(ty);
@ -1181,7 +1287,7 @@ int SwigType_typedef_using(const_String_or_char_ptr name) {
String *defined_name = 0;
/* Printf(stdout,"using %s\n", name); */
/* Printf(stdout, "using %s\n", name); */
if (!Swig_scopename_check(name))
return -1; /* Not properly qualified */