Index: ELF/Config.h =================================================================== --- ELF/Config.h +++ ELF/Config.h @@ -74,6 +74,7 @@ bool StripAll; bool SysvHash = true; bool Verbose; + bool WarnCommon = false; bool ZExecStack; bool ZNodelete; bool ZNow; Index: ELF/Driver.cpp =================================================================== --- ELF/Driver.cpp +++ ELF/Driver.cpp @@ -242,6 +242,7 @@ Config->Shared = Args.hasArg(OPT_shared); Config->StripAll = Args.hasArg(OPT_strip_all); Config->Verbose = Args.hasArg(OPT_verbose); + Config->WarnCommon = Args.hasArg(OPT_warn_common); Config->DynamicLinker = getString(Args, OPT_dynamic_linker); Config->Entry = getString(Args, OPT_entry); Index: ELF/Options.td =================================================================== --- ELF/Options.td +++ ELF/Options.td @@ -126,6 +126,9 @@ def version : Flag<["--", "-"], "version">, HelpText<"Display the version number">; +def warn_common : Flag<["--", "-"], "warn-common">, + HelpText<"Warn about duplicate common symbols">; + def whole_archive : Flag<["--", "-"], "whole-archive">, HelpText<"Force load of all members in a static library">; @@ -174,9 +177,9 @@ def fatal_warnings : Flag<["--"], "fatal-warnings">; def no_add_needed : Flag<["--"], "no-add-needed">; def no_fatal_warnings : Flag<["--"], "no-fatal-warnings">; +def no_warn_common : Flag<["--", "-"], "no-warn-common">; def no_warn_mismatch : Flag<["--"], "no-warn-mismatch">; def version_script : Separate<["--"], "version-script">; -def warn_common : Flag<["--"], "warn-common">; def warn_shared_textrel : Flag<["--"], "warn-shared-textrel">; def G : Separate<["-"], "G">; Index: ELF/Symbols.cpp =================================================================== --- ELF/Symbols.cpp +++ ELF/Symbols.cpp @@ -142,6 +142,14 @@ return -1; if (!std::get<0>(L) || !std::get<1>(L) || !std::get<2>(L)) return 1; + + if (Config->WarnCommon) { + if (isCommon() != Other->isCommon()) + warning("common " + this->getName() + " is overridden"); + else if (isCommon()) + warning("multiple common of " + this->getName()); + } + if (isCommon()) { if (!Other->isCommon()) return -1; Index: test/ELF/Inputs/warn-common.s =================================================================== --- test/ELF/Inputs/warn-common.s +++ test/ELF/Inputs/warn-common.s @@ -0,0 +1,2 @@ +.type arr,@object +.comm arr,8,4 Index: test/ELF/Inputs/warn-common2.s =================================================================== --- test/ELF/Inputs/warn-common2.s +++ test/ELF/Inputs/warn-common2.s @@ -0,0 +1,8 @@ +.type arr,@object +.data +.globl arr +.p2align 2 +arr: + .long 1 + .long 0 + .size arr, 8 Index: test/ELF/warn-common.s =================================================================== --- test/ELF/warn-common.s +++ test/ELF/warn-common.s @@ -0,0 +1,25 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t1.o +# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/warn-common.s -o %t2.o +# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/warn-common2.s -o %t3.o + +## Report multiple commons if warn-common is specified +# RUN: ld.lld --warn-common %t1.o %t2.o -o %t.out 2>&1 | FileCheck %s --check-prefix=WARN +# WARN: multiple common of arr + +## no-warn-common is ignored +# RUN: ld.lld --no-warn-common %t1.o %t2.o -o %t.out +# RUN: llvm-readobj %t.out > /dev/null + +## Report if common is overridden +# RUN: ld.lld --warn-common %t1.o %t3.o -o %t.out 2>&1 | FileCheck %s --check-prefix=OVER +# OVER: common arr is overridden + +## Report if common is overridden, but in different order +# RUN: ld.lld --warn-common %t3.o %t1.o -o %t.out 2>&1 | FileCheck %s --check-prefix=OVER + +.globl _start +_start: + +.type arr,@object +.comm arr,4,4