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
parent 1e1c0ad951
commit 6e6ce16e4e
11 changed files with 388 additions and 16 deletions

View File

@ -4,6 +4,7 @@ See the RELEASENOTES file for a summary of changes in each release.
Version 2.0.8 (in progress)
===========================
2012-06-27: wsfulton
Fix display of pointers in various places on 64 bit systems - only 32 bits were being shown.
@ -15,6 +16,45 @@ Version 2.0.8 (in progress)
2012-07-20: kwwette
[Octave] segfault-on-exit prevention hack now preserves exit status, and uses C99 _Exit().
2012-06-30: wsfulton
Fix namespace problems for symbols declared with a forward class declarations, such as:
namespace Space1 {
namespace Space2 {
struct XXX;
struct YYY;
}
struct Space2::YYY {};
struct Space1::Space2::XXX {};
void testXXX2(Space2::XXX xx) {}
void testYYY2(Space2::YYY yy) {}
}
where xx and yy were not recognised as the proxy classes XXX and YYY.
2012-06-30: wsfulton
Fix using declarations combined with using directives with forward class declarations so that
types are correctly found in scope.
namespace Outer2 {
namespace Space2 {
class Thing2;
}
}
using namespace Outer2;
using Space2::Thing2;
class Thing2 {};
// None of the methods below correctly used the Thing2 proxy class
void useit2(Thing2 t) {}
void useit2a(Outer2::Space2::Thing2 t) {}
void useit2b(::Outer2::Space2::Thing2 t) {}
void useit2c(Space2::Thing2 t) {}
namespace Outer2 {
void useit2d(Space2::Thing2 t) {}
}
2012-06-25: wsfulton
Fix using declarations combined with using directives so that types are correctly found in scope.
Example:
@ -28,6 +68,8 @@ Version 2.0.8 (in progress)
using Space2::Thing2; // using declaration
void useit2(Thing2 t) {}
Similarly for templated classes.
2012-05-29: wsfulton
Fix #3529601 - seg fault when a protected method has the "director"
feature but the parent class does not. Also fix similar problems with

View File

@ -257,6 +257,7 @@ CPP_TEST_CASES += \
namespace_class \
namespace_enum \
namespace_extend \
namespace_forward_declaration \
namespace_nested \
namespace_spaces \
namespace_template \
@ -443,6 +444,7 @@ CPP_TEST_CASES += \
using2 \
using_composition \
using_directive_and_declaration \
using_directive_and_declaration_forward \
using_extend \
using_inherit \
using_namespace \

View File

@ -0,0 +1,26 @@
import namespace_forward_declaration.*;
public class namespace_forward_declaration_runme {
static {
try {
System.loadLibrary("namespace_forward_declaration");
} catch (UnsatisfiedLinkError e) {
System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e);
System.exit(1);
}
}
public static void main(String argv[]) {
XXX xxx = new XXX();
namespace_forward_declaration.testXXX1(xxx);
namespace_forward_declaration.testXXX2(xxx);
namespace_forward_declaration.testXXX3(xxx);
YYY yyy = new YYY();
namespace_forward_declaration.testYYY1(yyy);
namespace_forward_declaration.testYYY2(yyy);
namespace_forward_declaration.testYYY3(yyy);
}
}

View File

@ -0,0 +1,53 @@
import using_directive_and_declaration_forward.*;
public class using_directive_and_declaration_forward_runme {
static {
try {
System.loadLibrary("using_directive_and_declaration_forward");
} catch (UnsatisfiedLinkError e) {
System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e);
System.exit(1);
}
}
public static void main(String argv[])
{
using_directive_and_declaration_forward.useit1(new Thing1());
using_directive_and_declaration_forward.useit1a(new Thing1());
using_directive_and_declaration_forward.useit1b(new Thing1());
using_directive_and_declaration_forward.useit1c(new Thing1());
using_directive_and_declaration_forward.useit2(new Thing2());
using_directive_and_declaration_forward.useit2a(new Thing2());
using_directive_and_declaration_forward.useit2b(new Thing2());
using_directive_and_declaration_forward.useit2c(new Thing2());
using_directive_and_declaration_forward.useit2d(new Thing2());
using_directive_and_declaration_forward.useit3(new Thing3());
using_directive_and_declaration_forward.useit3a(new Thing3());
using_directive_and_declaration_forward.useit3b(new Thing3());
using_directive_and_declaration_forward.useit3c(new Thing3());
using_directive_and_declaration_forward.useit3d(new Thing3());
using_directive_and_declaration_forward.useit4(new Thing4());
using_directive_and_declaration_forward.useit4a(new Thing4());
using_directive_and_declaration_forward.useit4b(new Thing4());
using_directive_and_declaration_forward.useit4c(new Thing4());
using_directive_and_declaration_forward.useit4d(new Thing4());
using_directive_and_declaration_forward.useit5(new Thing5());
using_directive_and_declaration_forward.useit5a(new Thing5());
using_directive_and_declaration_forward.useit5b(new Thing5());
using_directive_and_declaration_forward.useit5c(new Thing5());
using_directive_and_declaration_forward.useit5d(new Thing5());
using_directive_and_declaration_forward.useit7(new Thing7());
using_directive_and_declaration_forward.useit7a(new Thing7());
using_directive_and_declaration_forward.useit7b(new Thing7());
using_directive_and_declaration_forward.useit7c(new Thing7());
using_directive_and_declaration_forward.useit7d(new Thing7());
}
}

