Fix type lookup in the presence of using directives and using declarations

Fix some cases of type lookup failure via a combination of both using directives and
using declarations resulting in C++ code that did not compile as the generated type was
not fully qualified for use in the global namespace. Example below:

    namespace Space5 {
      namespace SubSpace5 {
        namespace SubSubSpace5 {
          struct F {};
        }
      }
      using namespace SubSpace5;
      using SubSubSpace5::F;
      void func(SubSubSpace5::F f);
    }
This commit is contained in:
William S Fulton 2017-08-12 10:11:38 +01:00
parent 8bf81b8718
commit bf98c5304f
6 changed files with 139 additions and 30 deletions

View File

@ -73,8 +73,7 @@ namespace Space5 {
struct SubSubSpace5::F { struct SubSubSpace5::F {
void ff(Space5::SubSpace5::SubSubSpace5::F, SubSpace5::SubSubSpace5::F, SubSubSpace5::F, F) {} void ff(Space5::SubSpace5::SubSubSpace5::F, SubSpace5::SubSubSpace5::F, SubSubSpace5::F, F) {}
}; };
// needs fixing void fff(Space5::SubSpace5::SubSubSpace5::F, SubSpace5::SubSubSpace5::F, SubSubSpace5::F, F) {}
void fff(Space5::SubSpace5::SubSubSpace5::F, SubSpace5::SubSubSpace5::F, /*SubSubSpace5::F,*/ F) {}
} }
namespace Space6 { namespace Space6 {

View File

@ -292,6 +292,7 @@ CPP_TEST_CASES += \
multiple_inheritance_shared_ptr \ multiple_inheritance_shared_ptr \
name_cxx \ name_cxx \
name_warnings \ name_warnings \
namespace_chase \
namespace_class \ namespace_class \
namespace_enum \ namespace_enum \
namespace_extend \ namespace_extend \

View File

@ -47,7 +47,7 @@ public class class_scope_namespace_runme {
class_scope_namespace.ccc(c, c); class_scope_namespace.ccc(c, c);
class_scope_namespace.ddd(d, d, d); class_scope_namespace.ddd(d, d, d);
class_scope_namespace.eee(e, e, e); class_scope_namespace.eee(e, e, e);
class_scope_namespace.fff(f, f, f); class_scope_namespace.fff(f, f, f, f);
class_scope_namespace.ggg(g, g); class_scope_namespace.ggg(g, g);
class_scope_namespace.hhh(h); class_scope_namespace.hhh(h);
class_scope_namespace.iii(i, i); class_scope_namespace.iii(i, i);

View File

@ -0,0 +1,26 @@
import namespace_chase.*;
public class namespace_chase_runme {
static {
try {
System.loadLibrary("namespace_chase");
} 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[])
{
Struct1A s1a = new Struct1A();
Struct1B s1b = new Struct1B();
Struct1C s1c = new Struct1C();
namespace_chase.sss3a(s1a, s1b, s1c);
namespace_chase.sss3b(s1a, s1b, s1c);
// needs fixing
// namespace_chase.sss3c(s1a, s1b, s1c);
}
}

View File

@ -0,0 +1,36 @@
%module namespace_chase
%inline %{
namespace Space1A {
struct Struct1A {};
namespace Space1B {
struct Struct1B {};
namespace Space1C {
struct Struct1C {};
}
}
}
namespace Space2A {
using namespace Space1A;
namespace Space2B {
using namespace Space1B;
namespace Space2C {
using namespace Space1C;
}
}
}
namespace Space3 {
using namespace Space2A;
void sss3a(Space1A::Struct1A, Space1A::Space1B::Struct1B, Space1A::Space1B::Space1C::Struct1C) {}
void sss3b(Struct1A, Space1B::Struct1B, Space1B::Space1C::Struct1C) {}
// To fix: the last two parameters below fail and result in SWIGTYPE_ types instead of proxy classes
void sss3c(Space2A::Struct1A, Space2A::Space1B::Struct1B, Space2A::Space1B::Space1C::Struct1C) {}
}
namespace Space4 {
using namespace Space2A;
using namespace Space2A::Space2B;
using namespace Space2A::Space2B::Space2C;
void sss4a(Struct1A, Struct1B, Space2C::Struct1C) {}
void sss4b(Struct1A, Struct1B, Struct1C) {}
}
%}

View File

@ -53,8 +53,7 @@
* typedef A B; * typedef A B;
* typedef B *C; * typedef B *C;
* *
* typetab is built as follows: * typetab in scope '' contains:
*
* "A" : "int" * "A" : "int"
* "B" : "A" * "B" : "A"
* "C" : "p.B" * "C" : "p.B"
@ -67,31 +66,76 @@
* ---> a(40).p.p.A (B --> A) * ---> a(40).p.p.A (B --> A)
* ---> a(40).p.p.int (A --> int) * ---> 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 * For inheritance, SWIG tries to resolve types back to the base class. For instance, if
* you have this: * you have this:
* *
* class Foo { * class Foo {
* public: * public:
* typedef int Integer; * typedef int Integer;
* }; * };
* struct Bar : public Foo {
* void blah(Integer x);
* };
* *
* class Bar : public Foo { * In this case typetab in scope '' contains:
* void blah(Integer x); * "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 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. * The scope-inheritance mechanism is used to manage C++ namespace aliases.
* For example, if you have this: * For example, if you have this:
* *
* namespace Foo { * namespace Foo {
* typedef int Integer; * typedef int Integer;
* } * }
* *
* namespace F = Foo; * namespace F = Foo;
* *
* In this case, "F::" is defined as a scope that "inherits" from Foo. Internally, * 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 * 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 * 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 * will generate a warning message (in the parser) and will place information into
* Foo instead. * Foo instead.
@ -968,8 +1012,17 @@ SwigType *SwigType_typedef_resolve_all(const SwigType *t) {
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
* SwigType_typedef_qualified() * SwigType_typedef_qualified()
* *
* Given a type declaration, this function tries to fully qualify it according to * Given a type declaration, this function tries to fully qualify it so that the
* typedef scope rules. * 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 * If the unary scope operator (::) is used as a prefix to the type to denote global
* scope, it is left in place. * scope, it is left in place.
* ----------------------------------------------------------------------------- */ * ----------------------------------------------------------------------------- */
@ -1030,20 +1083,14 @@ SwigType *SwigType_typedef_qualified(const SwigType *t) {
out of the current scope */ out of the current scope */
Typetab *cs = current_scope; Typetab *cs = current_scope;
while (cs) { if (cs) {
String *qs = SwigType_scope_name(cs); Typetab *found_scope = SwigType_find_scope(cs, e);
if (Len(qs)) { if (found_scope) {
Append(qs, "::"); String *qs = SwigType_scope_name(found_scope);
}
Append(qs, e);
if (Getattr(scopes, qs)) {
Clear(e); Clear(e);
Append(e, qs); Append(e, qs);
Delete(qs); Delete(qs);
break;
} }
Delete(qs);
cs = Getattr(cs, "parent");
} }
} }
} }