From aa2932f4090022ee9989d092bc05487622ba212d Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Mon, 17 Jul 2017 07:23:23 +0100 Subject: [PATCH 01/18] Typemap change for templates For templates only, the template parameters are fully resolved when handling typemaps. Without this, it is too hard to have decent rules to apply typemaps when parameter types are typedef'd and template parameters have default values. Fixes %clear for typedefs in templates, eg: %typemap("in") XXX::Long "..." template typename struct XXX { typedef long Long; }; %clear XXX::Long; as the typemap was previously incorrectly stored as a typemap for long instead of XXX::Long. --- .../python/typemap_template_typedef_runme.py | 32 +++++++++ .../test-suite/typemap_template_typedef.i | 66 +++++++++++++++++++ Source/Swig/typemap.c | 36 +++++++++- 3 files changed, 132 insertions(+), 2 deletions(-) create mode 100644 Examples/test-suite/python/typemap_template_typedef_runme.py create mode 100644 Examples/test-suite/typemap_template_typedef.i 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/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/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); } } From 26e14c4f189c0f269047c9a40d137293ecf9a983 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 22 Jul 2017 13:17:23 +0100 Subject: [PATCH 02/18] Fix scope lookup for template parameters containing unary scope operators Fixes cases like: namespace Alloc { template struct Rebind { typedef int Integer; }; } %template(RebindBucket) Alloc::Rebind< Bucket >; OR %template(RebindBucket) Alloc::Rebind< ::Bucket >; Alloc::Rebind< Bucket >::Integer Bucket1() { return 1; } Alloc::Rebind< ::Bucket >::Integer Bucket2() { return 2; } Alloc::Rebind<::template TemplateBucket>::Integer Bucket3() { return 3; }; --- Examples/test-suite/common.mk | 1 + .../java/cpp11_template_typedefs_runme.java | 19 +++ ...emplate_parameters_global_scope_runme.java | 75 ++++++++++ .../template_parameters_global_scope.i | 133 ++++++++++++++++++ Source/Swig/typesys.c | 38 ++++- 5 files changed, 260 insertions(+), 6 deletions(-) create mode 100644 Examples/test-suite/java/cpp11_template_typedefs_runme.java create mode 100644 Examples/test-suite/java/template_parameters_global_scope_runme.java create mode 100644 Examples/test-suite/template_parameters_global_scope.i diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index 146ada2c6..ab341e7a1 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -444,6 +444,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/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/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/template_parameters_global_scope.i b/Examples/test-suite/template_parameters_global_scope.i new file mode 100644 index 000000000..4c14ba4a3 --- /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/Source/Swig/typesys.c b/Source/Swig/typesys.c index e11fc781a..40155591c 100644 --- a/Source/Swig/typesys.c +++ b/Source/Swig/typesys.c @@ -248,10 +248,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 +434,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 +455,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) { @@ -911,6 +931,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 +954,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; } From 8bf3a342c2293d7c621076d26a6245bf5bbbbcb6 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Wed, 26 Jul 2017 18:54:54 +0100 Subject: [PATCH 03/18] Minor code optimisation in template_parameters_resolve --- Source/Swig/typesys.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Source/Swig/typesys.c b/Source/Swig/typesys.c index 40155591c..3bb776a2c 100644 --- a/Source/Swig/typesys.c +++ b/Source/Swig/typesys.c @@ -594,14 +594,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; } From 2681bbad366b8dfc1ed9aa599dcb14ed8684733d Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Wed, 26 Jul 2017 19:48:46 +0100 Subject: [PATCH 04/18] Improve description of template_parameters_resolve --- Source/Swig/typesys.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Source/Swig/typesys.c b/Source/Swig/typesys.c index 3bb776a2c..2fb514d5e 100644 --- a/Source/Swig/typesys.c +++ b/Source/Swig/typesys.c @@ -561,8 +561,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) { From 8753f9652ccc91f0aa080efff15207a4fa33c8ec Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sun, 30 Jul 2017 13:09:02 +0100 Subject: [PATCH 05/18] Namespace documentation minor corrections --- Doc/Manual/SWIGPlus.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Doc/Manual/SWIGPlus.html b/Doc/Manual/SWIGPlus.html index 3e7860b9b..b22f1c279 100644 --- a/Doc/Manual/SWIGPlus.html +++ b/Doc/Manual/SWIGPlus.html @@ -3915,6 +3915,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.

@@ -4203,9 +4205,7 @@ namespace foo {

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.

6.19.1 The nspace feature for namespaces

From 7ee76f93f99e01c9fb5de0bd91ab16178519f18c Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sun, 30 Jul 2017 13:41:45 +0100 Subject: [PATCH 06/18] More consistent formatting of examples in documentation --- Doc/Manual/Java.html | 4 +-- Doc/Manual/Lua.html | 18 ++++++------ Doc/Manual/Perl5.html | 6 ++-- Doc/Manual/Php.html | 6 ++-- Doc/Manual/Python.html | 37 ++++++++++++------------ Doc/Manual/SWIG.html | 20 ++++++------- Doc/Manual/SWIGPlus.html | 62 ++++++++++++++++++++-------------------- Doc/Manual/Scilab.html | 26 ++++++++--------- Doc/Manual/Tcl.html | 16 +++++------ 9 files changed, 96 insertions(+), 99 deletions(-) diff --git a/Doc/Manual/Java.html b/Doc/Manual/Java.html index e0178465c..e21440ee9 100644 --- a/Doc/Manual/Java.html +++ b/Doc/Manual/Java.html @@ -5278,7 +5278,7 @@ void * operator new(size_t t) { throw bad_alloc(); pJalloc->ref = 0; return static_cast<void *>( - static_cast<char *>(static_cast<void *>(pJalloc)) + sizeof(Jalloc)); + static_cast<char *>(static_cast<void *>(pJalloc)) + sizeof(Jalloc)); } } @@ -7240,7 +7240,7 @@ public class runme { example.print_args(animals); String args[] = example.get_args(); for (int i=0; i<args.length; i++) - System.out.println(i + ":" + args[i]); + System.out.println(i + ":" + args[i]); } } 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 suppor

