summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWilliam S Fulton <wsf@fultondesigns.co.uk>2013-02-08 06:34:35 +0000
committerWilliam S Fulton <wsf@fultondesigns.co.uk>2013-02-08 06:36:39 +0000
commitb725625e6fc29fc38e561f1c8455f4559add4d5e (patch)
tree552fcb8e4c1da82b7ea5bf7ba1a395bf4b35dfe7
parentc6bc7b881f0b8f7fa26cddbc8a997b7be877b6e1 (diff)
downloadswig-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.html13
-rw-r--r--Examples/test-suite/cpp0x_thread_local.i26
-rw-r--r--Examples/test-suite/java/cpp0x_thread_local_runme.java43
-rw-r--r--Examples/test-suite/python/cpp0x_thread_local_runme.py30
-rw-r--r--Source/CParse/parser.y4
-rw-r--r--Source/Modules/allocate.cxx2
-rw-r--r--Source/Modules/contract.cxx2
-rw-r--r--Source/Modules/directors.cxx4
-rw-r--r--Source/Modules/go.cxx4
-rw-r--r--Source/Modules/lang.cxx7
-rw-r--r--Source/Modules/typepass.cxx2
-rw-r--r--Source/Swig/cwrap.c6
-rw-r--r--Source/Swig/misc.c21
-rw-r--r--Source/Swig/naming.c3
-rw-r--r--Source/Swig/swig.h2
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);