Skip to content

Commit 49b72b8

Browse files
committed
fix bugs introduced for versions of clang < 7.0
1 parent 3031696 commit 49b72b8

File tree

139 files changed

+701
-349
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

139 files changed

+701
-349
lines changed

Makefile

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,10 @@ dcc.1: dcc help2man_include.txt
2020
help2man --include=help2man_include.txt ./dcc >dcc.1
2121

2222
tests: dcc
23-
tests/do_tests.sh
23+
tests/do_tests.sh ./dcc
24+
25+
tests_all_clang_versions: dcc
26+
set -x ; for compiler in /usr/bin/clang-[1-24-9]* ; do tests/do_tests.sh ./dcc $$compiler; done
2427

2528
debian: dcc
2629
rm -rf debian

compile.py

Lines changed: 47 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,9 @@
1010
COMMON_WARNING_ARGS = "-Wall -Wno-unused -Wunused-variable -Wunused-value -Wno-unused-result".split()
1111
COMMON_COMPILER_ARGS = COMMON_WARNING_ARGS + "-std=gnu11 -g -lm".split()
1212

13-
EXTRA_C_COMPILER_ARGS = COMMON_COMPILER_ARGS + "-Wunused-comparison -fcolor-diagnostics -fno-omit-frame-pointer -fno-common -funwind-tables -fno-optimize-sibling-calls -Qunused-arguments".split()
14-
GCC_ARGS = COMMON_COMPILER_ARGS + "-Wunused-but-set-variable -O -fdiagnostics-color -o /dev/null".split()
13+
CLANG_ONLY_ARGS = "-Wunused-comparison -fno-omit-frame-pointer -fno-common -funwind-tables -fno-optimize-sibling-calls -Qunused-arguments".split()
14+
15+
GCC_ARGS = COMMON_COMPILER_ARGS + "-Wunused-but-set-variable -O -o /dev/null".split()
1516

1617
MAXIMUM_SOURCE_FILE_EMBEDDED_BYTES = 1000000
1718

@@ -25,7 +26,13 @@
2526
def compile(debug=False):
2627
os.environ['PATH'] = os.path.dirname(os.path.realpath(sys.argv[0])) + ':/bin:/usr/bin:/usr/local/bin:/sbin:/usr/sbin:' + os.environ.get('PATH', '')
2728
args = parse_args(sys.argv[1:])
28-
29+
30+
# we have to set these explicitly because
31+
clang_args = COMMON_COMPILER_ARGS + CLANG_ONLY_ARGS
32+
if args.colorize_output:
33+
clang_args += ['-fcolor-diagnostics']
34+
clang_args += ['-fdiagnostics-color']
35+
2936
if args.which_sanitizer == "memory" and platform.architecture()[0][0:2] == '32':
3037
if search_path('valgrind'):
3138
# -fsanitize=memory requires 64-bits so we fallback to embedding valgrind
@@ -37,18 +44,21 @@ def compile(debug=False):
3744

3845
clang_version = None
3946
try:
40-
clang_version = subprocess.check_output(["clang", "--version"], universal_newlines=True)
47+
clang_version = subprocess.check_output([args.c_compiler, "--version"], universal_newlines=True)
4148
if debug:
4249
print("clang version:", clang_version)
43-
m = re.search("clang version (\d+\.\d+\.\d+)", clang_version, flags=re.I)
50+
m = re.search("clang version ((\d+)\.(\d+)\.\d+)", clang_version, flags=re.I)
4451
if m is not None:
4552
clang_version = m.group(1)
53+
clang_version_major = m.group(2)
54+
clang_version_minor = m.group(3)
55+
clang_version_float = float(m.group(2) + "." + m.group(3))
4656
except OSError as e:
4757
if debug:
4858
print(e)
4959

5060
if not clang_version:
51-
print("Can not get clang version", file=sys.stderr)
61+
print("Can not get version information for '%s'" % args.c_compiler, file=sys.stderr)
5262
sys.exit(1)
5363

5464
if args.which_sanitizer == "address" and platform.architecture()[0][0:2] == '32':
@@ -66,7 +76,7 @@ def compile(debug=False):
6676
if debug:
6777
print(e)
6878