SWIG 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

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

-
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
+
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..03f2c7048 100644 --- a/Doc/Manual/Perl5.html +++ b/Doc/Manual/Perl5.html @@ -3279,9 +3279,9 @@ suffice in most cases:

 %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 7d3d33ac1..c4ba2e3f8 100644 --- a/Doc/Manual/Php.html +++ b/Doc/Manual/Php.html @@ -1175,9 +1175,9 @@ should suffice in most cases:
 %feature("director:except") {
-    if ($error == FAILURE) {
-        throw Swig::DirectorMethodException();
-    }
+  if ($error == FAILURE) {
+    throw Swig::DirectorMethodException();
+  }
 }
 
diff --git a/Doc/Manual/Python.html b/Doc/Manual/Python.html index 1b73c08b7..169151d47 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); + } }
@@ -3133,9 +3132,9 @@ suffice in most cases:
 %feature("director:except") {
-    if ($error != NULL) {
-        throw Swig::DirectorMethodException();
-    }
+  if ($error != NULL) {
+    throw Swig::DirectorMethodException();
+  }
 }
 
@@ -4142,11 +4141,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;
 }
 
@@ -6526,7 +6525,7 @@ string that cannot be completely decoded as UTF-8: %inline %{ const char* non_utf8_c_str(void) { - return "h\xe9llo w\xc3\xb6rld"; + return "h\xe9llo w\xc3\xb6rld"; } %} diff --git a/Doc/Manual/SWIG.html b/Doc/Manual/SWIG.html index e5b441fbb..b1cb1b4dd 100644 --- a/Doc/Manual/SWIG.html +++ b/Doc/Manual/SWIG.html @@ -1266,12 +1266,12 @@ pointers. As a result, SWIG creates a wrapper like this:
 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;
 }
 
@@ -1280,10 +1280,10 @@ or if SWIG was run with the -c++ option:

 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;
 }
 
diff --git a/Doc/Manual/SWIGPlus.html b/Doc/Manual/SWIGPlus.html index b22f1c279..5841c7d43 100644 --- a/Doc/Manual/SWIGPlus.html +++ b/Doc/Manual/SWIGPlus.html @@ -2958,29 +2958,29 @@ To illustrate, consider the following 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];
+  }
 };
 
@@ -3704,10 +3704,10 @@ template <class T> class OuterTemplateClass {}; // 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 {}; @@ -4533,13 +4533,13 @@ 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
diff --git a/Doc/Manual/Scilab.html b/Doc/Manual/Scilab.html
index 14e03ff18..aef06e302 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..31408b312 100644 --- a/Doc/Manual/Tcl.html +++ b/Doc/Manual/Tcl.html @@ -3215,28 +3215,28 @@ helper functions to access arrays : %inline %{ double *new_double(int size) { - return (double *) malloc(size*sizeof(double)); + return (double *) malloc(size*sizeof(double)); } void delete_double(double *a) { - free(a); + free(a); } double get_double(double *a, int index) { - return a[index]; + return a[index]; } void set_double(double *a, int index, double val) { - a[index] = val; + a[index] = val; } int *new_int(int size) { - return (int *) malloc(size*sizeof(int)); + return (int *) malloc(size*sizeof(int)); } void delete_int(int *a) { - free(a); + free(a); } int get_int(int *a, int index) { - return a[index]; + return a[index]; } int set_int(int *a, int index, int val) { - a[index] = val; + a[index] = val; } %} From 8052211ac586e691c75bde7814803add8fe1b32f Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sun, 30 Jul 2017 13:56:47 +0100 Subject: [PATCH 07/18] More consistent formatting of examples in documentation --- Doc/Manual/CSharp.html | 40 ++++++++++++------------ Doc/Manual/Customization.html | 2 +- Doc/Manual/Extending.html | 58 +++++++++++++++++------------------ Doc/Manual/Java.html | 22 ++++++------- Doc/Manual/Perl5.html | 5 ++- Doc/Manual/SWIGPlus.html | 26 ++++++++-------- 6 files changed, 76 insertions(+), 77 deletions(-) diff --git a/Doc/Manual/CSharp.html b/Doc/Manual/CSharp.html index 5be63a340..d618f5a08 100644 --- a/Doc/Manual/CSharp.html +++ b/Doc/Manual/CSharp.html @@ -997,9 +997,9 @@ When the following C# code is executed:
 public class runme {
-    static void Main() {
-      example.positivesonly(-1);
-    }
+  static void Main() {
+    example.positivesonly(-1);
+  }
 }
 
@@ -1846,12 +1846,12 @@ and the following usage from C# after running the code through SWIG:
-      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);
 
@@ -1980,9 +1980,9 @@ and more or less equivalent usage from C#
-      Container container = new Container();
-      Element element = new Element(20);
-      container.setElement(element);
+  Container container = new Container();
+  Element element = new Element(20);
+  container.setElement(element);
 
@@ -1993,14 +1993,14 @@ In order to understand why, consider a garbage collection occuring...
-      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);
 
