[clang] [clang-repl] fix CleanUpPTU by removing decl according to C implicitly FuncitonDecl. (PR #178648)
via cfe-commits
cfe-commits at lists.llvm.org
Sat Feb 28 08:08:39 PST 2026
https://github.com/fogsong233 updated https://github.com/llvm/llvm-project/pull/178648
>From de28f1a58d2acec5483e4e897566f3987951554b Mon Sep 17 00:00:00 2001
From: fogsong233 <fogsong233 at gmail.com>
Date: Thu, 29 Jan 2026 20:35:46 +0800
Subject: [PATCH 1/8] fix CleanUpPTU by removing decl according to C implicitly
FuncitonDecl.
---
clang/lib/Interpreter/IncrementalParser.cpp | 34 ++++++++++++++++++-
.../incremental-c-implicit-error.c | 17 ++++++++++
2 files changed, 50 insertions(+), 1 deletion(-)
create mode 100644 clang/test/Interpreter/incremental-c-implicit-error.c
diff --git a/clang/lib/Interpreter/IncrementalParser.cpp b/clang/lib/Interpreter/IncrementalParser.cpp
index bf08911e23533..18cf62b360e32 100644
--- a/clang/lib/Interpreter/IncrementalParser.cpp
+++ b/clang/lib/Interpreter/IncrementalParser.cpp
@@ -18,6 +18,7 @@
#include "clang/Interpreter/PartialTranslationUnit.h"
#include "clang/Parse/Parser.h"
#include "clang/Sema/Sema.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/CrashRecoveryContext.h"
#include "llvm/Support/Error.h"
@@ -162,7 +163,9 @@ IncrementalParser::Parse(llvm::StringRef input) {
}
void IncrementalParser::CleanUpPTU(TranslationUnitDecl *MostRecentTU) {
- if (StoredDeclsMap *Map = MostRecentTU->getPrimaryContext()->getLookupPtr()) {
+ auto DeclsMapFilter = [MostRecentTU](StoredDeclsMap *Map) -> void {
+ if (!Map)
+ return;
for (auto &&[Key, List] : *Map) {
DeclContextLookupResult R = List.getLookupResult();
std::vector<NamedDecl *> NamedDeclsToRemove;
@@ -180,6 +183,11 @@ void IncrementalParser::CleanUpPTU(TranslationUnitDecl *MostRecentTU) {
List.remove(D);
}
}
+ };
+ DeclsMapFilter(MostRecentTU->getPrimaryContext()->getLookupPtr());
+ auto *ECCD = S.getASTContext().getExternCContextDecl();
+ if (ECCD) {
+ DeclsMapFilter(ECCD->getPrimaryContext()->getLookupPtr());
}
// FIXME: We should de-allocate MostRecentTU
@@ -192,6 +200,30 @@ void IncrementalParser::CleanUpPTU(TranslationUnitDecl *MostRecentTU) {
!D->getLangOpts().CPlusPlus)
S.IdResolver.RemoveDecl(ND);
}
+
+ // In C, implicit function declarations are not lexically attached to the
+ // current PTU, so they cannot be found in
+ // MostRecentTU->getPrimaryContext()->getLookupPtr(). We must traverse the
+ // entire IdentifierTable to locate them.
+ // FIXME: Is there a more lightweight solution?
+ llvm::SmallVector<NamedDecl *, 2> NamedDeclsToRemove;
+ if (S.getDiagnostics().hasErrorOccurred() && !S.getLangOpts().CPlusPlus) {
+ for (auto &Entry : S.getASTContext().Idents) {
+ IdentifierInfo *II = Entry.getValue();
+ if (II && II->getFETokenInfo()) {
+ for (auto It = S.IdResolver.begin(II); It != S.IdResolver.end(); ++It) {
+ NamedDecl *D = *It;
+ if (D->isImplicit() && isa<FunctionDecl>(D) &&
+ D->getTranslationUnitDecl() == MostRecentTU) {
+ NamedDeclsToRemove.push_back(D);
+ }
+ }
+ }
+ }
+ }
+ for (auto &&D : NamedDeclsToRemove) {
+ S.IdResolver.RemoveDecl(D);
+ }
}
PartialTranslationUnit &
diff --git a/clang/test/Interpreter/incremental-c-implicit-error.c b/clang/test/Interpreter/incremental-c-implicit-error.c
new file mode 100644
index 0000000000000..9f153f4138387
--- /dev/null
+++ b/clang/test/Interpreter/incremental-c-implicit-error.c
@@ -0,0 +1,17 @@
+// REQUIRES: host-supports-jit
+// RUN: cat %s | clang-repl -Xcc -x -Xcc c -Xcc -std=c17 -Xcc -fno-builtin 2>&1 | FileCheck %s
+// RUN: %if !system-windows %{ cat %s | clang-repl -Xcc -x -Xcc c -Xcc -std=c17 -Xcc -fno-builtin -Xcc -O2 2>&1 | FileCheck %s %}
+// see https://github.com/llvm/llvm-project/issues/171440.
+
+a();
+// CHECK: error: call to undeclared function 'a'
+// CHECK: ISO C99 and later do not support implicit function declarations
+
+void a() { return; }
+// CHECK-NOT: error: conflicting types
+
+a();
+// CHECK-NOT: Symbols not found
+
+int x = 10;
+%quit
\ No newline at end of file
>From dd479986611b508caa89005bbe5ac94685640757 Mon Sep 17 00:00:00 2001
From: fogsong233 <fogsong233 at gmail.com>
Date: Thu, 29 Jan 2026 21:42:47 +0800
Subject: [PATCH 2/8] add more check
---
clang/lib/Interpreter/IncrementalParser.cpp | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/clang/lib/Interpreter/IncrementalParser.cpp b/clang/lib/Interpreter/IncrementalParser.cpp
index 18cf62b360e32..6de7c6409f1ef 100644
--- a/clang/lib/Interpreter/IncrementalParser.cpp
+++ b/clang/lib/Interpreter/IncrementalParser.cpp
@@ -13,6 +13,7 @@
#include "IncrementalParser.h"
#include "IncrementalAction.h"
+#include "clang/AST/Decl.h"
#include "clang/AST/DeclContextInternals.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Interpreter/PartialTranslationUnit.h"
@@ -20,6 +21,7 @@
#include "clang/Sema/Sema.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/IR/Module.h"
+#include "llvm/Support/Casting.h"
#include "llvm/Support/CrashRecoveryContext.h"
#include "llvm/Support/Error.h"
@@ -213,9 +215,10 @@ void IncrementalParser::CleanUpPTU(TranslationUnitDecl *MostRecentTU) {
if (II && II->getFETokenInfo()) {
for (auto It = S.IdResolver.begin(II); It != S.IdResolver.end(); ++It) {
NamedDecl *D = *It;
- if (D->isImplicit() && isa<FunctionDecl>(D) &&
- D->getTranslationUnitDecl() == MostRecentTU) {
- NamedDeclsToRemove.push_back(D);
+ if (D->isImplicit() && D->getTranslationUnitDecl() == MostRecentTU) {
+ if (auto *FD = dyn_cast<FunctionDecl>(D);
+ FD && FD->getBuiltinID() == 0)
+ NamedDeclsToRemove.push_back(D);
}
}
}
>From 3b0b73dc59c91aa16ef39d18e11a66d417f3b37c Mon Sep 17 00:00:00 2001
From: fogsong233 <fogsong233 at gmail.com>
Date: Fri, 30 Jan 2026 11:58:51 +0800
Subject: [PATCH 3/8] fix case cleanUpPTU is called by undo
---
clang/lib/Interpreter/IncrementalParser.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/lib/Interpreter/IncrementalParser.cpp b/clang/lib/Interpreter/IncrementalParser.cpp
index 6de7c6409f1ef..a54b8a4b54aac 100644
--- a/clang/lib/Interpreter/IncrementalParser.cpp
+++ b/clang/lib/Interpreter/IncrementalParser.cpp
@@ -209,7 +209,7 @@ void IncrementalParser::CleanUpPTU(TranslationUnitDecl *MostRecentTU) {
// entire IdentifierTable to locate them.
// FIXME: Is there a more lightweight solution?
llvm::SmallVector<NamedDecl *, 2> NamedDeclsToRemove;
- if (S.getDiagnostics().hasErrorOccurred() && !S.getLangOpts().CPlusPlus) {
+ if (!S.getLangOpts().CPlusPlus) {
for (auto &Entry : S.getASTContext().Idents) {
IdentifierInfo *II = Entry.getValue();
if (II && II->getFETokenInfo()) {
>From 6c17e65b4972d9d134c374cd63b671a1e2df8431 Mon Sep 17 00:00:00 2001
From: fogsong233 <fogsong233 at gmail.com>
Date: Fri, 30 Jan 2026 12:01:06 +0800
Subject: [PATCH 4/8] Add more test.
---
clang/test/Interpreter/incremental-c-implicit-error.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/clang/test/Interpreter/incremental-c-implicit-error.c b/clang/test/Interpreter/incremental-c-implicit-error.c
index 9f153f4138387..4374223fc2c69 100644
--- a/clang/test/Interpreter/incremental-c-implicit-error.c
+++ b/clang/test/Interpreter/incremental-c-implicit-error.c
@@ -13,5 +13,14 @@ void a() { return; }
a();
// CHECK-NOT: Symbols not found
+p();
+// CHECK: error: call to undeclared function 'p'
+// CHECK: ISO C99 and later do not support implicit function declarations
+
+%undo
+
+void p() { return; }
+// CHECK-NOT: error: conflicting types
+
int x = 10;
%quit
\ No newline at end of file
>From fba1e6aa3973013ed2461f15ba49d210fd7039aa Mon Sep 17 00:00:00 2001
From: fogsong233 <fogsong233 at gmail.com>
Date: Fri, 30 Jan 2026 12:39:33 +0800
Subject: [PATCH 5/8] Add test.
---
clang/lib/Interpreter/IncrementalParser.cpp | 2 +-
.../Interpreter/incremental-c-implicit-error.c | 10 +---------
.../Interpreter/incremental-c-implicit-undo.c | 17 +++++++++++++++++
3 files changed, 19 insertions(+), 10 deletions(-)
create mode 100644 clang/test/Interpreter/incremental-c-implicit-undo.c
diff --git a/clang/lib/Interpreter/IncrementalParser.cpp b/clang/lib/Interpreter/IncrementalParser.cpp
index a54b8a4b54aac..e30cccc065f9f 100644
--- a/clang/lib/Interpreter/IncrementalParser.cpp
+++ b/clang/lib/Interpreter/IncrementalParser.cpp
@@ -21,7 +21,6 @@
#include "clang/Sema/Sema.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/IR/Module.h"
-#include "llvm/Support/Casting.h"
#include "llvm/Support/CrashRecoveryContext.h"
#include "llvm/Support/Error.h"
@@ -226,6 +225,7 @@ void IncrementalParser::CleanUpPTU(TranslationUnitDecl *MostRecentTU) {
}
for (auto &&D : NamedDeclsToRemove) {
S.IdResolver.RemoveDecl(D);
+ D->setInvalidDecl();
}
}
diff --git a/clang/test/Interpreter/incremental-c-implicit-error.c b/clang/test/Interpreter/incremental-c-implicit-error.c
index 4374223fc2c69..9ee2d6c7be2cf 100644
--- a/clang/test/Interpreter/incremental-c-implicit-error.c
+++ b/clang/test/Interpreter/incremental-c-implicit-error.c
@@ -13,14 +13,6 @@ void a() { return; }
a();
// CHECK-NOT: Symbols not found
-p();
-// CHECK: error: call to undeclared function 'p'
-// CHECK: ISO C99 and later do not support implicit function declarations
-
-%undo
-
-void p() { return; }
-// CHECK-NOT: error: conflicting types
int x = 10;
-%quit
\ No newline at end of file
+%quit
diff --git a/clang/test/Interpreter/incremental-c-implicit-undo.c b/clang/test/Interpreter/incremental-c-implicit-undo.c
new file mode 100644
index 0000000000000..2bb171fd642c7
--- /dev/null
+++ b/clang/test/Interpreter/incremental-c-implicit-undo.c
@@ -0,0 +1,17 @@
+// REQUIRES: host-supports-jit
+// RUN: cat %s | clang-repl -Xcc -x -Xcc c -Xcc -std=c17 -Xcc -fno-builtin -Xcc -Wno-error=implicit-function-declaration 2>&1 | FileCheck %s
+// RUN: %if !system-windows %{ cat %s | clang-repl -Xcc -x -Xcc c -Xcc -std=c17 -Xcc -fno-builtin -Xcc -O2 -Xcc -Wno-error=implicit-function-declaration 2>&1 | FileCheck %s %}
+
+a();
+
+void a() { return; }
+// CHECK: error: conflicting types
+
+p();
+%undo
+
+void p() { }
+// CHECK-NOT: error: conflicting types
+
+int x = 10;
+%quit
>From 627cc4b24ff7d180084d71f05dad18d91fe18565 Mon Sep 17 00:00:00 2001
From: fogsong233 <fogsong233 at gmail.com>
Date: Tue, 3 Feb 2026 00:00:39 +0800
Subject: [PATCH 6/8] remove windows restrict
---
clang/test/Interpreter/incremental-c-implicit-error.c | 2 +-
clang/test/Interpreter/incremental-c-implicit-undo.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/clang/test/Interpreter/incremental-c-implicit-error.c b/clang/test/Interpreter/incremental-c-implicit-error.c
index 9ee2d6c7be2cf..251fbb3f23c95 100644
--- a/clang/test/Interpreter/incremental-c-implicit-error.c
+++ b/clang/test/Interpreter/incremental-c-implicit-error.c
@@ -1,6 +1,6 @@
// REQUIRES: host-supports-jit
// RUN: cat %s | clang-repl -Xcc -x -Xcc c -Xcc -std=c17 -Xcc -fno-builtin 2>&1 | FileCheck %s
-// RUN: %if !system-windows %{ cat %s | clang-repl -Xcc -x -Xcc c -Xcc -std=c17 -Xcc -fno-builtin -Xcc -O2 2>&1 | FileCheck %s %}
+// RUN: cat %s | clang-repl -Xcc -x -Xcc c -Xcc -std=c17 -Xcc -fno-builtin -Xcc -O2 2>&1 | FileCheck %s
// see https://github.com/llvm/llvm-project/issues/171440.
a();
diff --git a/clang/test/Interpreter/incremental-c-implicit-undo.c b/clang/test/Interpreter/incremental-c-implicit-undo.c
index 2bb171fd642c7..8bd594d85f70f 100644
--- a/clang/test/Interpreter/incremental-c-implicit-undo.c
+++ b/clang/test/Interpreter/incremental-c-implicit-undo.c
@@ -1,6 +1,6 @@
// REQUIRES: host-supports-jit
// RUN: cat %s | clang-repl -Xcc -x -Xcc c -Xcc -std=c17 -Xcc -fno-builtin -Xcc -Wno-error=implicit-function-declaration 2>&1 | FileCheck %s
-// RUN: %if !system-windows %{ cat %s | clang-repl -Xcc -x -Xcc c -Xcc -std=c17 -Xcc -fno-builtin -Xcc -O2 -Xcc -Wno-error=implicit-function-declaration 2>&1 | FileCheck %s %}
+// RUN: cat %s | clang-repl -Xcc -x -Xcc c -Xcc -std=c17 -Xcc -fno-builtin -Xcc -O2 -Xcc -Wno-error=implicit-function-declaration 2>&1 | FileCheck %s
a();
>From 31b0fbc20870dfeca6ab0109f3395422bed92d10 Mon Sep 17 00:00:00 2001
From: fogsong233 <fogsong233 at gmail.com>
Date: Mon, 9 Feb 2026 22:07:09 +0800
Subject: [PATCH 7/8] Use new way
---
clang/lib/Interpreter/IncrementalParser.cpp | 58 +++++++++------------
1 file changed, 24 insertions(+), 34 deletions(-)
diff --git a/clang/lib/Interpreter/IncrementalParser.cpp b/clang/lib/Interpreter/IncrementalParser.cpp
index e30cccc065f9f..b824358307de4 100644
--- a/clang/lib/Interpreter/IncrementalParser.cpp
+++ b/clang/lib/Interpreter/IncrementalParser.cpp
@@ -19,7 +19,6 @@
#include "clang/Interpreter/PartialTranslationUnit.h"
#include "clang/Parse/Parser.h"
#include "clang/Sema/Sema.h"
-#include "llvm/ADT/SmallVector.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/CrashRecoveryContext.h"
#include "llvm/Support/Error.h"
@@ -164,9 +163,7 @@ IncrementalParser::Parse(llvm::StringRef input) {
}
void IncrementalParser::CleanUpPTU(TranslationUnitDecl *MostRecentTU) {
- auto DeclsMapFilter = [MostRecentTU](StoredDeclsMap *Map) -> void {
- if (!Map)
- return;
+ if (auto *Map = MostRecentTU->getPrimaryContext()->getLookupPtr()) {
for (auto &&[Key, List] : *Map) {
DeclContextLookupResult R = List.getLookupResult();
std::vector<NamedDecl *> NamedDeclsToRemove;
@@ -184,11 +181,30 @@ void IncrementalParser::CleanUpPTU(TranslationUnitDecl *MostRecentTU) {
List.remove(D);
}
}
- };
- DeclsMapFilter(MostRecentTU->getPrimaryContext()->getLookupPtr());
+ }
+
auto *ECCD = S.getASTContext().getExternCContextDecl();
- if (ECCD) {
- DeclsMapFilter(ECCD->getPrimaryContext()->getLookupPtr());
+ if (auto *Map = ECCD->getPrimaryContext()->getLookupPtr()) {
+ for (auto &&[Key, List] : *Map) {
+ DeclContextLookupResult R = List.getLookupResult();
+ std::vector<NamedDecl *> NamedDeclsToRemove;
+ for (NamedDecl *D : R) {
+ // Implicitly generated C decl is not attached to the current TU but
+ // lexically attached to the recent TU, so we need to check the lexical
+ // context.
+ DeclContext *LDC = D->getLexicalDeclContext();
+ while (LDC && !isa<TranslationUnitDecl>(LDC)) {
+ LDC = LDC->getLexicalParent();
+ }
+ TranslationUnitDecl *TopTU = cast_or_null<TranslationUnitDecl>(LDC);
+ if (TopTU == MostRecentTU)
+ NamedDeclsToRemove.push_back(D);
+ }
+ for (NamedDecl *D : NamedDeclsToRemove) {
+ List.remove(D);
+ S.IdResolver.RemoveDecl(D);
+ }
+ }
}
// FIXME: We should de-allocate MostRecentTU
@@ -201,32 +217,6 @@ void IncrementalParser::CleanUpPTU(TranslationUnitDecl *MostRecentTU) {
!D->getLangOpts().CPlusPlus)
S.IdResolver.RemoveDecl(ND);
}
-
- // In C, implicit function declarations are not lexically attached to the
- // current PTU, so they cannot be found in
- // MostRecentTU->getPrimaryContext()->getLookupPtr(). We must traverse the
- // entire IdentifierTable to locate them.
- // FIXME: Is there a more lightweight solution?
- llvm::SmallVector<NamedDecl *, 2> NamedDeclsToRemove;
- if (!S.getLangOpts().CPlusPlus) {
- for (auto &Entry : S.getASTContext().Idents) {
- IdentifierInfo *II = Entry.getValue();
- if (II && II->getFETokenInfo()) {
- for (auto It = S.IdResolver.begin(II); It != S.IdResolver.end(); ++It) {
- NamedDecl *D = *It;
- if (D->isImplicit() && D->getTranslationUnitDecl() == MostRecentTU) {
- if (auto *FD = dyn_cast<FunctionDecl>(D);
- FD && FD->getBuiltinID() == 0)
- NamedDeclsToRemove.push_back(D);
- }
- }
- }
- }
- }
- for (auto &&D : NamedDeclsToRemove) {
- S.IdResolver.RemoveDecl(D);
- D->setInvalidDecl();
- }
}
PartialTranslationUnit &
>From 3117ab65fa9550d406d9d7db711690c7f262afc2 Mon Sep 17 00:00:00 2001
From: fogsong233 <fogsong233 at gmail.com>
Date: Sun, 1 Mar 2026 00:08:09 +0800
Subject: [PATCH 8/8] resolve comments
---
clang/lib/Interpreter/IncrementalParser.cpp | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/clang/lib/Interpreter/IncrementalParser.cpp b/clang/lib/Interpreter/IncrementalParser.cpp
index b824358307de4..1329391fd0904 100644
--- a/clang/lib/Interpreter/IncrementalParser.cpp
+++ b/clang/lib/Interpreter/IncrementalParser.cpp
@@ -19,6 +19,7 @@
#include "clang/Interpreter/PartialTranslationUnit.h"
#include "clang/Parse/Parser.h"
#include "clang/Sema/Sema.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/CrashRecoveryContext.h"
#include "llvm/Support/Error.h"
@@ -163,7 +164,7 @@ IncrementalParser::Parse(llvm::StringRef input) {
}
void IncrementalParser::CleanUpPTU(TranslationUnitDecl *MostRecentTU) {
- if (auto *Map = MostRecentTU->getPrimaryContext()->getLookupPtr()) {
+ if (StoredDeclsMap *Map = MostRecentTU->getPrimaryContext()->getLookupPtr()) {
for (auto &&[Key, List] : *Map) {
DeclContextLookupResult R = List.getLookupResult();
std::vector<NamedDecl *> NamedDeclsToRemove;
@@ -183,19 +184,18 @@ void IncrementalParser::CleanUpPTU(TranslationUnitDecl *MostRecentTU) {
}
}
- auto *ECCD = S.getASTContext().getExternCContextDecl();
- if (auto *Map = ECCD->getPrimaryContext()->getLookupPtr()) {
+ ExternCContextDecl *ECCD = S.getASTContext().getExternCContextDecl();
+ if (StoredDeclsMap *Map = ECCD->getPrimaryContext()->getLookupPtr()) {
for (auto &&[Key, List] : *Map) {
DeclContextLookupResult R = List.getLookupResult();
- std::vector<NamedDecl *> NamedDeclsToRemove;
+ llvm::SmallVector<NamedDecl *, 4> NamedDeclsToRemove;
for (NamedDecl *D : R) {
// Implicitly generated C decl is not attached to the current TU but
// lexically attached to the recent TU, so we need to check the lexical
// context.
DeclContext *LDC = D->getLexicalDeclContext();
- while (LDC && !isa<TranslationUnitDecl>(LDC)) {
+ while (LDC && !isa<TranslationUnitDecl>(LDC))
LDC = LDC->getLexicalParent();
- }
TranslationUnitDecl *TopTU = cast_or_null<TranslationUnitDecl>(LDC);
if (TopTU == MostRecentTU)
NamedDeclsToRemove.push_back(D);
More information about the cfe-commits
mailing list