diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index bd3d1b4e10a4..470732ce684c 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -6074,6 +6074,8 @@ def warn_direct_ivar_access : Warning<"instance variable %0 is being " "directly accessed">, InGroup>, DefaultIgnore; // Spell-checking diagnostics +def warn_spellcheck_initiated : Warning<"spell-checking initiated for %0">, + InGroup>, DefaultIgnore; def err_unknown_type_or_class_name_suggest : Error< "unknown %select{type|class}2 name %0; did you mean %1?">; def err_unknown_typename_suggest : Error< diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 5f4bb1d84050..0f519398b75f 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -7430,6 +7430,8 @@ private: /// The parser maintains this state here. Scope *CurScope; + mutable IdentifierInfo *Ident_super; + protected: friend class Parser; friend class InitializationSequence; @@ -7447,6 +7449,8 @@ public: /// template substitution or instantiation. Scope *getCurScope() const { return CurScope; } + IdentifierInfo *getSuperIdentifier() const; + Decl *getObjCDeclContext() const; DeclContext *getCurLexicalContext() const { diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index 0ddd0619f927..4aeb511abd6a 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -90,7 +90,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, AccessCheckingSFINAE(false), InNonInstantiationSFINAEContext(false), NonInstantiationEntries(0), ArgumentPackSubstitutionIndex(-1), CurrentInstantiationScope(0), TyposCorrected(0), - AnalysisWarnings(*this) + AnalysisWarnings(*this), Ident_super(0) { TUScope = 0; @@ -1302,3 +1302,9 @@ bool Sema::tryToRecoverWithCall(ExprResult &E, const PartialDiagnostic &PD, E = ExprError(); return true; } + +IdentifierInfo *Sema::getSuperIdentifier() const { + if (!Ident_super) + Ident_super = &Context.Idents.get("super"); + return Ident_super; +} diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp index 78d8518b234c..6bb954315ab3 100644 --- a/clang/lib/Sema/SemaCodeComplete.cpp +++ b/clang/lib/Sema/SemaCodeComplete.cpp @@ -5315,7 +5315,7 @@ void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc, } else { // "super" may be the name of a type or variable. Figure out which // it is. - IdentifierInfo *Super = &Context.Idents.get("super"); + IdentifierInfo *Super = getSuperIdentifier(); NamedDecl *ND = LookupSingleName(S, Super, SuperLoc, LookupOrdinaryName); if ((CDecl = dyn_cast_or_null(ND))) { diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index eae6269ca69c..86ddad21f5d9 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -3734,6 +3734,16 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName, if (!ActiveTemplateInstantiations.empty()) return TypoCorrection(); + // Don't try to correct 'super'. + if (S && S->isInObjcMethodScope() && Typo == getSuperIdentifier()) + return TypoCorrection(); + + // This is for regression testing. It's disabled by default. + if (Diags.getDiagnosticLevel(diag::warn_spellcheck_initiated, + TypoName.getLoc()) != DiagnosticsEngine::Ignored) + Diag(TypoName.getLoc(), diag::warn_spellcheck_initiated) + << TypoName.getName(); + NamespaceSpecifierSet Namespaces(Context, CurContext, SS); TypoCorrectionConsumer Consumer(*this, Typo); diff --git a/clang/test/SemaObjC/typo-correction.m b/clang/test/SemaObjC/typo-correction.m new file mode 100644 index 000000000000..cb2c91bb76cb --- /dev/null +++ b/clang/test/SemaObjC/typo-correction.m @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 %s -verify -fsyntax-only -Wspellcheck + +@interface B +@property int x; +@end + +@interface S : B +@end + +// Spell-checking 'undefined' is ok. +undefined var; // expected-warning {{spell-checking initiated}} \ + // expected-error {{unknown type name}} + +typedef int super1; +@implementation S +-(void)foo { + // Spell-checking 'super' is not ok. + super.x = 0; + self.x = 0; +} +@end