Skip to content

[clang-repl] Fix error recovery while PTU cleanup #127467

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

Merged
merged 6 commits into from
Jun 2, 2025

Conversation

anutosh491
Copy link
Member

@anutosh491 anutosh491 commented Feb 17, 2025

Fixes #123300

What is seen

clang-repl> int x = 42;
clang-repl> auto capture = [&]() { return x * 2; };
In file included from <<< inputs >>>:1:
input_line_4:1:17: error: non-local lambda expression cannot have a capture-default
    1 | auto capture = [&]() { return x * 2; };
      |                 ^
zsh: segmentation fault  clang-repl --Xcc="-v"

(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x8)
  * frame #0: 0x0000000107b4f8b8 libclang-cpp.19.1.dylib`clang::IncrementalParser::CleanUpPTU(clang::PartialTranslationUnit&) + 988
    frame #1: 0x0000000107b4f1b4 libclang-cpp.19.1.dylib`clang::IncrementalParser::ParseOrWrapTopLevelDecl() + 416
    frame #2: 0x0000000107b4fb94 libclang-cpp.19.1.dylib`clang::IncrementalParser::Parse(llvm::StringRef) + 612
    frame #3: 0x0000000107b52fec libclang-cpp.19.1.dylib`clang::Interpreter::ParseAndExecute(llvm::StringRef, clang::Value*) + 180
    frame #4: 0x0000000100003498 clang-repl`main + 3560
    frame #5: 0x000000018d39a0e0 dyld`start + 2360

Though the error is justified, we shouldn't be interested in exiting through a segfault in such cases.

The issue is that empty named decls weren't being taken care of resulting into this assert

assert(getPtr() && "getFETokenInfo on an empty DeclarationName!");

Can also be seen when the example is attempted through xeus-cpp-lite.

image

@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" labels Feb 17, 2025
@anutosh491
Copy link
Member Author

Should be fixed now

clang-repl> int x = 5; auto capture = [&]() { return x * 2; };
In file included from <<< inputs >>>:1:
input_line_1:1:28: error: non-local lambda expression cannot have a capture-default
    1 | int x = 5; auto capture = [&]() { return x * 2; };
      |                            ^
error: Parsing failed.

@llvmbot
Copy link
Member

llvmbot commented Feb 17, 2025

@llvm/pr-subscribers-clang

Author: Anutosh Bhat (anutosh491)

Changes

Fixes #123300

What is seen

clang-repl&gt; int x = 42;
clang-repl&gt; auto capture = [&amp;]() { return x * 2; };
In file included from &lt;&lt;&lt; inputs &gt;&gt;&gt;:1:
input_line_4:1:17: error: non-local lambda expression cannot have a capture-default
    1 | auto capture = [&amp;]() { return x * 2; };
      |                 ^
zsh: segmentation fault  clang-repl --Xcc="-v"

Though the error is justified, we shouldn't be interested in exiting through a segfault in such cases.

The issue is that empty named decls weren't being taken care of resulting into this assert

assert(getPtr() && "getFETokenInfo on an empty DeclarationName!");

Can also be seen when the example is attempted through xeus-cpp-lite.

image


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

2 Files Affected:

  • (modified) clang/lib/Interpreter/IncrementalParser.cpp (+2-2)
  • (modified) clang/unittests/Interpreter/InterpreterTest.cpp (+7)
diff --git a/clang/lib/Interpreter/IncrementalParser.cpp b/clang/lib/Interpreter/IncrementalParser.cpp
index e43cea1baf43a..1ebef0e434b3d 100644
--- a/clang/lib/Interpreter/IncrementalParser.cpp
+++ b/clang/lib/Interpreter/IncrementalParser.cpp
@@ -178,8 +178,8 @@ void IncrementalParser::CleanUpPTU(TranslationUnitDecl *MostRecentTU) {
     if (!ND)
       continue;
     // Check if we need to clean up the IdResolver chain.
-    if (ND->getDeclName().getFETokenInfo() && !D->getLangOpts().ObjC &&
-        !D->getLangOpts().CPlusPlus)
+    if (!ND->getDeclName().isEmpty() && ND->getDeclName().getFETokenInfo() &&
+        !D->getLangOpts().ObjC && !D->getLangOpts().CPlusPlus)
       S.IdResolver.RemoveDecl(ND);
   }
 }
