Merge branch 'master' into gsoc2017-php7-classes-via-c-api
This commit is contained in:
commit
f72d9c1f21
103 changed files with 2332 additions and 853 deletions
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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"));
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue