Index: ELF/Config.h =================================================================== --- ELF/Config.h +++ ELF/Config.h @@ -76,6 +76,7 @@ bool SysvHash = true; bool Threads; bool Verbose; + bool WarnCommon; bool ZExecStack; bool ZNodelete; bool ZNow; Index: ELF/Driver.cpp =================================================================== --- ELF/Driver.cpp +++ ELF/Driver.cpp @@ -241,6 +241,7 @@ Config->StripAll = Args.hasArg(OPT_strip_all); Config->Threads = Args.hasArg(OPT_threads); 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 @@ -128,6 +128,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">; @@ -176,9 +179,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 @@ -107,6 +107,8 @@ } static int compareCommons(DefinedCommon *A, DefinedCommon *B) { + if (Config->WarnCommon) + warning("multiple common of " + A->getName()); A->Alignment = B->Alignment = std::max(A->Alignment, B->Alignment); if (A->Size < B->Size) return -1; @@ -147,6 +149,8 @@ if (isCommon() && Other->isCommon()) return compareCommons(cast(this), cast(Other)); + if (Config->WarnCommon) + warning("common " + this->getName() + " is overridden"); return isCommon() ? -1 : 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