Skip to content

Commit

Permalink
[GCChecker] fix tests and add Makefile
Browse files Browse the repository at this point in the history
  • Loading branch information
vtjnash committed Apr 24, 2020
1 parent 4c7ae77 commit a739e22
Show file tree
Hide file tree
Showing 7 changed files with 161 additions and 55 deletions.
19 changes: 19 additions & 0 deletions Make.inc
Original file line number Diff line number Diff line change
Expand Up @@ -1301,6 +1301,25 @@ ifeq ($(USE_SYSTEM_LIBM),1)
USE_BINARYBUILDER_OPENLIBM := 0
endif


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


# Make tricks

define dir_target
Expand Down
18 changes: 0 additions & 18 deletions src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -372,24 +372,6 @@ ifneq ($(BUILD_LLVM_CLANG),1)
endif
endif


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

clang-sa-%: $(SRCDIR)/%.c $(build_shlibdir)/libGCCheckerPlugin.$(SHLIB_EXT) | analyzegc-deps-check
@$(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 $<)
clang-sa-%: $(SRCDIR)/%.cpp $(build_shlibdir)/libGCCheckerPlugin.$(SHLIB_EXT) | analyzegc-deps-check
Expand Down
1 change: 1 addition & 0 deletions test/clangsa/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/Output/
2 changes: 1 addition & 1 deletion test/clangsa/GCPushPop.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// This file is a part of Julia. License is MIT: https://julialang.org/license

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

#include "julia.h"

Expand Down
19 changes: 19 additions & 0 deletions test/clangsa/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
SRCDIR := $(abspath $(dir $(lastword $(MAKEFILE_LIST))))
JULIAHOME := $(abspath $(SRCDIR)/../..)
include $(JULIAHOME)/Make.inc

check: $(SRCDIR)