69-
if clang_version and libc_version and clang_version[0] in "345" and libc_version >= 2.27:
79+
if libc_version and clang_version_float < 6 and libc_version >= 2.27:
7080
print("incompatible clang libc versions, disabling error detection by sanitiziers", file=sys.stderr)
7181
sanitizer_args = []
7282

@@ -79,8 +89,6 @@ def compile(debug=False):
7989
tar_n_bytes, tar_source = source_for_embedded_tarfile(args)
8090

8191
if args.which_sanitizer == "valgrind":
82-
sanitizer_args = []
83-
sanitizer_args = ['-fsanitize=undefined', '-fno-sanitize-recover=undefined,integer']
8492
wrapper_source = wrapper_source.replace('__DCC_SANITIZER_IS_VALGRIND__', '1')
8593
if args.embed_source:
8694
watcher = fr"python3 -E -c \"import os,sys,tarfile,tempfile\n\
@@ -92,27 +100,36 @@ def compile(debug=False):
92100
else:
93101
watcher = dcc_path + "--watch-stdin-for-valgrind-errors"
94102
wrapper_source = wrapper_source.replace('__DCC_MONITOR_VALGRIND__', watcher)
103+
sanitizer_args = []
95104
elif args.which_sanitizer == "memory":
96105
wrapper_source = wrapper_source.replace('__DCC_SANITIZER_IS_MEMORY__', '1')
97-
# FIXME if we enable '-fsanitize=undefined', '-fno-sanitize-recover=undefined,integer'
98-
# which would be preferable here we get uninitialized variable error message for undefined errors
106+
args.which_sanitizer = "memory"
99107
sanitizer_args = ['-fsanitize=memory']
100108
else:
101109
wrapper_source = wrapper_source.replace('__DCC_SANITIZER_IS_ADDRESS__', '1')
102110
# fixme add code to check version supports these
103-
sanitizer_args = ['-fsanitize=address', '-fsanitize=undefined', '-fno-sanitize-recover=undefined,integer']
111+
sanitizer_args = ['-fsanitize=address']
104112
args.which_sanitizer = "address"
113+
114+
if args.which_sanitizer != "memory":
115+
# FIXME if we enable '-fsanitize=undefined', '-fno-sanitize-recover=undefined,integer' for memory
116+
# which would be preferable here we get uninitialized variable error message for undefined errors
117+
sanitizer_args += ['-fsanitize=undefined']
118+
if clang_version_float >= 3.6:
119+
sanitizer_args += ['-fno-sanitize-recover=undefined,integer']
105120

106121
wrapper_source = wrapper_source.replace('__DCC_LEAK_CHECK_YES_NO__', "yes" if args.leak_check else "no")
107122
wrapper_source = wrapper_source.replace('__DCC_LEAK_CHECK_1_0__', "1" if args.leak_check else "0")
108123
wrapper_source = wrapper_source.replace('__DCC_SUPRESSIONS_FILE__', args.suppressions_file)
109124
wrapper_source = wrapper_source.replace('__DCC_STACK_USE_AFTER_RETURN__', "1" if args.stack_use_after_return else "0")
110125
wrapper_source = wrapper_source.replace('__DCC_NO_WRAP_MAIN__', "1" if args.no_wrap_main else "0")
126+
wrapper_source = wrapper_source.replace('__DCC_CLANG_VERSION_MAJOR__', clang_version_major)
127+
wrapper_source = wrapper_source.replace('__DCC_CLANG_VERSION_MINOR__', clang_version_minor)
111128

112129
# shared_libasan breaks easily ,e.g if there are libraries in /etc/ld.so.preload
113130
# and we can't override with verify_asan_link_order=0 for clang version < 5
114131
# and with clang-6 on debian __asan_default_options not called with shared_libasan
115-
if args.shared_libasan is None and clang_version[0] not in "3456":
132+
if args.shared_libasan is None and clang_version_float >= 7.0:
116133
args.shared_libasan = True
117134

118135
if args.shared_libasan and args.which_sanitizer == "address":
@@ -124,15 +141,15 @@ def compile(debug=False):
124141
wrapper_source = wrapper_source.replace('__DCC_EMBED_SOURCE__', '1')
125142
wrapper_source = tar_source + wrapper_source
126143