diff --git a/Doc/Manual/Customization.html b/Doc/Manual/Customization.html index 0e5fb2869..e5040fc9b 100644 --- a/Doc/Manual/Customization.html +++ b/Doc/Manual/Customization.html @@ -516,7 +516,7 @@ The special variables are often used in situations where method calls are logged $action } catch (MemoryError) { - croak("Out of memory in $decl"); + croak("Out of memory in $decl"); } } void log(const char *message); diff --git a/Doc/Manual/Extending.html b/Doc/Manual/Extending.html index bf70b69ac..c225d9554 100644 --- a/Doc/Manual/Extending.html +++ b/Doc/Manual/Extending.html @@ -2592,36 +2592,36 @@ command line options, simply use code similar to this:
 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/Java.html b/Doc/Manual/Java.html index e21440ee9..928adce67 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);
+  }
 
@@ -4335,16 +4335,16 @@ struct Vector { %extend Vector { char *toString() { - static char tmp[1024]; - sprintf(tmp, "Vector(%g, %g, %g)", $self->x, $self->y, $self->z); - return tmp; + static char tmp[1024]; + sprintf(tmp, "Vector(%g, %g, %g)", $self->x, $self->y, $self->z); + return tmp; } Vector(double x, double y, double z) { - Vector *v = (Vector *) malloc(sizeof(Vector)); - v->x = x; - v->y = y; - v->z = z; - return v; + Vector *v = (Vector *) malloc(sizeof(Vector)); + v->x = x; + v->y = y; + v->z = z; + return v; } }; diff --git a/Doc/Manual/Perl5.html b/Doc/Manual/Perl5.html index 03f2c7048..5e9a9e33e 100644 --- a/Doc/Manual/Perl5.html +++ b/Doc/Manual/Perl5.html @@ -1633,9 +1633,8 @@ class DoubleArray { void setitem(int i, double val) { if ((i >= 0) && (i < n)) ptr[i] = val; - else { + else throw RangeError(); - } } }; @@ -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); diff --git a/Doc/Manual/SWIGPlus.html b/Doc/Manual/SWIGPlus.html index 5841c7d43..3d8263e37 100644 --- a/Doc/Manual/SWIGPlus.html +++ b/Doc/Manual/SWIGPlus.html @@ -346,8 +346,8 @@ public: class Spam { public: - Foo *value; - ... + Foo *value; + ... }; @@ -726,7 +726,7 @@ public: class Grok : public Bar { public: - Grok(); // Not wrapped. No implementation of abstract spam(). + Grok(); // Not wrapped. No implementation of abstract spam(). }; @@ -4915,19 +4915,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);
 };
 
@@ -5008,14 +5008,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); }; From ba45861b462e91e266456f510036768c2aa55be5 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sun, 30 Jul 2017 16:49:21 +0100 Subject: [PATCH 08/18] More consistent formatting of examples in documentation --- Doc/Manual/Go.html | 4 +- Doc/Manual/SWIG.html | 16 ++--- Doc/Manual/SWIGPlus.html | 148 +++++++++++++++++++-------------------- 3 files changed, 84 insertions(+), 84 deletions(-) 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/SWIG.html b/Doc/Manual/SWIG.html index b1cb1b4dd..cff4e7dc2 100644 --- a/Doc/Manual/SWIG.html +++ b/Doc/Manual/SWIG.html @@ -1043,14 +1043,14 @@ expect :

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

diff --git a/Doc/Manual/SWIGPlus.html b/Doc/Manual/SWIGPlus.html index 3d8263e37..87fe30fa8 100644 --- a/Doc/Manual/SWIGPlus.html +++ b/Doc/Manual/SWIGPlus.html @@ -777,9 +777,9 @@ the normal constructor function. For example, if you have this:

 class List {
 public:
-    List();    
-    List(const List &);      // Copy constructor
-    ...
+  List();    
+  List(const List &);      // Copy constructor
+  ...
 };
 
@@ -803,7 +803,7 @@ through a special function like this:
 List *copy_List(List *f) {
-    return new List(*f);
+  return new List(*f);
 }
 
@@ -832,7 +832,7 @@ However, copy constructor wrappers can be generated if using the copyctor
@@ -851,9 +851,9 @@ could be wrapped, but they had to be renamed. For example:
 class Foo {
 public:
-    Foo();
+  Foo();
   %name(CopyFoo) Foo(const Foo &);
-    ...
+  ...
 };
 
@@ -969,8 +969,8 @@ not primitive types, such as classes. For instance, if you had another class lik
 class Foo {
 public:
-    List items;
-    ...
+  List items;
+  ...
 
@@ -982,10 +982,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;
 }
 
@@ -1007,10 +1007,10 @@ It is the naturalvar feature and can be used to effectively change the way acces
 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;
 }
 
@@ -1105,7 +1105,7 @@ SWIG will wrap all types of functions that have default arguments. For example m
 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 +1120,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 +1158,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); }; @@ -1485,8 +1485,8 @@ class A; %feature("valuewrapper") B; struct B { - B(); - // .... + B(); + // .... }; @@ -3000,15 +3000,15 @@ provide an expanded version of the class directly like this: %rename(intList) List<int>; // Rename to a suitable identifier 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); }; @@ -3244,15 +3244,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 +3275,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(int obj);
+  int length();
+  T get(int n);
 };
 
@@ -3587,11 +3587,11 @@ It is also possible to separate these declarations from the template class. For ... template<class T> class List { - ... - public: - List() { } - T get(int index); - ... + ... + public: + List() { } + T get(int index); + ... }; @@ -3609,9 +3609,9 @@ additional methods to a specific instantiation. For example: %template(intList) List<int>; %extend List<int> { - void blah() { - printf("Hey, I'm an List<int>!\n"); - } + void blah() { + printf("Hey, I'm an List<int>!\n"); + } }; @@ -3698,7 +3698,7 @@ template <class T> class OuterTemplateClass {}; // 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 @@ -3736,7 +3736,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() { }
 };
 
