From 044b71a30fa873952931341159c3773f23937868 Mon Sep 17 00:00:00 2001 From: Kaelyn Uhrain Date: Fri, 28 Feb 2014 18:12:42 +0000 Subject: [PATCH] Don't suggest non-static methods as corrections when they obviously won't work (i.e. when not doing a member lookup and not in a method from the same class or a descendant class). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@202520 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Sema/TypoCorrection.h | 5 ++++- lib/Sema/SemaLookup.cpp | 32 +++++++++++++++++++++++----- lib/Sema/SemaOverload.cpp | 2 +- test/SemaCXX/typo-correction-pt2.cpp | 9 ++++++++ 4 files changed, 41 insertions(+), 7 deletions(-) diff --git a/include/clang/Sema/TypoCorrection.h b/include/clang/Sema/TypoCorrection.h index f0b7726498..c28720b2b1 100644 --- a/include/clang/Sema/TypoCorrection.h +++ b/include/clang/Sema/TypoCorrection.h @@ -305,13 +305,16 @@ public: class FunctionCallFilterCCC : public CorrectionCandidateCallback { public: FunctionCallFilterCCC(Sema &SemaRef, unsigned NumArgs, - bool HasExplicitTemplateArgs); + bool HasExplicitTemplateArgs, + bool AllowNonStaticMethods = true); virtual bool ValidateCandidate(const TypoCorrection &candidate); private: unsigned NumArgs; bool HasExplicitTemplateArgs; + bool AllowNonStaticMethods; + DeclContext *CurContext; }; // @brief Callback class that effectively disabled typo correction diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index 1a47340d69..5df0a43621 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -4546,8 +4546,11 @@ bool CorrectionCandidateCallback::ValidateCandidate(const TypoCorrection &candid } FunctionCallFilterCCC::FunctionCallFilterCCC(Sema &SemaRef, unsigned NumArgs, - bool HasExplicitTemplateArgs) - : NumArgs(NumArgs), HasExplicitTemplateArgs(HasExplicitTemplateArgs) { + bool HasExplicitTemplateArgs, + bool AllowNonStaticMethods) + : NumArgs(NumArgs), HasExplicitTemplateArgs(HasExplicitTemplateArgs), + AllowNonStaticMethods(AllowNonStaticMethods), + CurContext(SemaRef.CurContext) { WantTypeSpecifiers = SemaRef.getLangOpts().CPlusPlus; WantRemainingKeywords = false; } @@ -4576,9 +4579,28 @@ bool FunctionCallFilterCCC::ValidateCandidate(const TypoCorrection &candidate) { return true; } } - if (FD && FD->getNumParams() >= NumArgs && - FD->getMinRequiredArguments() <= NumArgs) - return true; + + // Skip the current candidate if it is not a FunctionDecl or does not accept + // the current number of arguments. + if (!FD || !(FD->getNumParams() >= NumArgs && + FD->getMinRequiredArguments() <= NumArgs)) + continue; + + // If the current candidate is a non-static C++ method and non-static + // methods are being excluded, then skip the candidate unless the current + // DeclContext is a method in the same class or a descendent class of the + // candidate's parent class. + if (CXXMethodDecl *MD = dyn_cast(FD)) { + if (!AllowNonStaticMethods && !MD->isStatic()) { + CXXMethodDecl *CurMD = dyn_cast_or_null(CurContext); + CXXRecordDecl *CurRD = + CurMD ? CurMD->getParent()->getCanonicalDecl() : 0; + CXXRecordDecl *RD = MD->getParent()->getCanonicalDecl(); + if (!CurRD || (CurRD != RD && !CurRD->isDerivedFrom(RD))) + continue; + } + } + return true; } return false; } diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index fb77ba616f..eaf3d35148 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -10385,7 +10385,7 @@ BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn, LookupResult R(SemaRef, ULE->getName(), ULE->getNameLoc(), Sema::LookupOrdinaryName); FunctionCallFilterCCC Validator(SemaRef, Args.size(), - ExplicitTemplateArgs != 0); + ExplicitTemplateArgs != 0, false); NoTypoCorrectionCCC RejectAll; CorrectionCandidateCallback *CCC = AllowTypoCorrection ? (CorrectionCandidateCallback*)&Validator : diff --git a/test/SemaCXX/typo-correction-pt2.cpp b/test/SemaCXX/typo-correction-pt2.cpp index e08bef0741..e39a24bd09 100644 --- a/test/SemaCXX/typo-correction-pt2.cpp +++ b/test/SemaCXX/typo-correction-pt2.cpp @@ -234,3 +234,12 @@ class Baz { // expected-error {{expected member name or ';' after declaration specifiers}} }; } + +namespace PR18852 { +void func() { + struct foo { + void bar() {} + }; + bar(); // expected-error-re {{use of undeclared identifier 'bar'{{$}}}} +} +} -- 2.40.0