Merge branch 'templates-scope-enforcement'
* templates-scope-enforcement: Test a few %template errors Add using declarations to templates into typedef table. Fix type lookup in the presence of using directives and using declarations More docs on %template Testcase fix for nameclash in php %template scope enforcement and class definition fixes Template documentation tweaks More consistent formatting of examples in documentation More consistent formatting of examples in documentation Documentation corrections to use targetlang formatting More consistent formatting of examples in documentation More consistent formatting of examples in documentation More consistent formatting of examples in documentation Namespace documentation minor corrections Improve description of template_parameters_resolve Minor code optimisation in template_parameters_resolve Fix scope lookup for template parameters containing unary scope operators Typemap change for templates
This commit is contained in:
commit
32a454cfef
51 changed files with 1924 additions and 700 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;
|
||||
}
|
||||
|
|
@ -3523,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);
|
||||
|
|
|
|||
|
|
@ -1203,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"));
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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