diff --git a/Doc/Manual/CSharp.html b/Doc/Manual/CSharp.html index 4eb855022..70010c992 100644 --- a/Doc/Manual/CSharp.html +++ b/Doc/Manual/CSharp.html @@ -677,7 +677,7 @@ As a result, we get the following method in the module class:
public static void myArrayCopy(int[] sourceArray, int[] targetArray, int nitems) {
- examplePINVOKE.myArrayCopy(sourceArray, targetArray, nitems);
+ examplePINVOKE.myArrayCopy(sourceArray, targetArray, nitems);
}
public class runme {
- static void Main() {
- example.positivesonly(-1);
- }
+ static void Main() {
+ example.positivesonly(-1);
+ }
}
- Wheel wheel = new Bike(10).getWheel();
- Console.WriteLine("wheel size: " + wheel.size);
- // Simulate a garbage collection
- global::System.GC.Collect();
- global::System.GC.WaitForPendingFinalizers();
- global::System.Console.WriteLine("wheel size: " + wheel.size);
+ Wheel wheel = new Bike(10).getWheel();
+ Console.WriteLine("wheel size: " + wheel.size);
+ // Simulate a garbage collection
+ global::System.GC.Collect();
+ global::System.GC.WaitForPendingFinalizers();
+ global::System.Console.WriteLine("wheel size: " + wheel.size);
- Container container = new Container(); - Element element = new Element(20); - container.setElement(element); + Container container = new Container(); + Element element = new Element(20); + container.setElement(element);
- Container container = new Container();
- Element element = new Element(20);
- container.setElement(element);
- Console.WriteLine("element.value: " + container.getElement().value);
- // Simulate a garbage collection
- global::System.GC.Collect();
- global::System.GC.WaitForPendingFinalizers();
- global::System.Console.WriteLine("element.value: " + container.getElement().value);
+ Container container = new Container();
+ Element element = new Element(20);
+ container.setElement(element);
+ Console.WriteLine("element.value: " + container.getElement().value);
+ // Simulate a garbage collection
+ global::System.GC.Collect();
+ global::System.GC.WaitForPendingFinalizers();
+ global::System.Console.WriteLine("element.value: " + container.getElement().value);
void Language::main(int argc, char *argv[]) {
for (int i = 1; i < argc; i++) {
- if (argv[i]) {
- if (strcmp(argv[i], "-interface") == 0) {
- if (argv[i+1]) {
- interface = NewString(argv[i+1]);
- Swig_mark_arg(i);
- Swig_mark_arg(i+1);
- i++;
- } else {
- Swig_arg_error();
- }
- } else if (strcmp(argv[i], "-globals") == 0) {
- if (argv[i+1]) {
- global_name = NewString(argv[i+1]);
- Swig_mark_arg(i);
- Swig_mark_arg(i+1);
- i++;
- } else {
- Swig_arg_error();
- }
- } else if ((strcmp(argv[i], "-proxy") == 0)) {
- proxy_flag = 1;
- Swig_mark_arg(i);
- } else if (strcmp(argv[i], "-keyword") == 0) {
- use_kw = 1;
- Swig_mark_arg(i);
- } else if (strcmp(argv[i], "-help") == 0) {
- fputs(usage, stderr);
- }
- ...
+ if (argv[i]) {
+ if (strcmp(argv[i], "-interface") == 0) {
+ if (argv[i+1]) {
+ interface = NewString(argv[i+1]);
+ Swig_mark_arg(i);
+ Swig_mark_arg(i+1);
+ i++;
+ } else {
+ Swig_arg_error();
+ }
+ } else if (strcmp(argv[i], "-globals") == 0) {
+ if (argv[i+1]) {
+ global_name = NewString(argv[i+1]);
+ Swig_mark_arg(i);
+ Swig_mark_arg(i+1);
+ i++;
+ } else {
+ Swig_arg_error();
+ }
+ } else if ((strcmp(argv[i], "-proxy") == 0)) {
+ proxy_flag = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-keyword") == 0) {
+ use_kw = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-help") == 0) {
+ fputs(usage, stderr);
}
+ ...
+ }
}
}
diff --git a/Doc/Manual/Go.html b/Doc/Manual/Go.html
index f25e9850b..820921bd5 100644
--- a/Doc/Manual/Go.html
+++ b/Doc/Manual/Go.html
@@ -639,12 +639,12 @@ public:
virtual ~FooBarAbstract() {};
std::string FooBar() {
- return this->Foo() + ", " + this->Bar();
+ return this->Foo() + ", " + this->Bar();
};
protected:
virtual std::string Foo() {
- return "Foo";
+ return "Foo";
};
virtual std::string Bar() = 0;
diff --git a/Doc/Manual/Java.html b/Doc/Manual/Java.html
index fad2fc3d4..85757d1cb 100644
--- a/Doc/Manual/Java.html
+++ b/Doc/Manual/Java.html
@@ -3935,9 +3935,9 @@ where Swig::DirectorException::raise is a helper method in the Director
- static void raise(JNIEnv *jenv, jthrowable throwable) {
- throw DirectorException(jenv, throwable);
- }
+ static void raise(JNIEnv *jenv, jthrowable throwable) {
+ throw DirectorException(jenv, throwable);
+ }
a = new_doubleArray(10) # Create an array for i in range(0, 10): @@ -475,7 +475,7 @@ void print_array(double x[10]); Allows you to do this: -+@@ -2166,9 +2165,9 @@ have a class like this@@ -1951,11 +1950,11 @@ For example: %rename(Bar_spam) Bar::spam; namespace Foo { - int spam(); + int spam(); } namespace Bar { - int spam(); + int spam(); }import example c = example.doubleArray(10) # Create double[10] @@ -801,7 +801,7 @@ target language. In other words, if you were using a language like Tcl, and you wrote this, -@@ -1276,7 +1275,7 @@ Foo *BarToFoo(Bar *b) { } Foo *IncrFoo(Foo *f, int i) { - return f+i; + return f+i; } %} @@ -1386,7 +1385,7 @@ example, consider this:+diff --git a/Doc/Manual/Python.html b/Doc/Manual/Python.html index 9b9e51455..0c0023dea 100644 --- a/Doc/Manual/Python.html +++ b/Doc/Manual/Python.html @@ -226,16 +226,15 @@ resulting C file should be built as a python extension, inserting the module #include "example.h" int fact(int n) { - if (n < 0){ /* This should probably return an error, but this is simpler */ - return 0; - } - if (n == 0) { - return 1; - } - else { - /* testing for overflow would be a good idea here */ - return n * fact(n-1); - } + if (n < 0) { /* This should probably return an error, but this is simpler */ + return 0; + } + if (n == 0) { + return 1; + } else { + /* testing for overflow would be a good idea here */ + return n * fact(n-1); + } }@@ -1175,9 +1175,9 @@ should suffice in most cases:% foo Hello@@ -852,7 +852,7 @@ size_t parity(char *str, size_t len, size_t initial); Now, in the target language, you can use binary string data like this: -+@@ -1125,12 +1125,12 @@ Here is an example:@@ -3279,9 +3278,9 @@ suffice in most cases:>>> s = "H\x00\x15eg\x09\x20" >>> parity(s, 0) diff --git a/Doc/Manual/Lua.html b/Doc/Manual/Lua.html index c94fe31dc..c5c944225 100644 --- a/Doc/Manual/Lua.html +++ b/Doc/Manual/Lua.html @@ -1008,11 +1008,10 @@ The following operators cannot be overloaded (mainly because they are not supporSWIG also accepts the __str__() member function which converts an object to a string. This function should return a const char*, preferably to static memory. This will be used for the print() and tostring() functions in Lua. Assuming the complex class has a function
-@@ -2842,11 +2841,11 @@ this:const char* __str__() -{ - static char buffer[255]; - sprintf(buffer, "Complex(%g, %g)", this->re(), this->im()); - return buffer; +const char* __str__() { + static char buffer[255]; + sprintf(buffer, "Complex(%g, %g)", this->re(), this->im()); + return buffer; }@@ -1031,11 +1030,10 @@ Complex(10, 12)
It is also possible to overload the operator[], but currently this cannot be automatically performed. To overload the operator[] you need to provide two functions, __getitem__() and __setitem__()
-@@ -1888,9 +1887,9 @@ like this:class Complex -{ - //.... - double __getitem__(int i)const; // i is the index, returns the data - void __setitem__(int i, double d); // i is the index, d is the data +@@ -1057,7 +1057,7 @@ produces a single accessor function like this:class Complex { + //.... + double __getitem__(int i)const; // i is the index, returns the data + void __setitem__(int i, double d); // i is the index, d is the data };diff --git a/Doc/Manual/Perl5.html b/Doc/Manual/Perl5.html index 96e9f7517..8ea43ad6b 100644 --- a/Doc/Manual/Perl5.html +++ b/Doc/Manual/Perl5.html @@ -949,7 +949,7 @@ Foo *BarToFoo(Bar *b) { } Foo *IncrFoo(Foo *f, int i) { - return f+i; + return f+i; } %}
@@ -1092,11 +1092,11 @@ generates accessor functions such as this:int *Foo_x_get(Foo *self) { - return self->x; + return self->x; };@@ -1633,9 +1633,8 @@ class DoubleArray { void setitem(int i, double val) { if ((i >= 0) && (i < n)) ptr[i] = val; - else { + else throw RangeError(); - } } };Foo *Bar_f_get(Bar *b) { - return &b->f; + return &b->f; } void Bar_f_set(Bar *b, Foo *val) { - b->f = *val; + b->f = *val; }@@ -2313,8 +2312,8 @@ Consider the following data structure:%typemap(out) int { - $result = sv_newmortal(); - set_setiv($result, (IV) $1); - argvi++; + $result = sv_newmortal(); + set_setiv($result, (IV) $1); + argvi++; }@@ -2328,10 +2327,10 @@ To make the member writable, a "memberin" typemap can be used.#define SIZE 8 typedef struct { - int values[SIZE]; - ... + int values[SIZE]; + ... } Foo;@@ -2600,48 +2599,48 @@ package example::Vector; %BLESSEDMEMBERS = (); sub new () { - my $self = shift; - my @args = @_; - $self = vectorc::new_Vector(@args); - return undef if (!defined($self)); - bless $self, "example::Vector"; - $OWNER{$self} = 1; - my %retval; - tie %retval, "example::Vector", $self; - return bless \%retval, "Vector"; + my $self = shift; + my @args = @_; + $self = vectorc::new_Vector(@args); + return undef if (!defined($self)); + bless $self, "example::Vector"; + $OWNER{$self} = 1; + my %retval; + tie %retval, "example::Vector", $self; + return bless \%retval, "Vector"; } sub DESTROY { - return unless $_[0]->isa('HASH'); - my $self = tied(%{$_[0]}); - delete $ITERATORS{$self}; - if (exists $OWNER{$self}) { - examplec::delete_Vector($self)); - delete $OWNER{$self}; - } + return unless $_[0]->isa('HASH'); + my $self = tied(%{$_[0]}); + delete $ITERATORS{$self}; + if (exists $OWNER{$self}) { + examplec::delete_Vector($self)); + delete $OWNER{$self}; + } } sub FETCH { - my ($self, $field) = @_; - my $member_func = "vectorc::Vector_${field}_get"; - my $val = &$member_func($self); - if (exists $BLESSEDMEMBERS{$field}) { - return undef if (!defined($val)); - my %retval; - tie %retval, $BLESSEDMEMBERS{$field}, $val; - return bless \%retval, $BLESSEDMEMBERS{$field}; - } - return $val; + my ($self, $field) = @_; + my $member_func = "vectorc::Vector_${field}_get"; + my $val = &$member_func($self); + if (exists $BLESSEDMEMBERS{$field}) { + return undef if (!defined($val)); + my %retval; + tie %retval, $BLESSEDMEMBERS{$field}, $val; + return bless \%retval, $BLESSEDMEMBERS{$field}; + } + return $val; } sub STORE { - my ($self, $field, $newval) = @_; - my $member_func = "vectorc::Vector_${field}_set"; - if (exists $BLESSEDMEMBERS{$field}) { - &$member_func($self, tied(%{$newval})); - } else { - &$member_func($self, $newval); - } + my ($self, $field, $newval) = @_; + my $member_func = "vectorc::Vector_${field}_set"; + if (exists $BLESSEDMEMBERS{$field}) { + &$member_func($self, tied(%{$newval})); + } else { + &$member_func($self, $newval); + } }%typemap(memberin) int [SIZE] { - int i; - for (i = 0; i < SIZE; i++) { - $1[i] = $input[i]; - } + int i; + for (i = 0; i < SIZE; i++) { + $1[i] = $input[i]; + } }@@ -2985,7 +2984,7 @@ sub set_transform for (my $j = 0; $j < 4, $j++) { mat44_set($a, $i, $j, $x->[i][j]) - } + } } example.set_transform($im, $a); free_mat44($a); @@ -3104,14 +3103,14 @@ the methods one() and two() (but not three()): %feature("director") Foo; class Foo { public: - Foo(int foo); - virtual void one(); - virtual void two(); + Foo(int foo); + virtual void one(); + virtual void two(); }; class Bar: public Foo { public: - virtual void three(); + virtual void three(); };sub dot_product { - my @args = @_; - $args[0] = tied(%{$args[0]}); # Get the real pointer values - $args[1] = tied(%{$args[1]}); - my $result = vectorc::dot_product(@args); - return $result; + my @args = @_; + $args[0] = tied(%{$args[0]}); # Get the real pointer values + $args[1] = tied(%{$args[1]}); + my $result = vectorc::dot_product(@args); + return $result; }@@ -3305,8 +3304,8 @@ suitable exception handler:%feature("director:except") { - if ($error != NULL) { - throw Swig::DirectorMethodException(); - } + if ($error != NULL) { + throw Swig::DirectorMethodException(); + } }diff --git a/Doc/Manual/Php.html b/Doc/Manual/Php.html index 4e17db316..9a1178abf 100644 --- a/Doc/Manual/Php.html +++ b/Doc/Manual/Php.html @@ -986,14 +986,14 @@ the methods one() and two() (but not three()): %feature("director") Foo; class Foo { public: - Foo(int foo); - virtual void one(); - virtual void two(); + Foo(int foo); + virtual void one(); + virtual void two(); }; class Bar: public Foo { public: - virtual void three(); + virtual void three(); };%exception { - try { $action } - catch (Swig::DirectorException &e) { SWIG_fail; } + try { $action } + catch (Swig::DirectorException &e) { SWIG_fail; } }class Foo { public: - ... + ... }; class FooContainer { public: - void addFoo(Foo *); - ... + void addFoo(Foo *); + ... };@@ -1204,8 +1204,8 @@ suitable exception handler:%feature("director:except") { - if ($error == FAILURE) { - throw Swig::DirectorMethodException(); - } + if ($error == FAILURE) { + throw Swig::DirectorMethodException(); + } }diff --git a/Doc/Manual/Pike.html b/Doc/Manual/Pike.html index 22ab4e2a2..a8bc0d415 100644 --- a/Doc/Manual/Pike.html +++ b/Doc/Manual/Pike.html @@ -230,8 +230,8 @@ For example, given this C++ class declaration: class Shape { public: - static void print(); - static int nshapes; + static void print(); + static int nshapes; };%exception { - try { $action } - catch (Swig::DirectorException &e) { SWIG_fail; } + try { $action } + catch (Swig::DirectorException &e) { SWIG_fail; } }@@ -1716,9 +1715,9 @@ Similarly, if you have a class like this,struct Bar { - int x[16]; + int x[16]; };class Foo { public: - Foo(); - Foo(const Foo &); - ... + Foo(); + Foo(const Foo &); + ... };class Foo { public: - int x; - int spam(int); - ... + int x; + int spam(int); + ...
Foo *new_Foo() {
- return new Foo();
+ return new Foo();
}
void delete_Foo(Foo *f) {
- delete f;
+ delete f;
}
int Foo_x_get(Foo *f) {
- return f->x;
+ return f->x;
}
void Foo_x_set(Foo *f, int value) {
- f->x = value;
+ f->x = value;
}
int Foo_spam(Foo *f, int arg1) {
- return f->spam(arg1);
+ return f->spam(arg1);
}
typedef struct {
- PyObject_HEAD
- PyObject *dict;
- PyObject *args;
- PyObject *message;
+ PyObject_HEAD
+ PyObject *dict;
+ PyObject *args;
+ PyObject *message;
} PyBaseExceptionObject;
typedef struct {
- PyObject_HEAD
- void *ptr;
- swig_type_info *ty;
- int own;
- PyObject *next;
- PyObject *dict;
+ PyObject_HEAD
+ void *ptr;
+ swig_type_info *ty;
+ int own;
+ PyObject *next;
+ PyObject *dict;
} SwigPyObject;
class MyException {
public:
- MyException (const char *msg_);
- ~MyException ();
+ MyException (const char *msg_);
+ ~MyException ();
- const char *what () const;
+ const char *what () const;
private:
- char *msg;
+ char *msg;
};
class MyString {
public:
- MyString (const char *init);
- MyString operator+ (const char *other) const;
- ...
+ MyString (const char *init);
+ MyString operator+ (const char *other) const;
+ ...
};
@@ -2473,11 +2472,12 @@ slot entries. For example, suppose you have this class:
class Twit {
public:
- Twit operator+ (const Twit& twit) const;
+ Twit operator+ (const Twit& twit) const;
- // Forward to operator+
- Twit add (const Twit& twit) const
- { return *this + twit; }
+ // Forward to operator+
+ Twit add (const Twit& twit) const {
+ return *this + twit;
+ }
};
@@ -2565,9 +2565,9 @@ the function callback in the tp_hash slot for the builtin type for MyClass
static PyHeapTypeObject SwigPyBuiltin__MyClass_type = {
- ...
- (hashfunc) myHashFunc, /* tp_hash */
- ...
+ ...
+ (hashfunc) myHashFunc, /* tp_hash */
+ ...
class Foo {
public:
- Foo();
- Foo bar();
+ Foo();
+ Foo bar();
};
@@ -2666,9 +2666,9 @@ they came from. Therefore, the ownership is set to zero. For example:
class Foo {
public:
- ...
- Foo *spam();
- ...
+ ...
+ Foo *spam();
+ ...
};
@@ -2707,8 +2707,8 @@ or global variable. For example, consider this interface:
%module example
struct Foo {
- int value;
- Foo *next;
+ int value;
+ Foo *next;
};
Foo *head = 0;
@@ -2939,15 +2939,15 @@ the methods one() and two() (but not three()):
%feature("director") Foo;
class Foo {
public:
- Foo(int foo);
- virtual ~Foo();
- virtual void one();
- virtual void two();
+ Foo(int foo);
+ virtual ~Foo();
+ virtual void one();
+ virtual void two();
};
class Bar: public Foo {
public:
- virtual void three();
+ virtual void three();
};
@@ -3087,12 +3087,12 @@ references. Here is an example:
class Foo {
public:
- ...
+ ...
};
class FooContainer {
public:
- void addFoo(Foo *);
- ...
+ void addFoo(Foo *);
+ ...
};
@@ -3133,9 +3133,9 @@ suffice in most cases:
%feature("director:except") {
- if ($error != NULL) {
- throw Swig::DirectorMethodException();
- }
+ if ($error != NULL) {
+ throw Swig::DirectorMethodException();
+ }
}
%exception {
- try { $action }
- catch (Swig::DirectorException &e) { SWIG_fail; }
+ try { $action }
+ catch (Swig::DirectorException &e) { SWIG_fail; }
}
class Foo {
…
- virtual const int& bar();
+ virtual const int& bar();
…
};
@@ -3258,7 +3258,7 @@ types, wherever possible, for example
class Foo {
…
- virtual int bar();
+ virtual int bar();
…
};
@@ -3511,7 +3511,7 @@ def bar(*args):
class Foo {
public:
- int bar(int x);
+ int bar(int x);
};
@@ -3548,7 +3548,7 @@ proxy, just before the return statement.
class Foo {
public:
- int bar(int x);
+ int bar(int x);
};
@@ -3577,7 +3577,7 @@ SWIG version 1.3.28 you can use the directive forms
class Foo {
public:
- int bar(int x);
+ int bar(int x);
};
@@ -3606,8 +3606,8 @@ as it will then get attached to all the overloaded C++ methods. For example:
class Foo {
public:
- int bar(int x);
- int bar();
+ int bar(int x);
+ int bar();
};
@@ -4142,11 +4142,11 @@ Sometimes a C function expects an array to be passed as a pointer. For example,
int sumitems(int *first, int nitems) {
- int i, sum = 0;
- for (i = 0; i < nitems; i++) {
- sum += first[i];
- }
- return sum;
+ int i, sum = 0;
+ for (i = 0; i < nitems; i++) {
+ sum += first[i];
+ }
+ return sum;
}
# Copy a file def filecopy(source, target): - f1 = fopen(source, "r") - f2 = fopen(target, "w") - buffer = malloc(8192) - nbytes = fread(buffer, 8192, 1, f1) - while (nbytes > 0): - fwrite(buffer, 8192, 1, f2) - nbytes = fread(buffer, 8192, 1, f1) - free(buffer) + f1 = fopen(source, "r") + f2 = fopen(target, "w") + buffer = malloc(8192) + nbytes = fread(buffer, 8192, 1, f1) + while (nbytes > 0): + fwrite(buffer, 8192, 1, f2) + nbytes = fread(buffer, 8192, 1, f1) + free(buffer)
@@ -1236,9 +1236,9 @@ creating a wrapper equivalent to the following:
double wrap_dot_product(Vector *a, Vector *b) {
- Vector x = *a;
- Vector y = *b;
- return dot_product(x, y);
+ Vector x = *a;
+ Vector y = *b;
+ return dot_product(x, y);
}
Vector *wrap_cross_product(Vector *v1, Vector *v2) {
- Vector x = *v1;
- Vector y = *v2;
- Vector *result;
- result = (Vector *) malloc(sizeof(Vector));
- *(result) = cross(x, y);
- return result;
+ Vector x = *v1;
+ Vector y = *v2;
+ Vector *result;
+ result = (Vector *) malloc(sizeof(Vector));
+ *(result) = cross(x, y);
+ return result;
}
Vector *wrap_cross(Vector *v1, Vector *v2) {
- Vector x = *v1;
- Vector y = *v2;
- Vector *result = new Vector(cross(x, y)); // Uses default copy constructor
- return result;
+ Vector x = *v1;
+ Vector y = *v2;
+ Vector *result = new Vector(cross(x, y)); // Uses default copy constructor
+ return result;
}
struct Vector *new_Vector() {
- return (Vector *) calloc(1, sizeof(struct Vector));
+ return (Vector *) calloc(1, sizeof(struct Vector));
}
void delete_Vector(struct Vector *obj) {
- free(obj);
+ free(obj);
}
WORD Foo_w_get(Foo *f) {
- return f->w;
+ return f->w;
}
void Foo_w_set(FOO *f, WORD value) {
- f->w = value;
+ f->w = value;
}
// Add a new attribute to Vector
%extend Vector {
- const double magnitude;
+ const double magnitude;
}
// Now supply the implementation of the Vector_magnitude_get function
%{
diff --git a/Doc/Manual/SWIGPlus.html b/Doc/Manual/SWIGPlus.html
index 0667623bc..57da73d31 100644
--- a/Doc/Manual/SWIGPlus.html
+++ b/Doc/Manual/SWIGPlus.html
@@ -49,6 +49,16 @@
class List {
public:
- List();
- List(const List &); // Copy constructor
- ...
+ List();
+ List(const List &); // Copy constructor
+ ...
};
@@ -803,7 +813,7 @@ through a special function like this:
List *copy_List(List *f) {
- return new List(*f);
+ return new List(*f);
}
class Foo {
public:
- Foo();
+ Foo();
%name(CopyFoo) Foo(const Foo &);
- ...
+ ...
};
@@ -969,8 +979,8 @@ not primitive types, such as classes. For instance, if you had another class lik
class Foo {
public:
- List items;
- ...
+ List items;
+ ...
@@ -982,10 +992,10 @@ For example:
List *Foo_items_get(Foo *self) {
- return &self->items;
+ return &self->items;
}
void Foo_items_set(Foo *self, List *value) {
- self->items = *value;
+ self->items = *value;
}
const List &Foo_items_get(Foo *self) {
- return self->items;
+ return self->items;
}
void Foo_items_set(Foo *self, const List &value) {
- self->items = value;
+ self->items = value;
}
class Foo {
public:
- void bar(int x, int y = 3, int z = 4);
+ void bar(int x, int y = 3, int z = 4);
};
@@ -1120,9 +1130,9 @@ Thus for the example above, it is as if we had instead given the following to SW
class Foo {
public:
- void bar(int x, int y, int z);
- void bar(int x, int y);
- void bar(int x);
+ void bar(int x, int y, int z);
+ void bar(int x, int y);
+ void bar(int x);
};
@@ -1158,7 +1168,7 @@ can be re-activated by using the compactdefaultargs
%feature("compactdefaultargs") Foo::bar;
class Foo {
public:
- void bar(int x, int y = 3, int z = 4);
+ void bar(int x, int y = 3, int z = 4);
};
@@ -1278,7 +1288,7 @@ equivalent to one generated for the following declaration
class Foo {
public:
- ...
+ ...
};
void blah(Foo *f);
@@ -1485,8 +1495,8 @@ class A;
%feature("valuewrapper") B;
struct B {
- B();
- // ....
+ B();
+ // ....
};
@@ -2936,63 +2946,76 @@ as vector<int>. The wrapper for foo() will
accept either variant.
+-Starting with SWIG-1.3.7, simple C++ template declarations can also be -wrapped. SWIG-1.3.12 greatly expands upon the earlier implementation. Before discussing this any further, there are a few things -you need to know about template wrapping. First, a bare C++ template +There are a couple of important points about template wrapping. +First, a bare C++ template does not define any sort of runnable object-code for which SWIG can normally create a wrapper. Therefore, in order to wrap a template, you need to give SWIG information about a particular template -instantiation (e.g., vector<int>, +instantiation (e.g., vector<int>, array<double>, etc.). Second, an instantiation name such as vector<int> is generally not a valid identifier name in most target languages. Thus, you will need to give the -template instantiation a more suitable name such as intvector -when creating a wrapper. +template instantiation a more suitable name such as intvector.
-To illustrate, consider the following template definition: +To illustrate, consider the following class template definition:
template<class T> class List {
private:
- T *data;
- int nitems;
- int maxitems;
+ T *data;
+ int nitems;
+ int maxitems;
public:
- List(int max) {
- data = new T [max];
- nitems = 0;
- maxitems = max;
- }
- ~List() {
- delete [] data;
- };
- void append(T obj) {
- if (nitems < maxitems) {
- data[nitems++] = obj;
- }
- }
- int length() {
- return nitems;
- }
- T get(int n) {
- return data[n];
+ List(int max) {
+ data = new T [max];
+ nitems = 0;
+ maxitems = max;
+ }
+ ~List() {
+ delete [] data;
+ };
+ void append(T obj) {
+ if (nitems < maxitems) {
+ data[nitems++] = obj;
}
+ }
+ int length() {
+ return nitems;
+ }
+ T get(int n) {
+ return data[n];
+ }
};
-By itself, this template declaration is useless--SWIG simply ignores it -because it doesn't know how to generate any code until unless a definition of +By itself, this class template is useless--SWIG simply ignores it +because it doesn't know how to generate any code unless a definition of T is provided. +The %template directive is required to instantiate the template for use in a target language. +The directive requires an identifier name for use in the target language plus the template for instantiation. +The example below instantiates List<int> for use as a class named intList:
++%template(intList) List<int>; ++
-One way to create wrappers for a specific template instantiation is to simply -provide an expanded version of the class directly like this: +The instantiation expands the template code as a C++ compiler would do and then makes it available +under the given identifier name. +Essentially it is the same as wrapping the following concept code where +the class template definition has T expanded to int +(note that this is not entirely valid syntax):
-The %rename directive is needed to give the template class an appropriate identifier -name in the target language (most languages would not recognize C++ template syntax as a valid -class name). The rest of the code is the same as what would appear in a normal -class definition. -
- --Since manual expansion of templates gets old in a hurry, the %template directive can -be used to create instantiations of a template class. Semantically, %template is -simply a shortcut---it expands template code in exactly the same way as shown above. Here -are some examples: -
- --/* Instantiate a few different versions of the template */ -%template(intList) List<int>; -%template(doubleList) List<double>; --
The argument to %template() is the name of the instantiation in the target language. The name you choose should not conflict with @@ -3053,7 +3054,81 @@ typedef List<int> intList; // OK
-SWIG can also generate wrappers for function templates using a similar technique. +The %template directive +must always appear after the definition of the template to be expanded, so the following will work: +
+ +
+template<class T> class List { ... };
+%template(intList) List<int>;
+
++but if %template is used before the template definition, such as: +
+ +
+%template(intList) List<int>;
+template<class T> class List { ... };
+
++SWIG will generate an error: +
+ ++example.i:3: Error: Template 'List' undefined. ++
+Since the type system knows how to handle typedef, it is +generally not necessary to instantiate different versions of a template +for typenames that are equivalent. For instance, consider this code: +
+ ++%template(intList) List<int>; +typedef int Integer; +... +void foo(List<Integer> *x); ++
+In this case, List<Integer> is exactly the same type as +List<int>. Any use of List<Integer> is mapped back to the +instantiation of List<int> created earlier. Therefore, it is +not necessary to instantiate a new class for the type Integer (doing so is +redundant and will simply result in code bloat). +
+ ++The template provide to %template for instantiation must be the actual template and not a typedef to a template. +
+ ++typedef List<int> ListOfInt; + +%template(intList) List<int>; // ok +%template(intList) ListOfInt; // illegal - Syntax error ++
+SWIG can also generate wrappers for function templates using a similar technique +to that shown above for class templates. For example:
@@ -3073,6 +3148,28 @@ In this case, maxint and maxdouble become unique names for spe instantiations of the function. ++SWIG even supports overloaded templated functions. As usual the %template directive +is used to wrap templated functions. For example: +
+ +
+template<class T> void foo(T x) { };
+template<class T> void foo(T x, T y) { };
+
+%template(foo) foo<int>;
+
++This will generate two overloaded wrapper methods, the first will take a single integer as an argument +and the second will take two integer arguments. +
+ +The number of arguments supplied to %template should match that in the original template definition. Template default arguments are supported. For example: @@ -3110,28 +3207,8 @@ instantiation only once in order to reduce the potential for code bloat.
--Since the type system knows how to handle typedef, it is -generally not necessary to instantiate different versions of a template -for typenames that are equivalent. For instance, consider this code: -
+-%template(intList) vector<int>; -typedef int Integer; -... -void foo(vector<Integer> *x); --
-In this case, vector<Integer> is exactly the same type as -vector<int>. Any use of Vector<Integer> is mapped back to the -instantiation of vector<int> created earlier. Therefore, it is -not necessary to instantiate a new class for the type Integer (doing so is -redundant and will simply result in code bloat). -
When a template is instantiated using %template, information @@ -3158,13 +3235,13 @@ nothing is known about List<int>, you will get a warning message
-example.h:42: Warning 401. Nothing known about class 'List<int >'. Ignored. -example.h:42: Warning 401. Maybe you forgot to instantiate 'List<int >' using %template. +example.h:42: Warning 401. Nothing known about class 'List< int >'. Ignored. +example.h:42: Warning 401. Maybe you forgot to instantiate 'List< int >' using %template.
-If a template class inherits from another template class, you need to +If a class template inherits from another class template, you need to make sure that base classes are instantiated before derived classes. For example:
@@ -3235,6 +3312,9 @@ TEMPLATE_WRAP(PairStringInt, std::pair<string, int>) Note the use of a vararg macro for the type T. If this wasn't used, the comma in the templated type in the last example would not be possible. +The SWIG template mechanism does support specialization. For instance, if you define a class like this, @@ -3244,15 +3324,15 @@ a class like this,
template<> class List<int> {
private:
- int *data;
- int nitems;
- int maxitems;
+ int *data;
+ int nitems;
+ int maxitems;
public:
- List(int max);
- ~List();
- void append(int obj);
- int length();
- int get(int n);
+ List(int max);
+ ~List();
+ void append(int obj);
+ int length();
+ int get(int n);
};
@@ -3275,15 +3355,15 @@ code defines a template that is applied when the template argument is a pointer.
template<class T> class List<T*> {
private:
- T *data;
- int nitems;
- int maxitems;
+ T *data;
+ int nitems;
+ int maxitems;
public:
- List(int max);
- ~List();
- void append(int obj);
- int length();
- T get(int n);
+ List(int max);
+ ~List();
+ void append(T obj);
+ int length();
+ T get(int n);
};
@@ -3322,10 +3402,13 @@ SWIG implements template argument deduction so that the following partial specia
+-Member function templates are supported. The underlying principle is the same +Member templates are supported. The underlying principle is the same as for normal templates--SWIG can't create a wrapper unless you provide -more information about types. For example, a class with a member template might +more information about types. For example, a class with a member function template might look like this:
@@ -3399,11 +3482,6 @@ methods to the Foo class. --Note: because of the way that templates are handled, the %template directive -must always appear after the definition of the template to be expanded. -
-Now, if your target language supports overloading, you can even try
@@ -3424,7 +3502,7 @@ depending on the argument type.When used with members, the %template directive may be placed in another -template class. Here is a slightly perverse example: +class template. Here is a slightly perverse example:
This declaration is perfectly acceptable to SWIG, but the constructor template will be ignored unless you explicitly expand it. To do that, you could expand a few versions of the constructor -in the template class itself. For example: +in the class template itself. For example:
+The %template directive for a class template is the equivalent to an explicit instantiation +of a C++ class template. The scope for a valid %template instantiation is the same +as the scope required for a valid explicit instantiation of a C++ template. +A definition of the template for the explicit instantiation must be in scope +where the instantiation is declared and must not be enclosed within a different namespace. +
+ ++For example, a few %template instantiations and C++ explicit instantiations are shown below: +
+ +
+namespace N {
+ template<typename T> class C {};
+}
+
+// valid
+%template(cin) N::C<int>;
+template class N::C<int>;
+
+// valid
+namespace N {
+ %template(cin) C<int>;
+ template class C<int>;
+}
+
+// valid
+using namespace N;
+%template(cin) C<int>;
+template class C<int>;
+
+// valid
+using N::C;
+%template(cin) C<int>;
+template class C<int>;
+
+// ill-formed
+namespace unrelated {
+ using N::C;
+ %template(cin) C<int>;
+ template class C<int>;
+}
+
+// ill-formed
+namespace unrelated {
+ using namespace N;
+ %template(cin) C<int>;
+ template class C<int>;
+}
+
+// ill-formed
+namespace unrelated {
+ namespace N {
+ %template(cin) C<int>;
+ template class C<int>;
+ }
+}
+
+// ill-formed
+namespace unrelated {
+ %template(cin) N::C<int>;
+ template class N::C<int>;
+}
+
++When the scope is incorrect, such as for the ill-formed examples above, an error occurs: +
+ ++cpp_template_scope.i:34: Error: 'C' resolves to 'N::C' and was incorrectly instantiated +in scope 'unrelated' instead of within scope 'N'. ++
+A note for the C++ standard geeks out there; a valid instantiation is one which conforms to +the C++03 standard as C++11 made a change to disallow using declarations and using directives to find a template. +
+ ++// valid C++03, ill-formed C++11 +using N::C; +template class C<int>; ++
+Compatibility Note: Versions prior to SWIG-4.0.0 did not error out with incorrectly scoped +%template declarations, but this led to numerous subtle template scope problems. +
+ + +If all of this isn't quite enough and you really want to make someone's head explode, SWIG directives such as @@ -3568,7 +3750,7 @@ instantiation.
-It is also possible to separate these declarations from the template class. For example: +It is also possible to separate these declarations from the class template. For example:
-SWIG even supports overloaded templated functions. As usual the %template directive -is used to wrap templated functions. For example: -
- -
-template<class T> void foo(T x) { };
-template<class T> void foo(T x, T y) { };
-
-%template(foo) foo<int>;
-
--This will generate two overloaded wrapper methods, the first will take a single integer as an argument -and the second will take two integer arguments. -
-It is even possible to extend a class via %extend with template methods, for example:
@@ -3694,20 +3857,20 @@ For example:
template <class T> class OuterTemplateClass {};
-// The nested class OuterClass::InnerClass inherits from the template class
+// The nested class OuterClass::InnerClass inherits from the class template
// OuterTemplateClass<OuterClass::InnerStruct> and thus the template needs
// to be expanded with %template before the OuterClass declaration.
%template(OuterTemplateClass_OuterClass__InnerStruct)
- OuterTemplateClass<OuterClass::InnerStruct>
+ OuterTemplateClass<OuterClass::InnerStruct>
// Don't forget to use %feature("flatnested") for OuterClass::InnerStruct and
// OuterClass::InnerClass if the target language doesn't support nested classes.
class OuterClass {
- public:
- // Forward declarations:
- struct InnerStruct;
- class InnerClass;
+ public:
+ // Forward declarations:
+ struct InnerStruct;
+ class InnerClass;
};
struct OuterClass::InnerStruct {};
@@ -3736,7 +3899,7 @@ introduced a new class name. This name could then be used with other directives
%template(vectori) vector<int>;
%extend vectori {
- void somemethod() { }
+ void somemethod() { }
};
%template(vectori) vector<int>;
%extend vector<int> {
- void somemethod() { }
+ void somemethod() { }
};
@@ -3915,6 +4078,8 @@ then SWIG simply creates three wrapper functions bar(),
spam(), and blah() in the target language. SWIG
does not prepend the names with a namespace prefix nor are the
functions packaged in any kind of nested scope.
+Note that the default handling of flattening all the namespace scopes in the target language
+can be changed via the nspace feature.
@@ -4009,7 +4174,7 @@ in a different namespace. For example:
namespace foo {
- template<typename T> T max(T a, T b) { return a > b ? a : b; }
+ template<typename T> T max(T a, T b) { return a > b ? a : b; }
}
using foo::max;
@@ -4018,8 +4183,8 @@ using foo::max;
%template(maxfloat) foo::max<float>; // Okay (qualified name).
namespace bar {
- using namespace foo;
- %template(maxdouble) max<double>; // Okay.
+ using namespace foo;
+ %template(maxdouble) max<double>; // Okay.
}
Note: The flattening of namespaces is only intended to serve as a basic namespace implementation. -None of the target language modules are currently programmed -with any namespace awareness. In the future, language modules may or may not provide -more advanced namespace support. +More advanced handling of namespaces is discussed next.
-%rename(bbb) Space::ABC::aaa(T t); // will match but with lower precedence than ccc
+%rename(bbb) Space::ABC::aaa(T t); // will match but with lower precedence than ccc
%rename(ccc) Space::ABC<Space::XYZ>::aaa(Space::XYZ t);// will match but with higher precedence
- // than bbb
+ // than bbb
namespace Space {
class XYZ {};
@@ -4381,9 +4544,9 @@ class Error { };
class Foo {
public:
- ...
- void blah() throw(Error);
- ...
+ ...
+ void blah() throw(Error);
+ ...
};
@@ -4445,10 +4608,10 @@ struct Error4 : EBase { };
class Foo {
public:
- ...
- void bar();
- void blah() throw(Error1, Error2, Error3, Error4);
- ...
+ ...
+ void bar();
+ void blah() throw(Error1, Error2, Error3, Error4);
+ ...
};
@@ -4524,7 +4687,7 @@ for member pointers.
In some C++ programs, objects are often encapsulated by smart-pointers or proxy classes. This is sometimes done to implement automatic memory management (reference counting) or -persistence. Typically a smart-pointer is defined by a template class where +persistence. Typically a smart-pointer is defined by a class template where the -> operator has been overloaded. This class is then wrapped around some other class. For example:
@@ -4533,21 +4696,21 @@ around some other class. For example:
// Smart-pointer class
template<class T> class SmartPtr {
- T *pointee;
+ T *pointee;
public:
- SmartPtr(T *p) : pointee(p) { ... }
- T *operator->() {
- return pointee;
- }
- ...
+ SmartPtr(T *p) : pointee(p) { ... }
+ T *operator->() {
+ return pointee;
+ }
+ ...
};
// Ordinary class
class Foo_Impl {
public:
- int x;
- virtual void bar();
- ...
+ int x;
+ virtual void bar();
+ ...
};
// Smart-pointer wrapper
@@ -4555,13 +4718,13 @@ typedef SmartPtr<Foo_Impl> Foo;
// Create smart pointer Foo
Foo make_Foo() {
- return SmartPtr<Foo_Impl>(new Foo_Impl());
+ return SmartPtr<Foo_Impl>(new Foo_Impl());
}
// Do something with smart pointer Foo
void do_something(Foo f) {
- printf("x = %d\n", f->x);
- f->bar();
+ printf("x = %d\n", f->x);
+ f->bar();
}
// Call the wrapped smart pointer proxy class in the target language 'Foo'
@@ -4660,13 +4823,13 @@ example, if you have this code
class Foo {
public:
- int x;
+ int x;
};
class Bar {
public:
- int x;
- Foo *operator->();
+ int x;
+ Foo *operator->();
};
@@ -4915,19 +5078,19 @@ base classes. For example:
class Foo {
public:
- int blah(int x);
+ int blah(int x);
};
class Bar {
public:
- double blah(double x);
+ double blah(double x);
};
class FooBar : public Foo, public Bar {
public:
- using Foo::blah;
- using Bar::blah;
- char *blah(const char *x);
+ using Foo::blah;
+ using Bar::blah;
+ char *blah(const char *x);
};
@@ -4970,14 +5133,14 @@ you wrap this code in Python, the module works just like you would expect:
class Foo {
protected:
- int x;
- int blah(int x);
+ int x;
+ int blah(int x);
};
class Bar : public Foo {
public:
- using Foo::x; // Make x public
- using Foo::blah; // Make blah public
+ using Foo::x; // Make x public
+ using Foo::blah; // Make blah public
};
@@ -5008,14 +5171,14 @@ correctly, you can always change the interface to the following:
class FooBar : public Foo, public Bar {
public:
#ifndef SWIG
- using Foo::blah;
- using Bar::blah;
+ using Foo::blah;
+ using Bar::blah;
#else
- int blah(int x); // explicitly tell SWIG about other declarations
- double blah(double x);
+ int blah(int x); // explicitly tell SWIG about other declarations
+ double blah(double x);
#endif
- char *blah(const char *x);
+ char *blah(const char *x);
};
diff --git a/Doc/Manual/Scilab.html b/Doc/Manual/Scilab.html
index 44c570b9b..bfde99fa3 100644
--- a/Doc/Manual/Scilab.html
+++ b/Doc/Manual/Scilab.html
@@ -121,15 +121,15 @@ In this example we bind from C a function and a global variable into Scilab. The
double Foo = 3.0;
int fact(int n) {
- if (n < 0) {
- return 0;
- }
- else if (n == 0) {
- return 1;
- }
- else {
- return n * fact(n-1);
- }
+ if (n < 0) {
+ return 0;
+ }
+ else if (n == 0) {
+ return 1;
+ }
+ else {
+ return n * fact(n-1);
+ }
}
%}
@@ -896,8 +896,8 @@ Let's see it on an example of a struct with two members:
%inline %{
typedef struct {
- int x;
- int arr[4];
+ int x;
+ int arr[4];
} Foo;
%}
@@ -1143,11 +1143,11 @@ As explained in 6.15 SWI
%module example
void magnify(Square *square, double factor) {
- square->size *= factor;
+ square->size *= factor;
};
void magnify(Circle *circle, double factor) {
- square->radius *= factor;
+ square->radius *= factor;
};
diff --git a/Doc/Manual/Tcl.html b/Doc/Manual/Tcl.html
index 38d4103e0..41cb78661 100644
--- a/Doc/Manual/Tcl.html
+++ b/Doc/Manual/Tcl.html
@@ -958,7 +958,7 @@ Foo *BarToFoo(Bar *b) {
}
Foo *IncrFoo(Foo *f, int i) {
- return f+i;
+ return f+i;
}
%}
@@ -1054,7 +1054,7 @@ example, consider this:
struct Bar {
- int x[16];
+ int x[16];
};
class Foo {
public:
- Foo();
- Foo(const Foo &);
- ...
+ Foo();
+ Foo(const Foo &);
+ ...
};
@@ -1693,11 +1693,11 @@ For example:
%rename(Bar_spam) Bar::spam;
namespace Foo {
- int spam();
+ int spam();
}
namespace Bar {
- int spam();
+ int spam();
}
@@ -1886,19 +1886,19 @@ then SWIG transforms it into a set of low-level procedural wrappers. For example
Foo *new_Foo() {
- return new Foo();
+ return new Foo();
}
void delete_Foo(Foo *f) {
- delete f;
+ delete f;
}
int Foo_x_get(Foo *f) {
- return f->x;
+ return f->x;
}
void Foo_x_set(Foo *f, int value) {
- f->x = value;
+ f->x = value;
}
int Foo_spam(Foo *f, int arg1) {
- return f->spam(arg1);
+ return f->spam(arg1);
}
class Foo {
public:
- Foo();
- Foo bar();
+ Foo();
+ Foo bar();
};
@@ -1975,9 +1975,9 @@ they came from. Therefore, the ownership is set to zero. For example:
class Foo {
public:
- ...
- Foo *spam();
- ...
+ ...
+ Foo *spam();
+ ...
};
@@ -2011,8 +2011,8 @@ or global variable. For example, consider this interface:
%module example
struct Foo {
- int value;
- Foo *next;
+ int value;
+ Foo *next;
};
Foo *head = 0;
@@ -2465,9 +2465,9 @@ you might define a typemap like this:
%module example
%typemap(in) int {
- if (Tcl_GetIntFromObj(interp, $input, &$1) == TCL_ERROR)
- return TCL_ERROR;
- printf("Received an integer : %d\n", $1);
+ if (Tcl_GetIntFromObj(interp, $input, &$1) == TCL_ERROR)
+ return TCL_ERROR;
+ printf("Received an integer : %d\n", $1);
}
%inline %{
extern int fact(int n);
@@ -2585,7 +2585,7 @@ like this:
%typemap(out) int {
- Tcl_SetObjResult(interp, Tcl_NewIntObj($1));
+ Tcl_SetObjResult(interp, Tcl_NewIntObj($1));
}
%typemap(in) (...) {
- // Get variable length arguments (somehow)
- ...
+ // Get variable length arguments (somehow)
+ ...
}
%typemap(in) (const char *fmt, ...) {
diff --git a/Examples/test-suite/class_scope_namespace.i b/Examples/test-suite/class_scope_namespace.i
new file mode 100644
index 000000000..372727f3c
--- /dev/null
+++ b/Examples/test-suite/class_scope_namespace.i
@@ -0,0 +1,152 @@
+// Test a mix of forward class declarations, class definitions, using declarations and using directives.
+
+%module class_scope_namespace
+
+%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) H::HH;
+%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Space8::I::II;
+
+%inline %{
+struct A;
+namespace Space1 {
+ namespace SubSpace1 {
+ struct A {
+ void aa(Space1::SubSpace1::A, SubSpace1::A, A) {}
+ };
+ void aaa(Space1::SubSpace1::A, SubSpace1::A, A) {}
+ }
+}
+
+namespace Space2 {
+ struct B;
+}
+using Space2::B;
+struct B {
+ void bb(Space2::B, B) {}
+};
+void bbb(Space2::B, B) {}
+
+namespace Space3 {
+ namespace SubSpace3 {
+ struct C;
+ struct D;
+ }
+}
+struct C;
+struct D;
+namespace Space3 {
+ struct C;
+ struct SubSpace3::C {
+ void cc(Space3::SubSpace3::C, SubSpace3::C) {}
+ };
+ using SubSpace3::D;
+ struct SubSpace3::D {
+ void dd(Space3::SubSpace3::D, SubSpace3::D, D) {}
+ };
+ void ccc(Space3::SubSpace3::C, SubSpace3::C) {}
+ void ddd(Space3::SubSpace3::D, SubSpace3::D, D) {}
+}
+
+namespace Space4 {
+ namespace SubSpace4 {
+ struct E;
+ }
+}
+using namespace Space4;
+using SubSpace4::E;
+// Was added to incorrect namespace in swig-3.0.12
+struct SubSpace4::E {
+ void ee(Space4::SubSpace4::E, SubSpace4::E, E) {}
+};
+void eee(Space4::SubSpace4::E, SubSpace4::E, E) {}
+
+namespace Space5 {
+ namespace SubSpace5 {
+ namespace SubSubSpace5 {
+ struct F;
+ }
+ }
+}
+namespace Space5 {
+ using namespace SubSpace5;
+ using SubSubSpace5::F;
+ // Was added to incorrect namespace in swig-3.0.12
+ struct SubSubSpace5::F {
+ void ff(Space5::SubSpace5::SubSubSpace5::F, SubSpace5::SubSubSpace5::F, SubSubSpace5::F, F) {}
+ };
+ void fff(Space5::SubSpace5::SubSubSpace5::F, SubSpace5::SubSubSpace5::F, SubSubSpace5::F, F) {}
+}
+
+namespace Space6 {
+ struct G;
+ namespace SubSpace6 {
+ struct G;
+ }
+}
+namespace Space6 {
+ struct SubSpace6::G {
+ void gg(Space6::SubSpace6::G, SubSpace6::G) {}
+ };
+ void ggg(Space6::SubSpace6::G, SubSpace6::G) {}
+}
+
+struct HH;
+struct H {
+ struct HH {
+ void hh(H::HH) {}
+ };
+};
+void hhh(H::HH) {}
+
+namespace Space8 {
+ struct II;
+ struct I {
+ struct II {
+ void ii(Space8::I::II, I::II) {}
+ };
+ };
+ void iii(Space8::I::II, I::II) {}
+}
+
+struct J;
+namespace Space9 {
+ namespace SubSpace9 {
+ struct J {
+ void jj(Space9::SubSpace9::J, SubSpace9::J, J) {}
+ };
+ void jjj(Space9::SubSpace9::J, SubSpace9::J, J) {}
+ }
+}
+
+namespace Space10 {
+ struct K;
+}
+namespace Space10 {
+ namespace SubSpace10 {
+ struct K {
+ void kk(Space10::SubSpace10::K, SubSpace10::K, K) {}
+ };
+ void kkk(Space10::SubSpace10::K, SubSpace10::K, K) {}
+ }
+}
+
+namespace OtherSpace {
+ struct L;
+ struct M;
+}
+using OtherSpace::L;
+namespace Space11 {
+ using OtherSpace::M;
+ namespace SubSpace11 {
+ struct L {
+ void ll(Space11::SubSpace11::L, SubSpace11::L, L) {}
+ };
+ void lll(Space11::SubSpace11::L, SubSpace11::L, L) {}
+ struct M {
+ void mm(Space11::SubSpace11::M, SubSpace11::M, M) {}
+ };
+ void mmm(Space11::SubSpace11::M, SubSpace11::M, M) {}
+ }
+}
+
+%}
+
diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk
index b7ea38f10..e3448dcbc 100644
--- a/Examples/test-suite/common.mk
+++ b/Examples/test-suite/common.mk
@@ -136,6 +136,7 @@ CPP_TEST_CASES += \
char_binary \
char_strings \
chartest \
+ class_scope_namespace \
class_forward \
class_ignore \
class_scope_weird \
@@ -291,6 +292,7 @@ CPP_TEST_CASES += \
multiple_inheritance_shared_ptr \
name_cxx \
name_warnings \
+ namespace_chase \
namespace_class \
namespace_enum \
namespace_extend \
@@ -435,6 +437,7 @@ CPP_TEST_CASES += \
template_methods \
template_namespace_forward_declaration \
template_using_directive_and_declaration_forward \
+ template_using_directive_typedef \
template_nested \
template_nested_typemaps \
template_ns \
@@ -445,6 +448,7 @@ CPP_TEST_CASES += \
template_ns_enum2 \
template_ns_inherit \
template_ns_scope \
+ template_parameters_global_scope \
template_partial_arg \
template_partial_specialization \
template_partial_specialization_typedef \
diff --git a/Examples/test-suite/errors/cpp_class_definition.i b/Examples/test-suite/errors/cpp_class_definition.i
new file mode 100644
index 000000000..8381e75cc
--- /dev/null
+++ b/Examples/test-suite/errors/cpp_class_definition.i
@@ -0,0 +1,26 @@
+%module xxx
+
+// This should error but doesn't
+#if 0
+namespace OtherSpace {
+ struct L;
+}
+namespace Space11 {
+ namespace SubSpace11 {
+ using OtherSpace::L;
+ struct L {
+ void ll();
+ };
+ }
+}
+#endif
+
+namespace Space1 {
+ struct A;
+}
+namespace Space2 {
+ struct Space1::A {
+ void x();
+ };
+}
+
diff --git a/Examples/test-suite/errors/cpp_class_definition.stderr b/Examples/test-suite/errors/cpp_class_definition.stderr
new file mode 100644
index 000000000..2c4102842
--- /dev/null
+++ b/Examples/test-suite/errors/cpp_class_definition.stderr
@@ -0,0 +1 @@
+cpp_class_definition.i:22: Error: 'Space1::A' resolves to 'Space1::A' and was incorrectly instantiated in scope 'Space2' instead of within scope 'Space1'.
diff --git a/Examples/test-suite/errors/cpp_invalid_template.i b/Examples/test-suite/errors/cpp_invalid_template.i
new file mode 100644
index 000000000..ea0d7beac
--- /dev/null
+++ b/Examples/test-suite/errors/cpp_invalid_template.i
@@ -0,0 +1,9 @@
+%module cpp_invalid_scope
+
+%template(abc) SSS::AAA;
+
+namespace UUU {
+ struct JJJ;
+}
+
+%template(xxx) UUU::JJJ;
diff --git a/Examples/test-suite/errors/cpp_invalid_template.stderr b/Examples/test-suite/errors/cpp_invalid_template.stderr
new file mode 100644
index 000000000..f6bfaaf7d
--- /dev/null
+++ b/Examples/test-suite/errors/cpp_invalid_template.stderr
@@ -0,0 +1,3 @@
+cpp_invalid_template.i:3: Error: Undefined scope 'SSS'
+cpp_invalid_template.i:3: Error: Template 'SSS::AAA' undefined.
+cpp_invalid_template.i:9: Error: 'JJJ' is not defined as a template. (classforward)
diff --git a/Examples/test-suite/errors/cpp_namespace_template_bad.i b/Examples/test-suite/errors/cpp_namespace_template_bad.i
new file mode 100644
index 000000000..5c42d6dcb
--- /dev/null
+++ b/Examples/test-suite/errors/cpp_namespace_template_bad.i
@@ -0,0 +1,40 @@
+%module namespace_template
+
+namespace test {
+ template T max(T a, T b) { return (a > b) ? a : b; }
+ template class vector {
+ public:
+ vector() { }
+ ~vector() { }
+ };
+}
+
+namespace test2 {
+ using namespace test;
+ %template(maxshort) max;
+ %template(vectorshort) vector;
+}
+
+namespace test3 {
+ using test::max;
+ using test::vector;
+ %template(maxlong) max;
+ %template(vectorlong) vector;
+}
+
+namespace test4 {
+ using namespace test;
+ typedef int Integer;
+}
+
+namespace test4 {
+ %template(maxInteger) max;
+ %template(vectorInteger) vector;
+}
+
+using namespace test;
+namespace test5 {
+ %template(maxdouble) max;
+ %template(vectordouble) vector;
+}
+
diff --git a/Examples/test-suite/errors/cpp_namespace_template_bad.stderr b/Examples/test-suite/errors/cpp_namespace_template_bad.stderr
new file mode 100644
index 000000000..5965d529c
--- /dev/null
+++ b/Examples/test-suite/errors/cpp_namespace_template_bad.stderr
@@ -0,0 +1,9 @@
+cpp_namespace_template_bad.i:14: Error: 'max' resolves to 'test::max' and was incorrectly instantiated in scope 'test2' instead of within scope 'test'.
+cpp_namespace_template_bad.i:15: Error: 'vector' resolves to 'test::vector' and was incorrectly instantiated in scope 'test2' instead of within scope 'test'.
+cpp_namespace_template_bad.i:21: Error: 'max' resolves to 'test::max' and was incorrectly instantiated in scope 'test3' instead of within scope 'test'.
+cpp_namespace_template_bad.i:22: Error: 'vector' resolves to 'test::vector' and was incorrectly instantiated in scope 'test3' instead of within scope 'test'.
+cpp_namespace_template_bad.i:31: Error: 'max' resolves to 'test::max' and was incorrectly instantiated in scope 'test4' instead of within scope 'test'.
+cpp_namespace_template_bad.i:32: Error: 'vector' resolves to 'test::vector' and was incorrectly instantiated in scope 'test4' instead of within scope 'test'.
+cpp_namespace_template_bad.i:37: Error: 'max' resolves to 'test::max' and was incorrectly instantiated in scope 'test5' instead of within scope 'test'.
+cpp_namespace_template_bad.i:37: Error: Template 'max' undefined.
+cpp_namespace_template_bad.i:38: Error: 'vector' resolves to 'test::vector' and was incorrectly instantiated in scope 'test5' instead of within scope 'test'.
diff --git a/Examples/test-suite/errors/cpp_nested_template.stderr b/Examples/test-suite/errors/cpp_nested_template.stderr
index 9e46cff74..363a260f6 100644
--- a/Examples/test-suite/errors/cpp_nested_template.stderr
+++ b/Examples/test-suite/errors/cpp_nested_template.stderr
@@ -1,2 +1,4 @@
+cpp_nested_template.i:9: Error: 'Temply' resolves to '::Temply' and was incorrectly instantiated in scope 'A' instead of within scope ''.
cpp_nested_template.i:9: Warning 324: Named nested template instantiations not supported. Processing as if no name was given to %template().
+cpp_nested_template.i:18: Error: 'Temply' resolves to '::Temply' and was incorrectly instantiated in scope 'B' instead of within scope ''.
cpp_nested_template.i:18: Warning 324: Named nested template instantiations not supported. Processing as if no name was given to %template().
diff --git a/Examples/test-suite/errors/cpp_template_scope.i b/Examples/test-suite/errors/cpp_template_scope.i
new file mode 100644
index 000000000..ec0f0a577
--- /dev/null
+++ b/Examples/test-suite/errors/cpp_template_scope.i
@@ -0,0 +1,57 @@
+%module xxx
+
+namespace std {
+ template class vector {};
+}
+
+struct S1 {};
+struct S2 {};
+struct S3 {};
+struct S4 {};
+struct S5 {};
+struct S6 {};
+struct S7 {};
+
+// valid
+namespace std {
+ %template(vi1) vector;
+ template class vector;
+}
+
+// valid
+using namespace std;
+%template(vi2) vector;
+template class vector;
+
+// valid
+using std::vector;
+%template(vi3) vector;
+template class vector;
+
+// ill-formed
+namespace unrelated {
+ using std::vector;
+ %template(vi4) vector;
+ template class vector;
+}
+
+// ill-formed
+namespace unrelated {
+ using namespace std;
+ %template(vi5) vector;
+ template class vector;
+}
+
+// ill-formed
+namespace unrelated {
+ namespace std {
+ %template(vi6) vector;
+ template class vector;
+ }
+}
+
+// ill-formed
+namespace unrelated {
+ %template(vi7) std::vector;
+ template class std::vector;
+}
diff --git a/Examples/test-suite/errors/cpp_template_scope.stderr b/Examples/test-suite/errors/cpp_template_scope.stderr
new file mode 100644
index 000000000..e47630268
--- /dev/null
+++ b/Examples/test-suite/errors/cpp_template_scope.stderr
@@ -0,0 +1,11 @@
+cpp_template_scope.i:18: Warning 320: Explicit template instantiation ignored.
+cpp_template_scope.i:24: Warning 320: Explicit template instantiation ignored.
+cpp_template_scope.i:29: Warning 320: Explicit template instantiation ignored.
+cpp_template_scope.i:34: Error: 'vector' resolves to 'std::vector' and was incorrectly instantiated in scope 'unrelated' instead of within scope 'std'.
+cpp_template_scope.i:35: Warning 320: Explicit template instantiation ignored.
+cpp_template_scope.i:41: Error: 'vector' resolves to 'std::vector' and was incorrectly instantiated in scope 'unrelated' instead of within scope 'std'.
+cpp_template_scope.i:42: Warning 320: Explicit template instantiation ignored.
+cpp_template_scope.i:48: Error: 'vector' resolves to 'std::vector' and was incorrectly instantiated in scope 'unrelated::std' instead of within scope 'std'.
+cpp_template_scope.i:49: Warning 320: Explicit template instantiation ignored.
+cpp_template_scope.i:55: Error: 'std::vector' resolves to 'std::vector' and was incorrectly instantiated in scope 'unrelated' instead of within scope 'std'.
+cpp_template_scope.i:56: Warning 320: Explicit template instantiation ignored.
diff --git a/Examples/test-suite/java/class_scope_namespace_runme.java b/Examples/test-suite/java/class_scope_namespace_runme.java
new file mode 100644
index 000000000..9d74a6ca6
--- /dev/null
+++ b/Examples/test-suite/java/class_scope_namespace_runme.java
@@ -0,0 +1,59 @@
+
+import class_scope_namespace.*;
+
+public class class_scope_namespace_runme {
+
+ static {
+ try {
+ System.loadLibrary("class_scope_namespace");
+ } 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[])
+ {
+ A a = new A();
+ B b = new B();
+ C c = new C();
+ D d = new D();
+ E e = new E();
+ F f = new F();
+ G g = new G();
+ H.HH h = new H.HH();
+ I.II i = new I.II();
+ J j = new J();
+ K k = new K();
+ L l = new L();
+ M m = new M();
+
+ a.aa(a, a, a);
+ b.bb(b, b);
+ c.cc(c, c);
+ d.dd(d, d, d);
+ e.ee(e, e, e);
+ f.ff(f, f, f, f);
+ g.gg(g, g);
+ h.hh(h);
+ i.ii(i, i);
+ j.jj(j, j, j);
+ k.kk(k, k, k);
+ l.ll(l, l, l);
+ m.mm(m, m, m);
+
+ class_scope_namespace.aaa(a, a, a);
+ class_scope_namespace.bbb(b, b);
+ class_scope_namespace.ccc(c, c);
+ class_scope_namespace.ddd(d, d, d);
+ class_scope_namespace.eee(e, e, e);
+ class_scope_namespace.fff(f, f, f, f);
+ class_scope_namespace.ggg(g, g);
+ class_scope_namespace.hhh(h);
+ class_scope_namespace.iii(i, i);
+ class_scope_namespace.jjj(j, j, j);
+ class_scope_namespace.kkk(k, k, k);
+ class_scope_namespace.lll(l, l, l);
+ class_scope_namespace.mmm(m, m, m);
+ }
+}
diff --git a/Examples/test-suite/java/cpp11_template_typedefs_runme.java b/Examples/test-suite/java/cpp11_template_typedefs_runme.java
new file mode 100644
index 000000000..473e7cf07
--- /dev/null
+++ b/Examples/test-suite/java/cpp11_template_typedefs_runme.java
@@ -0,0 +1,19 @@
+import cpp11_template_typedefs.*;
+
+public class cpp11_template_typedefs_runme {
+
+ static {
+ try {
+ System.loadLibrary("cpp11_template_typedefs");
+ } 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[]) {
+ int alloc1 = cpp11_template_typedefs.get_bucket_allocator1();
+ int alloc2 = cpp11_template_typedefs.get_bucket_allocator2();
+ }
+}
+
diff --git a/Examples/test-suite/java/namespace_chase_runme.java b/Examples/test-suite/java/namespace_chase_runme.java
new file mode 100644
index 000000000..9b4898bd0
--- /dev/null
+++ b/Examples/test-suite/java/namespace_chase_runme.java
@@ -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);
+ }
+}
diff --git a/Examples/test-suite/java/namespace_template_runme.java b/Examples/test-suite/java/namespace_template_runme.java
new file mode 100644
index 000000000..c0c7ba135
--- /dev/null
+++ b/Examples/test-suite/java/namespace_template_runme.java
@@ -0,0 +1,32 @@
+
+import namespace_template.*;
+
+public class namespace_template_runme {
+
+ static {
+ try {
+ System.loadLibrary("namespace_template");
+ } 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[]) {
+ vectorchar vc = new vectorchar();
+ vectorshort vs = new vectorshort();
+ vectorint vi = new vectorint();
+ vectorlong vl = new vectorlong();
+
+ vc.blah((char)10);
+ vs.blah((short)10);
+ vi.blah(10);
+ vl.blah(10);
+
+ vc.vectoruse(vc, vc);
+ vs.vectoruse(vs, vs);
+ vi.vectoruse(vi, vi);
+ vl.vectoruse(vl, vl);
+ }
+}
+
diff --git a/Examples/test-suite/java/template_parameters_global_scope_runme.java b/Examples/test-suite/java/template_parameters_global_scope_runme.java
new file mode 100644
index 000000000..a536fe476
--- /dev/null
+++ b/Examples/test-suite/java/template_parameters_global_scope_runme.java
@@ -0,0 +1,75 @@
+import template_parameters_global_scope.*;
+
+public class template_parameters_global_scope_runme {
+
+ static {
+ try {
+ System.loadLibrary("template_parameters_global_scope");
+ } 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[]) {
+
+ int alloc = 0;
+
+ // Check 1
+ alloc = template_parameters_global_scope.Bucket1();
+ alloc = template_parameters_global_scope.Bucket2();
+ alloc = template_parameters_global_scope.Bucket3();
+ alloc = template_parameters_global_scope.Bucket4();
+ alloc = template_parameters_global_scope.Bucket5();
+ alloc = template_parameters_global_scope.Bucket6();
+
+ // Check 2
+ alloc = template_parameters_global_scope.Spade1();
+ alloc = template_parameters_global_scope.Spade2();
+ alloc = template_parameters_global_scope.Spade3();
+ alloc = template_parameters_global_scope.Spade4();
+ alloc = template_parameters_global_scope.Spade5();
+ alloc = template_parameters_global_scope.Spade6();
+
+ // Check 3
+ alloc = template_parameters_global_scope.Ball1();
+ alloc = template_parameters_global_scope.Ball2();
+ alloc = template_parameters_global_scope.Ball3();
+ alloc = template_parameters_global_scope.Ball4();
+ alloc = template_parameters_global_scope.Ball5();
+ alloc = template_parameters_global_scope.Ball6();
+
+ // Check 4
+ alloc = template_parameters_global_scope.Bat1();
+ alloc = template_parameters_global_scope.Bat2();
+ alloc = template_parameters_global_scope.Bat3();
+ alloc = template_parameters_global_scope.Bat4();
+ alloc = template_parameters_global_scope.Bat5();
+ alloc = template_parameters_global_scope.Bat6();
+
+ // Check 5
+ alloc = template_parameters_global_scope.Chair1();
+ alloc = template_parameters_global_scope.Chair2();
+ alloc = template_parameters_global_scope.Chair3();
+ alloc = template_parameters_global_scope.Chair4();
+ alloc = template_parameters_global_scope.Chair5();
+ alloc = template_parameters_global_scope.Chair6();
+
+ // Check 6
+ alloc = template_parameters_global_scope.Table1();
+ alloc = template_parameters_global_scope.Table2();
+ alloc = template_parameters_global_scope.Table3();
+ alloc = template_parameters_global_scope.Table4();
+ alloc = template_parameters_global_scope.Table5();
+ alloc = template_parameters_global_scope.Table6();
+
+ /*
+ alloc = template_parameters_global_scope.rejig1();
+ alloc = template_parameters_global_scope.rejig2();
+ alloc = template_parameters_global_scope.rejig3();
+ alloc = template_parameters_global_scope.rejig4();
+ alloc = template_parameters_global_scope.rejig5();
+ alloc = template_parameters_global_scope.rejig6();
+ */
+ }
+}
diff --git a/Examples/test-suite/java/template_using_directive_and_declaration_forward_runme.java b/Examples/test-suite/java/template_using_directive_and_declaration_forward_runme.java
index 080945e02..3aab5fa8f 100644
--- a/Examples/test-suite/java/template_using_directive_and_declaration_forward_runme.java
+++ b/Examples/test-suite/java/template_using_directive_and_declaration_forward_runme.java
@@ -19,32 +19,32 @@ public class template_using_directive_and_declaration_forward_runme {
template_using_directive_and_declaration_forward.useit1b(new Thing1Int());
template_using_directive_and_declaration_forward.useit1c(new Thing1Int());
-//BROKEN template_using_directive_and_declaration_forward.useit2(new Thing2Int());
+ template_using_directive_and_declaration_forward.useit2(new Thing2Int());
template_using_directive_and_declaration_forward.useit2a(new Thing2Int());
template_using_directive_and_declaration_forward.useit2b(new Thing2Int());
template_using_directive_and_declaration_forward.useit2c(new Thing2Int());
template_using_directive_and_declaration_forward.useit2d(new Thing2Int());
-//BROKEN template_using_directive_and_declaration_forward.useit3(new Thing3Int());
+ template_using_directive_and_declaration_forward.useit3(new Thing3Int());
template_using_directive_and_declaration_forward.useit3a(new Thing3Int());
template_using_directive_and_declaration_forward.useit3b(new Thing3Int());
template_using_directive_and_declaration_forward.useit3c(new Thing3Int());
template_using_directive_and_declaration_forward.useit3d(new Thing3Int());
-//BROKEN template_using_directive_and_declaration_forward.useit4(new Thing4Int());
+ template_using_directive_and_declaration_forward.useit4(new Thing4Int());
template_using_directive_and_declaration_forward.useit4a(new Thing4Int());
template_using_directive_and_declaration_forward.useit4b(new Thing4Int());
template_using_directive_and_declaration_forward.useit4c(new Thing4Int());
template_using_directive_and_declaration_forward.useit4d(new Thing4Int());
-//BROKEN template_using_directive_and_declaration_forward.useit5(new Thing5Int());
+ template_using_directive_and_declaration_forward.useit5(new Thing5Int());
template_using_directive_and_declaration_forward.useit5a(new Thing5Int());
template_using_directive_and_declaration_forward.useit5b(new Thing5Int());
template_using_directive_and_declaration_forward.useit5c(new Thing5Int());
template_using_directive_and_declaration_forward.useit5d(new Thing5Int());
-//BROKEN template_using_directive_and_declaration_forward.useit7(new Thing7Int());
+ template_using_directive_and_declaration_forward.useit7(new Thing7Int());
template_using_directive_and_declaration_forward.useit7a(new Thing7Int());
template_using_directive_and_declaration_forward.useit7b(new Thing7Int());
template_using_directive_and_declaration_forward.useit7c(new Thing7Int());
diff --git a/Examples/test-suite/java/template_using_directive_typedef_runme.java b/Examples/test-suite/java/template_using_directive_typedef_runme.java
new file mode 100644
index 000000000..bec077399
--- /dev/null
+++ b/Examples/test-suite/java/template_using_directive_typedef_runme.java
@@ -0,0 +1,31 @@
+
+import template_using_directive_typedef.*;
+
+public class template_using_directive_typedef_runme {
+
+ static {
+ try {
+ System.loadLibrary("template_using_directive_typedef");
+ } 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[]) {
+ Vector_Obj vo = new Vector_Obj();
+
+ Holder h = new Holder();
+ h.holder_use1(vo, vo, vo);
+ h.holder_use2(vo, vo, vo);
+ h.holder_use3(vo, vo, vo);
+
+ template_using_directive_typedef.tns_holder_use(vo, vo);
+ template_using_directive_typedef.tns_use(vo, vo, vo);
+ template_using_directive_typedef.global_holder_use(vo);
+ template_using_directive_typedef.global_use(vo, vo, vo);
+ template_using_directive_typedef.ns1_holder_use(vo);
+ template_using_directive_typedef.ns2_holder_use(vo, vo, vo, vo);
+ }
+}
+
diff --git a/Examples/test-suite/namespace_chase.i b/Examples/test-suite/namespace_chase.i
new file mode 100644
index 000000000..5e3921d0d
--- /dev/null
+++ b/Examples/test-suite/namespace_chase.i
@@ -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) {}
+ }
+%}
diff --git a/Examples/test-suite/namespace_template.i b/Examples/test-suite/namespace_template.i
index a36abb19b..8a4b6dca9 100644
--- a/Examples/test-suite/namespace_template.i
+++ b/Examples/test-suite/namespace_template.i
@@ -2,10 +2,10 @@
%module namespace_template
-%warnfilter(SWIGWARN_RUBY_WRONG_NAME) vector; /* Ruby, wrong class name */
-%warnfilter(SWIGWARN_RUBY_WRONG_NAME) test2::vector; /* Ruby, wrong class name */
-%warnfilter(SWIGWARN_RUBY_WRONG_NAME) test3::vector; /* Ruby, wrong class name */
-%warnfilter(SWIGWARN_RUBY_WRONG_NAME) vector; /* Ruby, wrong class name */
+%warnfilter(SWIGWARN_RUBY_WRONG_NAME) test::vector; /* Ruby, wrong class name */
+%warnfilter(SWIGWARN_RUBY_WRONG_NAME) test::vector; /* Ruby, wrong class name */
+%warnfilter(SWIGWARN_RUBY_WRONG_NAME) test::vector; /* Ruby, wrong class name */
+%warnfilter(SWIGWARN_RUBY_WRONG_NAME) test::vector; /* Ruby, wrong class name */
%{
#ifdef max
@@ -23,20 +23,9 @@ namespace test {
char * blah(T x) {
return (char *) "vector::blah";
}
+ void vectoruse(vector a, test::vector b) {}
};
}
-
-namespace test2 {
- using namespace test;
-}
-
-namespace test3 {
- using test::max;
- using test::vector;
-}
-
-using namespace test2;
-namespace T4 = test;
%}
namespace test {
@@ -48,6 +37,7 @@ namespace test {
char * blah(T x) {
return (char *) "vector::blah";
}
+ void vectoruse(vector a, test::vector b) {}
};
}
@@ -55,30 +45,26 @@ using namespace test;
%template(maxint) max;
%template(vectorint) vector;
-namespace test2 {
- using namespace test;
+namespace test {
%template(maxshort) max;
%template(vectorshort) vector;
}
-namespace test3 {
- using test::max;
- using test::vector;
+namespace test {
%template(maxlong) max;
%template(vectorlong) vector;
}
%inline %{
-namespace test4 {
- using namespace test;
- typedef int Integer;
+namespace test {
+ typedef char Char;
}
%}
-namespace test4 {
- %template(maxInteger) max;
- %template(vectorInteger) vector;
+namespace test {
+ %template(maxchar) max;
+ %template(vectorchar) vector;
}
diff --git a/Examples/test-suite/python/template_using_directive_typedef_runme.py b/Examples/test-suite/python/template_using_directive_typedef_runme.py
new file mode 100644
index 000000000..363a3b754
--- /dev/null
+++ b/Examples/test-suite/python/template_using_directive_typedef_runme.py
@@ -0,0 +1,15 @@
+import template_using_directive_typedef
+
+vo = template_using_directive_typedef.Vector_Obj();
+
+h = template_using_directive_typedef.Holder();
+h.holder_use1(vo, vo, vo);
+h.holder_use2(vo, vo, vo);
+h.holder_use3(vo, vo, vo);
+
+template_using_directive_typedef.tns_holder_use(vo, vo);
+template_using_directive_typedef.tns_use(vo, vo, vo);
+template_using_directive_typedef.global_holder_use(vo);
+template_using_directive_typedef.global_use(vo, vo, vo);
+template_using_directive_typedef.ns1_holder_use(vo);
+template_using_directive_typedef.ns2_holder_use(vo, vo, vo, vo);
diff --git a/Examples/test-suite/python/typemap_template_typedef_runme.py b/Examples/test-suite/python/typemap_template_typedef_runme.py
new file mode 100644
index 000000000..a2458367e
--- /dev/null
+++ b/Examples/test-suite/python/typemap_template_typedef_runme.py
@@ -0,0 +1,32 @@
+from typemap_template_typedef import *
+
+def check(got, expected):
+ if got != expected:
+ raise RuntimeError("got: " + str(got) + " expected: " + str(expected))
+
+x = XXXInt()
+
+check(x.aa1(0), 0)
+check(x.aa2(0), 55)
+check(x.aa3(0), 0)
+check(aa1(0), 0)
+check(aa2(0), 0)
+
+check(x.bb1(0), 0)
+check(x.bb2(0), 66)
+check(x.bb3(0), 0)
+check(bb1(0), 0)
+check(bb2(0), 0)
+
+check(x.cc1(0), 0)
+check(x.cc2(0), 77)
+check(x.cc3(0), 77)
+check(cc1(0), 0)
+check(cc2(0), 0)
+
+check(x.dd1(0), 0)
+check(x.dd2(0), 88)
+check(x.dd3(0), 0)
+check(dd1(0), 0)
+check(dd2(0), 0)
+
diff --git a/Examples/test-suite/smart_pointer_namespace2.i b/Examples/test-suite/smart_pointer_namespace2.i
index 882799862..e78364c25 100644
--- a/Examples/test-suite/smart_pointer_namespace2.i
+++ b/Examples/test-suite/smart_pointer_namespace2.i
@@ -49,11 +49,6 @@ namespace one
};
}
-%define PTR_DEF(o)
-typedef one::Ptr o ## _ptr;
-%template(o ## _ptr) one::Ptr;
-%enddef
-
namespace one
{
class Obj1
@@ -63,7 +58,8 @@ namespace one
void donothing() {}
};
- PTR_DEF(Obj1)
+ typedef one::Ptr Obj1_ptr;
+ %template(Obj1_ptr) one::Ptr;
}
namespace two
@@ -75,6 +71,9 @@ namespace two
void donothing() {}
};
- PTR_DEF(Obj2)
+ typedef one::Ptr Obj2_ptr;
}
+using two::Obj2;
+%template(Obj2_ptr) one::Ptr;
+
diff --git a/Examples/test-suite/template_nested_typemaps.i b/Examples/test-suite/template_nested_typemaps.i
index 54f5bc503..577a88e14 100644
--- a/Examples/test-suite/template_nested_typemaps.i
+++ b/Examples/test-suite/template_nested_typemaps.i
@@ -1,25 +1,30 @@
-#pragma SWIG nowarn=SWIGWARN_PARSE_NESTED_TEMPLATE
-
%module template_nested_typemaps
-// Testing that the typemaps invoked within a class via %template are picked up by appropriate methods
+#pragma SWIG nowarn=SWIGWARN_PARSE_NAMED_NESTED_CLASS
-template struct Typemap {
- %typemap(in) T {
- $1 = -99;
- }
-};
-template <> struct Typemap { // Note explicit specialization
- %typemap(in) short {
- $1 = -77;
- }
-};
+// Testing that the typemaps invoked within a class via %template are picked up by appropriate methods
+// Only for languages that support nested classes
%inline %{
int globalInt1(int s) { return s; }
short globalShort1(short s) { return s; }
template struct Breeze {
+ template struct Typemap {
+#ifdef SWIG
+ %typemap(in) TMT {
+ $1 = -99;
+ }
+#endif
+ };
+ template struct TypemapShort {
+#ifdef SWIG
+ %typemap(in) short {
+ $1 = -77;
+ }
+#endif
+ };
+
int methodInt1(int s) { return s; }
#if defined(SWIG)
%template() Typemap;
@@ -29,7 +34,7 @@ template struct Breeze {
short methodShort1(short s) { return s; }
#if defined(SWIG)
- %template(TypemapShort) Typemap; // should issue warning SWIGWARN_PARSE_NESTED_TEMPLATE
+ %template() TypemapShort;
#endif
short methodShort2(short s) { return s; } // should pick up the typemap within Typemap
};
diff --git a/Examples/test-suite/template_parameters_global_scope.i b/Examples/test-suite/template_parameters_global_scope.i
new file mode 100644
index 000000000..a828187b5
--- /dev/null
+++ b/Examples/test-suite/template_parameters_global_scope.i
@@ -0,0 +1,133 @@
+%module template_parameters_global_scope
+
+%inline %{
+namespace Alloc {
+ template struct Rebind {
+ typedef int Integer;
+ };
+}
+%}
+
+%inline %{
+struct Bucket_ {};
+typedef Bucket_ TDBucket;
+typedef ::Bucket_ TDGlobalBucket;
+%}
+
+// Check 1: %template no unary scope operator
+%template(RebindBucket) Alloc::Rebind< Bucket_ >;
+
+%inline %{
+Alloc::Rebind< Bucket_ >::Integer Bucket1() { return 1; }
+Alloc::Rebind< ::Bucket_ >::Integer Bucket2() { return 2; }
+Alloc::Rebind< TDBucket >::Integer Bucket3() { return 3; }
+Alloc::Rebind< ::TDBucket >::Integer Bucket4() { return 4; }
+Alloc::Rebind< TDGlobalBucket >::Integer Bucket5() { return 5; }
+Alloc::Rebind< ::TDGlobalBucket >::Integer Bucket6() { return 6; }
+%}
+
+// Check 2: %template with unary scope operator
+%inline %{
+struct Spade {};
+typedef Spade TDSpade;
+typedef ::Spade TDGlobalSpade;
+%}
+%template(RebindSpade) Alloc::Rebind< ::Spade >;
+
+%inline %{
+Alloc::Rebind< Spade >::Integer Spade1() { return 1; }
+Alloc::Rebind< ::Spade >::Integer Spade2() { return 2; }
+Alloc::Rebind< TDSpade >::Integer Spade3() { return 3; }
+Alloc::Rebind< ::TDSpade >::Integer Spade4() { return 4; }
+Alloc::Rebind< TDGlobalSpade >::Integer Spade5() { return 5; }
+Alloc::Rebind< ::TDGlobalSpade >::Integer Spade6() { return 6; }
+%}
+
+// Check 3: %template typedef no unary scope operator
+%inline %{
+struct Ball {};
+typedef Ball TDBall;
+typedef ::Ball TDGlobalBall;
+%}
+%template(RebindBall) Alloc::Rebind< TDBall >;
+
+%inline %{
+Alloc::Rebind< Ball >::Integer Ball1() { return 1; }
+Alloc::Rebind< ::Ball >::Integer Ball2() { return 2; }
+Alloc::Rebind< TDBall >::Integer Ball3() { return 3; }
+Alloc::Rebind< ::TDBall >::Integer Ball4() { return 4; }
+Alloc::Rebind< TDGlobalBall >::Integer Ball5() { return 5; }
+Alloc::Rebind< ::TDGlobalBall >::Integer Ball6() { return 6; }
+%}
+
+// Check 4: %template typedef with unary scope operator
+%inline %{
+struct Bat {};
+typedef Bat TDBat;
+typedef ::Bat TDGlobalBat;
+%}
+%template(RebindBat) Alloc::Rebind< ::TDBat >;
+
+%inline %{
+Alloc::Rebind< Bat >::Integer Bat1() { return 1; }
+Alloc::Rebind< ::Bat >::Integer Bat2() { return 2; }
+Alloc::Rebind< TDBat >::Integer Bat3() { return 3; }
+Alloc::Rebind< ::TDBat >::Integer Bat4() { return 4; }
+Alloc::Rebind< TDGlobalBat >::Integer Bat5() { return 5; }
+Alloc::Rebind< ::TDGlobalBat >::Integer Bat6() { return 6; }
+%}
+
+// Check 5: %template double typedef no unary scope operator
+%inline %{
+struct Chair {};
+typedef Chair TDChair;
+typedef ::Chair TDGlobalChair;
+%}
+%template(RebindChair) Alloc::Rebind< TDGlobalChair >;
+
+%inline %{
+Alloc::Rebind< Chair >::Integer Chair1() { return 1; }
+Alloc::Rebind< ::Chair >::Integer Chair2() { return 2; }
+Alloc::Rebind< TDChair >::Integer Chair3() { return 3; }
+Alloc::Rebind< ::TDChair >::Integer Chair4() { return 4; }
+Alloc::Rebind< TDGlobalChair >::Integer Chair5() { return 5; }
+Alloc::Rebind< ::TDGlobalChair >::Integer Chair6() { return 6; }
+%}
+
+// Check 6: %template double typedef with unary scope operator
+%inline %{
+struct Table {};
+typedef Table TDTable;
+typedef ::Table TDGlobalTable;
+%}
+%template(RebindTable) Alloc::Rebind< ::TDGlobalTable >;
+
+%inline %{
+Alloc::Rebind< Table >::Integer Table1() { return 1; }
+Alloc::Rebind< ::Table >::Integer Table2() { return 2; }
+Alloc::Rebind< TDTable >::Integer Table3() { return 3; }
+Alloc::Rebind< ::TDTable >::Integer Table4() { return 4; }
+Alloc::Rebind< TDGlobalTable >::Integer Table5() { return 5; }
+Alloc::Rebind< ::TDGlobalTable >::Integer Table6() { return 6; }
+%}
+
+#if 0
+%inline %{
+namespace Alloc {
+ template struct Rejig {
+ typedef int Integer;
+ };
+}
+%}
+
+%template(RejigSpade) Alloc::Rejig<::Spade>;
+
+%inline %{
+Alloc::Rejig<>::Integer rejig1() { return 1; }
+Alloc::Rejig< ::Spade >::Integer rejig2() { return 2; }
+Alloc::Rejig< ::TDSpade >::Integer rejig3() { return 3; }
+Alloc::Rejig< ::TDSpade >::Integer rejig4() { return 4; }
+Alloc::Rejig< TDGlobalSpade >::Integer rejig5() { return 5; }
+Alloc::Rejig< ::TDGlobalSpade >::Integer rejig6() { return 6; }
+%}
+#endif
diff --git a/Examples/test-suite/template_partial_specialization.i b/Examples/test-suite/template_partial_specialization.i
index 8781fbbda..a7afd3000 100644
--- a/Examples/test-suite/template_partial_specialization.i
+++ b/Examples/test-suite/template_partial_specialization.i
@@ -32,7 +32,7 @@ namespace One {
%template(H) One::OneParm;
// %template scope explicit specializations
-namespace ONE {
+namespace One {
%template(I) One::OneParm;
%template(J) ::One::OneParm;
}
@@ -42,7 +42,7 @@ namespace One {
}
// %template scope partial specializations
-namespace ONE {
+namespace One {
%template(BB) One::OneParm;
%template(BBB) ::One::OneParm;
}
diff --git a/Examples/test-suite/template_partial_specialization_typedef.i b/Examples/test-suite/template_partial_specialization_typedef.i
index 6fdbf99aa..9c00efc98 100644
--- a/Examples/test-suite/template_partial_specialization_typedef.i
+++ b/Examples/test-suite/template_partial_specialization_typedef.i
@@ -59,7 +59,7 @@ namespace One {
%template(H) One::OneParm;
// %template scope explicit specializations
-namespace ONE {
+namespace One {
%template(I) One::OneParm;
%template(J) ::One::OneParm;
}
@@ -69,7 +69,7 @@ namespace One {
}
// %template scope partial specializations
-namespace ONE {
+namespace One {
%template(BB) One::OneParm;
%template(BBB) ::One::OneParm;
}
diff --git a/Examples/test-suite/typemap_template_typedef.i b/Examples/test-suite/typemap_template_typedef.i
new file mode 100644
index 000000000..c84416ef9
--- /dev/null
+++ b/Examples/test-suite/typemap_template_typedef.i
@@ -0,0 +1,66 @@
+%module typemap_template_typedef
+//%module("templatereduce") typemap_template_typedef
+
+%typemap(in) int TMAP55 %{ $1 = 55; /* int TMAP55 typemap */ %}
+%typemap(in) int TMAP66 %{ $1 = 66; /* int TMAP66 typemap */ %}
+%typemap(in) int TMAP77 %{ $1 = 77; /* int TMAP77 typemap */ %}
+%typemap(in) int TMAP88 %{ $1 = 88; /* int TMAP88 typemap */ %}
+
+%apply int TMAP77 { XXX::Long cc }
+
+%inline %{
+typedef int Integer;
+
+template struct XXX {
+#ifdef SWIG
+// In swig-3.0.12 'Long aa' was actually stored as 'long aa' in typemap table instead of 'XXX::Long aa'
+%apply int TMAP55 { Long aa }
+%apply int TMAP66 { XXX::Long bb }
+%apply int TMAP88 { XXX::Long dd }
+#endif
+ typedef long Long;
+ long aa1(long aa) { return aa; }
+ long aa2(Long aa) { return aa; }
+ long bb1(long bb) { return bb; }
+ long bb2(Long bb) { return bb; }
+ long cc1(long cc) { return cc; }
+ long cc2(Long cc) { return cc; }
+ long dd1(long dd) { return dd; }
+ long dd2(Long dd) { return dd; }
+#ifdef SWIG
+%clear Long aa;
+%clear XXX::Long bb;
+%clear XXX::Long dd;
+#endif
+ long aa3(Long aa) { return aa; }
+ long bb3(Long bb) { return bb; }
+ long cc3(Long cc) { return cc; }
+ long dd3(Long dd) { return dd; }
+};
+%}
+
+%template(XXXInt) XXX;
+
+%clear XXX::Long cc;
+
+%inline %{
+ long aa1(XXX::Long aa) { return aa; }
+ long aa2(long aa) { return aa; }
+ long bb1(XXX::Long bb) { return bb; }
+ long bb2(long bb) { return bb; }
+ long cc1(XXX::Long cc) { return cc; }
+ long cc2(long cc) { return cc; }
+ long dd1(XXX::Long dd) { return dd; }
+ long dd2(long dd) { return dd; }
+%}
+
+%inline %{
+typedef Integer INTEGER;
+template struct YYY {
+ void meff(T1 t1, T2 t2) {}
+};
+%}
+%template(YYYIntInt) YYY;
+%inline %{
+ void whyohwhy(YYY yy) {}
+%}
diff --git a/Source/CParse/parser.y b/Source/CParse/parser.y
index db5ff9f97..a4167b12d 100644
--- a/Source/CParse/parser.y
+++ b/Source/CParse/parser.y
@@ -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($$,"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($$, "nested:innerscope", nscope_inner);
Setattr($$, "nested:nscope", nscope);
diff --git a/Source/Modules/typepass.cxx b/Source/Modules/typepass.cxx
index 281c96ad0..57125fcbb 100644
--- a/Source/Modules/typepass.cxx
+++ b/Source/Modules/typepass.cxx
@@ -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"));
- */
}
}
}
diff --git a/Source/Swig/misc.c b/Source/Swig/misc.c
index cfa0c68b3..f80fb678f 100644
--- a/Source/Swig/misc.c
+++ b/Source/Swig/misc.c
@@ -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()
*
diff --git a/Source/Swig/swig.h b/Source/Swig/swig.h
index f25f0993e..0bcd53a66 100644
--- a/Source/Swig/swig.h
+++ b/Source/Swig/swig.h
@@ -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);
diff --git a/Source/Swig/typemap.c b/Source/Swig/typemap.c
index 8970c719d..c0f5397c1 100644
--- a/Source/Swig/typemap.c
+++ b/Source/Swig/typemap.c
@@ -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);
}
}
diff --git a/Source/Swig/typesys.c b/Source/Swig/typesys.c
index e11fc781a..409e28f35 100644
--- a/Source/Swig/typesys.c
+++ b/Source/Swig/typesys.c
@@ -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 */