Skip to content

[LLD][COFF] Handle --start-lib/--end-lib group in the same way as other archives #136496

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

aganea
Copy link
Member

@aganea aganea commented Apr 20, 2025

This introduces CmdLineArchive which is inteded as a virtual object files (.OBJ/.O) container, in the same way as ArchiveFile is. The purpose of this container is to later track its position on the command line, in regards to other archives (.LIBs) present on the command line, which is important for landing #85290

This PR is an attempt to split #85290 into smaller pieces.

@llvmbot
Copy link
Member

llvmbot commented Apr 20, 2025

@llvm/pr-subscribers-platform-windows

@llvm/pr-subscribers-lld

Author: Alexandre Ganea (aganea)

Changes

This introduces CmdLineArchive which is inteded as a virtual object files (.OBJ/.O) container, in the same way as ArchiveFile. The purpose of this container is to later track its position on the command line, in regards to other archives (.LIBs) present on the command line, which is important for landing #85290

This PR is an attempt to split #85290 into smaller pieces.


Patch is 21.39 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/136496.diff

5 Files Affected:

  • (modified) lld/COFF/Driver.cpp (+60-40)
  • (modified) lld/COFF/Driver.h (+11-7)
  • (modified) lld/COFF/InputFiles.cpp (+29-15)
  • (modified) lld/COFF/InputFiles.h (+41-17)
  • (modified) lld/COFF/SymbolTable.cpp (+3-9)
diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp
index e3ff647209e72..9487868f109fa 100644
--- a/lld/COFF/Driver.cpp
+++ b/lld/COFF/Driver.cpp
@@ -200,28 +200,13 @@ static bool compatibleMachineType(COFFLinkerContext &ctx, MachineTypes mt) {
   }
 }
 
