llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Haojian Wu (hokein)

<details>
<summary>Changes</summary>

During error recovery, a synthetic token (whose length is 0) can be inserted 
past the end of a FileID, e.g.  inserting ")" when a macro-arg containing a 
comma should be guarded by parentheses.

When calculating the location after this token, the calculated `AfterLoc` can 
point exactly to the start of the next FileID (`NextLocalOffset`), any source 
manager operations on the `AfterLoc` is invalid.
  
This patch adds a safe guard in `Lexer::isAtEndOfMacroExpansion` to prevent 
passing this invalid location to `SourceManager`.

 Fixes #<!-- -->115007
 Fixes #<!-- -->21755

---
Full diff: https://github.com/llvm/llvm-project/pull/191734.diff


2 Files Affected:

- (modified) clang/lib/Lex/Lexer.cpp (+14-2) 
- (added) clang/test/Parser/macro-braces-recovery.cpp (+31) 


``````````diff
diff --git a/clang/lib/Lex/Lexer.cpp b/clang/lib/Lex/Lexer.cpp
index 10246552bb13d..989c4e0cb7cef 100644
--- a/clang/lib/Lex/Lexer.cpp
+++ b/clang/lib/Lex/Lexer.cpp
@@ -920,8 +920,20 @@ bool Lexer::isAtEndOfMacroExpansion(SourceLocation loc,
 
   SourceLocation afterLoc = loc.getLocWithOffset(tokLen);
   SourceLocation expansionLoc;
-  if (!SM.isAtEndOfImmediateMacroExpansion(afterLoc, &expansionLoc))
-    return false;
+  FileID FID = SM.getFileID(loc);
+
+  if (SM.isInFileID(afterLoc, FID)) {
+    if (!SM.isAtEndOfImmediateMacroExpansion(afterLoc, &expansionLoc))
+      return false;
+  } else {
+    // During error recovery, a zero-length synthetic token might be inserted
+    // past the end of the FileID, e.g. inserting ")" when a macro-arg
+    // containing a comma should be guarded by parentheses. In this case,
+    // afterLoc reaches the `NextLocalOffset` boundary, any operations on 
afterLoc will be invalid!
+    const SrcMgr::SLocEntry &Entry = SM.getSLocEntry(FID);
+    assert(Entry.isExpansion() && "Should be in an expansion");
+    expansionLoc = Entry.getExpansion().getExpansionLocEnd();
+  }
 
   if (expansionLoc.isFileID()) {
     // No other macro expansions.
diff --git a/clang/test/Parser/macro-braces-recovery.cpp 
b/clang/test/Parser/macro-braces-recovery.cpp
new file mode 100644
index 0000000000000..e8842f44bd623
--- /dev/null
+++ b/clang/test/Parser/macro-braces-recovery.cpp
@@ -0,0 +1,31 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+namespace GH21755 {
+#define M(x) f x // expected-note {{macro 'M' defined here}}
+
+// expected-error@+5 {{too many arguments provided to function-like macro 
invocation}}
+// expected-note@+4 {{parentheses are required around macro argument 
containing braced initializer list}}
+// expected-error@+3 {{a type specifier is required for all declarations}}
+// expected-error@+2 {{expected ')'}}
+// expected-note@+1 {{to match this '('}}
+M(0 {,}) // expected-error {{expected ';' after top level declarator}}
+}
+
+namespace GH115007 {
+class Foo { // expected-note {{candidate constructor (the implicit copy 
constructor) not viable}} \
+            // expected-note {{candidate constructor (the implicit move 
constructor) not viable}}
+public:
+  Foo(int); // expected-note {{candidate constructor not viable: requires 1 
argument, but 2 were provided}}
+  bool operator==(const int l); // expected-note {{candidate function not 
viable: no known conversion from 'Foo' to 'const int' for 1st argument}}
+};
+#define EQ(x,y) (void)(x == y) // expected-note {{macro 'EQ' defined here}}
+
+void test_EQ() {
+  Foo F = Foo{1};
+  // expected-error@+4 {{too many arguments provided to function-like macro 
invocation}}
+  // expected-note@+3 {{parentheses are required around macro argument 
containing braced initializer list}}
+  // expected-error@+2 {{no matching constructor for initialization of 'Foo'}}
+  // expected-error@+1 {{invalid operands to binary expression ('Foo' and 
'Foo')}}
+  EQ(F,Foo{1,2});
+}
+}

``````````

</details>


https://github.com/llvm/llvm-project/pull/191734
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to