Skip to content

Commit 9eef4d1

Browse files
authored
Remove delayed typo expressions (#143423)
This removes the delayed typo correction functionality from Clang (regular typo correction still remains) due to fragility of the solution. An RFC was posted here: https://discourse.llvm.org/t/rfc-removing-support-for-delayed-typo-correction/86631 and while that RFC was asking for folks to consider stepping up to be maintainers, and we did have a few new contributors show some interest, experiments show that it's likely worth it to remove this functionality entirely and focus efforts on improving regular typo correction. This removal fixes ~20 open issues (quite possibly more), improves compile time performance by roughly .3-.4% (https://llvm-compile-time-tracker.com/?config=Overview&stat=instructions%3Au&remote=AaronBallman&sortBy=date), and does not appear to regress diagnostic behavior in a way we wouldn't find acceptable. Fixes #142457 Fixes #139913 Fixes #138850 Fixes #137867 Fixes #137860 Fixes #107840 Fixes #93308 Fixes #69470 Fixes #59391 Fixes #58172 Fixes #46215 Fixes #45915 Fixes #45891 Fixes #44490 Fixes #36703 Fixes #32903 Fixes #23312 Fixes #69874
1 parent 541e511 commit 9eef4d1

File tree

116 files changed

+438
-2147
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

116 files changed

+438
-2147
lines changed

clang-tools-extra/clangd/unittests/HoverTests.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -974,7 +974,7 @@ class Foo final {})cpp";
974974
HI.Name = "abc";
975975
HI.Kind = index::SymbolKind::Variable;
976976
HI.NamespaceScope = "";
977-
HI.Definition = "int abc = <recovery - expr>()";
977+
HI.Definition = "int abc";
978978
HI.Type = "int";
979979
HI.AccessSpecifier = "public";
980980
}},

clang/docs/ReleaseNotes.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -622,6 +622,14 @@ Improvements to Clang's diagnostics
622622

623623
- Improved the FixIts for unused lambda captures.
624624

625+
- Delayed typo correction was removed from the compiler; immediate typo
626+
correction behavior remains the same. Delayed typo correction facilities were
627+
fragile and unmaintained, and the removal closed the following issues:
628+
#GH142457, #GH139913, #GH138850, #GH137867, #GH137860, #GH107840, #GH93308,
629+
#GH69470, #GH59391, #GH58172, #GH46215, #GH45915, #GH45891, #GH44490,
630+
#GH36703, #GH32903, #GH23312, #GH69874.
631+
632+
625633
Improvements to Clang's time-trace
626634
----------------------------------
627635

clang/include/clang/AST/Expr.h

Lines changed: 1 addition & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -240,8 +240,7 @@ class Expr : public ValueStmt {
240240
return static_cast<bool>(getDependence() & ExprDependence::UnexpandedPack);
241241
}
242242

243-
/// Whether this expression contains subexpressions which had errors, e.g. a
244-
/// TypoExpr.
243+
/// Whether this expression contains subexpressions which had errors.
245244
bool containsErrors() const {
246245
return static_cast<bool>(getDependence() & ExprDependence::Error);
247246
}
@@ -6965,36 +6964,6 @@ class AtomicExpr : public Expr {
69656964
}
69666965
};
69676966

6968-
/// TypoExpr - Internal placeholder for expressions where typo correction
6969-
/// still needs to be performed and/or an error diagnostic emitted.
6970-
class TypoExpr : public Expr {
6971-
// The location for the typo name.
6972-
SourceLocation TypoLoc;
6973-
6974-
public:
6975-
TypoExpr(QualType T, SourceLocation TypoLoc)
6976-
: Expr(TypoExprClass, T, VK_LValue, OK_Ordinary), TypoLoc(TypoLoc) {
6977-
assert(T->isDependentType() && "TypoExpr given a non-dependent type");
6978-
setDependence(ExprDependence::TypeValueInstantiation |
6979-
ExprDependence::Error);
6980-
}
6981-
6982-
child_range children() {
6983-
return child_range(child_iterator(), child_iterator());
6984-
}
6985-
const_child_range children() const {
6986-
return const_child_range(const_child_iterator(), const_child_iterator());
6987-
}
6988-
6989-
SourceLocation getBeginLoc() const LLVM_READONLY { return TypoLoc; }
6990-
SourceLocation getEndLoc() const LLVM_READONLY { return TypoLoc; }
6991-
6992-
static bool classof(const Stmt *T) {
6993-
return T->getStmtClass() == TypoExprClass;
6994-
}
6995-
6996-
};
6997-
69986967
/// This class represents BOTH the OpenMP Array Section and OpenACC 'subarray',
69996968
/// with a boolean differentiator.
70006969
/// OpenMP 5.0 [2.1.5, Array Sections].