@@ -3750,7 +3750,7 @@ as the class name. For example:
 %template(vectori) vector<int>;
 %extend vector<int> {
-    void somemethod() { }
+  void somemethod() { }
 };
 
@@ -4011,7 +4011,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;
@@ -4020,8 +4020,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.
 }
 
@@ -4445,10 +4445,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); + ... }; @@ -4545,8 +4545,8 @@ public: // Ordinary class class Foo_Impl { public: - int x; - virtual void bar(); + int x; + virtual void bar(); ... }; @@ -4555,13 +4555,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 +4660,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->();
 };
 
@@ -4970,14 +4970,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
 };
 
From c454f2ce2f91e0f458121033ffa349c283eeeb30 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sun, 30 Jul 2017 17:02:47 +0100 Subject: [PATCH 09/18] Documentation corrections to use targetlang formatting --- Doc/Manual/Library.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Doc/Manual/Library.html b/Doc/Manual/Library.html index a800c2d73..f41799bf0 100644 --- a/Doc/Manual/Library.html +++ b/Doc/Manual/Library.html @@ -411,7 +411,7 @@ void print_array(double x[10]); Now, in a scripting language, you might write this:

-
+
 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:
 

-
+
 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,
 

-
+
 % 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:

-
+
 >>> s = "H\x00\x15eg\x09\x20"
 >>> parity(s, 0)

From 04131a988f49286fde74fb9d74c5c4bd1ade8454 Mon Sep 17 00:00:00 2001
From: William S Fulton 
Date: Sun, 30 Jul 2017 17:18:55 +0100
Subject: [PATCH 10/18] More consistent formatting of examples in documentation

---
 Doc/Manual/CSharp.html   |   2 +-
 Doc/Manual/Perl5.html    | 114 ++++++++++++++++++-------------------
 Doc/Manual/Php.html      |  18 +++---
 Doc/Manual/Pike.html     |   4 +-
 Doc/Manual/Python.html   | 119 ++++++++++++++++++++-------------------
 Doc/Manual/SWIG.html     |  16 +++---
 Doc/Manual/SWIGPlus.html |   2 +-
 Doc/Manual/Tcl.html      |  46 +++++++--------
 8 files changed, 161 insertions(+), 160 deletions(-)

diff --git a/Doc/Manual/CSharp.html b/Doc/Manual/CSharp.html
index d618f5a08..bb3524ac5 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);
 }
 
diff --git a/Doc/Manual/Perl5.html b/Doc/Manual/Perl5.html index 5e9a9e33e..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; } %}
@@ -1057,7 +1057,7 @@ produces a single accessor function like this:
 int *Foo_x_get(Foo *self) {
-    return self->x;
+  return self->x;
 };
 
@@ -1092,11 +1092,11 @@ generates accessor functions such as this:
 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;
 }
 
@@ -1887,9 +1887,9 @@ like this:
 %typemap(out) int {
-    $result = sv_newmortal();
-    set_setiv($result, (IV) $1);
-    argvi++;
+  $result = sv_newmortal();
+  set_setiv($result, (IV) $1);
+  argvi++;
 }
 
@@ -2312,8 +2312,8 @@ Consider the following data structure:
 #define SIZE  8
 typedef struct {
-    int   values[SIZE];
-    ...
+  int   values[SIZE];
+  ...
 } Foo;
 
 
@@ -2327,10 +2327,10 @@ To make the member writable, a "memberin" typemap can be used.
 %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];
+  }
 }
 
 
@@ -2599,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); + } }
@@ -2841,11 +2841,11 @@ this:
 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;
 }
 
@@ -3103,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(); };
@@ -3304,8 +3304,8 @@ suitable exception handler:
 %exception {
-    try { $action }
-    catch (Swig::DirectorException &e) { SWIG_fail; }
+  try { $action }
+  catch (Swig::DirectorException &e) { SWIG_fail; }
 }
 
diff --git a/Doc/Manual/Php.html b/Doc/Manual/Php.html index c4ba2e3f8..4fda4cc69 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(); };
@@ -1125,12 +1125,12 @@ Here is an example:
 class Foo {
 public:
-    ...
+  ...
 };
 class FooContainer {
 public:
-    void addFoo(Foo *);
-    ...
+  void addFoo(Foo *);
+  ...
 };
 
@@ -1204,8 +1204,8 @@ suitable exception handler:
 %exception {
-    try { $action }
-    catch (Swig::DirectorException &e) { SWIG_fail; }
+  try { $action }
+  catch (Swig::DirectorException &e) { SWIG_fail; }
 }
 
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; }; diff --git a/Doc/Manual/Python.html b/Doc/Manual/Python.html index 169151d47..e294db86d 100644 --- a/Doc/Manual/Python.html +++ b/Doc/Manual/Python.html @@ -1275,7 +1275,7 @@ Foo *BarToFoo(Bar *b) { } Foo *IncrFoo(Foo *f, int i) { - return f+i; + return f+i; } %} @@ -1385,7 +1385,7 @@ example, consider this:
 struct Bar {
-    int  x[16];
+  int  x[16];
 };
 
@@ -1715,9 +1715,9 @@ Similarly, if you have a class like this,
 class Foo {
 public:
-    Foo();
-    Foo(const Foo &);
-    ...
+  Foo();
+  Foo(const Foo &);
+  ...
 };
 
@@ -1950,11 +1950,11 @@ For example: %rename(Bar_spam) Bar::spam; namespace Foo { - int spam(); + int spam(); } namespace Bar { - int spam(); + int spam(); } @@ -2165,9 +2165,9 @@ have a class like this
 class Foo {
 public:
-    int x;
-    int spam(int);
-    ...
+  int x;
+  int spam(int);
+  ...
 
@@ -2178,19 +2178,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);
 }
 
