[clang] [Sema] Skip ExternalSource query and clear DeleteExprs in incremental mode (PR #192856)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Apr 20 01:06:26 PDT 2026
https://github.com/lucasvallejoo updated https://github.com/llvm/llvm-project/pull/192856
>From b98a1d03542b45ea23412a7f254469c59d24236c Mon Sep 17 00:00:00 2001
From: lucasvallejoo <lucas.valfac at gmail.com>
Date: Sun, 19 Apr 2026 18:46:14 +0200
Subject: [PATCH 1/2] [Sema] Skip ExternalSource query and clear DeleteExprs in
incremental mode
In incremental compilation (e.g. ROOT/Cling REPL), ActOnEndOfTranslationUnit()
is called once per user input line rather than once at program end. This caused
two performance issues:
1. ReadMismatchingDeleteExpressions() queried the ExternalSource (PCH/modules)
on every cycle, causing redundant disk I/O that severely degraded performance
in long REPL sessions.
2. DeleteExprs accumulated entries across cycles without being cleared, leading
to unbounded memory growth and O(N^2) redundant AST traversals.
This patch guards the ExternalSource query by checking that incremental processing
is NOT enabled, and adds DeleteExprs.clear() after each analysis pass, following
the same pattern used elsewhere in ActOnEndOfTranslationUnit() for REPL mode.
A regression test is included to verify that warn_mismatched_delete_new
continues to fire correctly in incremental mode after this change.
Patch by Axel Naumann.
Note: This upstreaming effort is part of the preparation for the compiler fellowship program.
---
clang/lib/Sema/Sema.cpp | 7 ++++---
.../SemaCXX/warn-mismatched-delete-incremental.cpp | 12 ++++++++++++
2 files changed, 16 insertions(+), 3 deletions(-)
create mode 100644 clang/test/SemaCXX/warn-mismatched-delete-incremental.cpp
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index ef45d5842c795..6f539a8fbd7b5 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -686,12 +686,12 @@ void Sema::PrintStats() const {
void Sema::diagnoseNullableToNonnullConversion(QualType DstType,
QualType SrcType,
SourceLocation Loc) {
- std::optional<NullabilityKind> ExprNullability = SrcType->getNullability();
+ NullabilityKindOrNone ExprNullability = SrcType->getNullability();
if (!ExprNullability || (*ExprNullability != NullabilityKind::Nullable &&
*ExprNullability != NullabilityKind::NullableResult))
return;
- std::optional<NullabilityKind> TypeNullability = DstType->getNullability();
+ NullabilityKindOrNone TypeNullability = DstType->getNullability();
if (!TypeNullability || *TypeNullability != NullabilityKind::NonNull)
return;
@@ -1670,7 +1670,7 @@ void Sema::ActOnEndOfTranslationUnit() {
}
if (!Diags.isIgnored(diag::warn_mismatched_delete_new, SourceLocation())) {
- if (ExternalSource)
+ if (ExternalSource && !PP.isIncrementalProcessingEnabled())
ExternalSource->ReadMismatchingDeleteExpressions(DeleteExprs);
for (const auto &DeletedFieldInfo : DeleteExprs) {
for (const auto &DeleteExprLoc : DeletedFieldInfo.second) {
@@ -1678,6 +1678,7 @@ void Sema::ActOnEndOfTranslationUnit() {
DeleteExprLoc.second);
}
}
+ DeleteExprs.clear();
}
AnalysisWarnings.IssueWarnings(Context.getTranslationUnitDecl());
diff --git a/clang/test/SemaCXX/warn-mismatched-delete-incremental.cpp b/clang/test/SemaCXX/warn-mismatched-delete-incremental.cpp
new file mode 100644
index 0000000000000..aba924bae59a1
--- /dev/null
+++ b/clang/test/SemaCXX/warn-mismatched-delete-incremental.cpp
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -fincremental-extensions -verify %s
+// Regression test for incremental-mode handling of warn_mismatched_delete_new
+// in Sema::ActOnEndOfTranslationUnit(). Ensures the diagnostic fires correctly
+// in incremental mode and that DeleteExprs does not accumulate stale entries
+// across EndOfTU cycles.
+
+struct S {
+ int *p;
+ S() : p(new int[10]) {}
+ ~S() { delete p; } // expected-warning {{'delete' applied to a pointer that was allocated with 'new[]'; did you mean 'delete[]'?}}
+ // expected-note at -2 {{allocated with 'new[]' here}}
+};
\ No newline at end of file
>From bc061613d0653e9cc18292c3d24737e2c0b84607 Mon Sep 17 00:00:00 2001
From: lucasvallejoo <lucas.valfac at gmail.com>
Date: Sun, 19 Apr 2026 18:46:14 +0200
Subject: [PATCH 2/2] [Sema] Skip ExternalSource query and clear DeleteExprs in
incremental mode In incremental compilation (e.g. ROOT/Cling REPL),
ActOnEndOfTranslationUnit() is called once per user input line rather than
once at program end. This caused two performance issues:
1. ReadMismatchingDeleteExpressions() queried the ExternalSource (PCH/modules)
on every cycle, causing redundant disk I/O that severely degraded performance
in long REPL sessions.
2. DeleteExprs accumulated entries across cycles without being cleared, leading
to unbounded memory growth and O(N^2) redundant AST traversals.
This patch guards the ExternalSource query by checking that incremental processing
is NOT enabled, and adds DeleteExprs.clear() after each analysis pass, following
the same pattern used elsewhere in ActOnEndOfTranslationUnit() for REPL mode.
A regression test is included to verify that warn_mismatched_delete_new
continues to fire correctly in incremental mode after this change.
Patch by Axel Naumann.
Note: This upstreaming effort is part of the preparation for the compiler fellowship program.
---
clang/lib/Sema/Sema.cpp | 4 ++--
clang/test/SemaCXX/warn-mismatched-delete-incremental.cpp | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index 6f539a8fbd7b5..8eb7660330d99 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -686,12 +686,12 @@ void Sema::PrintStats() const {
void Sema::diagnoseNullableToNonnullConversion(QualType DstType,
QualType SrcType,
SourceLocation Loc) {
- NullabilityKindOrNone ExprNullability = SrcType->getNullability();
+ std::optional<NullabilityKind> ExprNullability = SrcType->getNullability();
if (!ExprNullability || (*ExprNullability != NullabilityKind::Nullable &&
*ExprNullability != NullabilityKind::NullableResult))
return;
- NullabilityKindOrNone TypeNullability = DstType->getNullability();
+ std::optional<NullabilityKind> TypeNullability = DstType->getNullability();
if (!TypeNullability || *TypeNullability != NullabilityKind::NonNull)
return;
diff --git a/clang/test/SemaCXX/warn-mismatched-delete-incremental.cpp b/clang/test/SemaCXX/warn-mismatched-delete-incremental.cpp
index aba924bae59a1..fb8ee23c79025 100644
--- a/clang/test/SemaCXX/warn-mismatched-delete-incremental.cpp
+++ b/clang/test/SemaCXX/warn-mismatched-delete-incremental.cpp
@@ -1,5 +1,5 @@
// RUN: %clang_cc1 -fincremental-extensions -verify %s
-// Regression test for incremental-mode handling of warn_mismatched_delete_new
+// Regression test for warn_mismatched_delete_new in incremental mode
// in Sema::ActOnEndOfTranslationUnit(). Ensures the diagnostic fires correctly
// in incremental mode and that DeleteExprs does not accumulate stale entries
// across EndOfTU cycles.
More information about the cfe-commits
mailing list