TESTS = $(patsubst $(SRCDIR)/%,%,$(wildcard $(SRCDIR)/*.c)) $(wildcard $(SRCDIR)/*.cpp)

$(SRCDIR) $(TESTS):
PATH=$(build_bindir):$(build_depsbindir):$$PATH \
LD_LIBRARY_PATH="${build_libdir}:$$LD_LIBRARY_PATH" \
CLANGSA_FLAGS="${CLANGSA_FLAGS}" \
CLANGSACXX_FLAGS="${CLANGSACXX_FLAGS}" \
CPPFLAGS_FLAGS="${CPPFLAGS_FLAGS}" \
CFLAGS_FLAGS="${CFLAGS_FLAGS}" \
CXXFLAGS_FLAGS="${CXXFLAGS_FLAGS}" \
$(build_depsbindir)/lit/lit.py -v $@

.PHONY: $(TESTS) $(SRCDIR) check all
130 changes: 94 additions & 36 deletions test/clangsa/MissingRoots.c
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
// This file is a part of Julia. License is MIT: https://julialang.org/license

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

#include "julia.h"
#include "julia_internal.h"

extern void look_at_value(jl_value_t *v);
extern void process_unrooted(jl_value_t *maybe_unrooted JL_MAYBE_UNROOTED);
extern void jl_gc_safepoint();

void unrooted_argument() {
jl_((jl_value_t*)jl_svec1(NULL)); // expected-warning{{Passing non-rooted value as argument to function}}
// expected-note@-1{{Passing non-rooted value as argument to function}}
look_at_value((jl_value_t*)jl_svec1(NULL)); // expected-warning{{Passing non-rooted value as argument to function}}
// expected-note@-1{{Passing non-rooted value as argument to function}}
// expected-note@-2{{Started tracking value here}}
};

void simple_svec() {
Expand All @@ -16,13 +21,10 @@ void simple_svec() {
assert(jl_svecref(val, 0) == NULL);
}

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

jl_value_t *root_value() {
Expand All @@ -34,6 +36,64 @@ jl_value_t *root_value() {
return ret;
};

void root_value_data() {
jl_svec_t *val = jl_svec1(NULL); // expected-note{{Started tracking value here}}
jl_value_t **data = jl_svec_data(val);
JL_GC_PUSH1(&val); // expected-note{{GC frame changed here}}
// expected-note@-1{{Value was rooted here}}
jl_gc_safepoint();
look_at_value(*data);
JL_GC_POP(); // expected-note{{GC frame changed here}}
// expected-note@-1{{Root was released here}}
jl_gc_safepoint(); // expected-note{{Value may have been GCed here}}
*data; // expected-warning{{Creating derivative of value that may have been GCed}}
// expected-note@-1{{Creating derivative of value that may have been GCed}}
};

void root_value_data2() {
jl_svec_t *val = jl_svec1(NULL); // expected-note{{Started tracking value here}}
jl_value_t **data = jl_svec_data(val);
JL_GC_PUSH1(&val); // expected-note{{GC frame changed here}}
// expected-note@-1{{Value was rooted here}}
jl_gc_safepoint();
look_at_value(data[0]);
JL_GC_POP(); // expected-note{{GC frame changed here}}
// expected-note@-1{{Root was released here}}
jl_gc_safepoint(); // expected-note{{Value may have been GCed here}}
data[0]; // expected-warning{{Creating derivative of value that may have been GCed}}
// expected-note@-1{{Creating derivative of value that may have been GCed}}
};


void root_value_data3() {
jl_svec_t *val = jl_svec1(NULL); // expected-note{{Started tracking value here}}
jl_value_t **data = jl_svec_data(val);
JL_GC_PUSH1(&val); // expected-note{{GC frame changed here}}
// expected-note@-1{{Value was rooted here}}
jl_gc_safepoint();
look_at_value(**&data);
JL_GC_POP(); // expected-note{{GC frame changed here}}
// expected-note@-1{{Root was released here}}
jl_gc_safepoint(); // expected-note{{Value may have been GCed here}}
**&data; // expected-warning{{Creating derivative of value that may have been GCed}}
// expected-note@-1{{Creating derivative of value that may have been GCed}}
};

void root_value_data4() {
jl_svec_t *val = jl_svec1(NULL); // expected-note{{Started tracking value here}}
jl_value_t **data = jl_svec_data(val);
JL_GC_PUSH1(&val); // expected-note{{GC frame changed here}}
// expected-note@-1{{Value was rooted here}}
jl_gc_safepoint();
look_at_value(*&data[0]);
JL_GC_POP(); // expected-note{{GC frame changed here}}
// expected-note@-1{{Root was released here}}
jl_gc_safepoint(); // expected-note{{Value may have been GCed here}}
*&data[0]; // expected-warning{{Creating derivative of value that may have been GCed}}
// expected-note@-1{{Creating derivative of value that may have been GCed}}
};


jl_value_t *existing_root() {
jl_svec_t *val = NULL;
JL_GC_PUSH1(&val);
Expand All @@ -46,7 +106,7 @@ jl_value_t *existing_root() {

jl_value_t *late_root() {
jl_svec_t *val = NULL;
val = jl_svec1(NULL);
val = jl_svec1(NULL); // expected-note {{Started tracking value here}}
jl_gc_safepoint(); // expected-note {{Value may have been GCed here}}
JL_GC_PUSH1(&val); // expected-warning{{Trying to root value which may have been GCed}}
// expected-note@-1{{Trying to root value which may have been GCed}}
Expand All @@ -58,8 +118,8 @@ jl_value_t *late_root() {
jl_value_t *late_root2() {
jl_svec_t *val = NULL;
jl_svec_t *val2 = NULL;
JL_GC_PUSH1(&val);
val2 = jl_svec1(NULL);
JL_GC_PUSH1(&val); // expected-note {{GC frame changed here}}
val2 = jl_svec1(NULL); // expected-note {{Started tracking value here}}
jl_gc_safepoint(); // expected-note {{Value may have been GCed here}}
val = val2; // expected-warning{{Trying to root value which may have been GCed}}
// expected-note@-1{{Trying to root value which may have been GCed}}
Expand All @@ -71,19 +131,18 @@ jl_value_t *late_root2() {
jl_value_t *already_freed() {
jl_svec_t *val = NULL;
JL_GC_PUSH1(&val);
val = jl_svec1(NULL); // expected-note {{Value was rooted here}}
JL_GC_POP(); // exptected-noted {{Root was released here}}
jl_gc_safepoint(); // expected-note {{Value may have been GCed here}}
jl_value_t *ret = jl_svecref(val, 0); // expected-warning{{Argument value may have been GCed}}
// expected-note@-1{{Argument value may have been GCed}}
val = jl_svec1(NULL);
JL_GC_POP();
jl_gc_safepoint();
jl_value_t *ret = jl_svecref(val, 0);
return ret;
};

int field_access() {
jl_svec_t *val = jl_svec1(NULL);
jl_svec_t *val = jl_svec1(NULL); // expected-note {{Started tracking value here}}
jl_gc_safepoint(); // expected-note{{Value may have been GCed here}}
return val->length == 1; // expected-warning{{Creating derivative of value that may have been GCed}}
// expected-note@-1{{Creating derivative of value that may have been GCed}}
return val->length == 1; // expected-warning{{Trying to access value which may have been GCed}}
// expected-note@-1{{Trying to access value which may have been GCed}}
}

int pushargs_roots() {
Expand All @@ -98,27 +157,26 @@ int pushargs_roots() {

int pushargs_roots_freed() {
jl_value_t **margs;
jl_svec_t *val = jl_svec1(NULL);;
JL_GC_PUSHARGS(margs, 1);
jl_svec_t *val = jl_svec1(NULL); // expected-note{{Started tracking value here}}
JL_GC_PUSHARGS(margs, 1); // expected-note{{GC frame changed here}}
margs[0] = (jl_value_t*)val; // expected-note{{Value was rooted here}}
JL_GC_POP(); // expected-note{{Root was released here}}
JL_GC_POP(); // expected-note{{GC frame changed here}}
// expected-note@-1{{Root was released here}}
jl_gc_safepoint(); // expected-note{{Value may have been GCed here}}
return val->length == 1; // expected-warning{{Creating derivative of value that may have been GCed}}
// expected-note@-1{{Creating derivative of value that may have been GCed}}
return val->length == 1; // expected-warning{{Trying to access value which may have been GCed}}
// expected-note@-1{{Trying to access value which may have been GCed}}
}

extern void process_unrooted(jl_value_t *maybe_unrooted JL_MAYBE_UNROOTED);
int unrooted() {
jl_svec_t *val = jl_svec1(NULL);
jl_svec_t *val = jl_svec1(NULL); // expected-note{{Started tracking value here}}
// This is ok
process_unrooted((jl_value_t*)val); // expected-note{{Value may have been GCed here}}
// This is not
return val->length == 1; // expected-warning{{Creating derivative of value that may have been GCed}}
// expected-note@-1{{Creating derivative of value that may have been GCed}}
return val->length == 1; // expected-warning{{Trying to access value which may have been GCed}}
// expected-note@-1{{Trying to access value which may have been GCed}}
}

extern jl_value_t *global_value JL_GLOBALLY_ROOTED;
extern void look_at_value(jl_value_t *v);
void globally_rooted() {
jl_value_t *val = global_value;
jl_gc_safepoint();
Expand Down Expand Up @@ -284,20 +342,22 @@ void assoc_exact_broken(jl_value_t **args, size_t n, int8_t offs, size_t world)
}
*/

void assoc_exact_ok(jl_value_t **args, size_t n, int8_t offs, size_t world) {
void assoc_exact_ok(jl_value_t *args1, jl_value_t **args, size_t n, int8_t offs, size_t world) {
jl_typemap_level_t *cache = jl_new_typemap_level();
JL_GC_PUSH1(&cache);
jl_typemap_assoc_exact(cache->any, args, n, offs, world);
jl_typemap_assoc_exact(cache->any, args1, args, n, offs, world);
JL_GC_POP();
}

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

void box_special_cases2() {
jl_(jl_box_long(0));
look_at_value(jl_box_long(0));
}

jl_value_t *alloc_something();
Expand Down Expand Up @@ -330,7 +390,6 @@ typedef struct _varbinding {
jl_value_t *ub;
} jl_varbinding_t;

extern void look_at_value(jl_value_t *v);
extern void escape_vb(jl_varbinding_t **vb);
void stack_rooted(jl_value_t *lb JL_MAYBE_UNROOTED, jl_value_t *ub JL_MAYBE_UNROOTED) {
jl_varbinding_t vb = { NULL, lb, ub };
Expand All @@ -340,11 +399,10 @@ void stack_rooted(jl_value_t *lb JL_MAYBE_UNROOTED, jl_value_t *ub JL_MAYBE_UNRO
JL_GC_POP();
}

extern void look_at_value(jl_value_t *v);
void JL_NORETURN throw_internal(jl_value_t *e JL_MAYBE_UNROOTED)
{
jl_ptls_t ptls = jl_get_ptls_states();
ptls->exception_in_transit = e;
ptls->sig_exception = e;
jl_gc_unsafe_enter(ptls);
look_at_value(e);
}
27 changes: 27 additions & 0 deletions test/clangsa/lit.cfg.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import os
import sys
import re
import platform

import lit.util
import lit.formats

config.name = 'Julia-GCChecker'
config.suffixes = ['.c','.cpp']
config.test_source_root = os.path.dirname(__file__)
config.test_format = lit.formats.ShTest(True)
config.substitutions.append(('%shlibext', '.dylib' if platform.system() == 'Darwin' else '.dll' if
platform.system() == 'Windows' else '.so'))
config.substitutions.append(("%julia_home", os.path.join(os.path.dirname(__file__), "../..")))

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']))
config.environment['PATH'] = path
config.environment['HOME'] = "/tmp"
config.environment['CLANGSA_FLAGS'] = os.environ.get('CLANGSA_FLAGS', "")
config.environment['CLANGSA_CXXFLAGS'] = os.environ.get('CLANGSA_CXXFLAGS', "")
config.environment['CPPFLAGS'] = os.environ.get('CPPFLAGS', "")
config.environment['CFLAGS'] = os.environ.get('CFLAGS', "")
config.environment['CXXFLAGS'] = os.environ.get('CXXFLAGS', "")

if platform.machine() == "x86_64":
config.available_features.add('x86_64')

0 comments on commit a739e22

Please sign in to comment.