clang/include/clang/AST/RecursiveASTVisitor.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2956,7 +2956,6 @@ DEF_TRAVERSE_STMT(CXXRewrittenBinaryOperator, {
29562956
}
29572957
})
29582958
DEF_TRAVERSE_STMT(OpaqueValueExpr, {})
2959-
DEF_TRAVERSE_STMT(TypoExpr, {})
29602959
DEF_TRAVERSE_STMT(RecoveryExpr, {})
29612960
DEF_TRAVERSE_STMT(CUDAKernelCallExpr, {})
29622961

clang/include/clang/Basic/StmtNodes.td

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,6 @@ def ShuffleVectorExpr : StmtNode<Expr>;
202202
def ConvertVectorExpr : StmtNode<Expr>;
203203
def BlockExpr : StmtNode<Expr>;
204204
def OpaqueValueExpr : StmtNode<Expr>;
205-
def TypoExpr : StmtNode<Expr>;
206205
def RecoveryExpr : StmtNode<Expr>;
207206
def BuiltinBitCastExpr : StmtNode<ExplicitCastExpr>;
208207
def EmbedExpr : StmtNode<Expr>;

clang/include/clang/Parse/Parser.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4169,8 +4169,7 @@ class Parser : public CodeCompletionHandler {
41694169
bool ParseExpressionList(SmallVectorImpl<Expr *> &Exprs,
41704170
llvm::function_ref<void()> ExpressionStarts =
41714171
llvm::function_ref<void()>(),
4172-
bool FailImmediatelyOnInvalidExpr = false,
4173-
bool EarlyTypoCorrection = false);
4172+
bool FailImmediatelyOnInvalidExpr = false);
41744173

41754174
/// ParseSimpleExpressionList - A simple comma-separated list of expressions,
41764175
/// used for misc language extensions.

clang/include/clang/Sema/Sema.h

Lines changed: 5 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -6713,10 +6713,6 @@ class Sema final : public SemaBase {
67136713
/// this expression evaluation context.
67146714
unsigned NumCleanupObjects;
67156715

6716-
/// The number of typos encountered during this expression evaluation
6717-
/// context (i.e. the number of TypoExprs created).
6718-
unsigned NumTypos;
6719-
67206716
MaybeODRUseExprSet SavedMaybeODRUseExprs;
67216717

67226718
/// The lambdas that are present within this context, if it
@@ -6813,7 +6809,7 @@ class Sema final : public SemaBase {
68136809
Decl *ManglingContextDecl,
68146810
ExpressionKind ExprContext)
68156811
: Context(Context), ParentCleanup(ParentCleanup),
6816-
NumCleanupObjects(NumCleanupObjects), NumTypos(0),
6812+
NumCleanupObjects(NumCleanupObjects),
68176813
ManglingContextDecl(ManglingContextDecl), ExprContext(ExprContext),
68186814
InDiscardedStatement(false), InImmediateFunctionContext(false),
68196815
InImmediateEscalatingFunctionContext(false) {}
@@ -7146,8 +7142,7 @@ class Sema final : public SemaBase {
71467142
CorrectionCandidateCallback &CCC,
71477143
TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr,
71487144
ArrayRef<Expr *> Args = {},
7149-
DeclContext *LookupCtx = nullptr,
7150-
TypoExpr **Out = nullptr);
7145+
DeclContext *LookupCtx = nullptr);
71517146

