Index: ELF/Symbols.cpp =================================================================== --- ELF/Symbols.cpp +++ ELF/Symbols.cpp @@ -575,34 +575,38 @@ if (config->allowMultipleDefinition) return; + auto makeLoc = [&](InputSectionBase *sec, uint64_t offset, + InputFile *file) -> std::string { + if (!sec) + return "\n>>> defined in " + toString(file); + std::string loc = "\n>>> defined at "; + std::string src = sec->getSrcMsg(*sym, offset); + if (!src.empty()) + loc += src + "\n>>> "; + loc += sec->getObjMsg(offset); + return loc; + }; + Defined *d = cast(sym); - if (!d->section || !errSec) { - error("duplicate symbol: " + toString(*sym) + "\n>>> defined in " + - toString(sym->file) + "\n>>> defined in " + toString(newFile)); - return; + InputSectionBase *sec = cast_or_null(d->section); + std::string msg = "duplicate symbol: " + toString(*sym); + + if (errorHandler().vsDiagnostics) { + // Print separate error messages for each source location so that both of + // them can be extracted and printed in the corresponding message header. + error(msg + makeLoc(sec, d->value, sym->file)); + error(msg + makeLoc(errSec, errOffset, newFile)); + } else { + // Construct and print an error message in the form of: + // + // ld.lld: error: duplicate symbol: foo + // >>> defined at bar.c:30 + // >>> bar.o (/home/alice/src/bar.o) + // >>> defined at baz.c:563 + // >>> baz.o in archive libbaz.a + error(msg + makeLoc(sec, d->value, sym->file) + + makeLoc(errSec, errOffset, newFile)); } - - // Construct and print an error message in the form of: - // - // ld.lld: error: duplicate symbol: foo - // >>> defined at bar.c:30 - // >>> bar.o (/home/alice/src/bar.o) - // >>> defined at baz.c:563 - // >>> baz.o in archive libbaz.a - auto *sec1 = cast(d->section); - std::string src1 = sec1->getSrcMsg(*sym, d->value); - std::string obj1 = sec1->getObjMsg(d->value); - std::string src2 = errSec->getSrcMsg(*sym, errOffset); - std::string obj2 = errSec->getObjMsg(errOffset); - - std::string msg = "duplicate symbol: " + toString(*sym) + "\n>>> defined at "; - if (!src1.empty()) - msg += src1 + "\n>>> "; - msg += obj1 + "\n>>> defined at "; - if (!src2.empty()) - msg += src2 + "\n>>> "; - msg += obj2; - error(msg); } void Symbol::resolveCommon(const CommonSymbol &other) { Index: test/ELF/vs-diagnostics-duplicate.s =================================================================== --- test/ELF/vs-diagnostics-duplicate.s +++ test/ELF/vs-diagnostics-duplicate.s @@ -8,18 +8,21 @@ // CHECK: duplicate.s(15): error: duplicate symbol: bar // CHECK-NEXT: >>> defined at duplicate.s:15 // CHECK-NEXT: >>>{{.*}}1.o:(.text+0x{{.+}}) -// CHECK: >>> defined at duplicate2.s:20 -// CHECK: >>>{{.*}}2.o:(.text+0x{{.+}}) +// CHECK: duplicate2.s(20): error: duplicate symbol: bar +// CHECK-NEXT: >>> defined at duplicate2.s:20 +// CHECK-NEXT: >>>{{.*}}2.o:(.text+0x{{.+}}) // Case 2. The source locations are unknown for both symbols. // CHECK: {{.*}}ld.lld{{.*}}: error: duplicate symbol: foo // CHECK-NEXT: >>> defined at {{.*}}1.o:(.text+0x{{.+}}) +// CHECK: {{.*}}ld.lld{{.*}}: error: duplicate symbol: foo // CHECK-NEXT: >>> defined at {{.*}}2.o:(.text+0x{{.+}}) // Case 3. For the second definition of `baz` we know only the source file found in a STT_FILE symbol. // CHECK: duplicate.s(30): error: duplicate symbol: baz // CHECK-NEXT: >>> defined at duplicate.s:30 // CHECK-NEXT: >>> {{.*}}1.o:(.text+0x{{.+}}) +// CHECK: {{.*}}ld.lld{{.*}}: error: duplicate symbol: baz // CHECK-NEXT: >>> defined at duplicate3.s // CHECK-NEXT: >>> {{.*}}3.o:(.text+0x{{.+}})