-void LinkerDriver::addFile(InputFile *file) {
-  Log(ctx) << "Reading " << toString(file);
-  if (file->lazy) {
-    if (auto *f = dyn_cast<BitcodeFile>(file))
-      f->parseLazy();
-    else
-      cast<ObjFile>(file)->parseLazy();
-  } else {
-    file->parse();
-    if (auto *f = dyn_cast<ObjFile>(file)) {
-      ctx.objFileInstances.push_back(f);
-    } else if (auto *f = dyn_cast<BitcodeFile>(file)) {
-      if (ltoCompilationDone) {
-        Err(ctx) << "LTO object file " << toString(file)
-                 << " linked in after "
-                    "doing LTO compilation.";
-      }
-      f->symtab.bitcodeFileInstances.push_back(f);
-    } else if (auto *f = dyn_cast<ImportFile>(file)) {
-      ctx.importFileInstances.push_back(f);
-    }
+void LinkerDriver::addFile(InputFile *file, CmdLineArchive *inCmdLineArchive) {
+  if (inCmdLineArchive) {
+    inCmdLineArchive->addInputFile(file); // schedule for lazy parsing
+    return;
   }
+  Log(ctx) << "Reading " << toString(file);
+  file->maybeParse();
 
   MachineTypes mt = file->getMachineType();
   // The ARM64EC target must be explicitly specified and cannot be inferred.
@@ -259,7 +244,8 @@ MemoryBufferRef LinkerDriver::takeBuffer(std::unique_ptr<MemoryBuffer> mb) {
 }
 
 void LinkerDriver::addBuffer(std::unique_ptr<MemoryBuffer> mb,
-                             bool wholeArchive, bool lazy) {
+                             bool wholeArchive,
+                             CmdLineArchive *inCmdLineArchive) {
   StringRef filename = mb->getBufferIdentifier();
 
   MemoryBufferRef mbref = takeBuffer(std::move(mb));
@@ -267,9 +253,15 @@ void LinkerDriver::addBuffer(std::unique_ptr<MemoryBuffer> mb,
   // File type is detected by contents, not by file extension.
   switch (identify_magic(mbref.getBuffer())) {
   case file_magic::windows_resource:
+    assert(!inCmdLineArchive &&
+           "Cannot specify a RES file inside a --start-lib/--end-lib group.");
     resources.push_back(mbref);
     break;
   case file_magic::archive:
+    // FIXME: We could later support --start-lib/--end-lib groups, to allow for
+    // "extending" an existing archive/LIB.
+    assert(!inCmdLineArchive &&
+           "Cannot specify a LIB file inside a --start-lib/--end-lib group.");
     if (wholeArchive) {
       std::unique_ptr<Archive> file =
           CHECK(Archive::create(mbref), filename + ": failed to parse archive");
@@ -284,13 +276,15 @@ void LinkerDriver::addBuffer(std::unique_ptr<MemoryBuffer> mb,
     addFile(make<ArchiveFile>(ctx, mbref));
     break;
   case file_magic::bitcode:
-    addFile(BitcodeFile::create(ctx, mbref, "", 0, lazy));
+    addFile(BitcodeFile::create(ctx, mbref, "", 0), inCmdLineArchive);
     break;
   case file_magic::coff_object:
   case file_magic::coff_import_library:
-    addFile(ObjFile::create(ctx, mbref, lazy));
+    addFile(ObjFile::create(ctx, mbref), inCmdLineArchive);
     break;
   case file_magic::pdb:
+    assert(!inCmdLineArchive &&
+           "Cannot specify a PDB file inside a --start-lib/--end-lib group.");
     addFile(make<PDBInputFile>(ctx, mbref));
     break;
   case file_magic::coff_cl_gl_object:
@@ -299,6 +293,9 @@ void LinkerDriver::addBuffer(std::unique_ptr<MemoryBuffer> mb,
     break;
   case file_magic::pecoff_executable:
     if (ctx.config.mingw) {
+      assert(
+          !inCmdLineArchive &&
+          "Cannot specify a PE/EXE file inside a --start-lib/--end-lib group.");
       addFile(make<DLLFile>(ctx.symtab, mbref));
       break;
     }
@@ -315,7 +312,9 @@ void LinkerDriver::addBuffer(std::unique_ptr<MemoryBuffer> mb,
   }
 }
 
-void LinkerDriver::enqueuePath(StringRef path, bool wholeArchive, bool lazy) {
+void LinkerDriver::enqueuePath(
+    StringRef path, bool wholeArchive,
+    std::optional<std::shared_future<CmdLineArchive *>> inCmdLineArchive) {
   auto future = std::make_shared<std::future<MBErrPair>>(
       createFutureForFile(std::string(path)));
   std::string pathStr = std::string(path);
@@ -354,7 +353,9 @@ void LinkerDriver::enqueuePath(StringRef path, bool wholeArchive, bool lazy) {
       else
         Err(ctx) << msg << "; did you mean '" << nearest << "'";
     } else
-      ctx.driver.addBuffer(std::move(mb), wholeArchive, lazy);
+      ctx.driver.addBuffer(std::move(mb), wholeArchive,
+                           inCmdLineArchive ? inCmdLineArchive->get()
+                                            : nullptr);
   });
 }
 
@@ -373,8 +374,7 @@ void LinkerDriver::addArchiveBuffer(MemoryBufferRef mb, StringRef symName,
   if (magic == file_magic::coff_object) {
     obj = ObjFile::create(ctx, mb);
   } else if (magic == file_magic::bitcode) {
-    obj = BitcodeFile::create(ctx, mb, parentName, offsetInArchive,
-                              /*lazy=*/false);
+    obj = BitcodeFile::create(ctx, mb, parentName, offsetInArchive);
   } else if (magic == file_magic::coff_cl_gl_object) {
     Err(ctx) << mb.getBufferIdentifier()
              << ": is not a native COFF file. Recompile without /GL?";
@@ -494,7 +494,7 @@ void LinkerDriver::parseDirectives(InputFile *file) {
       break;
     case OPT_defaultlib:
       if (std::optional<StringRef> path = findLibIfNew(arg->getValue()))
-        enqueuePath(*path, false, false);
+        enqueuePath(*path);
       break;
     case OPT_entry:
       if (!arg->getValue()[0])
@@ -2177,32 +2177,50 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
   // and OPT_end_lib.
   {
     llvm::TimeTraceScope timeScope2("Parse & queue inputs");
-    bool inLib = false;
+    std::optional<std::shared_future<CmdLineArchive *>> inCmdLineArchive;
     for (auto *arg : args) {
       switch (arg->getOption().getID()) {
       case OPT_end_lib:
-        if (!inLib)
+        if (!inCmdLineArchive) {
           Err(ctx) << "stray " << arg->getSpelling();
-        inLib = false;
+        } else {
+          enqueueTask([=]() { inCmdLineArchive->get()->maybeParse(); });
+          inCmdLineArchive = std::nullopt;
+        }
         break;
       case OPT_start_lib:
-        if (inLib)
+        if (inCmdLineArchive) {
           Err(ctx) << "nested " << arg->getSpelling();
-        inLib = true;
+        } else {
+          auto a = std::make_shared<std::promise<CmdLineArchive *>>();
+          inCmdLineArchive = a->get_future().share();
+          enqueueTask([&, a]() {
+            // In is important to create a fake archive here so that we
+            // remember its placement on the command-line. This will be
+            // later needed to resolve symbols in the archive order required
+            // by the MSVC specification.
+            a->set_value(make<CmdLineArchive>(
+                ctx.symtab, MemoryBufferRef({}, "<cmdline-lib>")));
+          });
+        }
         break;
       case OPT_wholearchive_file:
         if (std::optional<StringRef> path = findFileIfNew(arg->getValue()))
-          enqueuePath(*path, true, inLib);
+          enqueuePath(*path, true, inCmdLineArchive);
         break;
       case OPT_INPUT:
         if (std::optional<StringRef> path = findFileIfNew(arg->getValue()))
-          enqueuePath(*path, isWholeArchive(*path), inLib);
+          enqueuePath(*path, isWholeArchive(*path), inCmdLineArchive);
         break;
       default:
         // Ignore other options.
         break;
       }
     }
+    if (inCmdLineArchive) {
+      Warn(ctx) << "--start-lib with no --end-lib";
+      enqueueTask([=]() { inCmdLineArchive->get()->maybeParse(); });
+    }
   }
 
   // Read all input files given via the command line.
@@ -2236,7 +2254,7 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
   // addWinSysRootLibSearchPaths(), which is why they are in a separate loop.
   for (auto *arg : args.filtered(OPT_defaultlib))
     if (std::optional<StringRef> path = findLibIfNew(arg->getValue()))
-      enqueuePath(*path, false, false);
+      enqueuePath(*path);
   run();
   if (errorCount())
     return;
@@ -2553,9 +2571,11 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
 
         if (args.hasArg(OPT_include_optional)) {
           // Handle /includeoptional
-          for (auto *arg : args.filtered(OPT_include_optional))
-            if (isa_and_nonnull<LazyArchive>(symtab.find(arg->getValue())))
+          for (auto *arg : args.filtered(OPT_include_optional)) {
+            Symbol *sym = ctx.symtab.find(arg->getValue());
+            if (sym && (isa<LazyArchive>(sym) || isa<LazyObject>(sym)))
               symtab.addGCRoot(arg->getValue());
+          }
         }
       });
     } while (run());
@@ -2720,7 +2740,7 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
   // /manifestdependency: enables /manifest unless an explicit /manifest:no is
   // also passed.
   if (config->manifest == Configuration::Embed)
-    addBuffer(createManifestRes(), false, false);
+    addBuffer(createManifestRes(), false);
   else if (config->manifest == Configuration::SideBySide ||
            (config->manifest == Configuration::Default &&
             !config->manifestDependencies.empty()))
diff --git a/lld/COFF/Driver.h b/lld/COFF/Driver.h
index 14c97a98875bf..59fbc97e1910e 100644
--- a/lld/COFF/Driver.h
+++ b/lld/COFF/Driver.h
@@ -22,6 +22,7 @@
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/TarWriter.h"
 #include "llvm/WindowsDriver/MSVCPaths.h"
+#include <future>
 #include <memory>
 #include <optional>
 #include <set>
@@ -80,7 +81,7 @@ class LinkerDriver {
 
   void linkerMain(llvm::ArrayRef<const char *> args);
 
-  void addFile(InputFile *file);
+  void addFile(InputFile *file, CmdLineArchive *inCmdLineArchive = nullptr);
 
   void addClangLibSearchPaths(const std::string &argv0);
 
@@ -88,18 +89,23 @@ class LinkerDriver {
   void enqueueArchiveMember(const Archive::Child &c, const Archive::Symbol &sym,
                             StringRef parentName);
 
-  void enqueuePDB(StringRef Path) { enqueuePath(Path, false, false); }
+  void enqueuePDB(StringRef Path) { enqueuePath(Path); }
 
   MemoryBufferRef takeBuffer(std::unique_ptr<MemoryBuffer> mb);
 
-  void enqueuePath(StringRef path, bool wholeArchive, bool lazy);
+  // Schedule a input file for reading.
+  void enqueuePath(StringRef path, bool wholeArchive = false,
+                   std::optional<std::shared_future<CmdLineArchive *>>
+                       inCmdLineArchive = std::nullopt);
+
+  void pullArm64ECIcallHelper();
 
   // Returns a list of chunks of selected symbols.
   std::vector<Chunk *> getChunks() const;
 
   std::unique_ptr<llvm::TarWriter> tar; // for /linkrepro
 
-  void pullArm64ECIcallHelper();
+  bool ltoCompilationDone = false;
 
 private:
   // Searches a file from search paths.
@@ -170,7 +176,7 @@ class LinkerDriver {
   std::set<std::string> visitedLibs;
 
   void addBuffer(std::unique_ptr<MemoryBuffer> mb, bool wholeArchive,
-                 bool lazy);
+                 CmdLineArchive *inCmdLineArchive = nullptr);
   void addArchiveBuffer(MemoryBufferRef mbref, StringRef symName,
                         StringRef parentName, uint64_t offsetInArchive);
 
@@ -258,8 +264,6 @@ class LinkerDriver {
   // Create export thunks for exported and patchable Arm64EC function symbols.
   void createECExportThunks();
   void maybeCreateECExportThunk(StringRef name, Symbol *&sym);
-
-  bool ltoCompilationDone = false;
 };
 
 // Create enum with OPT_xxx values for each option in Options.td
diff --git a/lld/COFF/InputFiles.cpp b/lld/COFF/InputFiles.cpp
index 7fb42bb681939..20c4613aa422e 100644
--- a/lld/COFF/InputFiles.cpp
+++ b/lld/COFF/InputFiles.cpp
@@ -226,8 +226,19 @@ lld::coff::getArchiveMembers(COFFLinkerContext &ctx, Archive *file) {
   return v;
 }
 
-ObjFile::ObjFile(SymbolTable &symtab, COFFObjectFile *coffObj, bool lazy)
-    : InputFile(symtab, ObjectKind, coffObj->getMemoryBufferRef(), lazy),
+void CmdLineArchive::parse() {
+  for (InputFile *f : files) {
+    if (auto *o = dyn_cast<ObjFile>(f))
+      o->parseLazy();
+    else if (auto *b = dyn_cast<BitcodeFile>(f))
+      b->parseLazy();
+  }
+}
+
+void CmdLineArchive::addInputFile(InputFile *f) { files.push_back(f); }
+
+ObjFile::ObjFile(SymbolTable &symtab, COFFObjectFile *coffObj)
+    : InputFile(symtab, ObjectKind, coffObj->getMemoryBufferRef()),
       coffObj(coffObj) {}
 
 ObjFile *ObjFile::create(COFFLinkerContext &ctx, MemoryBufferRef m, bool lazy) {
@@ -241,8 +252,7 @@ ObjFile *ObjFile::create(COFFLinkerContext &ctx, MemoryBufferRef m, bool lazy) {
     Fatal(ctx) << m.getBufferIdentifier() << " is not a COFF file";
 
   bin->release();
-  return make<ObjFile>(ctx.getSymtab(MachineTypes(obj->getMachine())), obj,
-                       lazy);
+  return make<ObjFile>(ctx.getSymtab(MachineTypes(obj->getMachine())), obj);
 }
 
 void ObjFile::parseLazy() {
@@ -257,8 +267,6 @@ void ObjFile::parseLazy() {
     if (coffSym.isAbsolute() && ignoredSymbolName(name))
       continue;
     symtab.addLazyObject(this, name);
-    if (!lazy)
-      return;
     i += coffSym.getNumberOfAuxSymbols();
   }
 }
@@ -299,6 +307,8 @@ void ObjFile::initializeECThunks() {
 }
 
 void ObjFile::parse() {
+  symtab.ctx.objFileInstances.push_back(this);
+
   // Read section and symbol tables.
   initializeChunks();
   initializeSymbols();
@@ -1201,6 +1211,8 @@ ImportThunkChunk *ImportFile::makeImportThunk() {
 }
 
 void ImportFile::parse() {
+  symtab.ctx.importFileInstances.push_back(this);
+
   const auto *hdr =
       reinterpret_cast<const coff_import_header *>(mb.getBufferStart());
 
@@ -1307,14 +1319,14 @@ void ImportFile::parse() {
 }
 
 BitcodeFile::BitcodeFile(SymbolTable &symtab, MemoryBufferRef mb,
-                         std::unique_ptr<lto::InputFile> &o, bool lazy)
-    : InputFile(symtab, BitcodeKind, mb, lazy) {
+                         std::unique_ptr<lto::InputFile> &o)
+    : InputFile(symtab, BitcodeKind, mb) {
   obj.swap(o);
 }
 
 BitcodeFile *BitcodeFile::create(COFFLinkerContext &ctx, MemoryBufferRef mb,
                                  StringRef archiveName,
-                                 uint64_t offsetInArchive, bool lazy) {
+                                 uint64_t offsetInArchive) {
   std::string path = mb.getBufferIdentifier().str();
   if (ctx.config.thinLTOIndexOnly)
     path = replaceThinLTOSuffix(mb.getBufferIdentifier(),
@@ -1335,13 +1347,18 @@ BitcodeFile *BitcodeFile::create(COFFLinkerContext &ctx, MemoryBufferRef mb,
                                                utostr(offsetInArchive)));
 
   std::unique_ptr<lto::InputFile> obj = check(lto::InputFile::create(mbref));
-  return make<BitcodeFile>(ctx.getSymtab(getMachineType(obj.get())), mb, obj,
-                           lazy);
+  return make<BitcodeFile>(ctx.getSymtab(getMachineType(obj.get())), mb, obj);
 }
 
 BitcodeFile::~BitcodeFile() = default;
 
 void BitcodeFile::parse() {
+  if (symtab.ctx.driver.ltoCompilationDone) {
+    Err(symtab.ctx) << "LTO object file " << toString(this)
+                    << " linked in after doing LTO compilation.";
+  }
+  symtab.bitcodeFileInstances.push_back(this);
+
   llvm::StringSaver &saver = lld::saver();
 
   std::vector<std::pair<Symbol *, bool>> comdat(obj->getComdatTable().size());
@@ -1406,11 +1423,8 @@ void BitcodeFile::parse() {
 
 void BitcodeFile::parseLazy() {
   for (const lto::InputFile::Symbol &sym : obj->symbols())
-    if (!sym.isUndefined()) {
+    if (!sym.isUndefined())
       symtab.addLazyObject(this, sym.getName());
-      if (!lazy)
-        return;
-    }
 }
 
 MachineTypes BitcodeFile::getMachineType(const llvm::lto::InputFile *obj) {
diff --git a/lld/COFF/InputFiles.h b/lld/COFF/InputFiles.h
index 21b9aeef21d4f..09553bb9e56d5 100644
--- a/lld/COFF/InputFiles.h
+++ b/lld/COFF/InputFiles.h
@@ -71,6 +71,7 @@ class InputFile {
 public:
   enum Kind {
     ArchiveKind,
+    CmdLineArchiveKind,
     ObjectKind,
     PDBKind,
     ImportKind,
@@ -83,14 +84,19 @@ class InputFile {
   // Returns the filename.
   StringRef getName() const { return mb.getBufferIdentifier(); }
 
-  // Reads a file (the constructor doesn't do that).
-  virtual void parse() = 0;
-
   // Returns the CPU type this file was compiled to.
   virtual MachineTypes getMachineType() const {
     return IMAGE_FILE_MACHINE_UNKNOWN;
   }
 
+  // Parse the file if it wasn't already parsed.
+  void maybeParse() {
+    if (parsed)
+      return;
+    parsed = true;
+    parse();
+  }
+
   MemoryBufferRef mb;
 
   // An archive file name if this file is created from an archive.
@@ -102,17 +108,18 @@ class InputFile {
   SymbolTable &symtab;
 
 protected:
-  InputFile(SymbolTable &s, Kind k, MemoryBufferRef m, bool lazy = false)
-      : mb(m), symtab(s), fileKind(k), lazy(lazy) {}
+  InputFile(SymbolTable &s, Kind k, MemoryBufferRef m)
+      : mb(m), symtab(s), fileKind(k) {}
+
+  // Reads a file (the constructor doesn't do that).
+  virtual void parse() = 0;
 
   StringRef directives;
 
+  bool parsed = false;
+
 private:
   const Kind fileKind;
-
-public:
-  // True if this is a lazy ObjFile or BitcodeFile.
-  bool lazy = false;
 };
 
 // .lib or .a file.
@@ -132,16 +139,30 @@ class ArchiveFile : public InputFile {
   llvm::DenseSet<uint64_t> seen;
 };
 
+// A synthetic --start-lib/--end-lib archive.
+class CmdLineArchive : public InputFile {
+public:
+  explicit CmdLineArchive(SymbolTable &s, MemoryBufferRef m)
+      : InputFile(s, CmdLineArchiveKind, m) {}
+  static bool classof(const InputFile *f) {
+    return f->kind() == CmdLineArchiveKind;
+  }
+  void parse() override;
+  void addInputFile(InputFile *f);
+
+private:
+  std::vector<InputFile *> files;
+};
+
 // .obj or .o file. This may be a member of an archive file.
 class ObjFile : public InputFile {
 public:
   static ObjFile *create(COFFLinkerContext &ctx, MemoryBufferRef mb,
                          bool lazy = false);
-  explicit ObjFile(SymbolTable &symtab, COFFObjectFile *coffObj, bool lazy);
+  explicit ObjFile(SymbolTable &symtab, COFFObjectFile *coffObj);
 
   static bool classof(const InputFile *f) { return f->kind() == ObjectKind; }
   void parse() override;
-  void parseLazy();
   MachineTypes getMachineType() const override;
   ArrayRef<Chunk *> getChunks() { return chunks; }
   ArrayRef<SectionChunk *> getDebugChunks() { return debugChunks; }
@@ -191,6 +212,9 @@ class ObjFile : public InputFile {
   // True if this file was compiled with /guard:ehcont.
   bool hasGuardEHCont() { return feat00Flags & 0x4000; }
 
+  // Add lazy references to the symbols in this file.
+  void parseLazy();
+
   // Pointer to the PDB module descriptor builder. Various debug info records
   // will reference object files by "module index", which is here. Things like
   // source files and section contributions are also recorded here. Will be null
@@ -391,24 +415,24 @@ class ImportFile : public InputFile {
 class BitcodeFile : public InputFile {
 public:
   explicit BitcodeFile(SymbolTable &symtab, MemoryBufferRef mb,
-                       std::unique_ptr<llvm::lto::InputFile> &obj, bool lazy);
+                       std::unique_ptr<llvm::lto::InputFile> &obj);
   ~BitcodeFile();
 
   static BitcodeFile *create(COFFLinkerContext &ctx, MemoryBufferRef mb,
-                             StringRef archiveName, uint64_t offsetInArchive,
-                             bool lazy);
+                             StringRef archiveName, uint64_t offsetInArchive);
   static bool classof(const InputFile *f) { return f->kind() == BitcodeKind; }
   ArrayRef<Symbol *> getSymbols() { return symbols; }
   MachineTypes getMachineType() const override {
     return getMachineType(obj.get());
   }
   static MachineTypes getMachineType(const llvm::lto::InputFile *obj);
-  void parseLazy();
+  void parse() override;
   std::unique_ptr<llvm::lto::InputFile> obj;
 
-private:
-  void parse() override;
+  // Add lazy references to the symbols in this file.
+  void parseLazy();
 
+private:
   std::vector<Symbol *> symbols;
 };
 
diff --git a/lld/COFF/SymbolTable.cpp b/lld/COFF/SymbolTable.cpp
index 8fb0ee4e890d6..020b1b37cdb3c 100644
--- a/lld/COFF/SymbolTable.cpp
+++ b/lld/COFF/SymbolTable.cpp
@@ -47,6 +47,8 @@ static COFFSyncStream errorOrWarn(COFFLinkerContext &ctx) {
 
 // Causes the file associated with a lazy ...
[truncated]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants