From 9a632eaa0ee73e4db701a8df74e92909d1fa350e Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Wed, 20 Oct 2010 03:06:34 +0000 Subject: [PATCH] Fix handling of property and ivar lookup in typo correction; the two kinds of lookup into Objective-C classes were tangled together, a situation that was compounded by automatically synthesized ivars. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@116907 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Sema/Sema.h | 4 + lib/Sema/SemaExpr.cpp | 4 +- lib/Sema/SemaLookup.cpp | 122 +++++++++++++----------- test/FixIt/typo.cpp | 4 +- test/FixIt/typo.m | 3 - test/SemaObjC/super.m | 2 +- test/SemaObjC/synth-provisional-ivars.m | 2 +- 7 files changed, 75 insertions(+), 66 deletions(-) diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 5e6497fe1b..108353f53b 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -1310,6 +1310,10 @@ public: CTC_CXXCasts, /// \brief A member lookup context. CTC_MemberLookup, + /// \brief An Objective-C ivar lookup context (e.g., self->ivar). + CTC_ObjCIvarLookup, + /// \brief An Objective-C property lookup context (e.g., self.prop). + CTC_ObjCPropertyLookup, /// \brief The receiver of an Objective-C message send within an /// Objective-C method where 'super' is a valid keyword. CTC_ObjCMessageReceiver diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 50f023abc8..587a76ed08 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -3231,7 +3231,9 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr, // Attempt to correct for typos in ivar names. LookupResult Res(*this, R.getLookupName(), R.getNameLoc(), LookupMemberName); - if (CorrectTypo(Res, 0, 0, IDecl, false, CTC_MemberLookup) && + if (CorrectTypo(Res, 0, 0, IDecl, false, + IsArrow? CTC_ObjCIvarLookup + : CTC_ObjCPropertyLookup) && (IV = Res.getAsSingle())) { Diag(R.getNameLoc(), diag::err_typecheck_member_reference_ivar_suggest) diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index 1294f4f013..29df503910 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -2785,6 +2785,57 @@ void TypoCorrectionConsumer::addKeywordResult(ASTContext &Context, BestResults[Keyword] = true; } +/// \brief Perform name lookup for a possible result for typo correction. +static void LookupPotentialTypoResult(Sema &SemaRef, + LookupResult &Res, + IdentifierInfo *Name, + Scope *S, CXXScopeSpec *SS, + DeclContext *MemberContext, + bool EnteringContext, + Sema::CorrectTypoContext CTC) { + Res.suppressDiagnostics(); + Res.clear(); + Res.setLookupName(Name); + if (MemberContext) { + if (ObjCInterfaceDecl *Class = dyn_cast(MemberContext)) { + if (CTC == Sema::CTC_ObjCIvarLookup) { + if (ObjCIvarDecl *Ivar = Class->lookupInstanceVariable(Name)) { + Res.addDecl(Ivar); + Res.resolveKind(); + return; + } + } + + if (ObjCPropertyDecl *Prop = Class->FindPropertyDeclaration(Name)) { + Res.addDecl(Prop); + Res.resolveKind(); + return; + } + } + + SemaRef.LookupQualifiedName(Res, MemberContext); + return; + } + + SemaRef.LookupParsedName(Res, S, SS, /*AllowBuiltinCreation=*/false, + EnteringContext); + + // Fake ivar lookup; this should really be part of + // LookupParsedName. + if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) { + if (Method->isInstanceMethod() && Method->getClassInterface() && + (Res.empty() || + (Res.isSingleResult() && + Res.getFoundDecl()->isDefinedOutsideFunctionOrMethod()))) { + if (ObjCIvarDecl *IV + = Method->getClassInterface()->lookupInstanceVariable(Name)) { + Res.addDecl(IV); + Res.resolveKind(); + } + } + } +} + /// \brief Try to "correct" a typo in the source code by finding /// visible declarations whose names are similar to the name that was /// present in the source code. @@ -2946,10 +2997,17 @@ DeclarationName Sema::CorrectTypo(LookupResult &Res, Scope *S, CXXScopeSpec *SS, WantCXXNamedCasts = true; break; + case CTC_ObjCPropertyLookup: + // FIXME: Add "isa"? + break; + case CTC_MemberLookup: if (getLangOptions().CPlusPlus) Consumer.addKeywordResult(Context, "template"); break; + + case CTC_ObjCIvarLookup: + break; } if (WantTypeSpecifiers) { @@ -3104,33 +3162,8 @@ DeclarationName Sema::CorrectTypo(LookupResult &Res, Scope *S, CXXScopeSpec *SS, // Perform name lookup on this name. IdentifierInfo *Name = &Context.Idents.get(I->getKey()); - Res.suppressDiagnostics(); - Res.clear(); - Res.setLookupName(Name); - if (MemberContext) - LookupQualifiedName(Res, MemberContext); - else { - LookupParsedName(Res, S, SS, /*AllowBuiltinCreation=*/false, - EnteringContext); - - // Fake ivar lookup; this should really be part of - // LookupParsedName. - if (ObjCMethodDecl *Method = getCurMethodDecl()) { - if (Method->isInstanceMethod() && Method->getClassInterface() && - (Res.empty() || - (Res.isSingleResult() && - Res.getFoundDecl()->isDefinedOutsideFunctionOrMethod()))) { - ObjCInterfaceDecl *ClassDeclared = 0; - if (ObjCIvarDecl *IV - = Method->getClassInterface()->lookupInstanceVariable(Name, - ClassDeclared)) { - Res.clear(); - Res.addDecl(IV); - Res.resolveKind(); - } - } - } - } + LookupPotentialTypoResult(*this, Res, Name, S, SS, MemberContext, + EnteringContext, CTC); switch (Res.getResultKind()) { case LookupResult::NotFound: @@ -3152,7 +3185,7 @@ DeclarationName Sema::CorrectTypo(LookupResult &Res, Scope *S, CXXScopeSpec *SS, case LookupResult::FoundOverloaded: case LookupResult::FoundUnresolvedValue: ++I; - LastLookupWasAccepted = false; + LastLookupWasAccepted = true; break; } @@ -3172,39 +3205,14 @@ DeclarationName Sema::CorrectTypo(LookupResult &Res, Scope *S, CXXScopeSpec *SS, Res.clear(); } else if (!LastLookupWasAccepted) { // Perform name lookup on this name. - Res.suppressDiagnostics(); - Res.clear(); - Res.setLookupName(Name); - if (MemberContext) - LookupQualifiedName(Res, MemberContext); - else { - LookupParsedName(Res, S, SS, /*AllowBuiltinCreation=*/false, - EnteringContext); - - // Fake ivar lookup; this should really be part of - // LookupParsedName. - if (ObjCMethodDecl *Method = getCurMethodDecl()) { - if (Method->isInstanceMethod() && Method->getClassInterface() && - (Res.empty() || - (Res.isSingleResult() && - Res.getFoundDecl()->isDefinedOutsideFunctionOrMethod()))) { - ObjCInterfaceDecl *ClassDeclared = 0; - if (ObjCIvarDecl *IV - = Method->getClassInterface()->lookupInstanceVariable(Name, - ClassDeclared)) { - Res.clear(); - Res.addDecl(IV); - Res.resolveKind(); - } - } - } - } + LookupPotentialTypoResult(*this, Res, Name, S, SS, MemberContext, + EnteringContext, CTC); } // Record the correction for unqualified lookup. if (IsUnqualifiedLookup) UnqualifiedTyposCorrected[Typo] - = std::make_pair(Consumer.begin()->getKey(), Consumer.begin()->second); + = std::make_pair(Name->getName(), Consumer.begin()->second); return &Context.Idents.get(Consumer.begin()->getKey()); } @@ -3218,7 +3226,7 @@ DeclarationName Sema::CorrectTypo(LookupResult &Res, Scope *S, CXXScopeSpec *SS, // Record the correction for unqualified lookup. if (IsUnqualifiedLookup) UnqualifiedTyposCorrected[Typo] - = std::make_pair(Consumer.begin()->getKey(), Consumer.begin()->second); + = std::make_pair("super", Consumer.begin()->second); return &Context.Idents.get("super"); } diff --git a/test/FixIt/typo.cpp b/test/FixIt/typo.cpp index 35666efe47..d1e732fd1d 100644 --- a/test/FixIt/typo.cpp +++ b/test/FixIt/typo.cpp @@ -2,9 +2,7 @@ // RUN: cp %s %t // RUN: %clang_cc1 -fsyntax-only -fixit -x c++ %t || true // RUN: %clang_cc1 -fsyntax-only -pedantic -Werror -x c++ %t -// -// FIXME: Disabled while we investigate failure. -// REQUIRES: disabled + namespace std { template class basic_string { // expected-note 2{{'basic_string' declared here}} public: diff --git a/test/FixIt/typo.m b/test/FixIt/typo.m index 0be21a0fe2..b8c57e46e3 100644 --- a/test/FixIt/typo.m +++ b/test/FixIt/typo.m @@ -2,9 +2,6 @@ // RUN: %clang_cc1 -triple x86_64-apple-darwin10 -x objective-c -E -P %s -o %t // RUN: %clang_cc1 -x objective-c -fsyntax-only -triple x86_64-apple-darwin10 -fobjc-nonfragile-abi -fixit %t || true // RUN: %clang_cc1 -x objective-c -fsyntax-only -triple x86_64-apple-darwin10 -fobjc-nonfragile-abi -pedantic -Werror %t -// -// FIXME: Disabled while we investigate failure. -// REQUIRES: disabled @interface NSString // expected-note{{'NSString' declared here}} + (int)method:(int)x; diff --git a/test/SemaObjC/super.m b/test/SemaObjC/super.m index c15df26f34..0c42e99d71 100644 --- a/test/SemaObjC/super.m +++ b/test/SemaObjC/super.m @@ -54,7 +54,7 @@ void f0(int super) { [super m]; // expected-warning{{receiver type 'int' is not 'id'}} \ expected-warning {{method '-m' not found (return type defaults to 'id')}} } -void f1(id puper) { +void f1(id puper) { // expected-note {{'puper' declared here}} [super m]; // expected-error{{use of undeclared identifier 'super'}} } diff --git a/test/SemaObjC/synth-provisional-ivars.m b/test/SemaObjC/synth-provisional-ivars.m index 10fdbdccb2..1fb1abb7ce 100644 --- a/test/SemaObjC/synth-provisional-ivars.m +++ b/test/SemaObjC/synth-provisional-ivars.m @@ -18,7 +18,7 @@ int bar; @end @implementation I -- (int) Meth { return PROP; } // expected-note{{'PROP' declared here}} +- (int) Meth { return PROP; } // expected-note 2{{'PROP' declared here}} @dynamic PROP1; - (int) Meth1 { return PROP1; } // expected-error {{use of undeclared identifier 'PROP1'}} -- 2.40.0