View File

@ -24,5 +24,6 @@ public class using_directive_and_declaration_runme {
Thing6 t6b = new Thing6();
t6b.b();
using_directive_and_declaration.useit6(t6a, t6b);
using_directive_and_declaration.useit7(new Thing7());
}
}

View File

@ -0,0 +1,35 @@
%module namespace_forward_declaration
%inline %{
namespace Space1 {
namespace Space2 {
struct XXX;
struct YYY;
}
struct Space2::YYY {
int yyy(int h) {
return h;
}
};
struct Space1::Space2::XXX {
int xxx(int h) {
return h;
}
};
void testXXX1(Space1::Space2::XXX xx) {
}
void testXXX2(Space2::XXX xx) {
}
void testXXX3(::Space1::Space2::XXX xx) {
}
void testYYY1(Space1::Space2::YYY yy) {
}
void testYYY2(Space2::YYY yy) {
}
void testYYY3(::Space1::Space2::YYY yy) {
}
}
%}

View File

@ -81,5 +81,26 @@ namespace Outer6 {
}
using namespace Outer6::Space6b;
void useit6(Outer6::Space6a::Thing6 ta, Thing6 tb) {}
namespace Outer7 {
namespace Space7 {
namespace Middle7 {
class Thing7;
}
}
}
using namespace Outer7::Space7;
class Middle7::Thing7 {};
using Middle7::Thing7;
void useit7(Thing7 t) {}
void useit7a(Outer7::Space7::Middle7::Thing7 t) {}
void useit7b(::Outer7::Space7::Middle7::Thing7 t) {}
void useit7c(Middle7::Thing7 t) {}
namespace Outer7 {
namespace Space7 {
void useit7d(Middle7::Thing7 t) {}
}
}
%}

View File

@ -0,0 +1,124 @@
%module using_directive_and_declaration_forward
// Test using directives combined with using declarations and forward declarations
%inline %{
namespace Outer1 {
namespace Space1 {
class Thing1;
}
}
using namespace Outer1::Space1;
using Outer1::Space1::Thing1;
class Thing1 {};
void useit1(Thing1 t) {}
void useit1a(Outer1::Space1::Thing1 t) {}
void useit1b(::Outer1::Space1::Thing1 t) {}
namespace Outer1 {
void useit1c(Space1::Thing1 t) {}
}
namespace Outer2 {
namespace Space2 {
class Thing2;
}
}
using namespace Outer2;
using Space2::Thing2;
class Thing2 {};
void useit2(Thing2 t) {}
void useit2a(Outer2::Space2::Thing2 t) {}
void useit2b(::Outer2::Space2::Thing2 t) {}
void useit2c(Space2::Thing2 t) {}
namespace Outer2 {
void useit2d(Space2::Thing2 t) {}
}
namespace Outer3 {
namespace Space3 {
namespace Middle3 {
class Thing3;
}
}
}
using namespace Outer3;
using namespace Space3;
using Middle3::Thing3;
class Thing3 {};
void useit3(Thing3 t) {}
void useit3a(Outer3::Space3::Middle3::Thing3 t) {}
void useit3b(::Outer3::Space3::Middle3::Thing3 t) {}
void useit3c(Middle3::Thing3 t) {}
namespace Outer3 {
namespace Space3 {
void useit3d(Middle3::Thing3 t) {}
}
}
namespace Outer4 {
namespace Space4 {
namespace Middle4 {
class Thing4;
}
}
}
using namespace Outer4::Space4;
using Middle4::Thing4;
class Thing4 {};
void useit4(Thing4 t) {}
void useit4a(Outer4::Space4::Middle4::Thing4 t) {}
void useit4b(::Outer4::Space4::Middle4::Thing4 t) {}
void useit4c(Middle4::Thing4 t) {}
namespace Outer4 {
namespace Space4 {
void useit4d(Middle4::Thing4 t) {}
}
}
namespace Outer5 {
namespace Space5 {
namespace Middle5 {
namespace More5 {
class Thing5;
}
}
}
}
using namespace ::Outer5::Space5;
using namespace Middle5;
using More5::Thing5;
class Thing5 {};
void useit5(Thing5 t) {}
void useit5a(Outer5::Space5::Middle5::More5::Thing5 t) {}
void useit5b(::Outer5::Space5::Middle5::More5::Thing5 t) {}
void useit5c(Middle5::More5::Thing5 t) {}
namespace Outer5 {
namespace Space5 {
void useit5d(Middle5::More5::Thing5 t) {}
}
}
namespace Outer7 {
namespace Space7 {
namespace Middle7 {
class Thing7;
}
}
}
using namespace Outer7::Space7;
class Middle7::Thing7 {};
using Middle7::Thing7;
void useit7(Thing7 t) {}
void useit7a(Outer7::Space7::Middle7::Thing7 t) {}
void useit7b(::Outer7::Space7::Middle7::Thing7 t) {}
void useit7c(Middle7::Thing7 t) {}
namespace Outer7 {
namespace Space7 {
void useit7d(Middle7::Thing7 t) {}
}
}
%}

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()