71527147
/// If \p D cannot be odr-used in the current expression evaluation context,
71537148
/// return a reason explaining why. Otherwise, return NOUR_None.
@@ -8748,40 +8743,6 @@ class Sema final : public SemaBase {
87488743

87498744
ExprResult CheckUnevaluatedOperand(Expr *E);
87508745

8751-
/// Process any TypoExprs in the given Expr and its children,
8752-
/// generating diagnostics as appropriate and returning a new Expr if there
8753-
/// were typos that were all successfully corrected and ExprError if one or
8754-
/// more typos could not be corrected.
8755-
///
8756-
/// \param E The Expr to check for TypoExprs.
8757-
///
8758-
/// \param InitDecl A VarDecl to avoid because the Expr being corrected is its
8759-
/// initializer.
8760-
///
8761-
/// \param RecoverUncorrectedTypos If true, when typo correction fails, it
8762-
/// will rebuild the given Expr with all TypoExprs degraded to RecoveryExprs.
8763-
///
8764-
/// \param Filter A function applied to a newly rebuilt Expr to determine if
8765-
/// it is an acceptable/usable result from a single combination of typo
8766-
/// corrections. As long as the filter returns ExprError, different
8767-
/// combinations of corrections will be tried until all are exhausted.
8768-
ExprResult CorrectDelayedTyposInExpr(
8769-
Expr *E, VarDecl *InitDecl = nullptr,
8770-
bool RecoverUncorrectedTypos = false,
8771-
llvm::function_ref<ExprResult(Expr *)> Filter =
8772-
[](Expr *E) -> ExprResult { return E; });
8773-
8774-
ExprResult CorrectDelayedTyposInExpr(
8775-
ExprResult ER, VarDecl *InitDecl = nullptr,
8776-
bool RecoverUncorrectedTypos = false,
8777-
llvm::function_ref<ExprResult(Expr *)> Filter =
8778-
[](Expr *E) -> ExprResult { return E; }) {
8779-
return ER.isInvalid()
8780-
? ER
8781-
: CorrectDelayedTyposInExpr(ER.get(), InitDecl,
8782-
RecoverUncorrectedTypos, Filter);
8783-
}
8784-
87858746
IfExistsResult
87868747
CheckMicrosoftIfExistsSymbol(Scope *S, CXXScopeSpec &SS,
87878748
const DeclarationNameInfo &TargetNameInfo);
@@ -9283,12 +9244,6 @@ class Sema final : public SemaBase {
92839244
/// for C++ records.
92849245
llvm::FoldingSet<SpecialMemberOverloadResultEntry> SpecialMemberCache;
92859246

9286-
/// Holds TypoExprs that are created from `createDelayedTypo`. This is used by
9287-
/// `TransformTypos` in order to keep track of any TypoExprs that are created
9288-
/// recursively during typo correction and wipe them away if the correction
9289-
/// fails.
9290-
llvm::SmallVector<TypoExpr *, 2> TypoExprs;
9291-
92929247
enum class AcceptableKind { Visible, Reachable };
92939248

92949249
// Members have to be NamespaceDecl* or TranslationUnitDecl*.
@@ -9376,10 +9331,6 @@ class Sema final : public SemaBase {
93769331
bool VolatileArg, bool RValueThis, bool ConstThis,
93779332
bool VolatileThis);
93789333

9379-
typedef std::function<void(const TypoCorrection &)> TypoDiagnosticGenerator;
9380-
typedef std::function<ExprResult(Sema &, TypoExpr *, TypoCorrection)>
9381-
TypoRecoveryCallback;
9382-
93839334
RedeclarationKind forRedeclarationInCurContext() const;
93849335

93859336
/// Look up a name, looking for a single declaration. Return
@@ -9733,51 +9684,6 @@ class Sema final : public SemaBase {
97339684
const ObjCObjectPointerType *OPT = nullptr,
97349685
bool RecordFailure = true);
97359686

9736-
/// Try to "correct" a typo in the source code by finding
9737-
/// visible declarations whose names are similar to the name that was
9738-
/// present in the source code.
9739-
///
9740-
/// \param TypoName the \c DeclarationNameInfo structure that contains
9741-
/// the name that was present in the source code along with its location.
9742-
///
9743-
/// \param LookupKind the name-lookup criteria used to search for the name.
9744-
///
9745-
/// \param S the scope in which name lookup occurs.
9746-
///
9747-
/// \param SS the nested-name-specifier that precedes the name we're
9748-
/// looking for, if present.
9749-
///
9750-
/// \param CCC A CorrectionCandidateCallback object that provides further
9751-
/// validation of typo correction candidates. It also provides flags for
9752-
/// determining the set of keywords permitted.
9753-
///
9754-
/// \param TDG A TypoDiagnosticGenerator functor that will be used to print
9755-
/// diagnostics when the actual typo correction is attempted.
9756-
///
9757-
/// \param TRC A TypoRecoveryCallback functor that will be used to build an
9758-
/// Expr from a typo correction candidate.
9759-
///
9760-
/// \param MemberContext if non-NULL, the context in which to look for
9761-
/// a member access expression.
9762-
///
9763-
/// \param EnteringContext whether we're entering the context described by
9764-
/// the nested-name-specifier SS.
9765-
///
9766-
/// \param OPT when non-NULL, the search for visible declarations will
9767-
/// also walk the protocols in the qualified interfaces of \p OPT.
9768-
///
9769-
/// \returns a new \c TypoExpr that will later be replaced in the AST with an
9770-
/// Expr representing the result of performing typo correction, or nullptr if
9771-
/// typo correction is not possible. If nullptr is returned, no diagnostics
9772-
/// will be emitted and it is the responsibility of the caller to emit any
9773-
/// that are needed.
9774-
TypoExpr *CorrectTypoDelayed(
9775-
const DeclarationNameInfo &Typo, Sema::LookupNameKind LookupKind,
9776-
Scope *S, CXXScopeSpec *SS, CorrectionCandidateCallback &CCC,
9777-
TypoDiagnosticGenerator TDG, TypoRecoveryCallback TRC,
9778-
CorrectTypoKind Mode, DeclContext *MemberContext = nullptr,
9779-
bool EnteringContext = false, const ObjCObjectPointerType *OPT = nullptr);
9780-
97819687
/// Kinds of missing import. Note, the values of these enumerators correspond
97829688
/// to %select values in diagnostics.
97839689
enum class MissingImportKind {
@@ -9796,20 +9702,6 @@ class Sema final : public SemaBase {
97969702
SourceLocation DeclLoc, ArrayRef<Module *> Modules,
97979703
MissingImportKind MIK, bool Recover);
97989704

9799-
struct TypoExprState {
9800-
std::unique_ptr<TypoCorrectionConsumer> Consumer;
9801-
TypoDiagnosticGenerator DiagHandler;
9802-
TypoRecoveryCallback RecoveryHandler;
9803-
TypoExprState();
9804-
TypoExprState(TypoExprState &&other) noexcept;
9805-
TypoExprState &operator=(TypoExprState &&other) noexcept;
9806-
};
9807-
9808-
const TypoExprState &getTypoExprState(TypoExpr *TE) const;
9809-
9810-
/// Clears the state of the given TypoExpr.
9811-
void clearDelayedTypo(TypoExpr *TE);
9812-
98139705
/// Called on #pragma clang __debug dump II
98149706
void ActOnPragmaDump(Scope *S, SourceLocation Loc, IdentifierInfo *II);
98159707

@@ -9832,23 +9724,15 @@ class Sema final : public SemaBase {
98329724
/// Determine if we could use all the declarations in the module.
98339725
bool isUsableModule(const Module *M);
98349726

9835-
/// Helper for CorrectTypo and CorrectTypoDelayed used to create and
9836-
/// populate a new TypoCorrectionConsumer. Returns nullptr if typo correction
9837-
/// should be skipped entirely.
9727+
/// Helper for CorrectTypo used to create and populate a new
9728+
/// TypoCorrectionConsumer. Returns nullptr if typo correction should be
9729+
/// skipped entirely.
98389730
std::unique_ptr<TypoCorrectionConsumer> makeTypoCorrectionConsumer(
98399731
const DeclarationNameInfo &Typo, Sema::LookupNameKind LookupKind,
98409732
Scope *S, CXXScopeSpec *SS, CorrectionCandidateCallback &CCC,
98419733
DeclContext *MemberContext, bool EnteringContext,
98429734
const ObjCObjectPointerType *OPT, bool ErrorRecovery);
98439735

9844-
/// The set of unhandled TypoExprs and their associated state.
9845-
llvm::MapVector<TypoExpr *, TypoExprState> DelayedTypos;
9846-
9847-
/// Creates a new TypoExpr AST node.
9848-
TypoExpr *createDelayedTypo(std::unique_ptr<TypoCorrectionConsumer> TCC,
9849-
TypoDiagnosticGenerator TDG,
9850-
TypoRecoveryCallback TRC, SourceLocation TypoLoc);
9851-
98529736
/// Cache for module units which is usable for current module.
98539737
llvm::DenseSet<const Module *> UsableModuleUnitsCache;
98549738

clang/include/clang/Sema/SemaInternal.h

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -314,20 +314,6 @@ class TypoCorrectionConsumer : public VisibleDeclConsumer {
314314
bool SearchNamespaces;
315315
};
316316

317-
inline Sema::TypoExprState::TypoExprState() {}
318-
319-
inline Sema::TypoExprState::TypoExprState(TypoExprState &&other) noexcept {
320-
*this = std::move(other);
321-
}
322-
323-
inline Sema::TypoExprState &Sema::TypoExprState::
324-
operator=(Sema::TypoExprState &&other) noexcept {
325-
Consumer = std::move(other.Consumer);
326-
DiagHandler = std::move(other.DiagHandler);
327-
RecoveryHandler = std::move(other.RecoveryHandler);
328-
return *this;
329-
}
330-
331317
} // end namespace clang
332318

333319
#endif

clang/lib/AST/Expr.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3611,7 +3611,6 @@ bool Expr::HasSideEffects(const ASTContext &Ctx,
36113611
case PackExpansionExprClass:
36123612
case SubstNonTypeTemplateParmPackExprClass:
36133613
case FunctionParmPackExprClass:
3614-
case TypoExprClass:
36153614
case RecoveryExprClass:
36163615
case CXXFoldExprClass:
36173616
// Make a conservative assumption for dependent nodes.

clang/lib/AST/ExprClassification.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,6 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
129129
// FIXME: Is this wise? Should they get their own kind?
130130
case Expr::UnresolvedLookupExprClass:
131131
case Expr::UnresolvedMemberExprClass:
132-
case Expr::TypoExprClass:
133132
case Expr::DependentCoawaitExprClass:
134133
case Expr::CXXDependentScopeMemberExprClass:
135134
case Expr::DependentScopeDeclRefExprClass:

clang/lib/AST/ExprConstant.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17327,7 +17327,6 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) {
1732717327
case Expr::CXXDeleteExprClass:
1732817328
case Expr::CXXPseudoDestructorExprClass:
1732917329
case Expr::UnresolvedLookupExprClass:
17330-
case Expr::TypoExprClass:
1733117330
case Expr::RecoveryExprClass:
1733217331
case Expr::DependentScopeDeclRefExprClass:
1733317332
case Expr::CXXConstructExprClass:

clang/lib/AST/ItaniumMangle.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4994,7 +4994,6 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity,
49944994
case Expr::ParenListExprClass:
49954995
case Expr::MSPropertyRefExprClass:
49964996
case Expr::MSPropertySubscriptExprClass:
4997-
case Expr::TypoExprClass: // This should no longer exist in the AST by now.
49984997
case Expr::RecoveryExprClass:
49994998
case Expr::ArraySectionExprClass:
50004999
case Expr::OMPArrayShapingExprClass:

clang/lib/AST/StmtPrinter.cpp

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2914,11 +2914,6 @@ void StmtPrinter::VisitOpaqueValueExpr(OpaqueValueExpr *Node) {
29142914
PrintExpr(Node->getSourceExpr());
29152915
}
29162916

2917-
void StmtPrinter::VisitTypoExpr(TypoExpr *Node) {
2918-
// TODO: Print something reasonable for a TypoExpr, if necessary.
2919-
llvm_unreachable("Cannot print TypoExpr nodes");
2920-
}
2921-
29222917
void StmtPrinter::VisitRecoveryExpr(RecoveryExpr *Node) {
29232918
OS << "<recovery-expr>(";
29242919
const char *Sep = "";

clang/lib/AST/StmtProfile.cpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2361,10 +2361,6 @@ void StmtProfiler::VisitOpaqueValueExpr(const OpaqueValueExpr *E) {
23612361
VisitExpr(E);
23622362
}
23632363

2364-
void StmtProfiler::VisitTypoExpr(const TypoExpr *E) {
2365-
VisitExpr(E);
2366-
}
2367-
23682364
void StmtProfiler::VisitSourceLocExpr(const SourceLocExpr *E) {
23692365
VisitExpr(E);
23702366
}

clang/lib/Parse/ParseCXXInlineMethods.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -422,7 +422,6 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) {
422422
DefArgResult = ParseBraceInitializer();
423423
} else
424424
DefArgResult = ParseAssignmentExpression();
425-
DefArgResult = Actions.CorrectDelayedTyposInExpr(DefArgResult, Param);
426425
if (DefArgResult.isInvalid()) {
427426
Actions.ActOnParamDefaultArgumentError(Param, EqualLoc,
428427
/*DefaultArg=*/nullptr);

0 commit comments

Comments
 (0)