diff --git a/clang/unittests/Interpreter/InterpreterTest.cpp b/clang/unittests/Interpreter/InterpreterTest.cpp
index 578f1d4c0eac6..56ab155ebf5a4 100644
--- a/clang/unittests/Interpreter/InterpreterTest.cpp
+++ b/clang/unittests/Interpreter/InterpreterTest.cpp
@@ -114,6 +114,13 @@ TEST_F(InterpreterTest, Errors) {
 
   RecoverErr = Interp->Parse("var1 = 424;");
   EXPECT_TRUE(!!RecoverErr);
+
+  Err = Interp->Parse("int x = 5; auto capture = [&]() { return x * 2; };").takeError();
+  EXPECT_THAT(DiagnosticOutput, HasSubstr("error: non-local lambda expression cannot have a capture-default"));
+  EXPECT_EQ("Parsing failed.", llvm::toString(std::move(Err)));
+
+  RecoverErr = Interp->Parse("int validVar = 10;");
+  EXPECT_TRUE(!!RecoverErr);
 }
 
 // Here we test whether the user can mix declarations and statements. The

@anutosh491
Copy link
Member Author

cc @ferdymercury @vgvassilev

Copy link

github-actions bot commented Feb 17, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

@anutosh491
Copy link
Member Author

Hmmm, the code formatter has a suggestion. Just increases the lines on a simple test. Not sure if the code formatter should be respected here !

@ferdymercury
Copy link

Thanks! fyi also @hahnjo

@anutosh491
Copy link
Member Author

For anyone interested in seeing the error at realtime, I am just leaving the static link for xeus-cpp-lite here.

https://compiler-research.org/xeus-cpp/lab/index.html

Possibly trying something like

int x = 5;
auto capture = [&]() { return x * 2; };

Should display the assertion error in the console.

@hahnjo hahnjo requested a review from vgvassilev February 17, 2025 10:30
@anutosh491 anutosh491 changed the title Fix error recovery while PTU cleanup [clang-repl] Fix error recovery while PTU cleanup Feb 18, 2025
@anutosh491
Copy link
Member Author

cc @vgvassilev

Copy link
Contributor

@vgvassilev vgvassilev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@anutosh491
Copy link
Member Author

Thanks for the review. The test lamda.cpp passes (https://github.com/llvm/llvm-project/actions/runs/13810830928/job/38631851756?pr=127467#step:4:20415) and I think this should be ready now.

Copy link
Contributor

@vgvassilev vgvassilev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lgtm!

@anutosh491 anutosh491 requested a review from vgvassilev May 13, 2025 09:07
Copy link
Contributor

@vgvassilev vgvassilev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Thank you.

@anutosh491 anutosh491 merged commit 3b4c51b into llvm:main Jun 2, 2025
11 checks passed
@anutosh491 anutosh491 deleted the captures branch June 2, 2025 14:47
@anutosh491
Copy link
Member Author

/cherry-pick 3b4c51b

@llvmbot
Copy link
Member

llvmbot commented Jun 2, 2025

/pull-request #142445

@llvmbot llvmbot moved this from Needs Triage to Done in LLVM Release Status Jun 2, 2025
sallto pushed a commit to sallto/llvm-project that referenced this pull request Jun 3, 2025
Fixes llvm#123300

What is seen 
```
clang-repl> int x = 42;
clang-repl> auto capture = [&]() { return x * 2; };
In file included from <<< inputs >>>:1:
input_line_4:1:17: error: non-local lambda expression cannot have a capture-default
    1 | auto capture = [&]() { return x * 2; };
      |                 ^
zsh: segmentation fault  clang-repl --Xcc="-v"

(lldb) bt
* thread llvm#1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x8)
  * frame #0: 0x0000000107b4f8b8 libclang-cpp.19.1.dylib`clang::IncrementalParser::CleanUpPTU(clang::PartialTranslationUnit&) + 988
    frame llvm#1: 0x0000000107b4f1b4 libclang-cpp.19.1.dylib`clang::IncrementalParser::ParseOrWrapTopLevelDecl() + 416
    frame llvm#2: 0x0000000107b4fb94 libclang-cpp.19.1.dylib`clang::IncrementalParser::Parse(llvm::StringRef) + 612
    frame llvm#3: 0x0000000107b52fec libclang-cpp.19.1.dylib`clang::Interpreter::ParseAndExecute(llvm::StringRef, clang::Value*) + 180
    frame llvm#4: 0x0000000100003498 clang-repl`main + 3560
    frame llvm#5: 0x000000018d39a0e0 dyld`start + 2360
```

Though the error is justified, we shouldn't be interested in exiting
through a segfault in such cases.

The issue is that empty named decls weren't being taken care of
resulting into this assert


https://github.com/llvm/llvm-project/blob/c1a229252617ed58f943bf3f4698bd8204ee0f04/clang/include/clang/AST/DeclarationName.h#L503

Can also be seen when the example is attempted through xeus-cpp-lite.


![image](https://github.com/user-attachments/assets/9b0e6ead-138e-4b06-9ad9-fcb9f8d5bf6e)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category
Projects
Development

Successfully merging this pull request may close these issues.

Clang-repl fails while trying Lambdas with capture
4 participants