127-
incremental_compilation_args = sanitizer_args + EXTRA_C_COMPILER_ARGS + args.user_supplied_compiler_args
144+
incremental_compilation_args = sanitizer_args + clang_args + args.user_supplied_compiler_args
128145
command = [args.c_compiler] + incremental_compilation_args
129146
if args.incremental_compilation:
130147
if args.debug:
131148
print('incremental compilation, running: ', " ".join(command), file=sys.stderr)
132149
sys.exit(subprocess.call(command))
133150

134151
# -x - must come after any filenames but before ld options
135-
command = [args.c_compiler] + args.user_supplied_compiler_args + ['-x', 'c', '-', ] + sanitizer_args + EXTRA_C_COMPILER_ARGS
152+
command = [args.c_compiler] + args.user_supplied_compiler_args + ['-x', 'c', '-', ] + sanitizer_args + clang_args
136153
if args.ifdef_main:
137154
command += ['-Dmain=__real_main']
138155
wrapper_source = wrapper_source.replace('__wrap_main', 'main')
@@ -141,10 +158,16 @@ def compile(debug=False):
141158

142159
if args.debug:
143160
print(" ".join(command), file=sys.stderr)
161+
144162
if args.debug > 1:
145-
print(" ".join(command), '<<eof', file=sys.stderr)
146-
print(wrapper_source)
147-
print("eof", file=sys.stderr)
163+
debug_wrapper_file = "dcc_main_wrapper.c"
164+
print("Leaving main_wrapper in", debug_wrapper_file, "compile with this command:", file=sys.stderr)
165+
print(" ".join(command).replace('-x c -', debug_wrapper_file), file=sys.stderr)
166+
try:
167+
with open(debug_wrapper_file,"w") as f:
168+
f.write(wrapper_source)
169+
except OSError as e:
170+
print(e)
148171
process = subprocess.run(command, input=wrapper_source, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True)
149172

150173
# workaround for https://github.com/android-ndk/ndk/issues/184
@@ -199,7 +222,8 @@ class Args(object):
199222
user_supplied_compiler_args = []
200223
explanations = True
201224
max_explanations = 3
202-
embed_source = True
225+
embed_source = True
226+
# FIXME - check terminal actually support ANSI
203227
colorize_output = sys.stderr.isatty() or os.environ.get('DCC_COLORIZE_OUTPUT', False)
204228
debug = int(os.environ.get('DCC_DEBUG', '0'))
205229
source_files = set()
@@ -259,6 +283,10 @@ def parse_arg(arg, next_arg, args):
259283
args.no_wrap_main = True
260284
elif arg.startswith('--c-compiler='):
261285
args.c_compiler = arg[arg.index('=') + 1:]
286+
elif arg == '-fcolor-diagnostics':
287+
args.colorize_output = True
288+
elif arg == '-fno-color-diagnostics':
289+
args.colorize_output = False
262290
elif arg == '-v' or arg == '--version':
263291
print('dcc version', VERSION)
264292
sys.exit(0)
@@ -282,10 +310,6 @@ def parse_clang_arg(arg, next_arg, args):
282310
args.user_supplied_compiler_args.append(arg)
283311
if arg == '-c':
284312
args.incremental_compilation = True
285-
elif arg == '-fcolor-diagnostics':
286-
args.colorize_output = True
287-
elif arg == '-fno-color-diagnostics':
288-
args.colorize_output = False
289313
elif arg == '-o' and next_arg:
290314
object_filename = next_arg
291315
if object_filename.endswith('.c') and os.path.exists(object_filename):

main_wrapper.c

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,17 @@
1616

1717
static int debug = 0;
1818

19-
void __dcc_start(void) __attribute__((constructor));
19+
void __dcc_start(void) __attribute__((constructor))
20+
#if __has_attribute(no_sanitize)
21+
__attribute__((no_sanitize("address", "memory", "undefined")))
22+
#endif
23+
;
2024

21-
static void _dcc_exit(void);
25+
static void _dcc_exit(void)
26+
#if __has_attribute(no_sanitize)
27+
__attribute__((no_sanitize("address", "memory", "undefined")))
28+
#endif
29+
;
2230

