[llvm] [AsmParser] Fixed `assembler local symbol not defined` unable to locate the exact line number. (PR #219719)

via llvm-commits llvm-commits at lists.llvm.org
Sat Aug 29 13:48:24 PDT 2026


https://github.com/zhangweize9-cyber updated https://github.com/llvm/llvm-project/pull/219719

>From 670b609b1e0d077f65383c331eee148c4c8d6b9c Mon Sep 17 00:00:00 2001
From: zhangweize9-cyber <zhangweize9 at gmail.com>
Date: Sun, 30 Aug 2026 02:06:12 +0800
Subject: [PATCH] [AsmParser] Fixed `assembler local symbol not defined` unable
 to locate the exact line number.

---
 llvm/include/llvm/MC/MCContext.h              | 14 +++++++++++
 llvm/lib/MC/MCExpr.cpp                        |  2 ++
 llvm/lib/MC/MCParser/AsmParser.cpp            | 25 ++++++++++++++-----
 .../undefined-local-symbol-location.s         | 13 ++++++++++
 4 files changed, 48 insertions(+), 6 deletions(-)
 create mode 100644 llvm/test/MC/AsmParser/undefined-local-symbol-location.s

diff --git a/llvm/include/llvm/MC/MCContext.h b/llvm/include/llvm/MC/MCContext.h
index 7e76abe08f56f..9eca783571898 100644
--- a/llvm/include/llvm/MC/MCContext.h
+++ b/llvm/include/llvm/MC/MCContext.h
@@ -162,6 +162,9 @@ class MCContext {
   /// We have three labels represented by the pairs (1, 0), (2, 0) and (1, 1)
   DenseMap<std::pair<unsigned, unsigned>, MCSymbol *> LocalSymbols;
 
+  /// Recording SymbolLocs.
+  DenseMap<const MCSymbol *, SMLoc> SymbolLocs;
+
   /// Keeps track of labels that are used in inline assembly.
   StringMap<MCSymbol *, BumpPtrAllocator &> InlineAsmUsedLabelNames;
 
@@ -481,6 +484,17 @@ class MCContext {
   /// \param Name - The symbol name, which must be unique across all symbols.
   LLVM_ABI MCSymbol *getOrCreateSymbol(const Twine &Name);
 
+  /// Set the initial source location for a symbol.
+  void setSymbolLoc(const MCSymbol *Sym, SMLoc Loc) {
+    if (Sym && Loc.isValid() && !SymbolLocs.count(Sym))
+      SymbolLocs[Sym] = Loc;
+  }
+
+  /// Get the recorded source location for a symbol.
+  SMLoc getSymbolLoc(const MCSymbol *Sym) const {
+    return SymbolLocs.lookup(Sym);
+  }
+
   /// Variant of getOrCreateSymbol that handles backslash-escaped symbols.
   /// For example, parse "a\"b\\" as a"\.
   LLVM_ABI MCSymbol *parseSymbol(const Twine &Name);
diff --git a/llvm/lib/MC/MCExpr.cpp b/llvm/lib/MC/MCExpr.cpp
index c23dc3c119a01..d5ce3ad8d29f0 100644
--- a/llvm/lib/MC/MCExpr.cpp
+++ b/llvm/lib/MC/MCExpr.cpp
@@ -226,6 +226,8 @@ MCSymbolRefExpr::MCSymbolRefExpr(const MCSymbol *Symbol, Spec specifier,
 const MCSymbolRefExpr *MCSymbolRefExpr::create(const MCSymbol *Sym,
                                                uint16_t specifier,
                                                MCContext &Ctx, SMLoc Loc) {
+  if (Sym && Loc.isValid())
+    Ctx.setSymbolLoc(Sym, Loc);
   return new (Ctx) MCSymbolRefExpr(Sym, specifier, Loc);
 }
 
diff --git a/llvm/lib/MC/MCParser/AsmParser.cpp b/llvm/lib/MC/MCParser/AsmParser.cpp
index 839dbca990578..8b446c2d2684a 100644
--- a/llvm/lib/MC/MCParser/AsmParser.cpp
+++ b/llvm/lib/MC/MCParser/AsmParser.cpp
@@ -1044,12 +1044,25 @@ bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) {
         // explicitly. If we know it's a variable, we have a definition for
         // the purposes of this check.
         if (Sym && Sym->isTemporary() && !Sym->isVariable() &&
-            !Sym->isDefined())
-          // FIXME: We would really like to refer back to where the symbol was
-          // first referenced for a source location. We need to add something
-          // to track that. Currently, we just point to the end of the file.
-          printError(getTok().getLoc(), "assembler local symbol '" +
-                                            Sym->getName() + "' not defined");
+            !Sym->isDefined()) {
+          SMLoc ErrorLoc = getContext().getSymbolLoc(Sym);
+          if (!ErrorLoc.isValid())
+            ErrorLoc = getTok().getLoc();
+
+          /// Achieve underline annotation effect.
+          SMRange SymbolRange;
+          if (ErrorLoc.isValid()) {
+            const char *StartPtr = ErrorLoc.getPointer();
+            SMLoc EndLoc =
+                SMLoc::getFromPointer(StartPtr + Sym->getName().size());
+            SymbolRange = SMRange(ErrorLoc, EndLoc);
+          }
+
+          printError(ErrorLoc,
+                     "assembler local symbol '" + Sym->getName() +
+                         "' not defined",
+                     SymbolRange);
+        }
       }
     }
 
diff --git a/llvm/test/MC/AsmParser/undefined-local-symbol-location.s b/llvm/test/MC/AsmParser/undefined-local-symbol-location.s
new file mode 100644
index 0000000000000..52be762a868a7
--- /dev/null
+++ b/llvm/test/MC/AsmParser/undefined-local-symbol-location.s
@@ -0,0 +1,13 @@
+// NOTE: Assertions have been autogenerated by utils/update_mc_test_checks.py UTC_ARGS: --version 6
+// RUN: not llvm-mc -triple=x86_64-apple-macos %s 2>&1 | FileCheck %s
+.text
+
+
+jmp L_undefined_temporary_symbol
+// CHECK: :[[@LINE-1]]:5: error: assembler local symbol 'L_undefined_temporary_symbol' not defined
+movl %eax
+// CHECK: :[[@LINE-1]]:1: error: too few operands for instruction
+movl $0x1234567890, %eax
+// CHECK: :[[@LINE-1]]:6: error: unknown token in expression
+invalid_inst_name %eax
+// CHECK: :[[@LINE-1]]:1: error: invalid instruction mnemonic 'invalid_inst_name'



More information about the llvm-commits mailing list