@@ -2309,10 +2309,10 @@ please refer to the python documentation:

 typedef struct {
-    PyObject_HEAD
-    PyObject *dict;
-    PyObject *args;
-    PyObject *message;
+  PyObject_HEAD
+  PyObject *dict;
+  PyObject *args;
+  PyObject *message;
 } PyBaseExceptionObject;
 
@@ -2322,12 +2322,12 @@ typedef struct {
 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;
 
@@ -2338,13 +2338,13 @@ typedef struct {
 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;
 };
 
@@ -2371,9 +2371,9 @@ strings, you can define an 'operator+ (const char*)' method :

 class MyString {
 public:
-    MyString (const char *init);
-    MyString operator+ (const char *other) const;
-    ...
+  MyString (const char *init);
+  MyString operator+ (const char *other) const;
+  ...
 };
 
@@ -2472,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;
+  }
 };
 
@@ -2635,8 +2636,8 @@ ownership of the result. For example:
 class Foo {
 public:
-    Foo();
-    Foo bar();
+  Foo();
+  Foo bar();
 };
 
@@ -2665,9 +2666,9 @@ they came from. Therefore, the ownership is set to zero. For example:
 class Foo {
 public:
-    ...
-    Foo *spam();
-    ...
+  ...
+  Foo *spam();
+  ...
 };
 
@@ -2706,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; @@ -2938,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(); }; @@ -3090,8 +3091,8 @@ public: }; class FooContainer { public: - void addFoo(Foo *); - ... + void addFoo(Foo *); + ... }; @@ -3161,8 +3162,8 @@ suitable exception handler:
 %exception {
-    try { $action }
-    catch (Swig::DirectorException &e) { SWIG_fail; }
+  try { $action }
+  catch (Swig::DirectorException &e) { SWIG_fail; }
 }
 
@@ -3239,7 +3240,7 @@ references, such as
 class Foo {
 …
-    virtual const int& bar();
+  virtual const int& bar();
 …
 };
 
@@ -3257,7 +3258,7 @@ types, wherever possible, for example
 class Foo {
 …
-    virtual int bar();
+  virtual int bar();
 …
 };
 
@@ -3510,7 +3511,7 @@ def bar(*args): class Foo { public: - int bar(int x); + int bar(int x); }; @@ -3547,7 +3548,7 @@ proxy, just before the return statement. class Foo { public: - int bar(int x); + int bar(int x); }; @@ -3576,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); }; @@ -3605,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(); }; diff --git a/Doc/Manual/SWIG.html b/Doc/Manual/SWIG.html index cff4e7dc2..a43ff94b5 100644 --- a/Doc/Manual/SWIG.html +++ b/Doc/Manual/SWIG.html @@ -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);
 }
 
@@ -2368,10 +2368,10 @@ defined in the interface. For example:
 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);
 }
 
@@ -2602,10 +2602,10 @@ like this:
 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;
 }
 
@@ -2896,7 +2896,7 @@ instead of a method. To do this, you might write some code like this:
 // 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 87fe30fa8..da4f54603 100644
--- a/Doc/Manual/SWIGPlus.html
+++ b/Doc/Manual/SWIGPlus.html
@@ -4042,7 +4042,7 @@ namespace foo {
   typedef int Integer;
   class bar {
     public:
-      ...
+    ...
   };
 }
 
diff --git a/Doc/Manual/Tcl.html b/Doc/Manual/Tcl.html
index 31408b312..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];
 };
 
@@ -1456,9 +1456,9 @@ Similarly, if you have a class like this,
 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);
 }
 
@@ -1945,8 +1945,8 @@ ownership of the result. For example:
 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));
 }
 
From 5779aa8d7966ae4ce983a822a0dc56014e3c295a Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sun, 30 Jul 2017 17:22:40 +0100 Subject: [PATCH 11/18] More consistent formatting of examples in documentation --- Doc/Manual/Python.html | 8 ++++---- Doc/Manual/SWIG.html | 2 +- Doc/Manual/SWIGPlus.html | 12 ++++++------ Doc/Manual/Varargs.html | 4 ++-- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Doc/Manual/Python.html b/Doc/Manual/Python.html index e294db86d..b43ca1949 100644 --- a/Doc/Manual/Python.html +++ b/Doc/Manual/Python.html @@ -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 */
+  ...
 
