Skip to content

Commit 524ab1f

Browse files
authored
Update test_implicit_func for LLVM 16 (#17623)
In LLVM 16, -Wincompatible-function-pointer types has been upgraded to an error by default. The functional change in this PR is to update test_implicit_func to incorporate this. (Currently it accepts either an error or a warning to avoid a complex DEPS roll). I also minimized the test to only test the behavior that is unique to emscripten (namely, the fact that -Wimplicit-function-declaration is an error in gnu89 mode rather than a warning as it is upstream).
1 parent 1c98800 commit 524ab1f

File tree

3 files changed

+24
-43
lines changed

3 files changed

+24
-43
lines changed

emcc.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -870,7 +870,7 @@ def get_clang_flags(user_args):
870870
cflags = None
871871

872872

873-
def get_cflags(user_args):
873+
def get_cflags(user_args, is_cxx):
874874
global cflags
875875
if cflags:
876876
return cflags
@@ -906,7 +906,9 @@ def get_cflags(user_args):
906906
# -Wno-error=implicit-function-declaration
907907
# or disable even a warning about it with
908908
# -Wno-implicit-function-declaration
909-
cflags += ['-Werror=implicit-function-declaration']
909+
# This is already an error in C++ so we don't need to inject extra flags.
910+
if not is_cxx:
911+
cflags += ['-Werror=implicit-function-declaration']
910912

911913
ports.add_cflags(cflags, settings)
912914

@@ -1133,7 +1135,7 @@ def run(args):
11331135

11341136
passthrough_flags = ['-print-search-dirs', '-print-libgcc-file-name']
11351137
if any(a in args for a in passthrough_flags) or any(a.startswith('-print-file-name=') for a in args):
1136-
return run_process([clang] + args + get_cflags(args), check=False).returncode
1138+
return run_process([clang] + args + get_cflags(args, run_via_emxx), check=False).returncode
11371139

11381140
## Process argument and setup the compiler
11391141
state = EmccState(args)
@@ -2728,7 +2730,7 @@ def get_compiler(src_file):
27282730
return CC
27292731

27302732
def get_clang_command(src_file):
2731-
return get_compiler(src_file) + get_cflags(state.orig_args) + compile_args + [src_file]
2733+
return get_compiler(src_file) + get_cflags(state.orig_args, use_cxx(src_file)) + compile_args + [src_file]
27322734

27332735
def get_clang_command_preprocessed(src_file):
27342736
return get_compiler(src_file) + get_clang_flags(state.orig_args) + compile_args + [src_file]

test/other/test_implicit_func.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#include <stdio.h>
2+
int main() {
3+
printf("hello %d\n", strnlen("waka", 2)); // Implicit declaration, no header, for strnlen
4+
int (*my_strnlen)(char*, ...) = strnlen;
5+
printf("hello %d\n", my_strnlen("shaka", 2));
6+
return 0;
7+
}

test/test_other.py

Lines changed: 11 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -3978,45 +3978,17 @@ def test_global_inits(self):
39783978
self.assertContainedIf('globalCtors', src, has_global)
39793979

39803980
def test_implicit_func(self):
3981-
create_file('src.c', r'''
3982-
#include <stdio.h>
3983-
int main()
3984-
{
3985-
printf("hello %d\n", strnlen("waka", 2)); // Implicit declaration, no header, for strnlen
3986-
int (*my_strnlen)(char*, ...) = strnlen;
3987-
printf("hello %d\n", my_strnlen("shaka", 2));
3988-
return 0;
3989-
}
3990-
''')
3991-
3992-
IMPLICIT_WARNING = "warning: implicit declaration of function 'strnlen' is invalid in C99"
3993-
IMPLICIT_WARNING_NEW = "warning: call to undeclared function 'strnlen'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]"
3994-
3995-
IMPLICIT_ERROR = "error: implicit declaration of function 'strnlen' is invalid in C99"
3996-
IMPLICIT_ERROR_NEW = "error: call to undeclared function 'strnlen'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]"
3997-
3998-
INCOMPATIBLE_WARNINGS = ('warning: incompatible pointer types', 'warning: incompatible function pointer types')
3999-
IMPLICIT_WARNINGS = (IMPLICIT_WARNING, IMPLICIT_WARNING_NEW)
4000-
IMPLICIT_ERRORS = (IMPLICIT_ERROR, IMPLICIT_ERROR_NEW)
4001-
4002-
for opts, expected, compile_expected in [
4003-
([], None, [IMPLICIT_ERRORS]),
4004-
# turn error into warning
4005-
(['-Wno-error=implicit-function-declaration'], ['hello '], [IMPLICIT_WARNINGS]),
4006-
# turn error into nothing at all (runtime output is incorrect)
4007-
(['-Wno-implicit-function-declaration'], ['hello '], []),
4008-
]:
4009-
print(opts, expected)
4010-
try_delete('a.out.js')
4011-
stderr = self.run_process([EMCC, 'src.c'] + opts, stderr=PIPE, check=False).stderr
4012-
for ce in compile_expected + [INCOMPATIBLE_WARNINGS]:
4013-
self.assertContained(ce, stderr)
4014-
if expected is None:
4015-
self.assertNotExists('a.out.js')
4016-
else:
4017-
output = self.run_js('a.out.js')
4018-
for e in expected:
4019-
self.assertContained(e, output)
3981+
# EMCC makes -Wimplict-function-declaration an error by default in all modes. Upstream LLVM
3982+
# emits a warning in gnu89 mode, but otherwise emcc's behavior is identical to upstream.
3983+
IMPLICIT_C89 = "error: implicit declaration of function 'strnlen'"
3984+
# Also check for -Wincompatible-function-pointer-types (it became an error in LLVM 16)
3985+
INCOMPATIBLE = ': incompatible function pointer types'
3986+
3987+
try_delete('implicit_func.o')
3988+
stderr = self.expect_fail(
3989+
[EMCC, path_from_root('test/other/test_implicit_func.c'), '-c', '-o', 'implicit_func.o', '-std=gnu89'])
3990+
self.assertContained(IMPLICIT_C89, stderr)
3991+
self.assertContained(INCOMPATIBLE, stderr)
40203992

40213993
@requires_native_clang
40223994
def test_bad_triple(self):

0 commit comments

Comments
 (0)