From 3f0eabc8bee1e56bc5b9ab6d07b7399efee062e0 Mon Sep 17 00:00:00 2001 From: Sam Clegg Date: Tue, 12 Dec 2023 09:33:30 -0800 Subject: [PATCH] Defer `'linker' input unused` warnings to clang. NFC Split out from #20884 --- emcc.py | 71 ++++++++++++++++++--------------------------- test/test_other.py | 6 +++- test/test_sanity.py | 6 ++-- 3 files changed, 38 insertions(+), 45 deletions(-) diff --git a/emcc.py b/emcc.py index 0b0f6446df105..226c5a983cca1 100644 --- a/emcc.py +++ b/emcc.py @@ -534,6 +534,13 @@ def run(args): ''') return 0 + ## Process argument and setup the compiler + state = EmccState(args) + options, newargs = phase_parse_arguments(state) + + if not shared.SKIP_SUBPROCS: + shared.check_sanity() + if '--version' in args: print(version_string()) print('''\ @@ -566,13 +573,6 @@ def run(args): print(shared.shlex_join(parts[1:])) return 0 - ## Process argument and setup the compiler - state = EmccState(args) - options, newargs = phase_parse_arguments(state) - - if not shared.SKIP_SUBPROCS: - shared.check_sanity() - if 'EMMAKEN_NO_SDK' in os.environ: exit_with_error('EMMAKEN_NO_SDK is no longer supported. The standard -nostdlib and -nostdinc flags should be used instead') @@ -618,9 +618,6 @@ def run(args): print(libname) return 0 - if not input_files and not state.link_flags: - exit_with_error('no input files') - if options.reproduce: create_reproduce_file(options.reproduce, args) @@ -641,8 +638,6 @@ def run(args): return link.run(linker_inputs, options, state, newargs) else: logger.debug('stopping after compile phase') - for flag in state.link_flags: - diagnostics.warning('unused-command-line-argument', "argument unused during compilation: '%s'" % flag[1]) return 0 @@ -670,9 +665,9 @@ def phase_parse_arguments(state): newargs = diagnostics.capture_warnings(newargs) for i in range(len(newargs)): - if newargs[i] in ('-l', '-L', '-I'): - # Scan for individual -l/-L/-I arguments and concatenate the next arg on - # if there is no suffix + if newargs[i] in ('-l', '-L', '-I', '-z'): + # Scan for flags that can be written as either one or two arguments + # and normalize them to the single argument form. newargs[i] += newargs[i + 1] newargs[i + 1] = '' @@ -764,18 +759,13 @@ def phase_setup(options, state, newargs): input_files.append((i, arg)) elif arg.startswith('-L'): state.add_link_flag(i, arg) - newargs[i] = '' elif arg.startswith('-l'): state.add_link_flag(i, arg) - newargs[i] = '' elif arg == '-z': state.add_link_flag(i, newargs[i]) state.add_link_flag(i + 1, newargs[i + 1]) - newargs[i] = '' - newargs[i + 1] = '' elif arg.startswith('-z'): state.add_link_flag(i, newargs[i]) - newargs[i] = '' elif arg.startswith('-Wl,'): # Multiple comma separated link flags can be specified. Create fake # fractional indices for these: -Wl,a,b,c,d at index 4 becomes: @@ -783,14 +773,10 @@ def phase_setup(options, state, newargs): link_flags_to_add = arg.split(',')[1:] for flag_index, flag in enumerate(link_flags_to_add): state.add_link_flag(i + float(flag_index) / len(link_flags_to_add), flag) - newargs[i] = '' elif arg == '-Xlinker': state.add_link_flag(i + 1, newargs[i + 1]) - newargs[i] = '' - newargs[i + 1] = '' elif arg == '-s': state.add_link_flag(i, newargs[i]) - newargs[i] = '' elif arg == '-': input_files.append((i, arg)) newargs[i] = '' @@ -950,11 +936,6 @@ def get_clang_output_extension(state): @ToolchainProfiler.profile_block('compile inputs') def phase_compile_inputs(options, state, newargs, input_files): - def is_link_flag(flag): - if flag in ('-nostdlib', '-nostartfiles', '-nolibc', '-nodefaultlibs'): - return True - return flag.startswith(('-l', '-L', '-Wl,')) - if shared.run_via_emxx: compiler = [shared.CLANG_CXX] else: @@ -964,7 +945,7 @@ def is_link_flag(flag): logger.debug('using compiler wrapper: %s', config.COMPILER_WRAPPER) compiler.insert(0, config.COMPILER_WRAPPER) - compile_args = [a for a in newargs if a and not is_link_flag(a)] + compile_args = newargs system_libs.ensure_sysroot() def get_language_mode(args): @@ -1002,7 +983,7 @@ def get_clang_command_asm(): # with -MF! (clang seems to not recognize it) logger.debug(('just preprocessor ' if state.has_dash_E else 'just dependencies: ') + ' '.join(cmd)) shared.check_call(cmd) - return [] + sys.exit(0) # Precompiled headers support if state.mode == Mode.PCH: @@ -1015,7 +996,7 @@ def get_clang_command_asm(): cmd += ['-o', options.output_file] logger.debug(f"running (for precompiled headers): {cmd[0]} {' '.join(cmd[1:])}") shared.check_call(cmd) - return [] + sys.exit(0) if state.mode == Mode.COMPILE_ONLY: inputs = [i[1] for i in input_files] @@ -1027,18 +1008,24 @@ def get_clang_command_asm(): cmd += ['-o', options.output_file] if get_file_suffix(options.output_file) == '.bc' and not settings.LTO and '-emit-llvm' not in state.orig_args: diagnostics.warning('emcc', '.bc output file suffix used without -flto or -emit-llvm. Consider using .o extension since emcc will output an object file, not a bitcode file') + ext = get_clang_output_extension(state) shared.check_call(cmd) - if not options.output_file: - # Rename object files to match --default-obj-ext - # TODO: Remove '--default-obj-ext' to reduce this complexity - ext = get_clang_output_extension(state) - if options.default_object_extension != ext: - for i in inputs: - output = unsuffixed_basename(i) + ext - new_output = unsuffixed_basename(i) + options.default_object_extension - shutil.move(output, new_output) - return [] + if not options.output_file and options.default_object_extension != ext: + for i in inputs: + output = unsuffixed_basename(i) + ext + new_output = unsuffixed_basename(i) + options.default_object_extension + shutil.move(output, new_output) + sys.exit(0) + + # In COMPILE_AND_LINK we need to compile source files too, but we also need to + # filter out the link flags + + def is_link_flag(flag): + if flag in ('-nostdlib', '-nostartfiles', '-nolibc', '-nodefaultlibs', '-s'): + return True + return flag.startswith(('-l', '-L', '-Wl,', '-z')) + compile_args = [a for a in compile_args if a and not is_link_flag(a)] linker_inputs = [] seen_names = {} diff --git a/test/test_other.py b/test/test_other.py index 3bb9aaf8fc90c..3f580838f5647 100644 --- a/test/test_other.py +++ b/test/test_other.py @@ -11458,7 +11458,7 @@ def test_linker_flags_pass_through(self): def test_linker_flags_unused(self): err = self.run_process([EMXX, test_file('hello_world.cpp'), '-c', '-lbar'], stderr=PIPE).stderr - self.assertContained("warning: argument unused during compilation: '-lbar' [-Wunused-command-line-argument]", err) + self.assertContained("warning: -lbar: 'linker' input unused [-Wunused-command-line-argument]", err) def test_linker_input_unused(self): self.run_process([EMXX, '-c', test_file('hello_world.cpp')]) @@ -14279,3 +14279,7 @@ def test_strndup(self): def test_errar(self): self.do_other_test('test_errar.c') + + def test_no_input_files(self): + err = self.expect_fail([EMCC, '-c']) + self.assertContained('clang: error: no input files', err) diff --git a/test/test_sanity.py b/test/test_sanity.py index e3f1316355901..942469ae7a280 100644 --- a/test/test_sanity.py +++ b/test/test_sanity.py @@ -142,11 +142,13 @@ def do(self, command, env=None): def check_working(self, command, expected=None): if type(command) is not list: command = [command] + if command == [EMCC]: + command = [EMCC, '--version'] if expected is None: if command[0] == EMCC or (len(command) >= 2 and command[1] == EMCC): - expected = 'no input files' + expected = 'emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld)' else: - expected = "could not find the following tests: blahblah" + expected = 'could not find the following tests: blahblah' output = self.do(command) self.assertContained(expected, output)