From: Kaelyn Uhrain Date: Fri, 13 Jan 2012 21:28:55 +0000 (+0000) Subject: Convert SemaExprMember.cpp to pass a callback object to CorrectTypo, X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e4c7f90da208ed2caeab784b32f416a50eed8da3;p=clang Convert SemaExprMember.cpp to pass a callback object to CorrectTypo, improving the typo correction results in certain situations. This is also the first typo correction callback conversion to affect an existing unit test. :) git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@148140 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaExprMember.cpp b/lib/Sema/SemaExprMember.cpp index 478b2dd436..0080156376 100644 --- a/lib/Sema/SemaExprMember.cpp +++ b/lib/Sema/SemaExprMember.cpp @@ -509,6 +509,20 @@ bool Sema::CheckQualifiedMemberReference(Expr *BaseExpr, return true; } +namespace { + +// Callback to only accept typo corrections that are either a ValueDecl or a +// FunctionTemplateDecl. +class RecordMemberExprValidatorCCC : public CorrectionCandidateCallback { + public: + virtual bool ValidateCandidate(const TypoCorrection &candidate) { + NamedDecl *ND = candidate.getCorrectionDecl(); + return ND && (isa(ND) || isa(ND)); + } +}; + +} + static bool LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R, SourceRange BaseRange, const RecordType *RTy, @@ -559,13 +573,12 @@ LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R, // We didn't find anything with the given name, so try to correct // for typos. DeclarationName Name = R.getLookupName(); + RecordMemberExprValidatorCCC Validator; TypoCorrection Corrected = SemaRef.CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(), NULL, - &SS, DC, false, - Sema::CTC_MemberLookup); - NamedDecl *ND = Corrected.getCorrectionDecl(); + &SS, &Validator, DC); R.clear(); - if (ND && (isa(ND) || isa(ND))) { + if (NamedDecl *ND = Corrected.getCorrectionDecl()) { std::string CorrectedStr( Corrected.getAsString(SemaRef.getLangOptions())); std::string CorrectedQuotedStr( @@ -1094,12 +1107,12 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr, if (!IV) { // Attempt to correct for typos in ivar names. - LookupResult Res(*this, R.getLookupName(), R.getNameLoc(), - LookupMemberName); - TypoCorrection Corrected = CorrectTypo( - R.getLookupNameInfo(), LookupMemberName, NULL, NULL, IDecl, false, - IsArrow ? CTC_ObjCIvarLookup : CTC_ObjCPropertyLookup); - if ((IV = Corrected.getCorrectionDeclAs())) { + DeclFilterCCC Validator; + Validator.IsObjCIvarLookup = IsArrow; + if (TypoCorrection Corrected = CorrectTypo(R.getLookupNameInfo(), + LookupMemberName, NULL, NULL, + &Validator, IDecl)) { + IV = Corrected.getCorrectionDeclAs(); Diag(R.getNameLoc(), diag::err_typecheck_member_reference_ivar_suggest) << IDecl->getDeclName() << MemberName << IV->getDeclName() @@ -1115,8 +1128,6 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr, << FixItHint::CreateReplacement(OpLoc, "."); return ExprError(); } - Res.clear(); - Res.setLookupName(Member); Diag(MemberLoc, diag::err_typecheck_member_reference_ivar) << IDecl->getDeclName() << MemberName diff --git a/test/SemaCXX/member-expr.cpp b/test/SemaCXX/member-expr.cpp index db5a051826..dbddd1c2e3 100644 --- a/test/SemaCXX/member-expr.cpp +++ b/test/SemaCXX/member-expr.cpp @@ -94,11 +94,11 @@ namespace test5 { namespace PR7508 { struct A { struct CleanupScope {}; - void PopCleanupBlock(); + void PopCleanupBlock(); // expected-note{{'PopCleanupBlock' declared here}} }; void foo(A &a) { - a.PopCleanupScope(); // expected-error{{no member named 'PopCleanupScope' in 'PR7508::A'}} + a.PopCleanupScope(); // expected-error{{no member named 'PopCleanupScope' in 'PR7508::A'; did you mean 'PopCleanupBlock'?}} } } diff --git a/test/SemaCXX/typo-correction.cpp b/test/SemaCXX/typo-correction.cpp index a4cbbb85e6..bc3433b598 100644 --- a/test/SemaCXX/typo-correction.cpp +++ b/test/SemaCXX/typo-correction.cpp @@ -37,10 +37,14 @@ inline error_condition make_error_condition(errc _e) { // refer to a base class or non-static data member. struct BaseType { }; struct Derived : public BaseType { // expected-note {{base class 'BaseType' specified here}} - static int base_type; + static int base_type; // expected-note {{'base_type' declared here}} Derived() : basetype() {} // expected-error{{initializer 'basetype' does not name a non-static data member or base class; did you mean the base class 'BaseType'?}} }; +int get_type(struct Derived *st) { + return st->Base_Type; // expected-error{{no member named 'Base_Type' in 'Derived'; did you mean 'base_type'?}} +} + // In this example, somename should not be corrected to the cached correction // "some_name" since "some_name" is a class and a namespace name is needed. class some_name {}; // expected-note {{'some_name' declared here}}