2331
static void _signal_handler(int signum)
2432
#if __has_attribute(no_sanitize)
@@ -63,6 +71,12 @@ __attribute__((optnone))
6371

6472
#undef main
6573

74+
int __wrap_main(int argc, char *argv[], char *envp[])
75+
#if __has_attribute(no_sanitize)
76+
__attribute__((no_sanitize("address", "memory", "undefined")))
77+
#endif
78+
;
79+
6680
#if !__DCC_SANITIZER_IS_VALGRIND__
6781

6882
// wrapping ASAN
@@ -83,7 +97,6 @@ int __wrap_main(int argc, char *argv[], char *envp[]) {
8397
#else
8498

8599
// wrapping valgrind
86-
87100
int __wrap_main(int argc, char *argv[], char *envp[]) {
88101
extern int __real_main(int argc, char *argv[], char *envp[]);
89102
char mypath[PATH_MAX];
@@ -217,7 +230,7 @@ void __asan_on_error() {
217230
if (debug) fprintf(stderr, "__asan_on_error\n");
218231

219232
char *report = "";
220-
#if __DCC_SANITIZER_IS_ADDRESS__
233+
#if __DCC_SANITIZER_IS_ADDRESS__ && __DCC_CLANG_VERSION_MAJOR__ >= 6
221234
extern char *__asan_get_report_description();
222235
extern int __asan_report_present();
223236
if (__asan_report_present()) {
@@ -244,17 +257,18 @@ char *__msan_default_options() {
244257
return "verbosity=0:print_stacktrace=1:halt_on_error=1:detect_leaks=__DCC_LEAK_CHECK_1_0__";
245258
}
246259

247-
extern void __ubsan_get_current_report_data(char **OutIssueKind, char **OutMessage, char **OutFilename, unsigned int *OutLine, unsigned int *OutCol, char **OutMemoryAddr);
248-
249260
void __ubsan_on_report(void) {
250261
if (debug) fprintf(stderr, "__ubsan_on_report\n");
251262

263+
#if __DCC_CLANG_VERSION_MAJOR__ >= 7 && !__DCC_SANITIZER_IS_MEMORY__
252264
char *OutIssueKind;
253265
char *OutMessage;
254266
char *OutFilename;
255267
unsigned int OutLine;
256268
unsigned int OutCol;
257269
char *OutMemoryAddr;
270+
extern void __ubsan_get_current_report_data(char **OutIssueKind, char **OutMessage, char **OutFilename, unsigned int *OutLine, unsigned int *OutCol, char **OutMemoryAddr);
271+
258272
__ubsan_get_current_report_data(&OutIssueKind, &OutMessage, &OutFilename, &OutLine, &OutCol, &OutMemoryAddr);
259273

260274
// buffer + putenv is ugly - but safer?
@@ -267,7 +281,7 @@ void __ubsan_on_report(void) {
267281
snprintf(buffer[5], sizeof buffer[5], "DCC_UBSAN_ERROR_MEMORYADDR=%s", OutMemoryAddr);
268282
for (int i = 0; i < sizeof buffer/sizeof buffer[0]; i++)
269283
putenv(buffer[i]);
270-
284+
#endif
271285
_explain_error();
272286
// not reached
273287
}

packaging/debian/debian/control

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ Build-Depends: debhelper (>= 9)
77
Package: dcc
88
Architecture: all
99
Depends: python3 (>= 3.6), gdb(>= 7.12), clang(>= 4.0)
10-
Recommends: valgrind(>= 1:3.13)
10+
Recommends: valgrind(>= 1:3.13), clang(>= 7.0)
1111
Homepage: https://github.com/COMP1511UNSW/dcc
1212
Description: compiler for novice C programmers
1313
dcc compiles C programs using clang and adds explanations suitable

tests/do_tests.sh

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,15 +39,16 @@ for src_file in tests/extracted_compile_time_tests/*.c tests/compile_time/*.c te
3939
do
4040
rm -f a.out
4141

42-
compile_options_list=$(egrep '^//dcc_flags=' "$src_file"|sed 's?//??;s? ?#?g')
42+
compile_options_list=$(egrep '^//dcc_flags=' "$src_file"|sed 's?//??;s/ /#/g')
4343
compile_options_list=${compile_options_list:-'dcc_flags=""'}
4444

4545
for compile_options in $compile_options_list
4646
do
47+
compile_options=$(echo "$compile_options"|sed 's/#/ /g')
4748
case "$src_file" in
4849
*.c)
4950
dcc_flags=
50-
suffix=`echo $compile_options|sed 's/^dcc_flags=//;s/["$]//g;s/src_file//'`
51+
suffix=`echo $compile_options|sed 's/^dcc_flags=//;s/ /_/g;s/["$]//g;s/src_file//'`
5152
eval $compile_options
5253
expected_stderr_file="$expected_output_dir/`basename $src_file .c`$suffix.txt"
5354
#echo "$dcc" --c-compiler=$c_compiler $dcc_flags "$src_file"
Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
tests/compile_time/add_int_to_string.c:4:17: warning: adding 'int' to a string does not append to the string [-Wstring-plus-int]
1+
tests/compile_time/add_int_to_string.c:4:17: warning: adding 'int' to a string does not append to the string [-Wstring-plus-int]
22
printf("hello" + argc);
3-
 ~~~~~~~~^~~~~~
4-
tests/compile_time/add_int_to_string.c:4:17: note: use array indexing to silence this warning
3+
~~~~~~~~^~~~~~
4+
tests/compile_time/add_int_to_string.c:4:17: note: use array indexing to silence this warning
55
printf("hello" + argc);
6-
 ^
7-
 & [ ]
6+
^
7+
& [ ]
88
dcc explanation: Careful, you can't concatenate values and strings in C using the `+` operator, as you seem to be trying to do on line 4 of `tests/compile_time/add_int_to_string.c`.
99
Odds are you want to provide `printf` with a format code for that value and pass that value to `printf` as an argument.
1010

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
tests/compile_time/array_static_illegal_index.c:3:2: warning: array index 5 is past the end of the array (which contains 5 elements) [-Warray-bounds]
1+
tests/compile_time/array_static_illegal_index.c:3:2: warning: array index 5 is past the end of the array (which contains 5 elements) [-Warray-bounds]
22
a[5] = 0;
3-
 ^ ~
4-
tests/compile_time/array_static_illegal_index.c:2:2: note: array 'a' declared here
3+
^ ~
4+
tests/compile_time/array_static_illegal_index.c:2:2: note: array 'a' declared here
55
int a[5];
6-
 ^
6+
^
77
dcc explanation: Careful, on line 3 of `tests/compile_time/array_static_illegal_index.c`, it looks like you're trying to access location 5 of `a`, which doesn't exist; `a` isn't that long.
88
Keep in mind that arrays are 0-indexed.
99

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
tests/compile_time/array_string_index.c:3:3: error: array subscript is not an integer
1+
tests/compile_time/array_string_index.c:3:3: error: array subscript is not an integer
22
a["0"] = 0;
3-
 ^~~~
3+
^~~~
44
dcc explanation: Looks like you're trying to access an element of the array `a` on line 3 of `tests/compile_time/array_string_index.c`, but your index (`"0"`) is not of type `int`.
55
Right now, your index is of type `string` instead.
66
Make sure your index (the value between square brackets) is an `int`.
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
tests/extracted_compile_time_tests/assert_without_closing_parenthesis.c:5:2: error: unterminated function-like macro invocation
1+
tests/extracted_compile_time_tests/assert_without_closing_parenthesis.c:5:2: error: unterminated function-like macro invocation
22
assert(argc == 1;
3-
 ^
3+
^
44
dcc explanation: it looks like there is a missing closing bracket on the assert on line 5 of tests/extracted_compile_time_tests/assert_without_closing_parenthesis.c
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
tests/extracted_compile_time_tests/assign_array_to_int.c:4:10: warning: incompatible pointer to integer conversion assigning to 'int' from 'int [3]' [-Wint-conversion]
1+
tests/extracted_compile_time_tests/assign_array_to_int.c:4:10: warning: incompatible pointer to integer conversion assigning to 'int' from 'int [3]' [-Wint-conversion]
22
a[0][0] = a[1];
3-
 ^ ~~~~
3+
^ ~~~~
44
dcc explanation: you are attempting to assign a[1] which is an array to an int variable.
55

0 commit comments

Comments
 (0)