diff options
author | William S Fulton <wsf@fultondesigns.co.uk> | 2013-02-08 06:34:35 +0000 |
---|---|---|
committer | William S Fulton <wsf@fultondesigns.co.uk> | 2013-02-08 06:36:39 +0000 |
commit | b725625e6fc29fc38e561f1c8455f4559add4d5e (patch) | |
tree | 552fcb8e4c1da82b7ea5bf7ba1a395bf4b35dfe7 | |
parent | c6bc7b881f0b8f7fa26cddbc8a997b7be877b6e1 (diff) | |
download | swig-b725625e6fc29fc38e561f1c8455f4559add4d5e.tar.gz |
Add support for thread_local when specified with other legitimate storage class specifiers - extern and static
-rw-r--r-- | Doc/Manual/Cpp0x.html | 13 | ||||
-rw-r--r-- | Examples/test-suite/cpp0x_thread_local.i | 26 | ||||
-rw-r--r-- | Examples/test-suite/java/cpp0x_thread_local_runme.java | 43 | ||||
-rw-r--r-- | Examples/test-suite/python/cpp0x_thread_local_runme.py | 30 | ||||
-rw-r--r-- | Source/CParse/parser.y | 4 | ||||
-rw-r--r-- | Source/Modules/allocate.cxx | 2 | ||||
-rw-r--r-- | Source/Modules/contract.cxx | 2 | ||||
-rw-r--r-- | Source/Modules/directors.cxx | 4 | ||||
-rw-r--r-- | Source/Modules/go.cxx | 4 | ||||
-rw-r--r-- | Source/Modules/lang.cxx | 7 | ||||
-rw-r--r-- | Source/Modules/typepass.cxx | 2 | ||||
-rw-r--r-- | Source/Swig/cwrap.c | 6 | ||||
-rw-r--r-- | Source/Swig/misc.c | 21 | ||||
-rw-r--r-- | Source/Swig/naming.c | 3 | ||||
-rw-r--r-- | Source/Swig/swig.h | 2 |
15 files changed, 145 insertions, 24 deletions
diff --git a/Doc/Manual/Cpp0x.html b/Doc/Manual/Cpp0x.html index e9576ec84..457a7e41d 100644 --- a/Doc/Manual/Cpp0x.html +++ b/Doc/Manual/Cpp0x.html @@ -722,17 +722,22 @@ OutputType var3 = 3.1416_suffix; <H3><a name="Cpp0x_Thread_local_storage"></a>7.2.20 Thread-local storage</H3> -<p>SWIG correctly parses the <tt>thread_local</tt> keyword. For example, a variable +<p>SWIG correctly parses the <tt>thread_local</tt> keyword. For example, variable reachable by the current thread can be defined as:</p> <div class="code"><pre> struct A { - thread_local int val; + static thread_local int val; }; +thread_local int global_val; </pre></div> -<p>The new C++0x threading libraries are ignored because each SWIG target language offers -its own threading facilities.</p> +<p> +The use of the <tt>thread_local</tt> storage specifier does not affect the wrapping process; it does not modify +the wrapper code compared to when it is not specified. +A variable will be thread local if accessed from different threads from the target language in the +same way that it will be thread local if accessed from C++ code. +</p> <H3><a name="Cpp0x_Defaulting/deleting_of_standard_functions_on_C++_objects"></a>7.2.21 Defaulting/deleting of standard functions on C++ objects</H3> diff --git a/Examples/test-suite/cpp0x_thread_local.i b/Examples/test-suite/cpp0x_thread_local.i index 2ec633319..5ba01ea58 100644 --- a/Examples/test-suite/cpp0x_thread_local.i +++ b/Examples/test-suite/cpp0x_thread_local.i @@ -1,11 +1,29 @@ -/* This testcase checks whether SWIG correctly parses the 'thread_local' - keyword before the member type and name. */ +/* This testcase checks whether SWIG correctly parses the 'thread_local' storage specifier */ %module cpp0x_thread_local %inline %{ -struct A { - thread_local int val; +struct ThreadLocals { +// thread_local int tval; // members must also be declared static + static thread_local int stval; + thread_local static int tsval; + static thread_local const int stcval88 = 88; + thread_local static const int tscval99 = 99; }; +thread_local int tval; +static thread_local int stval; +thread_local static int tsval; +extern thread_local int etval; +thread_local extern int teval; + +thread_local int ThreadLocals::stval = 11; +thread_local int ThreadLocals::tsval = 22; +thread_local const int ThreadLocals::stcval88; +thread_local const int ThreadLocals::tscval99; %} +%{ +// externs +thread_local int etval = 33; +thread_local int teval = 44; +%} diff --git a/Examples/test-suite/java/cpp0x_thread_local_runme.java b/Examples/test-suite/java/cpp0x_thread_local_runme.java new file mode 100644 index 000000000..adc88a903 --- /dev/null +++ b/Examples/test-suite/java/cpp0x_thread_local_runme.java @@ -0,0 +1,43 @@ +import cpp0x_thread_local.*; + +public class cpp0x_thread_local_runme { + + static { + try { + System.loadLibrary("cpp0x_thread_local"); + } 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[]) + { + if (ThreadLocals.getStval() != 11) + throw new RuntimeException(); + if (ThreadLocals.getTsval() != 22) + throw new RuntimeException(); + if (ThreadLocals.tscval99 != 99) + throw new RuntimeException(); + + cpp0x_thread_local.setEtval(-11); + if (cpp0x_thread_local.getEtval() != -11) + throw new RuntimeException(); + + cpp0x_thread_local.setStval(-22); + if (cpp0x_thread_local.getStval() != -22) + throw new RuntimeException(); + + cpp0x_thread_local.setTsval(-33); + if (cpp0x_thread_local.getTsval() != -33) + throw new RuntimeException(); + + cpp0x_thread_local.setEtval(-44); + if (cpp0x_thread_local.getEtval() != -44) + throw new RuntimeException(); + + cpp0x_thread_local.setTeval(-55); + if (cpp0x_thread_local.getTeval() != -55) + throw new RuntimeException(); + } +} diff --git a/Examples/test-suite/python/cpp0x_thread_local_runme.py b/Examples/test-suite/python/cpp0x_thread_local_runme.py new file mode 100644 index 000000000..b4aa177f6 --- /dev/null +++ b/Examples/test-suite/python/cpp0x_thread_local_runme.py @@ -0,0 +1,30 @@ +from cpp0x_thread_local import * + +t = ThreadLocals() +if t.stval != 11: + raise RuntimeError +if t.tsval != 22: + raise RuntimeError +if t.tscval99 != 99: + raise RuntimeError + +cvar.etval = -11 +if cvar.etval != -11: + raise RuntimeError + +cvar.stval = -22 +if cvar.stval != -22: + raise RuntimeError + +cvar.tsval = -33 +if cvar.tsval != -33: + raise RuntimeError + +cvar.etval = -44 +if cvar.etval != -44: + raise RuntimeError + +cvar.teval = -55 +if cvar.teval != -55: + raise RuntimeError + diff --git a/Source/CParse/parser.y b/Source/CParse/parser.y index 45b691689..33f11958e 100644 --- a/Source/CParse/parser.y +++ b/Source/CParse/parser.y @@ -5041,6 +5041,10 @@ storage_class : EXTERN { $$ = "extern"; } | EXPLICIT { $$ = "explicit"; } | CONSTEXPR { $$ = "constexpr"; } | THREAD_LOCAL { $$ = "thread_local"; } + | THREAD_LOCAL STATIC { $$ = "static thread_local"; } + | STATIC THREAD_LOCAL { $$ = "static thread_local"; } + | EXTERN THREAD_LOCAL { $$ = "extern thread_local"; } + | THREAD_LOCAL EXTERN { $$ = "extern thread_local"; } | empty { $$ = 0; } ; diff --git a/Source/Modules/allocate.cxx b/Source/Modules/allocate.cxx index 5320d9689..dee044bf3 100644 --- a/Source/Modules/allocate.cxx +++ b/Source/Modules/allocate.cxx @@ -771,7 +771,7 @@ Allocate(): /* Check to see if this is a static member or not. If so, we add an attribute cplus:staticbase that saves the current class */ - if (checkAttribute(n, "storage", "static")) { + if (Swig_storage_isstatic(n)) { Setattr(n, "cplus:staticbase", inclass); } diff --git a/Source/Modules/contract.cxx b/Source/Modules/contract.cxx index 5fa5bcad5..ffd799cfd 100644 --- a/Source/Modules/contract.cxx +++ b/Source/Modules/contract.cxx @@ -307,7 +307,7 @@ int Contracts::cDeclaration(Node *n) { return SWIG_OK; if (Getattr(n, "feature:contract")) - ret = emit_contract(n, (InClass && !checkAttribute(n, "storage", "static"))); + ret = emit_contract(n, InClass && !Swig_storage_isstatic(n)); return ret; } diff --git a/Source/Modules/directors.cxx b/Source/Modules/directors.cxx index 4cb38d0aa..2fdda5a12 100644 --- a/Source/Modules/directors.cxx +++ b/Source/Modules/directors.cxx @@ -275,8 +275,8 @@ String *Swig_method_decl(SwigType *rettype, SwigType *decl, const_String_or_char void Swig_director_emit_dynamic_cast(Node *n, Wrapper *f) { // TODO: why is the storage element removed in staticmemberfunctionHandler ?? if ((!is_public(n) && (is_member_director(n) || GetFlag(n, "explicitcall"))) || - (is_non_virtual_protected_access(n) && !(checkAttribute(n, "staticmemberfunctionHandler:storage", "static") || - checkAttribute(n, "storage", "static")) + (is_non_virtual_protected_access(n) && !(Swig_storage_isstatic_custom(n, "staticmemberfunctionHandler:storage") || + Swig_storage_isstatic(n)) && !Equal(nodeType(n), "constructor"))) { Node *parent = Getattr(n, "parentNode"); String *dirname; diff --git a/Source/Modules/go.cxx b/Source/Modules/go.cxx index fa706cb62..52e2459b7 100644 --- a/Source/Modules/go.cxx +++ b/Source/Modules/go.cxx @@ -1611,7 +1611,7 @@ private: return goComplexConstant(n, type); } - if (Getattr(n, "storage") && Strcmp(Getattr(n, "storage"), "static") == 0) { + if (Swig_storage_isstatic(n)) { return goComplexConstant(n, type); } @@ -4860,7 +4860,7 @@ private: bool isStatic(Node *n) { String *storage = Getattr(n, "storage"); - return (storage && (Strcmp(storage, "static") == 0 || Strcmp(storage, "friend") == 0) && (!SmartPointer || !Getattr(n, "allocate:smartpointeraccess"))); + return (storage && (Swig_storage_isstatic(n) || Strcmp(storage, "friend") == 0) && (!SmartPointer || !Getattr(n, "allocate:smartpointeraccess"))); } /* ---------------------------------------------------------------------- diff --git a/Source/Modules/lang.cxx b/Source/Modules/lang.cxx index 1890add23..b4ad9c879 100644 --- a/Source/Modules/lang.cxx +++ b/Source/Modules/lang.cxx @@ -1058,7 +1058,7 @@ int Language::cDeclaration(Node *n) { int Language::functionHandler(Node *n) { String *storage = Getattr(n, "storage"); int isfriend = CurrentClass && Cmp(storage, "friend") == 0; - int isstatic = CurrentClass && Cmp(storage, "static") == 0 && !(SmartPointer && Getattr(n, "allocate:smartpointeraccess")); + int isstatic = CurrentClass && Swig_storage_isstatic(n) && !(SmartPointer && Getattr(n, "allocate:smartpointeraccess")); Parm *p = Getattr(n, "parms"); if (GetFlag(n, "feature:del")) { /* the method acts like a delete operator, ie, we need to disown the parameter */ @@ -1366,7 +1366,6 @@ int Language::variableHandler(Node *n) { if (!CurrentClass) { globalvariableHandler(n); } else { - String *storage = Getattr(n, "storage"); Swig_save("variableHandler", n, "feature:immutable", NIL); if (SmartPointer) { /* If a smart-pointer and it's a constant access, we have to set immutable */ @@ -1374,7 +1373,7 @@ int Language::variableHandler(Node *n) { SetFlag(n, "feature:immutable"); } } - if ((Cmp(storage, "static") == 0) && !(SmartPointer && Getattr(n, "allocate:smartpointeraccess"))) { + if (Swig_storage_isstatic(n) && !(SmartPointer && Getattr(n, "allocate:smartpointeraccess"))) { staticmembervariableHandler(n); } else { membervariableHandler(n); @@ -1428,7 +1427,7 @@ int Language::membervariableHandler(Node *n) { String *target = 0; if (!Extend) { if (SmartPointer) { - if (checkAttribute(n, "storage", "static")) { + if (Swig_storage_isstatic(n)) { Node *sn = Getattr(n, "cplus:staticbase"); String *base = Getattr(sn, "name"); target = NewStringf("%s::%s", base, name); diff --git a/Source/Modules/typepass.cxx b/Source/Modules/typepass.cxx index af16afb21..7eebfe80b 100644 --- a/Source/Modules/typepass.cxx +++ b/Source/Modules/typepass.cxx @@ -995,7 +995,7 @@ class TypePass:private Dispatcher { String *symname = Getattr(n, "sym:name"); while (c) { if (Strcmp(nodeType(c), "cdecl") == 0) { - if (!(checkAttribute(c, "storage", "static") + if (!(Swig_storage_isstatic(c) || checkAttribute(c, "storage", "typedef") || checkAttribute(c, "storage", "friend") || (Getattr(c, "feature:extend") && !Getattr(c, "code")) diff --git a/Source/Swig/cwrap.c b/Source/Swig/cwrap.c index de93d84c0..f48108e15 100644 --- a/Source/Swig/cwrap.c +++ b/Source/Swig/cwrap.c @@ -922,7 +922,7 @@ int Swig_MethodToFunction(Node *n, const_String_or_char_ptr nspace, String *clas self = NewString("(*(this))->"); is_smart_pointer_overload = 1; } - else if (Cmp(Getattr(n, "storage"), "static") == 0) { + else if (Swig_storage_isstatic(n)) { String *cname = Getattr(n, "classname") ? Getattr(n, "classname") : classname; String *ctname = SwigType_namestr(cname); self = NewStringf("(*(%s const *)this)->", ctname); @@ -1064,7 +1064,7 @@ int Swig_MethodToFunction(Node *n, const_String_or_char_ptr nspace, String *clas String *func = NewStringf("%s(", mangled); String *cres; - if (Cmp(Getattr(n, "storage"), "static") != 0) { + if (!Swig_storage_isstatic(n)) { String *pname = Swig_cparm_name(pp, i); String *ctname = SwigType_namestr(cname); String *fadd = 0; @@ -1467,7 +1467,7 @@ int Swig_MembergetToFunction(Node *n, String *classname, int flags) { int varcref = flags & CWRAP_NATURAL_VAR; if (flags & CWRAP_SMART_POINTER) { - if (checkAttribute(n, "storage", "static")) { + if (Swig_storage_isstatic(n)) { Node *sn = Getattr(n, "cplus:staticbase"); String *base = Getattr(sn, "name"); self = NewStringf("%s::", base); diff --git a/Source/Swig/misc.c b/Source/Swig/misc.c index 05dd0c480..1b8d79daf 100644 --- a/Source/Swig/misc.c +++ b/Source/Swig/misc.c @@ -263,6 +263,27 @@ void Swig_filename_unescape(String *filename) { } /* ----------------------------------------------------------------------------- + * Swig_storage_isstatic_custom() + * + * Determine if the storage class specifier is static + * ----------------------------------------------------------------------------- */ + +int Swig_storage_isstatic_custom(Node *n, const_String_or_char_ptr storage_name) { + const String *storage = Getattr(n, storage_name); + return storage ? Strncmp(storage, "static", 6) == 0 : 0; +} + +/* ----------------------------------------------------------------------------- + * Swig_storage_isstatic() + * + * Determine if the storage class specifier is static + * ----------------------------------------------------------------------------- */ + +int Swig_storage_isstatic(Node *n) { + return Swig_storage_isstatic_custom(n, "storage"); +} + +/* ----------------------------------------------------------------------------- * Swig_string_escape() * * Takes a string object and produces a string with escape codes added to it. diff --git a/Source/Swig/naming.c b/Source/Swig/naming.c index a4bff35af..119f816dc 100644 --- a/Source/Swig/naming.c +++ b/Source/Swig/naming.c @@ -938,8 +938,7 @@ static int nodes_are_equivalent(Node *a, Node *b, int a_inclass) { } /* static functions */ - if ((Cmp(a_storage, "static") == 0) - || (Cmp(b_storage, "static") == 0)) { + if (Swig_storage_isstatic(a) || Swig_storage_isstatic(b)) { if (Cmp(a_storage, b_storage) != 0) return 0; } diff --git a/Source/Swig/swig.h b/Source/Swig/swig.h index 2dd027155..eccc18308 100644 --- a/Source/Swig/swig.h +++ b/Source/Swig/swig.h @@ -315,6 +315,8 @@ extern int ParmList_is_compactdefargs(ParmList *p); extern void Swig_filename_correct(String *filename); extern String *Swig_filename_escape(String *filename); extern void Swig_filename_unescape(String *filename); + extern int Swig_storage_isstatic_custom(Node *n, const_String_or_char_ptr storage); + extern int Swig_storage_isstatic(Node *n); extern String *Swig_string_escape(String *s); extern String *Swig_string_mangle(const String *s); extern void Swig_scopename_split(const String *s, String **prefix, String **last); |