Skip to content

Commit a739e22

Browse files
committed
[GCChecker] fix tests and add Makefile
1 parent 4c7ae77 commit a739e22

File tree

7 files changed

+161
-55
lines changed

7 files changed

+161
-55
lines changed

Make.inc

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1301,6 +1301,25 @@ ifeq ($(USE_SYSTEM_LIBM),1)
13011301
USE_BINARYBUILDER_OPENLIBM := 0
13021302
endif
13031303

1304+
1305+
# Note: we're passing *FLAGS here computed based on your system compiler to
1306+
# clang. If that causes you problems, you might want to build and/or run
1307+
# specific clang-sa-* files with clang explicitly selected:
1308+
# make CC=~+/../usr/tools/clang CXX=~+/../usr/tools/clang USECLANG=1 analyzegc
1309+
# make USECLANG=1 clang-sa-*
1310+
CLANGSA_FLAGS :=
1311+
CLANGSA_CXXFLAGS :=
1312+
ifeq ($(OS), Darwin) # on new XCode, the files are hidden
1313+
CLANGSA_FLAGS += -isysroot $(shell xcode-select -p)/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk
1314+
CLANGSA_CXXFLAGS += -isystem $(shell xcode-select -p)/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1
1315+
endif
1316+
ifeq ($(USEGCC),1)
1317+
# try to help clang find the c++ files for CC by guessing the value for --prefix
1318+
# by dropping lib/gcc/<platform>/<version> from the install directory it reports
1319+
CLANGSA_CXXFLAGS += --gcc-toolchain="$(abspath $(shell LANG=C $(CC) -print-search-dirs | grep '^install: ' | sed -e "s/^install: //")/../../../..)"
1320+
endif
1321+
1322+
13041323
# Make tricks
13051324

13061325
define dir_target

src/Makefile

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -372,24 +372,6 @@ ifneq ($(BUILD_LLVM_CLANG),1)
372372
endif
373373
endif
374374

375-
376-
# Note: we're passing *FLAGS here computed based on your system compiler to
377-
# clang. If that causes you problems, you might want to build and/or run
378-
# specific clang-sa-* files with clang explicitly selected:
379-
# make CC=~+/../usr/tools/clang CXX=~+/../usr/tools/clang USECLANG=1 analyzegc
380-
# make USECLANG=1 clang-sa-*
381-
CLANGSA_FLAGS :=
382-
CLANGSA_CXXFLAGS :=
383-
ifeq ($(OS), Darwin) # on new XCode, the files are hidden
384-
CLANGSA_FLAGS += -isysroot $(shell xcode-select -p)/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk
385-
CLANGSA_CXXFLAGS += -isystem $(shell xcode-select -p)/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1
386-
endif
387-
ifeq ($(USEGCC),1)
388-
# try to help clang find the c++ files for CC by guessing the value for --prefix
389-
# by dropping lib/gcc/<platform>/<version> from the install directory it reports
390-
CLANGSA_CXXFLAGS += --gcc-toolchain="$(abspath $(shell LANG=C $(CC) -print-search-dirs | grep '^install: ' | sed -e "s/^install: //")/../../../..)"
391-
endif
392-
393375
clang-sa-%: $(SRCDIR)/%.c $(build_shlibdir)/libGCCheckerPlugin.$(SHLIB_EXT) | analyzegc-deps-check
394376
@$(call PRINT_ANALYZE, $(build_depsbindir)/clang --analyze -Xanalyzer -analyzer-werror -Xanalyzer -analyzer-output=text -Xclang -load -Xclang $(build_shlibdir)/libGCCheckerPlugin.$(SHLIB_EXT) $(CLANGSA_FLAGS) $(JCPPFLAGS) $(JCFLAGS) $(DEBUGFLAGS) -Xclang -analyzer-checker=core$(COMMA)julia.GCChecker --analyzer-no-default-checks -fcolor-diagnostics -Werror -x c $<)
395377
clang-sa-%: $(SRCDIR)/%.cpp $(build_shlibdir)/libGCCheckerPlugin.$(SHLIB_EXT) | analyzegc-deps-check

test/clangsa/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/Output/

test/clangsa/GCPushPop.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// This file is a part of Julia. License is MIT: https://julialang.org/license
22

