summaryrefslogtreecommitdiff
path: root/testing/cffi0
diff options
context:
space:
mode:
authorArmin Rigo <arigo@tunes.org>2019-10-14 09:16:01 +0200
committerArmin Rigo <arigo@tunes.org>2019-10-14 09:16:01 +0200
commit2e1c8e4f059b1ae7cc06a1f45f40bbbf9d08f5d0 (patch)
treed4747cf3365cc6a782b226acecfebd612ad00105 /testing/cffi0
parent7fa9a5f8a80e0e460c486a7f90ae12886b22b0d9 (diff)
downloadcffi-2e1c8e4f059b1ae7cc06a1f45f40bbbf9d08f5d0.tar.gz
Add a warning when we use in cdef() a global variable without also specifying a storage class (extern or static)
Diffstat (limited to 'testing/cffi0')
-rw-r--r--testing/cffi0/test_function.py14
-rw-r--r--testing/cffi0/test_ownlib.py8
-rw-r--r--testing/cffi0/test_parsing.py8
-rw-r--r--testing/cffi0/test_verify.py62
4 files changed, 48 insertions, 44 deletions
diff --git a/testing/cffi0/test_function.py b/testing/cffi0/test_function.py
index 120d7eb..d1f9ce4 100644
--- a/testing/cffi0/test_function.py
+++ b/testing/cffi0/test_function.py
@@ -113,7 +113,7 @@ class TestFunction(object):
ffi = FFI(backend=self.Backend())
ffi.cdef("""
int fputs(const char *, void *);
- void *stderr;
+ extern void *stderr;
""")
needs_dlopen_none()
ffi.C = ffi.dlopen(None)
@@ -130,7 +130,7 @@ class TestFunction(object):
ffi = FFI(backend=self.Backend())
ffi.cdef("""
int fputs(char *, void *);
- void *stderr;
+ extern void *stderr;
""")
needs_dlopen_none()
ffi.C = ffi.dlopen(None)
@@ -147,7 +147,7 @@ class TestFunction(object):
ffi = FFI(backend=self.Backend())
ffi.cdef("""
int fprintf(void *, const char *format, ...);
- void *stderr;
+ extern void *stderr;
""")
needs_dlopen_none()
ffi.C = ffi.dlopen(None)
@@ -209,7 +209,7 @@ class TestFunction(object):
py.test.skip("probably no symbol 'stderr' in the lib")
ffi.cdef("""
int fputs(const char *, void *);
- void *stderr;
+ extern void *stderr;
""")
needs_dlopen_none()
ffi.C = ffi.dlopen(None)
@@ -256,7 +256,7 @@ class TestFunction(object):
py.test.skip("probably no symbol 'stdout' in the lib")
ffi = FFI(backend=self.Backend())
ffi.cdef("""
- void *stdout;
+ extern void *stdout;
""")
needs_dlopen_none()
C = ffi.dlopen(None)
@@ -496,7 +496,7 @@ class TestFunction(object):
ffi.cdef("""
typedef enum { MYE1, MYE2 } myenum_t;
double myfunc(double);
- double myvar;
+ extern double myvar;
const double myconst;
#define MYFOO 42
""")
@@ -507,7 +507,7 @@ class TestFunction(object):
if self.Backend is CTypesBackend:
py.test.skip("not with the ctypes backend")
ffi = FFI(backend=self.Backend())
- ffi.cdef("int foobar(void); int foobaz;")
+ ffi.cdef("int foobar(void); extern int foobaz;")
lib = ffi.dlopen(lib_m)
ffi.dlclose(lib)
e = py.test.raises(ValueError, getattr, lib, 'foobar')
diff --git a/testing/cffi0/test_ownlib.py b/testing/cffi0/test_ownlib.py
index a06df20..9295163 100644
--- a/testing/cffi0/test_ownlib.py
+++ b/testing/cffi0/test_ownlib.py
@@ -201,7 +201,7 @@ class TestOwnLib(object):
py.test.skip("fix the auto-generation of the tiny test lib")
ffi = FFI(backend=self.Backend())
ffi.cdef("""
- int my_array[7];
+ extern int my_array[7];
""")
ownlib = ffi.dlopen(self.module)
for i in range(7):
@@ -223,7 +223,7 @@ class TestOwnLib(object):
py.test.skip("not supported by the ctypes backend")
ffi = FFI(backend=self.Backend())
ffi.cdef("""
- int my_array[];
+ extern int my_array[];
""")
ownlib = ffi.dlopen(self.module)
for i in range(7):
@@ -291,7 +291,7 @@ class TestOwnLib(object):
long bottom;
} RECT;
- long left, top, right, bottom;
+ extern long left, top, right, bottom;
RECT ReturnRect(int i, RECT ar, RECT* br, POINT cp, RECT dr,
RECT *er, POINT fp, RECT gr);
@@ -321,7 +321,7 @@ class TestOwnLib(object):
if self.Backend is CTypesBackend:
py.test.skip("not implemented with the ctypes backend")
ffi = FFI(backend=self.Backend())
- ffi.cdef("long left; int test_getting_errno(void);")
+ ffi.cdef("extern long left; int test_getting_errno(void);")
lib = ffi.dlopen(self.module)
lib.left = 123456
p = ffi.addressof(lib, "left")
diff --git a/testing/cffi0/test_parsing.py b/testing/cffi0/test_parsing.py
index 2c29b86..3fc3783 100644
--- a/testing/cffi0/test_parsing.py
+++ b/testing/cffi0/test_parsing.py
@@ -324,6 +324,7 @@ def test_WPARAM_on_windows():
assert value == sys.maxsize * 2 - 40
def test__is_constant_globalvar():
+ import warnings
for input, expected_output in [
("int a;", False),
("const int a;", True),
@@ -341,10 +342,13 @@ def test__is_constant_globalvar():
("const int a[5][6];", False),
]:
ffi = FFI()
- ffi.cdef(input)
+ with warnings.catch_warnings(record=True) as log:
+ warnings.simplefilter("always")
+ ffi.cdef(input)
declarations = ffi._parser._declarations
assert ('constant a' in declarations) == expected_output
assert ('variable a' in declarations) == (not expected_output)
+ assert len(log) == (1 - expected_output)
def test_restrict():
from cffi import model
@@ -354,7 +358,7 @@ def test_restrict():
("int *a;", False),
]:
ffi = FFI()
- ffi.cdef(input)
+ ffi.cdef("extern " + input)
tp, quals = ffi._parser._declarations['variable a']
assert bool(quals & model.Q_RESTRICT) == expected_output
diff --git a/testing/cffi0/test_verify.py b/testing/cffi0/test_verify.py
index b1033c5..f4ea092 100644
--- a/testing/cffi0/test_verify.py
+++ b/testing/cffi0/test_verify.py
@@ -286,7 +286,7 @@ def test_all_integer_and_float_types():
def test_var_signed_integer_types():
ffi = FFI()
lst = all_signed_integer_types(ffi)
- csource = "\n".join(["%s somevar_%s;" % (tp, tp.replace(' ', '_'))
+ csource = "\n".join(["static %s somevar_%s;" % (tp, tp.replace(' ', '_'))
for tp in lst])
ffi.cdef(csource)
lib = ffi.verify(csource)
@@ -305,7 +305,7 @@ def test_var_signed_integer_types():
def test_var_unsigned_integer_types():
ffi = FFI()
lst = all_unsigned_integer_types(ffi)
- csource = "\n".join(["%s somevar_%s;" % (tp, tp.replace(' ', '_'))
+ csource = "\n".join(["static %s somevar_%s;" % (tp, tp.replace(' ', '_'))
for tp in lst])
ffi.cdef(csource)
lib = ffi.verify(csource)
@@ -817,8 +817,8 @@ def test_define_int():
def test_access_variable():
ffi = FFI()
- ffi.cdef("int foo(void);\n"
- "int somenumber;")
+ ffi.cdef("static int foo(void);\n"
+ "static int somenumber;")
lib = ffi.verify("""
static int somenumber = 2;
static int foo(void) {
@@ -835,7 +835,7 @@ def test_access_variable():
def test_access_address_of_variable():
# access the address of 'somenumber': need a trick
ffi = FFI()
- ffi.cdef("int somenumber; static int *const somenumberptr;")
+ ffi.cdef("static int somenumber; static int *const somenumberptr;")
lib = ffi.verify("""
static int somenumber = 2;
#define somenumberptr (&somenumber)
@@ -848,7 +848,7 @@ def test_access_address_of_variable():
def test_access_array_variable(length=5):
ffi = FFI()
ffi.cdef("int foo(int);\n"
- "int somenumber[%s];" % (length,))
+ "static int somenumber[%s];" % (length,))
lib = ffi.verify("""
static int somenumber[] = {2, 2, 3, 4, 5};
static int foo(int i) {
@@ -880,7 +880,7 @@ def test_access_struct_variable():
ffi = FFI()
ffi.cdef("struct foo { int x; ...; };\n"
"int foo(int);\n"
- "struct foo stuff;")
+ "static struct foo stuff;")
lib = ffi.verify("""
struct foo { int x, y, z; };
static struct foo stuff = {2, 5, 8};
@@ -904,9 +904,9 @@ def test_access_struct_variable():
def test_access_callback():
ffi = FFI()
- ffi.cdef("int (*cb)(int);\n"
- "int foo(int);\n"
- "void reset_cb(void);")
+ ffi.cdef("static int (*cb)(int);\n"
+ "static int foo(int);\n"
+ "static void reset_cb(void);")
lib = ffi.verify("""
static int g(int x) { return x * 7; }
static int (*cb)(int);
@@ -922,9 +922,9 @@ def test_access_callback():
def test_access_callback_function_typedef():
ffi = FFI()
ffi.cdef("typedef int mycallback_t(int);\n"
- "mycallback_t *cb;\n"
- "int foo(int);\n"
- "void reset_cb(void);")
+ "static mycallback_t *cb;\n"
+ "static int foo(int);\n"
+ "static void reset_cb(void);")
lib = ffi.verify("""
static int g(int x) { return x * 7; }
static int (*cb)(int);
@@ -1074,7 +1074,7 @@ def test_autofilled_struct_as_argument():
def test_autofilled_struct_as_argument_dynamic():
ffi = FFI()
ffi.cdef("struct foo_s { long a; ...; };\n"
- "int (*foo)(struct foo_s);")
+ "static int (*foo)(struct foo_s);")
lib = ffi.verify("""
struct foo_s {
double b;
@@ -1083,7 +1083,7 @@ def test_autofilled_struct_as_argument_dynamic():
int foo1(struct foo_s s) {
return (int)s.a - (int)s.b;
}
- int (*foo)(struct foo_s s) = &foo1;
+ static int (*foo)(struct foo_s s) = &foo1;
""")
e = py.test.raises(NotImplementedError, lib.foo, "?")
msg = ("ctype 'struct foo_s' not supported as argument. It is a struct "
@@ -1453,7 +1453,7 @@ def test_bool():
py.test.skip("_Bool not in MSVC")
ffi = FFI()
ffi.cdef("struct foo_s { _Bool x; };"
- "_Bool foo(_Bool); _Bool (*foop)(_Bool);")
+ "_Bool foo(_Bool); static _Bool (*foop)(_Bool);")
lib = ffi.verify("""
struct foo_s { _Bool x; };
int foo(int arg) {
@@ -1462,7 +1462,7 @@ def test_bool():
_Bool _foofunc(_Bool x) {
return !x;
}
- _Bool (*foop)(_Bool) = _foofunc;
+ static _Bool (*foop)(_Bool) = _foofunc;
""")
p = ffi.new("struct foo_s *")
p.x = 1
@@ -1653,7 +1653,7 @@ def test_FILE_stored_in_stdout():
def test_FILE_stored_explicitly():
ffi = FFI()
- ffi.cdef("int myprintf11(const char *, int); FILE *myfile;")
+ ffi.cdef("int myprintf11(const char *, int); extern FILE *myfile;")
lib = ffi.verify("""
#include <stdio.h>
FILE *myfile;
@@ -1679,19 +1679,19 @@ def test_FILE_stored_explicitly():
def test_global_array_with_missing_length():
ffi = FFI()
- ffi.cdef("int fooarray[];")
+ ffi.cdef("extern int fooarray[];")
lib = ffi.verify("int fooarray[50];")
assert repr(lib.fooarray).startswith("<cdata 'int *'")
def test_global_array_with_dotdotdot_length():
ffi = FFI()
- ffi.cdef("int fooarray[...];")
+ ffi.cdef("extern int fooarray[...];")
lib = ffi.verify("int fooarray[50];")
assert repr(lib.fooarray).startswith("<cdata 'int[50]'")
def test_bad_global_array_with_dotdotdot_length():
ffi = FFI()
- ffi.cdef("int fooarray[...];")
+ ffi.cdef("extern int fooarray[...];")
py.test.raises(VerificationError, ffi.verify, "char fooarray[23];")
def test_struct_containing_struct():
@@ -1812,7 +1812,7 @@ def test_string_to_voidp_arg():
def test_callback_indirection():
ffi = FFI()
ffi.cdef("""
- int (*python_callback)(int how_many, int *values);
+ static int (*python_callback)(int how_many, int *values);
int (*const c_callback)(int,...); /* pass this ptr to C routines */
int some_c_function(int(*cb)(int,...));
""")
@@ -1946,24 +1946,24 @@ def test_typeof_func_with_struct_argument():
def test_bug_const_char_ptr_array_1():
ffi = FFI()
- ffi.cdef("""const char *a[...];""")
+ ffi.cdef("""extern const char *a[...];""")
lib = ffi.verify("""const char *a[5];""")
assert repr(ffi.typeof(lib.a)) == "<ctype 'char *[5]'>"
def test_bug_const_char_ptr_array_2():
from cffi import FFI # ignore warnings
ffi = FFI()
- ffi.cdef("""const int a[];""")
+ ffi.cdef("""extern const int a[];""")
lib = ffi.verify("""const int a[5];""")
assert repr(ffi.typeof(lib.a)) == "<ctype 'int *'>"
def _test_various_calls(force_libffi):
cdef_source = """
- int xvalue;
- long long ivalue, rvalue;
- float fvalue;
- double dvalue;
- long double Dvalue;
+ extern int xvalue;
+ extern long long ivalue, rvalue;
+ extern float fvalue;
+ extern double dvalue;
+ extern long double Dvalue;
signed char tf_bb(signed char x, signed char c);
unsigned char tf_bB(signed char x, unsigned char c);
short tf_bh(signed char x, short c);
@@ -2147,7 +2147,7 @@ def test_verify_dlopen_flags():
# exported symbols as well. So we must not export a simple name
# like 'foo'!
ffi1 = FFI()
- ffi1.cdef("int foo_verify_dlopen_flags;")
+ ffi1.cdef("extern int foo_verify_dlopen_flags;")
lib1 = ffi1.verify("int foo_verify_dlopen_flags;",
flags=ffi1.RTLD_GLOBAL | ffi1.RTLD_LAZY)
@@ -2161,7 +2161,7 @@ def test_verify_dlopen_flags():
def get_second_lib():
# Hack, using modulename makes the test fail
ffi2 = FFI()
- ffi2.cdef("int foo_verify_dlopen_flags;")
+ ffi2.cdef("extern int foo_verify_dlopen_flags;")
lib2 = ffi2.verify("int foo_verify_dlopen_flags;",
flags=ffi2.RTLD_GLOBAL | ffi2.RTLD_LAZY)
return lib2