[lld] 2a89356 - [ELF] Add till and rewrite while (... consume("}"))

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 26 17:13:41 PDT 2024


Author: Fangrui Song
Date: 2024-07-26T17:13:37-07:00
New Revision: 2a89356d64a274f7171b45d8b7b05b6315a6f627

URL: https://github.com/llvm/llvm-project/commit/2a89356d64a274f7171b45d8b7b05b6315a6f627
DIFF: https://github.com/llvm/llvm-project/commit/2a89356d64a274f7171b45d8b7b05b6315a6f627.diff

LOG: [ELF] Add till and rewrite while (... consume("}"))

After #100493, the idiom `while (!errorCount() && !consume("}"))` could
lead to inaccurate diagnostics or dead loops. Introduce till to change
the code pattern.

Added: 
    

Modified: 
    lld/ELF/ScriptLexer.cpp
    lld/ELF/ScriptLexer.h
    lld/ELF/ScriptParser.cpp
    lld/test/ELF/linkerscript/phdrs.s
    lld/test/ELF/linkerscript/sections.s

Removed: 
    


################################################################################
diff  --git a/lld/ELF/ScriptLexer.cpp b/lld/ELF/ScriptLexer.cpp
index d3a1586332f99..51282dba53c83 100644
--- a/lld/ELF/ScriptLexer.cpp
+++ b/lld/ELF/ScriptLexer.cpp
@@ -234,6 +234,17 @@ void ScriptLexer::expect(StringRef expect) {
   }
 }
 
+ScriptLexer::Token ScriptLexer::till(StringRef tok) {
+  StringRef str = next();
+  if (str == tok)
+    return {};
+  if (!atEOF())
+    return {str};
+  prevTok = {};
+  setError("unexpected EOF");
+  return {};
+}
+
 // Returns true if S encloses T.
 static bool encloses(StringRef s, StringRef t) {
   return s.bytes_begin() <= t.bytes_begin() && t.bytes_end() <= s.bytes_end();

diff  --git a/lld/ELF/ScriptLexer.h b/lld/ELF/ScriptLexer.h
index 7651908d60200..bc2b5fee618f7 100644
--- a/lld/ELF/ScriptLexer.h
+++ b/lld/ELF/ScriptLexer.h
@@ -32,6 +32,12 @@ class ScriptLexer {
   Buffer curBuf;
   SmallVector<Buffer, 0> buffers;
 
+  struct Token {
+    StringRef str;
+    explicit operator bool() const { return !str.empty(); }
+    operator StringRef() const { return str; }
+  };
+
   // The token before the last next().
   StringRef prevTok;
   // Rules for what is a token are 
diff erent when we are in an expression.
@@ -54,6 +60,7 @@ class ScriptLexer {
   void skip();
   bool consume(StringRef tok);
   void expect(StringRef expect);
+  Token till(StringRef tok);
   std::string getCurrentLocation();
   MemoryBufferRef getCurrentMB();
 

diff  --git a/lld/ELF/ScriptParser.cpp b/lld/ELF/ScriptParser.cpp
index 7303bb564afad..bdfa106090ca5 100644
--- a/lld/ELF/ScriptParser.cpp
+++ b/lld/ELF/ScriptParser.cpp
@@ -527,10 +527,9 @@ void ScriptParser::readOutputFormat() {
 
 void ScriptParser::readPhdrs() {
   expect("{");
-
-  while (!errorCount() && !consume("}")) {
+  while (auto tok = till("}")) {
     PhdrsCommand cmd;
-    cmd.name = next();
+    cmd.name = tok;
     cmd.type = readPhdrType();
 
     while (!errorCount() && !consume(";")) {
@@ -626,15 +625,14 @@ SmallVector<SectionCommand *, 0> ScriptParser::readOverlay() {
 
 void ScriptParser::readOverwriteSections() {
   expect("{");
-  while (!errorCount() && !consume("}"))
-    script->overwriteSections.push_back(readOutputSectionDescription(next()));
+  while (auto tok = till("}"))
+    script->overwriteSections.push_back(readOutputSectionDescription(tok));
 }
 
 void ScriptParser::readSections() {
   expect("{");
   SmallVector<SectionCommand *, 0> v;
-  while (!errorCount() && !consume("}")) {
-    StringRef tok = next();
+  while (auto tok = till("}")) {
     if (tok == "OVERLAY") {
       for (SectionCommand *cmd : readOverlay())
         v.push_back(cmd);
@@ -1005,8 +1003,7 @@ OutputDesc *ScriptParser::readOutputSectionDescription(StringRef outSec) {
     osec->constraint = ConstraintKind::ReadWrite;
   expect("{");
 
-  while (!errorCount() && !consume("}")) {
-    StringRef tok = next();
+  while (auto tok = till("}")) {
     if (tok == ";") {
       // Empty commands are allowed. Do nothing here.
     } else if (SymbolAssignment *assign = readAssignment(tok)) {
@@ -1806,8 +1803,7 @@ Expr ScriptParser::readMemoryAssignment(StringRef s1, StringRef s2,
 // MEMORY { name [(attr)] : ORIGIN = origin, LENGTH = len ... }
 void ScriptParser::readMemory() {
   expect("{");
-  while (!errorCount() && !consume("}")) {
-    StringRef tok = next();
+  while (auto tok = till("}")) {
     if (tok == "INCLUDE") {
       readInclude();
       continue;

diff  --git a/lld/test/ELF/linkerscript/phdrs.s b/lld/test/ELF/linkerscript/phdrs.s
index 18307bcf36675..9768c4ccdbacb 100644
--- a/lld/test/ELF/linkerscript/phdrs.s
+++ b/lld/test/ELF/linkerscript/phdrs.s
@@ -101,7 +101,8 @@ PHDRS { text PT_FOO FOOHDR; }
 PHDRS { text PT_LOAD ;
 
 # RUN: not ld.lld -T unclosed.lds a.o 2>&1 | FileCheck --check-prefix=UNCLOSED %s
-#     UNCLOSED:error: unclosed.lds:1: invalid program header type:
+#     UNCLOSED:error: unclosed.lds:1: unexpected EOF
+# UNCLOSED-NOT:{{.}}
 
 #--- a.s
 .global _start

diff  --git a/lld/test/ELF/linkerscript/sections.s b/lld/test/ELF/linkerscript/sections.s
index 0453a12ceb147..dbedd12a9129e 100644
--- a/lld/test/ELF/linkerscript/sections.s
+++ b/lld/test/ELF/linkerscript/sections.s
@@ -103,7 +103,8 @@ SECTIONS {
    .text : { *(.text) }
 
 # RUN: not ld.lld -T unclosed.lds a.o 2>&1 | FileCheck --check-prefix=UNCLOSED %s
-# UNCLOSED: error: unclosed.lds:1: malformed number:
+#     UNCLOSED:error: unclosed.lds:1: unexpected EOF
+# UNCLOSED-NOT:{{.}}
 
 #--- unclosed-out.lds
 SECTIONS {


        


More information about the llvm-commits mailing list