[LLD] Search archives for symbol defs to override COMMON symbols.
This patch changes the archive handling to enable the semantics needed
for legacy FORTRAN common blocks and block data. When we have a COMMON
definition of a symbol and are including an archive, LLD will now
search the members for global/weak defintions to override the COMMON
symbol. The previous LLD behavior (where a member would only be included
if it satisifed some other needed symbol definition) can be re-enabled with the
option '-no-fortran-common'.
Differential Revision: https://reviews.llvm.org/D86142
diff --git a/lld/ELF/Symbols.cpp b/lld/ELF/Symbols.cpp
index a2153da..a54f68e 100644
--- a/lld/ELF/Symbols.cpp
+++ b/lld/ELF/Symbols.cpp
@@ -689,7 +689,33 @@
other.value);
}
+template <class LazyT>
+static void replaceCommon(Symbol &oldSym, const LazyT &newSym) {
+ backwardReferences.erase(&oldSym);
+ oldSym.replace(newSym);
+ newSym.fetch();
+}
+
template <class LazyT> void Symbol::resolveLazy(const LazyT &other) {
+ // For common objects, we want to look for global or weak definitions that
+ // should be fetched as the cannonical definition instead.
+ if (isCommon() && elf::config->fortranCommon) {
+ if (auto *laSym = dyn_cast<LazyArchive>(&other)) {
+ ArchiveFile *archive = cast<ArchiveFile>(laSym->file);
+ const Archive::Symbol &archiveSym = laSym->sym;
+ if (archive->shouldFetchForCommon(archiveSym)) {
+ replaceCommon(*this, other);
+ return;
+ }
+ } else if (auto *loSym = dyn_cast<LazyObject>(&other)) {
+ LazyObjFile *obj = cast<LazyObjFile>(loSym->file);
+ if (obj->shouldFetchForCommon(loSym->getName())) {
+ replaceCommon(*this, other);
+ return;
+ }
+ }
+ }
+
if (!isUndefined()) {
// See the comment in resolveUndefined().
if (isDefined())