Fix using declarations combined with using directives with forward class
references. git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@13502 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
parent
1e1c0ad951
commit
6e6ce16e4e
11 changed files with 388 additions and 16 deletions
|
|
@ -205,7 +205,7 @@ static String *yyrename = 0;
|
|||
|
||||
/* Forward renaming operator */
|
||||
|
||||
static String *resolve_node_scope(String *cname);
|
||||
static String *resolve_create_node_scope(String *cname);
|
||||
|
||||
|
||||
Hash *Swig_cparse_features(void) {
|
||||
|
|
@ -867,26 +867,86 @@ 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 specified in the prefix are found, or created in the current namespace.
|
||||
* So ultimately the scope is changed to that required for the base name.
|
||||
* 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 no scope separator (::) in the input, then nothing happens! */
|
||||
static String *resolve_node_scope(String *cname) {
|
||||
* 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) {
|
||||
Symtab *gscope = 0;
|
||||
Node *cname_node = 0;
|
||||
int skip_lookup = 0;
|
||||
nscope = 0;
|
||||
nscope_inner = 0;
|
||||
|
||||
if (Swig_scopename_check(cname)) {
|
||||
String *prefix = Swig_scopename_prefix(cname);
|
||||
if (prefix && (Strncmp(prefix,"::",2) == 0))
|
||||
skip_lookup = 1;
|
||||
}
|
||||
cname_node = skip_lookup ? 0 : Swig_symbol_clookup_no_inherit(cname, 0);
|
||||
|
||||
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. */
|
||||
Symtab *symtab = Getattr(cname_node, "sym:symtab");
|
||||
Node *sym_weak = Getattr(cname_node, "sym:weak");
|
||||
if (symtab && sym_weak) {
|
||||
/* 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));
|
||||
}
|
||||
} 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);
|
||||
} 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);
|
||||
}
|
||||
Delete(base);
|
||||
}
|
||||
Delete(current_scopename);
|
||||
Delete(found_scopename);
|
||||
}
|
||||
}
|
||||
|
||||
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 */
|
||||
String *nprefix = NewString(Char(prefix)+2);
|
||||
Delete(prefix);
|
||||
prefix= nprefix;
|
||||
gscope = set_scope_to_global();
|
||||
}
|
||||
if (!prefix || (Len(prefix) == 0)) {
|
||||
}
|
||||
if (Len(prefix) == 0) {
|
||||
/* 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,
|
||||
|
|
@ -904,8 +964,7 @@ static String *resolve_node_scope(String *cname) {
|
|||
} else {
|
||||
Symtab *nstab = Getattr(ns,"symtab");
|
||||
if (!nstab) {
|
||||
Swig_error(cparse_file,cparse_line,
|
||||
"'%s' is not defined as a valid scope.\n", prefix);
|
||||
Swig_error(cparse_file,cparse_line, "'%s' is not defined as a valid scope.\n", prefix);
|
||||
ns = 0;
|
||||
} else {
|
||||
/* Check if the node scope is the current scope */
|
||||
|
|
@ -986,6 +1045,7 @@ static String *resolve_node_scope(String *cname) {
|
|||
}
|
||||
Delete(prefix);
|
||||
}
|
||||
|
||||
return cname;
|
||||
}
|
||||
|
||||
|
|
@ -2784,7 +2844,7 @@ template_directive: SWIGTEMPLATE LPAREN idstringopt RPAREN idcolonnt LESSTHAN va
|
|||
|
||||
/* If the class name is qualified, we need to create or lookup namespace entries */
|
||||
if (!inclass) {
|
||||
$5 = resolve_node_scope($5);
|
||||
$5 = resolve_create_node_scope($5);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -3406,7 +3466,7 @@ cpp_class_decl : storage_class cpptype idcolon inherit LBRACE {
|
|||
prev_symtab = Swig_symbol_current();
|
||||
|
||||
/* If the class name is qualified. We need to create or lookup namespace/scope entries */
|
||||
scope = resolve_node_scope($3);
|
||||
scope = resolve_create_node_scope($3);
|
||||
Setfile(scope,cparse_file);
|
||||
Setline(scope,cparse_line);
|
||||
$3 = scope;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue