Skip to content

Fix crash with delayed typo correction #140571

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

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

AaronBallman
Copy link
Collaborator

Delayed typo correction does not emit a diagnostic until the end of the
TU. However, codegen is run on each top-level declaration unless an
unrecoverable error occurred. The check for the diagnostic ensures that
CodeGen does not have to handle generating code for invalid constructs.

Due to typo correction delaying unrecoverable diagnostic emission until
the end of the TU, we would try to run CodeGen on invalid AST nodes and
that broke some invariants. Now, we specify that an unrecoverable error
will be emitted when emitting the delayed typo correction so that we
skip performing code generation.

Fixes #140461

Delayed typo correction does not emit a diagnostic until the end of the
TU. However, codegen is run on each top-level declaration unless an
unrecoverable error occurred. The check for the diagnostic ensures that
CodeGen does not have to handle generating code for invalid constructs.

Due to typo correction delaying unrecoverable diagnostic emission until
the end of the TU, we would try to run CodeGen on invalid AST nodes and
that broke some invariants. Now, we specify that an unrecoverable error
will be emitted when emitting the delayed typo correction so that we
skip performing code generation.

Fixes llvm#140461
@AaronBallman AaronBallman added clang Clang issues not falling into any other category c++ clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:codegen IR generation bugs: mangling, exceptions, etc. crash-on-invalid labels May 19, 2025
@llvmbot
Copy link
Member

llvmbot commented May 19, 2025

@llvm/pr-subscribers-clang-codegen

@llvm/pr-subscribers-clang

Author: Aaron Ballman (AaronBallman)

Changes

Delayed typo correction does not emit a diagnostic until the end of the
TU. However, codegen is run on each top-level declaration unless an
unrecoverable error occurred. The check for the diagnostic ensures that
CodeGen does not have to handle generating code for invalid constructs.

Due to typo correction delaying unrecoverable diagnostic emission until
the end of the TU, we would try to run CodeGen on invalid AST nodes and
that broke some invariants. Now, we specify that an unrecoverable error
will be emitted when emitting the delayed typo correction so that we
skip performing code generation.

Fixes #140461


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

4 Files Affected:

  • (modified) clang/docs/ReleaseNotes.rst (+3)
  • (modified) clang/include/clang/Basic/Diagnostic.h (+12)
  • (modified) clang/lib/Sema/SemaLookup.cpp (+7)
  • (added) clang/test/CodeGenCXX/typo-correction-delayed.cpp (+11)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 472b70b46fcc0..faa9c95211791 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -537,6 +537,9 @@ Improvements to Clang's diagnostics
   constant expression. Prior to this, the error inaccurately implied that assert
   could not be used at all in a constant expression (#GH130458)
 
+- No longer crashing during code generation due to delayed typo correction not
+  causing an unrecoverable error until the end of the translation unit. (#GH140461)
+
 - A new off-by-default warning ``-Wms-bitfield-padding`` has been added to alert to cases where bit-field
   packing may differ under the MS struct ABI (#GH117428).
 
diff --git a/clang/include/clang/Basic/Diagnostic.h b/clang/include/clang/Basic/Diagnostic.h
index 49ef22d4e4eb6..0e540fb2db346 100644
--- a/clang/include/clang/Basic/Diagnostic.h
+++ b/clang/include/clang/Basic/Diagnostic.h
@@ -861,6 +861,18 @@ class DiagnosticsEngine : public RefCountedBase<DiagnosticsEngine> {
 
   bool hasErrorOccurred() const { return ErrorOccurred; }
 
+  /// Sometimes we know an error will be produced at the end of a translation
+  /// unit, such as a delayed typo correction. However, CodeGen is run on each
+  /// top-level decl in an incremental fashion. We don't want CodeGen to run on
+  /// a declaration if an unrecoverable error occurred, but in those cases, the
+  /// error has not yet been emitted. This helper function lets you specify
+  /// that an unrecoverable error will occur later, specifically to ensure that
+  /// CodeGen is not run on those declarations.
+  void setUnrecoverableErrorWillOccur() {
+    UnrecoverableErrorOccurred = true;
+    ErrorOccurred = true;
+  }
+
   /// Errors that actually prevent compilation, not those that are
   /// upgraded from a warning by -Werror.
   bool hasUncompilableErrorOccurred() const {
diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index 29bf274f8a39f..f263feeda17a2 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -5419,6 +5419,13 @@ TypoExpr *Sema::CorrectTypoDelayed(
     TypoDiagnosticGenerator TDG, TypoRecoveryCallback TRC, CorrectTypoKind Mode,
     DeclContext *MemberContext, bool EnteringContext,
     const ObjCObjectPointerType *OPT) {
+
+  // A typo is an unrecoverable diagnostic. However, we sometimes perform code
+  // gen incrementally rather than waiting until the end of the TU, which means
+  // we want to tell the diagnostics engine that an unrecoverable error will
+  // occur eventually.
+  getDiagnostics().setUnrecoverableErrorWillOccur();
+
   auto Consumer = makeTypoCorrectionConsumer(
       TypoName, LookupKind, S, SS, CCC, MemberContext, EnteringContext, OPT,
       Mode == CorrectTypoKind::ErrorRecovery);
diff --git a/clang/test/CodeGenCXX/typo-correction-delayed.cpp b/clang/test/CodeGenCXX/typo-correction-delayed.cpp
new file mode 100644
index 0000000000000..3000e768fd163
--- /dev/null
+++ b/clang/test/CodeGenCXX/typo-correction-delayed.cpp
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -emit-llvm %s -verify -o /dev/null
+
+// Previously, delayed typo correction would cause a crash because codegen is
+// run on each top-level declaration as we finish with it unless an
+// unrecoverable error occured. However, with delayed typo correction, the
+// error is not emit until the end of the TU, so CodeGen would be run on
+// invalid declarations.
+namespace GH140461 {
+auto s{new auto(one)}; // expected-error {{use of undeclared identifier 'one'}}
+} // namespace GH140461
+

@AaronBallman
Copy link
Collaborator Author

Linux precommit CI failure looks to be unrelated. Given that this is an interaction between Sema and CodeGen, I'd like at least one approval from John or Eli before I land.

Copy link
Contributor

@cor3ntin cor3ntin left a comment

Choose a reason for hiding this comment

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

Did you check if that fixes any of the other delayed typo issues?

@AaronBallman
Copy link
Collaborator Author

Did you check if that fixes any of the other delayed typo issues?

I suspect it might, but I'm currently working on a PR to disable delayed typo correction entirely with intent to remove the feature. When I work on that patch, I plan to check all the delayed typo related diagnostics at that point to ensure they'll all be closed once the feature is removed. At which point, this PR may not be necessary. So I'm going to hold off on landing this PR for now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c++ clang:codegen IR generation bugs: mangling, exceptions, etc. clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category crash-on-invalid
Projects
None yet
4 participants