diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 8e6cf62e11752..7735129ba10c9 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 { 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 55428af73011c..27e86827152f6 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -5420,6 +5420,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 +