[lld] 7a7cea9 - [ELF] Version script: simplify wildcard matching. NFC (#223202)

via llvm-commits llvm-commits at lists.llvm.org
Sat Sep 12 21:32:28 PDT 2026


Author: Fangrui Song
Date: 2026-09-13T04:32:23Z
New Revision: 7a7cea921c3e450903b57e5f4b2992f1dce4c410

URL: https://github.com/llvm/llvm-project/commit/7a7cea921c3e450903b57e5f4b2992f1dce4c410
DIFF: https://github.com/llvm/llvm-project/commit/7a7cea921c3e450903b57e5f4b2992f1dce4c410.diff

LOG: [ELF] Version script: simplify wildcard matching. NFC (#223202)

Replace a loop over non-"*" wildcard patterns and another loop over "*"
with a single loop that calls the inlined
`SymbolTable::assignWildcardVersion`.

Added: 
    

Modified: 
    lld/ELF/SymbolTable.cpp
    lld/ELF/SymbolTable.h

Removed: 
    


################################################################################
diff  --git a/lld/ELF/SymbolTable.cpp b/lld/ELF/SymbolTable.cpp
index 6841b5ca15a5d..810cb6df5afcd 100644
--- a/lld/ELF/SymbolTable.cpp
+++ b/lld/ELF/SymbolTable.cpp
@@ -234,16 +234,14 @@ bool SymbolTable::assignExactVersion(SymbolVersion ver, uint16_t versionId) {
   return !syms.empty();
 }
 
-void SymbolTable::assignWildcardVersion(SymbolVersion ver, uint16_t versionId) {
-  // Exact matching takes precedence over fuzzy matching,
-  // so we set a version to a symbol only if no version has been assigned
-  // to the symbol. This behavior is compatible with GNU.
-  for (Symbol *sym : findAllByVersion(ver, /*includeNonDefault=*/false))
-    if (!sym->versionScriptAssigned) {
-      sym->versionScriptAssigned = true;
-      sym->versionId = versionId;
-    }
-}
+namespace {
+struct WildcardPattern {
+  SymbolVersion ver;
+  uint16_t versionId;
+  WildcardPattern(const SymbolVersion &ver, uint16_t versionId)
+      : ver(ver), versionId(versionId) {}
+};
+} // namespace
 
 // This function processes version scripts by updating the versionId
 // member of symbols.
@@ -276,51 +274,55 @@ void SymbolTable::scanVersionScript() {
         assignExact(pat, VER_NDX_LOCAL, "local");
   }
 
-  // Next, assign versions to wildcards that are not "*". Note that because the
-  // last match takes precedence over previous matches, we iterate over the
-  // definitions in the reverse order.
-  for (VersionDefinition &v : llvm::reverse(ctx.arg.versionDefinitions)) {
-    for (SymbolVersion &pat : v.nonLocalPatterns)
-      if (pat.hasWildcard && pat.name != "*")
-        assignWildcardVersion(pat, v.id);
-    for (SymbolVersion &pat : v.localPatterns)
-      if (pat.hasWildcard && pat.name != "*")
-        assignWildcardVersion(pat, VER_NDX_LOCAL);
-  }
-
-  // Then, assign versions to "*". In GNU linkers they have lower priority than
-  // other wildcards.
+  // Next, collect wildcards in precedence order, where "*" patterns have the
+  // lowest precedence in GNU ld. Because the last match takes precedence over
+  // previous matches, we iterate over the definitions in the reverse order.
+  SmallVector<WildcardPattern, 0> pats, asterisks;
   bool globalAsteriskFound = false;
   bool localAsteriskFound = false;
   bool asteriskReported = false;
-  auto assignAsterisk = [&](SymbolVersion &pat, VersionDefinition *ver,
-                            bool isLocal) {
-    if (!asteriskReported) {
-      if ((isLocal && globalAsteriskFound) ||
-          (!isLocal && localAsteriskFound)) {
-        Warn(ctx)
-            << "wildcard pattern '*' is used for both 'local' and 'global' "
-               "scopes in version script";
-        asteriskReported = true;
-      } else if (!isLocal && globalAsteriskFound) {
-        Warn(ctx) << "wildcard pattern '*' is used for multiple version "
-                     "definitions in "
-                     "version script";
-        asteriskReported = true;
-      } else {
-        localAsteriskFound = isLocal;
-        globalAsteriskFound = !isLocal;
+  for (VersionDefinition &v : llvm::reverse(ctx.arg.versionDefinitions)) {
+    for (bool isLocal : {false, true}) {
+      uint16_t id = isLocal ? VER_NDX_LOCAL : v.id;
+      for (SymbolVersion &pat :
+           isLocal ? v.localPatterns : v.nonLocalPatterns) {
+        if (!pat.hasWildcard)
+          continue;
+        if (pat.name != "*") {
+          pats.emplace_back(pat, id);
+          continue;
+        }
+        if (!asteriskReported) {
+          if ((isLocal && globalAsteriskFound) ||
+              (!isLocal && localAsteriskFound)) {
+            Warn(ctx)
+                << "wildcard pattern '*' is used for both 'local' and 'global' "
+                   "scopes in version script";
+            asteriskReported = true;
+          } else if (!isLocal && globalAsteriskFound) {
+            Warn(ctx) << "wildcard pattern '*' is used for multiple version "
+                         "definitions in version script";
+            asteriskReported = true;
+          } else {
+            localAsteriskFound = isLocal;
+            globalAsteriskFound = !isLocal;
+          }
+        }
+        asterisks.emplace_back(pat, id);
+      }
+    }
+  }
+  pats.append(asterisks);
+
+  // Exact matching takes precedence over wildcard matching, so a wildcard
+  // assigns a version only if none has been assigned.
+  for (auto &pat : pats) {
+    for (Symbol *sym : findAllByVersion(pat.ver, /*includeNonDefault=*/false)) {
+      if (!sym->versionScriptAssigned) {
+        sym->versionScriptAssigned = true;
+        sym->versionId = pat.versionId;
       }
     }
-    assignWildcardVersion(pat, isLocal ? (uint16_t)VER_NDX_LOCAL : ver->id);
-  };
-  for (VersionDefinition &v : llvm::reverse(ctx.arg.versionDefinitions)) {
-    for (SymbolVersion &pat : v.nonLocalPatterns)
-      if (pat.hasWildcard && pat.name == "*")
-        assignAsterisk(pat, &v, false);
-    for (SymbolVersion &pat : v.localPatterns)
-      if (pat.hasWildcard && pat.name == "*")
-        assignAsterisk(pat, &v, true);
   }
 
   // Handle --dynamic-list. If a specified symbol is also matched by local: in a

diff  --git a/lld/ELF/SymbolTable.h b/lld/ELF/SymbolTable.h
index e485ad2edb000..058684bf84af2 100644
--- a/lld/ELF/SymbolTable.h
+++ b/lld/ELF/SymbolTable.h
@@ -88,7 +88,6 @@ class SymbolTable {
 
   llvm::StringMap<SmallVector<Symbol *, 0>> &getDemangledSyms();
   bool assignExactVersion(SymbolVersion ver, uint16_t versionId);
-  void assignWildcardVersion(SymbolVersion ver, uint16_t versionId);
 
   Ctx &ctx;
 


        


More information about the llvm-commits mailing list