@@ -3087,7 +3087,7 @@ references. Here is an example:
 class Foo {
 public:
-    ...
+  ...
 };
 class FooContainer {
 public:
diff --git a/Doc/Manual/SWIG.html b/Doc/Manual/SWIG.html
index a43ff94b5..c05ed456c 100644
--- a/Doc/Manual/SWIG.html
+++ b/Doc/Manual/SWIG.html
@@ -389,7 +389,7 @@ For example
 /* bar not wrapped unless foo has been defined and 
    the declaration of bar within foo has already been parsed */
 int foo::bar(int) {
-    ... whatever ...
+  ... whatever ...
 }
 
diff --git a/Doc/Manual/SWIGPlus.html b/Doc/Manual/SWIGPlus.html index da4f54603..d0a8f2c9c 100644 --- a/Doc/Manual/SWIGPlus.html +++ b/Doc/Manual/SWIGPlus.html @@ -706,7 +706,7 @@ class Foo { protected: Foo(); // Not wrapped. public: - ... + ... }; @@ -1278,7 +1278,7 @@ equivalent to one generated for the following declaration
 class Foo {
 public:
-    ...
+  ...
 };
 
 void blah(Foo *f);    
@@ -4381,9 +4381,9 @@ class Error { };
 
 class Foo {
 public:
-    ...
-    void blah() throw(Error);
-    ...
+  ...
+  void blah() throw(Error);
+  ...
 };
 
@@ -4547,7 +4547,7 @@ class Foo_Impl { public: int x; virtual void bar(); - ... + ... }; // Smart-pointer wrapper diff --git a/Doc/Manual/Varargs.html b/Doc/Manual/Varargs.html index fb58ee39a..eba816382 100644 --- a/Doc/Manual/Varargs.html +++ b/Doc/Manual/Varargs.html @@ -423,8 +423,8 @@ Variable length arguments may be used in typemap specifications. For example:
 %typemap(in) (...) {
-    // Get variable length arguments (somehow)
-    ...
+  // Get variable length arguments (somehow)
+  ...
 }
 
 %typemap(in) (const char *fmt, ...) {

From 97ae9d66bc7b8cd1fe78680c1253a222c5864c55 Mon Sep 17 00:00:00 2001
From: William S Fulton 
Date: Tue, 8 Aug 2017 19:40:39 +0100
Subject: [PATCH 12/18] Template documentation tweaks

Add subsections to the template documentation
Rewrite some of the template introduction
---
 Doc/Manual/Contents.html |   9 ++
 Doc/Manual/SWIGPlus.html | 227 +++++++++++++++++++++++----------------
 2 files changed, 146 insertions(+), 90 deletions(-)

diff --git a/Doc/Manual/Contents.html b/Doc/Manual/Contents.html
index 56afca857..67f0c3965 100644
--- a/Doc/Manual/Contents.html
+++ b/Doc/Manual/Contents.html
@@ -246,6 +246,15 @@
 
  • Wrapping overloaded operators
  • Class extension
  • Templates +
  • Namespaces
    • The nspace feature for namespaces diff --git a/Doc/Manual/SWIGPlus.html b/Doc/Manual/SWIGPlus.html index d0a8f2c9c..7cc0d5387 100644 --- a/Doc/Manual/SWIGPlus.html +++ b/Doc/Manual/SWIGPlus.html @@ -49,6 +49,15 @@
    • Wrapping overloaded operators
    • Class extension
    • Templates +
    • Namespaces
      • The nspace feature for namespaces @@ -2936,23 +2945,24 @@ as vector<int>. The wrapper for foo() will accept either variant.

        +

        6.18.1 The %template directive

        + +

        -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:

        @@ -2985,14 +2995,26 @@ public:
         

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

        @@ -3014,28 +3036,6 @@ public:
        -

        -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 +3053,67 @@ 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). +

    + +

    6.18.2 Function templates

    + + +

    +SWIG can also generate wrappers for function templates using a similar technique +to that shown above for class templates. For example:

    @@ -3073,6 +3133,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. +

    + +

    6.18.3 Default template 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 +3192,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: -

    +

    6.18.4 Template base classes

    -
    -
    -%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 +3220,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 +3297,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.

    +

    6.18.5 Template specialization

    + +

    The SWIG template mechanism does support specialization. For instance, if you define a class like this, @@ -3281,7 +3346,7 @@ private: public: List(int max); ~List(); - void append(int obj); + void append(T obj); int length(); T get(int n); }; @@ -3322,10 +3387,13 @@ SWIG implements template argument deduction so that the following partial specia +

    6.18.6 Member templates

    + +

    -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 +3467,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 +3487,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:

    @@ -3475,7 +3538,7 @@ template<class T1, class T2> struct pair {

    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:

    @@ -3536,6 +3599,9 @@ constructor, that will dispatch the proper call depending on the argument type.

    +

    6.18.7 More on templates

    + +

    If all of this isn't quite enough and you really want to make someone's head explode, SWIG directives such as @@ -3568,7 +3634,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:

    @@ -3616,25 +3682,6 @@ additional methods to a specific instantiation. 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,7 +3741,7 @@ 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)
    @@ -4524,7 +4571,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:

    From 959e6272082e416303d80d7326430d1fd0b4c432 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Wed, 9 Aug 2017 00:06:24 +0100 Subject: [PATCH 13/18] %template scope enforcement and class definition fixes The scoping rules around %template have been specified and enforced. 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 now 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 and explicit instantiations of std::vector are shown below: // valid namespace std { %template(vin) vector; template class vector; } // valid using namespace std; %template(vin) vector; template class vector; // valid using std::vector; %template(vin) vector; template class vector; // ill-formed namespace unrelated { using std::vector; %template(vin) vector; template class vector; } // ill-formed namespace unrelated { using namespace std; %template(vin) vector; template class vector; } // ill-formed namespace unrelated { namespace std { %template(vin) vector; template class vector; } } // ill-formed namespace unrelated { %template(vin) std::vector; template class std::vector; } When the scope is incorrect, an error now occurs such as: cpp_template_scope.i:34: Error: 'vector' resolves to 'std::vector' and was incorrectly instantiated in scope 'unrelated' instead of within scope 'std'. Previously SWIG accepted the ill-formed examples above but this led to numerous subtle template scope problems especially in the presence of using declarations and using directives as well as with %feature and %typemap. Actually, 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 std::vector; template class vector; Similar fixes for defining classes using forward class references have also been put in place. For example: namespace Space1 { struct A; } namespace Space2 { struct Space1::A { void x(); } } will now error out with: cpp_class_definition.i:5: Error: 'Space1::A' resolves to 'Space1::A' and was incorrectly instantiated in scope 'Space2' instead of within scope 'Space1'. --- Doc/Manual/Contents.html | 1 + Doc/Manual/SWIGPlus.html | 108 ++++++++++- Examples/test-suite/class_scope_namespace.i | 153 ++++++++++++++++ Examples/test-suite/common.mk | 1 + .../test-suite/errors/cpp_class_definition.i | 26 +++ .../errors/cpp_class_definition.stderr | 1 + .../errors/cpp_namespace_template_bad.i | 40 +++++ .../errors/cpp_namespace_template_bad.stderr | 9 + .../errors/cpp_nested_template.stderr | 2 + .../test-suite/errors/cpp_template_scope.i | 57 ++++++ .../errors/cpp_template_scope.stderr | 11 ++ .../java/class_scope_namespace_runme.java | 59 ++++++ .../java/namespace_template_runme.java | 32 ++++ Examples/test-suite/namespace_template.i | 40 ++--- .../test-suite/smart_pointer_namespace2.i | 13 +- .../test-suite/template_nested_typemaps.i | 33 ++-- .../template_partial_specialization.i | 4 +- .../template_partial_specialization_typedef.i | 4 +- Source/CParse/parser.y | 170 ++++++++++++------ Source/Swig/misc.c | 38 +++- Source/Swig/swig.h | 1 + 21 files changed, 689 insertions(+), 114 deletions(-) create mode 100644 Examples/test-suite/class_scope_namespace.i create mode 100644 Examples/test-suite/errors/cpp_class_definition.i create mode 100644 Examples/test-suite/errors/cpp_class_definition.stderr create mode 100644 Examples/test-suite/errors/cpp_namespace_template_bad.i create mode 100644 Examples/test-suite/errors/cpp_namespace_template_bad.stderr create mode 100644 Examples/test-suite/errors/cpp_template_scope.i create mode 100644 Examples/test-suite/errors/cpp_template_scope.stderr create mode 100644 Examples/test-suite/java/class_scope_namespace_runme.java create mode 100644 Examples/test-suite/java/namespace_template_runme.java diff --git a/Doc/Manual/Contents.html b/Doc/Manual/Contents.html index 67f0c3965..3d9f6fd3b 100644 --- a/Doc/Manual/Contents.html +++ b/Doc/Manual/Contents.html @@ -253,6 +253,7 @@
  • Template base classes
  • Template specialization
  • Member templates +
  • Scoping and templates
  • More on templates
  • Namespaces diff --git a/Doc/Manual/SWIGPlus.html b/Doc/Manual/SWIGPlus.html index 7cc0d5387..13c81588d 100644 --- a/Doc/Manual/SWIGPlus.html +++ b/Doc/Manual/SWIGPlus.html @@ -56,6 +56,7 @@
  • Template base classes
  • Template specialization
  • Member templates +
  • Scoping and templates
  • More on templates
  • Namespaces @@ -3599,7 +3600,108 @@ constructor, that will dispatch the proper call depending on the argument type.

    -

    6.18.7 More on templates

    +

    6.18.7 Scoping and templates

    + + +

    +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. +

    + + +

    6.18.8 More on templates

    @@ -4348,9 +4450,9 @@ In the example below, the generic template type is used to rename to bbb

    -%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 {};
    diff --git a/Examples/test-suite/class_scope_namespace.i b/Examples/test-suite/class_scope_namespace.i
    new file mode 100644
    index 000000000..08a9f01dc
    --- /dev/null
    +++ b/Examples/test-suite/class_scope_namespace.i
    @@ -0,0 +1,153 @@
    +// 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) {}
    +  };
    +// needs fixing
    +  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 ab341e7a1..0c896825f 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 \
    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_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..e80779413
    --- /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);
    +    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/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/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/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_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/Source/CParse/parser.y b/Source/CParse/parser.y
    index 69dce5534..30408e73b 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;
     		  }
    @@ -3520,7 +3578,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/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);
    
    From 1434449041eee60fb13dfe9a0ddea6be88fc88df Mon Sep 17 00:00:00 2001
    From: William S Fulton 
    Date: Wed, 9 Aug 2017 09:15:50 +0100
    Subject: [PATCH 14/18] Testcase fix for nameclash in php
    
    ---
     .../test-suite/template_parameters_global_scope.i    | 12 ++++++------
     1 file changed, 6 insertions(+), 6 deletions(-)
    
    diff --git a/Examples/test-suite/template_parameters_global_scope.i b/Examples/test-suite/template_parameters_global_scope.i
    index 4c14ba4a3..a828187b5 100644
    --- a/Examples/test-suite/template_parameters_global_scope.i
    +++ b/Examples/test-suite/template_parameters_global_scope.i
    @@ -9,17 +9,17 @@ namespace Alloc {
     %}
     
     %inline %{
    -struct Bucket {};
    -typedef Bucket TDBucket;
    -typedef ::Bucket TDGlobalBucket;
    +struct Bucket_ {};
    +typedef Bucket_ TDBucket;
    +typedef ::Bucket_ TDGlobalBucket;
     %}
     
     // Check 1: %template no unary scope operator
    -%template(RebindBucket) Alloc::Rebind< Bucket >;
    +%template(RebindBucket) Alloc::Rebind< Bucket_ >;
     
     %inline %{
    -Alloc::Rebind< Bucket >::Integer Bucket1() { return 1; }
    -Alloc::Rebind< ::Bucket >::Integer Bucket2() { return 2; }
    +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; }
    
    From 8bf81b8718ba413f66a9dc41e06a50f113e68edd Mon Sep 17 00:00:00 2001
    From: William S Fulton 
    Date: Wed, 9 Aug 2017 20:54:32 +0100
    Subject: [PATCH 15/18] More docs on %template
    
    ---
     Doc/Manual/SWIGPlus.html | 14 ++++++++++++++
     1 file changed, 14 insertions(+)
    
    diff --git a/Doc/Manual/SWIGPlus.html b/Doc/Manual/SWIGPlus.html
    index 13c81588d..28e0e839f 100644
    --- a/Doc/Manual/SWIGPlus.html
    +++ b/Doc/Manual/SWIGPlus.html
    @@ -3109,6 +3109,20 @@ not necessary to instantiate a new class for the type Integer (doing so
     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
    +
    +
    + +

    6.18.2 Function templates

    From bf98c5304faed50fa0c1f09228c55f21fcb06691 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 12 Aug 2017 10:11:38 +0100 Subject: [PATCH 16/18] Fix type lookup in the presence of using directives and using declarations Fix some cases of type lookup failure via a combination of both using directives and using declarations resulting in C++ code that did not compile as the generated type was not fully qualified for use in the global namespace. Example below: namespace Space5 { namespace SubSpace5 { namespace SubSubSpace5 { struct F {}; } } using namespace SubSpace5; using SubSubSpace5::F; void func(SubSubSpace5::F f); } --- Examples/test-suite/class_scope_namespace.i | 3 +- Examples/test-suite/common.mk | 1 + .../java/class_scope_namespace_runme.java | 2 +- .../java/namespace_chase_runme.java | 26 +++++ Examples/test-suite/namespace_chase.i | 36 +++++++ Source/Swig/typesys.c | 101 +++++++++++++----- 6 files changed, 139 insertions(+), 30 deletions(-) create mode 100644 Examples/test-suite/java/namespace_chase_runme.java create mode 100644 Examples/test-suite/namespace_chase.i diff --git a/Examples/test-suite/class_scope_namespace.i b/Examples/test-suite/class_scope_namespace.i index 08a9f01dc..372727f3c 100644 --- a/Examples/test-suite/class_scope_namespace.i +++ b/Examples/test-suite/class_scope_namespace.i @@ -73,8 +73,7 @@ namespace Space5 { struct SubSubSpace5::F { void ff(Space5::SubSpace5::SubSubSpace5::F, SubSpace5::SubSubSpace5::F, SubSubSpace5::F, F) {} }; -// needs fixing - void fff(Space5::SubSpace5::SubSubSpace5::F, SubSpace5::SubSubSpace5::F, /*SubSubSpace5::F,*/ F) {} + void fff(Space5::SubSpace5::SubSubSpace5::F, SubSpace5::SubSubSpace5::F, SubSubSpace5::F, F) {} } namespace Space6 { diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index 0c896825f..ce6544279 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -292,6 +292,7 @@ CPP_TEST_CASES += \ multiple_inheritance_shared_ptr \ name_cxx \ name_warnings \ + namespace_chase \ namespace_class \ namespace_enum \ namespace_extend \ diff --git a/Examples/test-suite/java/class_scope_namespace_runme.java b/Examples/test-suite/java/class_scope_namespace_runme.java index e80779413..9d74a6ca6 100644 --- a/Examples/test-suite/java/class_scope_namespace_runme.java +++ b/Examples/test-suite/java/class_scope_namespace_runme.java @@ -47,7 +47,7 @@ public class class_scope_namespace_runme { 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); + 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); 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/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/Source/Swig/typesys.c b/Source/Swig/typesys.c index 2fb514d5e..e460b422a 100644 --- a/Source/Swig/typesys.c +++ b/Source/Swig/typesys.c @@ -53,8 +53,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 +66,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. @@ -968,8 +1012,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. * ----------------------------------------------------------------------------- */ @@ -1030,20 +1083,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"); } } } From 96e99416d76c3e0201a7b60417a0c24f845ba5b8 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Tue, 15 Aug 2017 22:38:03 +0100 Subject: [PATCH 17/18] Add using declarations to templates into typedef table. Fixes #1051. Using declarations to templates were missing in SWIG's internal typedef tables. This led to a few problems, such as, templates that did not instantiate and generated C++ code that did not compile as SWIG did not know what scope the template was in. This happened mostly when a using declaration was used on a template type in a completely unrelated namespace. --- Examples/test-suite/common.mk | 1 + ...rective_and_declaration_forward_runme.java | 10 ++--- ...emplate_using_directive_typedef_runme.java | 31 +++++++++++++ .../template_using_directive_typedef_runme.py | 15 +++++++ Source/Modules/typepass.cxx | 3 -- Source/Swig/typesys.c | 45 +++++++++++++++---- 6 files changed, 89 insertions(+), 16 deletions(-) create mode 100644 Examples/test-suite/java/template_using_directive_typedef_runme.java create mode 100644 Examples/test-suite/python/template_using_directive_typedef_runme.py diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index ce6544279..e5e60a330 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -436,6 +436,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 \ 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/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/Source/Modules/typepass.cxx b/Source/Modules/typepass.cxx index bf8028c29..43ada4d4b 100644 --- a/Source/Modules/typepass.cxx +++ b/Source/Modules/typepass.cxx @@ -1199,10 +1199,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/typesys.c b/Source/Swig/typesys.c index e460b422a..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: * @@ -210,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 */ @@ -660,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 */ @@ -786,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); @@ -1106,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); @@ -1176,9 +1208,6 @@ SwigType *SwigType_typedef_qualified(const SwigType *t) { Delete(tprefix); Delete(qprefix); Delete(parms); - /* - Delete(dt); - */ } Append(result, e); Delete(ty); @@ -1258,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 */ From 09af283371edab461a4ddd0df147ce86e8547c04 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Tue, 15 Aug 2017 23:12:55 +0100 Subject: [PATCH 18/18] Test a few %template errors --- Examples/test-suite/errors/cpp_invalid_template.i | 9 +++++++++ Examples/test-suite/errors/cpp_invalid_template.stderr | 3 +++ 2 files changed, 12 insertions(+) create mode 100644 Examples/test-suite/errors/cpp_invalid_template.i create mode 100644 Examples/test-suite/errors/cpp_invalid_template.stderr 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)