3-
// RUN: %clang --analyze -Xanalyzer -analyzer-output=text -Xclang -load -Xclang %gc_plugin -Xclang -verify -I%julia_home/src -I%julia_home/src/support -I%julia_home/usr/include -Xclang -analyzer-checker=core,julia.GCChecker -x c++ %s
3+
// RUN: clang --analyze -Xanalyzer -analyzer-output=text -Xclang -load -Xclang libGCCheckerPlugin%shlibext -Xclang -verify -I%julia_home/src -I%julia_home/src/support -I%julia_home/usr/include ${CLANGSA_FLAGS} ${CPPFLAGS} ${CFLAGS} -Xclang -analyzer-checker=core,julia.GCChecker -x c++ %s
44

55
#include "julia.h"
66

test/clangsa/Makefile

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
SRCDIR := $(abspath $(dir $(lastword $(MAKEFILE_LIST))))
2+
JULIAHOME := $(abspath $(SRCDIR)/../..)
3+
include $(JULIAHOME)/Make.inc
4+
5+
check: $(SRCDIR)
6+
7+
TESTS = $(patsubst $(SRCDIR)/%,%,$(wildcard $(SRCDIR)/*.c)) $(wildcard $(SRCDIR)/*.cpp)
8+
9+
$(SRCDIR) $(TESTS):
10+
PATH=$(build_bindir):$(build_depsbindir):$$PATH \
11+
LD_LIBRARY_PATH="${build_libdir}:$$LD_LIBRARY_PATH" \
12+
CLANGSA_FLAGS="${CLANGSA_FLAGS}" \
13+
CLANGSACXX_FLAGS="${CLANGSACXX_FLAGS}" \
14+
CPPFLAGS_FLAGS="${CPPFLAGS_FLAGS}" \
15+
CFLAGS_FLAGS="${CFLAGS_FLAGS}" \
16+
CXXFLAGS_FLAGS="${CXXFLAGS_FLAGS}" \
17+
$(build_depsbindir)/lit/lit.py -v $@
18+
19+
.PHONY: $(TESTS) $(SRCDIR) check all

test/clangsa/MissingRoots.c

Lines changed: 94 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,18 @@
11
// This file is a part of Julia. License is MIT: https://julialang.org/license
22

3-
// RUN: %clang --analyze -Xanalyzer -analyzer-output=text -Xclang -load -Xclang %gc_plugin -I%julia_home/src -I%julia_home/src/support -I%julia_home/usr/include -Xclang -analyzer-checker=core,julia.GCChecker --analyzer-no-default-checks -Xclang -verify -Xclang -verify-ignore-unexpected=note -x c %s
3+
// RUN: clang --analyze -Xanalyzer -analyzer-output=text -Xclang -load -Xclang libGCCheckerPlugin%shlibext -I%julia_home/src -I%julia_home/src/support -I%julia_home/usr/include ${CLANGSA_FLAGS} ${CPPFLAGS} ${CFLAGS} -Xclang -analyzer-checker=core,julia.GCChecker --analyzer-no-default-checks -Xclang -verify -x c %s
44

55
#include "julia.h"
66
#include "julia_internal.h"
77

8+
extern void look_at_value(jl_value_t *v);
9+
extern void process_unrooted(jl_value_t *maybe_unrooted JL_MAYBE_UNROOTED);
10+
extern void jl_gc_safepoint();
11+
812
void unrooted_argument() {
9-
jl_((jl_value_t*)jl_svec1(NULL)); // expected-warning{{Passing non-rooted value as argument to function}}
10-
// expected-note@-1{{Passing non-rooted value as argument to function}}
13+
look_at_value((jl_value_t*)jl_svec1(NULL)); // expected-warning{{Passing non-rooted value as argument to function}}
14+
// expected-note@-1{{Passing non-rooted value as argument to function}}
15+
// expected-note@-2{{Started tracking value here}}
1116
};
1217

1318
void simple_svec() {
@@ -16,13 +21,10 @@ void simple_svec() {
1621
assert(jl_svecref(val, 0) == NULL);
1722
}
1823

19-
extern void jl_gc_safepoint();
2024
jl_value_t *simple_missing_root() {
2125
jl_svec_t *val = jl_svec1(NULL);
22-
// This is a GC safepoint, so the above value could have been freed
23-
jl_gc_safepoint(); // expected-note {{Value may have been GCed here}}
24-
return jl_svecref(val, 0); // expected-warning{{Argument value may have been GCed}}
25-
// expected-note@-1{{Argument value may have been GCed}}
26+
jl_gc_safepoint();
27+
return jl_svecref(val, 0); // XXX-expected-warning{{Passing non-rooted value as argument to function}}
2628
};
2729

2830
jl_value_t *root_value() {
@@ -34,6 +36,64 @@ jl_value_t *root_value() {
3436
return ret;
3537
};
3638

39+
void root_value_data() {
40+
jl_svec_t *val = jl_svec1(NULL); // expected-note{{Started tracking value here}}
41+
jl_value_t **data = jl_svec_data(val);
42+
JL_GC_PUSH1(&val); // expected-note{{GC frame changed here}}
43+
// expected-note@-1{{Value was rooted here}}
44+
jl_gc_safepoint();
45+
look_at_value(*data);
46+
JL_GC_POP(); // expected-note{{GC frame changed here}}
47+
// expected-note@-1{{Root was released here}}
48+
jl_gc_safepoint(); // expected-note{{Value may have been GCed here}}
49+
*data; // expected-warning{{Creating derivative of value that may have been GCed}}
50+
// expected-note@-1{{Creating derivative of value that may have been GCed}}
51+
};
52+
53+
void root_value_data2() {
54+
jl_svec_t *val = jl_svec1(NULL); // expected-note{{Started tracking value here}}
55+
jl_value_t **data = jl_svec_data(val);
56+
JL_GC_PUSH1(&val); // expected-note{{GC frame changed here}}
57+
// expected-note@-1{{Value was rooted here}}
58+
jl_gc_safepoint();
59+
look_at_value(data[0]);
60+
JL_GC_POP(); // expected-note{{GC frame changed here}}
61+
// expected-note@-1{{Root was released here}}
62+
jl_gc_safepoint(); // expected-note{{Value may have been GCed here}}
63+
data[0]; // expected-warning{{Creating derivative of value that may have been GCed}}
64+
// expected-note@-1{{Creating derivative of value that may have been GCed}}
65+
};
66+
67+
68+
void root_value_data3() {
69+
jl_svec_t *val = jl_svec1(NULL); // expected-note{{Started tracking value here}}
70+
jl_value_t **data = jl_svec_data(val);
71+
JL_GC_PUSH1(&val); // expected-note{{GC frame changed here}}
72+
// expected-note@-1{{Value was rooted here}}
73+
jl_gc_safepoint();
74+
look_at_value(**&data);
75+
JL_GC_POP(); // expected-note{{GC frame changed here}}
76+
// expected-note@-1{{Root was released here}}
77+
jl_gc_safepoint(); // expected-note{{Value may have been GCed here}}
78+
**&data; // expected-warning{{Creating derivative of value that may have been GCed}}
79+
// expected-note@-1{{Creating derivative of value that may have been GCed}}
80+
};
81+
82+
void root_value_data4() {
83+
jl_svec_t *val = jl_svec1(NULL); // expected-note{{Started tracking value here}}
84+
jl_value_t **data = jl_svec_data(val);
85+
JL_GC_PUSH1(&val); // expected-note{{GC frame changed here}}
86+
// expected-note@-1{{Value was rooted here}}
87+
jl_gc_safepoint();
88+
look_at_value(*&data[0]);
89+
JL_GC_POP(); // expected-note{{GC frame changed here}}
90+
// expected-note@-1{{Root was released here}}
91+
jl_gc_safepoint(); // expected-note{{Value may have been GCed here}}
92+
*&data[0]; // expected-warning{{Creating derivative of value that may have been GCed}}
93+
// expected-note@-1{{Creating derivative of value that may have been GCed}}
94+
};
95+
96+
3797
jl_value_t *existing_root() {
3898
jl_svec_t *val = NULL;
3999
JL_GC_PUSH1(&val);
@@ -46,7 +106,7 @@ jl_value_t *existing_root() {
46106

47107
jl_value_t *late_root() {
48108
jl_svec_t *val = NULL;
49-
val = jl_svec1(NULL);
109+
val = jl_svec1(NULL); // expected-note {{Started tracking value here}}
50110
jl_gc_safepoint(); // expected-note {{Value may have been GCed here}}
51111
JL_GC_PUSH1(&val); // expected-warning{{Trying to root value which may have been GCed}}
52112
// expected-note@-1{{Trying to root value which may have been GCed}}
@@ -58,8 +118,8 @@ jl_value_t *late_root() {
58118
jl_value_t *late_root2() {
59119
jl_svec_t *val = NULL;
60120
jl_svec_t *val2 = NULL;
61-
JL_GC_PUSH1(&val);
62-
val2 = jl_svec1(NULL);
121+
JL_GC_PUSH1(&val); // expected-note {{GC frame changed here}}
122+
val2 = jl_svec1(NULL); // expected-note {{Started tracking value here}}
63123
jl_gc_safepoint(); // expected-note {{Value may have been GCed here}}
64124
val = val2; // expected-warning{{Trying to root value which may have been GCed}}
65125
// expected-note@-1{{Trying to root value which may have been GCed}}
@@ -71,19 +131,18 @@ jl_value_t *late_root2() {
71131
jl_value_t *already_freed() {
72132
jl_svec_t *val = NULL;
73133
JL_GC_PUSH1(&val);
74-
val = jl_svec1(NULL); // expected-note {{Value was rooted here}}
75-
JL_GC_POP(); // exptected-noted {{Root was released here}}
76-
jl_gc_safepoint(); // expected-note {{Value may have been GCed here}}
77-
jl_value_t *ret = jl_svecref(val, 0); // expected-warning{{Argument value may have been GCed}}
78-
// expected-note@-1{{Argument value may have been GCed}}
134+
val = jl_svec1(NULL);
135+
JL_GC_POP();
136+
jl_gc_safepoint();
137+
jl_value_t *ret = jl_svecref(val, 0);
79138
return ret;
80139
};
81140

82141
int field_access() {
83-
jl_svec_t *val = jl_svec1(NULL);
142+
jl_svec_t *val = jl_svec1(NULL); // expected-note {{Started tracking value here}}
84143
jl_gc_safepoint(); // expected-note{{Value may have been GCed here}}
85-
return val->length == 1; // expected-warning{{Creating derivative of value that may have been GCed}}
86-
// expected-note@-1{{Creating derivative of value that may have been GCed}}
144+
return val->length == 1; // expected-warning{{Trying to access value which may have been GCed}}
145+
// expected-note@-1{{Trying to access value which may have been GCed}}
87146
}
88147

89148
int pushargs_roots() {
@@ -98,27 +157,26 @@ int pushargs_roots() {
98157

99158
int pushargs_roots_freed() {
100159
jl_value_t **margs;
101-
jl_svec_t *val = jl_svec1(NULL);;
102-
JL_GC_PUSHARGS(margs, 1);
160+
jl_svec_t *val = jl_svec1(NULL); // expected-note{{Started tracking value here}}
161+
JL_GC_PUSHARGS(margs, 1); // expected-note{{GC frame changed here}}
103162
margs[0] = (jl_value_t*)val; // expected-note{{Value was rooted here}}
104-
JL_GC_POP(); // expected-note{{Root was released here}}
163+
JL_GC_POP(); // expected-note{{GC frame changed here}}
164+
// expected-note@-1{{Root was released here}}
105165
jl_gc_safepoint(); // expected-note{{Value may have been GCed here}}
106-
return val->length == 1; // expected-warning{{Creating derivative of value that may have been GCed}}
107-
// expected-note@-1{{Creating derivative of value that may have been GCed}}
166+
return val->length == 1; // expected-warning{{Trying to access value which may have been GCed}}
167+
// expected-note@-1{{Trying to access value which may have been GCed}}
108168
}
109169

110-
extern void process_unrooted(jl_value_t *maybe_unrooted JL_MAYBE_UNROOTED);
111170
int unrooted() {
112-
jl_svec_t *val = jl_svec1(NULL);
171+
jl_svec_t *val = jl_svec1(NULL); // expected-note{{Started tracking value here}}
113172
// This is ok
114173
process_unrooted((jl_value_t*)val); // expected-note{{Value may have been GCed here}}
115174
// This is not
116-
return val->length == 1; // expected-warning{{Creating derivative of value that may have been GCed}}
117-
// expected-note@-1{{Creating derivative of value that may have been GCed}}
175+
return val->length == 1; // expected-warning{{Trying to access value which may have been GCed}}
176+
// expected-note@-1{{Trying to access value which may have been GCed}}
118177
}
119178

120179
extern jl_value_t *global_value JL_GLOBALLY_ROOTED;
121-
extern void look_at_value(jl_value_t *v);
122180
void globally_rooted() {
123181
jl_value_t *val = global_value;
124182
jl_gc_safepoint();
@@ -284,20 +342,22 @@ void assoc_exact_broken(jl_value_t **args, size_t n, int8_t offs, size_t world)
284342
}
285343
*/
286344

287-
void assoc_exact_ok(jl_value_t **args, size_t n, int8_t offs, size_t world) {
345+
void assoc_exact_ok(jl_value_t *args1, jl_value_t **args, size_t n, int8_t offs, size_t world) {
288346
jl_typemap_level_t *cache = jl_new_typemap_level();
289347
JL_GC_PUSH1(&cache);
290-
jl_typemap_assoc_exact(cache->any, args, n, offs, world);
348+
jl_typemap_assoc_exact(cache->any, args1, args, n, offs, world);
291349
JL_GC_POP();
292350
}
293351

294352
// jl_box_* special cases
295353
void box_special_cases1(int i) {
296-
jl_(jl_box_long(i)); //expected-warning{{Passing non-rooted value as argument to function that may GC}}
354+
look_at_value(jl_box_long(i)); // expected-warning{{Passing non-rooted value as argument to function}}
355+
// expected-note@-1{{Passing non-rooted value as argument to function}}
356+
// expected-note@-2{{Started tracking value here}}
297357
}
298358

299359
void box_special_cases2() {
300-
jl_(jl_box_long(0));
360+
look_at_value(jl_box_long(0));
301361
}
302362

303363
jl_value_t *alloc_something();
@@ -330,7 +390,6 @@ typedef struct _varbinding {
330390
jl_value_t *ub;
331391
} jl_varbinding_t;
332392

333-
extern void look_at_value(jl_value_t *v);
334393
extern void escape_vb(jl_varbinding_t **vb);
335394
void stack_rooted(jl_value_t *lb JL_MAYBE_UNROOTED, jl_value_t *ub JL_MAYBE_UNROOTED) {
336395
jl_varbinding_t vb = { NULL, lb, ub };
@@ -340,11 +399,10 @@ void stack_rooted(jl_value_t *lb JL_MAYBE_UNROOTED, jl_value_t *ub JL_MAYBE_UNRO
340399
JL_GC_POP();
341400
}
342401

343-
extern void look_at_value(jl_value_t *v);
344402
void JL_NORETURN throw_internal(jl_value_t *e JL_MAYBE_UNROOTED)
345403
{
346404
jl_ptls_t ptls = jl_get_ptls_states();
347-
ptls->exception_in_transit = e;
405+
ptls->sig_exception = e;
348406
jl_gc_unsafe_enter(ptls);
349407
look_at_value(e);
350408
}

test/clangsa/lit.cfg.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import os
2+
import sys
3+
import re
4+
import platform
5+
6+
import lit.util
7+
import lit.formats
8+
9+
config.name = 'Julia-GCChecker'
10+
config.suffixes = ['.c','.cpp']
11+
config.test_source_root = os.path.dirname(__file__)
12+
config.test_format = lit.formats.ShTest(True)
13+
config.substitutions.append(('%shlibext', '.dylib' if platform.system() == 'Darwin' else '.dll' if
14+
platform.system() == 'Windows' else '.so'))
15+
config.substitutions.append(("%julia_home", os.path.join(os.path.dirname(__file__), "../..")))
16+
17+
path = os.path.pathsep.join((os.path.join(os.path.dirname(__file__),"../../usr/tools"), os.path.join(os.path.dirname(__file__),"../../usr/bin"), config.environment['PATH']))
18+
config.environment['PATH'] = path
19+
config.environment['HOME'] = "/tmp"
20+
config.environment['CLANGSA_FLAGS'] = os.environ.get('CLANGSA_FLAGS', "")
21+
config.environment['CLANGSA_CXXFLAGS'] = os.environ.get('CLANGSA_CXXFLAGS', "")
22+
config.environment['CPPFLAGS'] = os.environ.get('CPPFLAGS', "")
23+
config.environment['CFLAGS'] = os.environ.get('CFLAGS', "")
24+
config.environment['CXXFLAGS'] = os.environ.get('CXXFLAGS', "")
25+
26+
if platform.machine() == "x86_64":
27+
config.available_features.add('x86_64')

0 commit comments

Comments
 (0)