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:
William S Fulton 2012-08-04 20:23:07 +00:00
commit 6e6ce16e4e
11 changed files with 388 additions and 16 deletions

View file

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

View file

@ -227,6 +227,7 @@ extern "C" {
extern void Swig_symbol_cadd(const_String_or_char_ptr symname, Node *node);
extern Node *Swig_symbol_clookup(const_String_or_char_ptr symname, Symtab *tab);
extern Node *Swig_symbol_clookup_check(const_String_or_char_ptr symname, Symtab *tab, int (*check) (Node *));
extern Node *Swig_symbol_clookup_no_inherit(const_String_or_char_ptr name, Symtab *n);
extern Symtab *Swig_symbol_cscope(const_String_or_char_ptr symname, Symtab *tab);
extern Node *Swig_symbol_clookup_local(const_String_or_char_ptr symname, Symtab *tab);
extern Node *Swig_symbol_clookup_local_check(const_String_or_char_ptr symname, Symtab *tab, int (*check) (Node *));

View file

@ -176,6 +176,8 @@ static Hash *current_symtab = 0; /* Current symbol table node */
static Hash *symtabs = 0; /* Hash of all symbol tables by fully-qualified name */
static Hash *global_scope = 0; /* Global scope */
static int use_inherit = 1;
/* common attribute keys, to avoid calling find_key all the times */
@ -482,9 +484,9 @@ void Swig_symbol_alias(const_String_or_char_ptr aliasname, Symtab *s) {
/* -----------------------------------------------------------------------------
* Swig_symbol_inherit()
*
* Inherit symbols from another scope.
* Primarily for using directives, such as 'using namespace X;'.
* Not for using declarations, such as 'using A;'.
* Inherit symbols from another scope. Primarily for C++ inheritance and
* for using directives, such as 'using namespace X;'
* but not for using declarations, such as 'using A;'.
* ----------------------------------------------------------------------------- */
void Swig_symbol_inherit(Symtab *s) {
@ -970,7 +972,7 @@ static Node *_symbol_lookup(const String *name, Symtab *symtab, int (*check) (No
}
inherit = Getattr(symtab, "inherit");
if (inherit) {
if (inherit && use_inherit) {
int i, len;
len = Len(inherit);
for (i = 0; i < len; i++) {
@ -1060,7 +1062,7 @@ static Node *symbol_lookup_qualified(const_String_or_char_ptr name, Symtab *symt
/* Check inherited scopes */
if (!n) {
List *inherit = Getattr(symtab, "inherit");
if (inherit) {
if (inherit && use_inherit) {
int i, len;
len = Len(inherit);
for (i = 0; i < len; i++) {
@ -1327,6 +1329,11 @@ Node *Swig_symbol_clookup_local_check(const_String_or_char_ptr name, Symtab *n,
return s;
}
Node *Swig_symbol_clookup_no_inherit(const_String_or_char_ptr name, Symtab *n) {
use_inherit = 0;
Swig_symbol_clookup(name, n);
use_inherit = 1;
}
/* -----------------------------------------------------------------------------
* Swig_symbol_cscope()