From: Kaelyn Uhrain Date: Fri, 27 Sep 2013 19:40:12 +0000 (+0000) Subject: Avoid the hard-coded limit on the number of typo corrections attempted. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6243f627680fbf7c5bf2f339967d806f47153746;p=clang Avoid the hard-coded limit on the number of typo corrections attempted. Move some tests from typo-correction.cpp to typo-correction-pt2.cpp because they were running afoul of the hard-coded limit of 20 typos corrected. Some of the tests after it were still working due to the limit not applying to cached corrections and in cases where a non-NULL MemberContext is passed in to Sema::CorrectTypo. Most of the moved tests still passed after being moved, but the test involving "data_struct" had only been passing because the test had exceeded that limit so a fix for it is also included (most of the changes to ParseStmt.cpp are shared with and originated from another typo correction impovement that was split into a separate commit). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@191544 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp index 8084a8fa5e..63fd1a51e4 100644 --- a/lib/Parse/ParseStmt.cpp +++ b/lib/Parse/ParseStmt.cpp @@ -111,6 +111,33 @@ Parser::ParseStatementOrDeclaration(StmtVector &Stmts, bool OnlyStatement, return Actions.ProcessStmtAttributes(Res.get(), Attrs.getList(), Attrs.Range); } +namespace { +class StatementFilterCCC : public CorrectionCandidateCallback { +public: + StatementFilterCCC(Token nextTok) : NextToken(nextTok) { + WantTypeSpecifiers = nextTok.is(tok::l_paren) || nextTok.is(tok::less) || + nextTok.is(tok::identifier) || nextTok.is(tok::star) || + nextTok.is(tok::amp) || nextTok.is(tok::l_square); + WantExpressionKeywords = nextTok.is(tok::l_paren) || + nextTok.is(tok::identifier) || + nextTok.is(tok::arrow) || nextTok.is(tok::period); + WantRemainingKeywords = nextTok.is(tok::l_paren) || nextTok.is(tok::semi) || + nextTok.is(tok::identifier) || + nextTok.is(tok::l_brace); + WantCXXNamedCasts = false; + } + + virtual bool ValidateCandidate(const TypoCorrection &candidate) { + if (FieldDecl *FD = candidate.getCorrectionDeclAs()) + return isa(FD); + return CorrectionCandidateCallback::ValidateCandidate(candidate); + } + +private: + Token NextToken; +}; +} + StmtResult Parser::ParseStatementOrDeclarationAfterAttributes(StmtVector &Stmts, bool OnlyStatement, SourceLocation *TrailingElseLoc, @@ -149,21 +176,8 @@ Retry: if (Next.isNot(tok::coloncolon)) { // Try to limit which sets of keywords should be included in typo // correction based on what the next token is. - // FIXME: Pass the next token into the CorrectionCandidateCallback and - // do this filtering in a more fine-grained manner. - CorrectionCandidateCallback DefaultValidator; - DefaultValidator.WantTypeSpecifiers = - Next.is(tok::l_paren) || Next.is(tok::less) || - Next.is(tok::identifier) || Next.is(tok::star) || - Next.is(tok::amp) || Next.is(tok::l_square); - DefaultValidator.WantExpressionKeywords = - Next.is(tok::l_paren) || Next.is(tok::identifier) || - Next.is(tok::arrow) || Next.is(tok::period); - DefaultValidator.WantRemainingKeywords = - Next.is(tok::l_paren) || Next.is(tok::semi) || - Next.is(tok::identifier) || Next.is(tok::l_brace); - DefaultValidator.WantCXXNamedCasts = false; - if (TryAnnotateName(/*IsAddressOfOperand*/false, &DefaultValidator) + StatementFilterCCC Validator(Next); + if (TryAnnotateName(/*IsAddressOfOperand*/false, &Validator) == ANK_Error) { // Handle errors here by skipping up to the next semicolon or '}', and // eat the semicolon if that's what stopped us. diff --git a/test/SemaCXX/typo-correction-pt2.cpp b/test/SemaCXX/typo-correction-pt2.cpp index 543a5823f7..59eb0609c3 100644 --- a/test/SemaCXX/typo-correction-pt2.cpp +++ b/test/SemaCXX/typo-correction-pt2.cpp @@ -5,6 +5,37 @@ // attempt within a single file (which is to avoid having very broken files take // minutes to finally be rejected by the parser). +namespace bogus_keyword_suggestion { +void test() { + status = "OK"; // expected-error-re {{use of undeclared identifier 'status'$}} + return status; // expected-error-re {{use of undeclared identifier 'status'$}} + } +} + +namespace PR13387 { +struct A { + void CreateFoo(float, float); + void CreateBar(float, float); +}; +struct B : A { + using A::CreateFoo; + void CreateFoo(int, int); +}; +void f(B &x) { + x.Createfoo(0,0); // expected-error {{no member named 'Createfoo' in 'PR13387::B'; did you mean 'CreateFoo'?}} +} +} + +struct DataStruct {void foo();}; +struct T { + DataStruct data_struct; + void f(); +}; +// should be void T::f(); +void f() { + data_struct->foo(); // expected-error-re{{use of undeclared identifier 'data_struct'$}} +} + namespace PR12287 { class zif { void nab(int); diff --git a/test/SemaCXX/typo-correction.cpp b/test/SemaCXX/typo-correction.cpp index c2c79d2203..d779e2a448 100644 --- a/test/SemaCXX/typo-correction.cpp +++ b/test/SemaCXX/typo-correction.cpp @@ -246,37 +246,6 @@ namespace outer { } } -namespace bogus_keyword_suggestion { -void test() { - status = "OK"; // expected-error-re{{use of undeclared identifier 'status'$}} - return status; // expected-error-re{{use of undeclared identifier 'status'$}} - } -} - -namespace PR13387 { -struct A { - void CreateFoo(float, float); - void CreateBar(float, float); -}; -struct B : A { - using A::CreateFoo; - void CreateFoo(int, int); -}; -void f(B &x) { - x.Createfoo(0,0); // expected-error {{no member named 'Createfoo' in 'PR13387::B'; did you mean 'CreateFoo'?}} -} -} - -struct DataStruct {void foo();}; -struct T { - DataStruct data_struct; - void f(); -}; -// should be void T::f(); -void f() { - data_struct->foo(); // expected-error-re{{use of undeclared identifier 'data_struct'$}} -} - namespace b6956809_test1 { struct A {}; struct B {}; @@ -319,9 +288,13 @@ namespace b6956809_test2 { } } +// This test should have one correction, followed by an error without a +// suggestion due to exceeding the maximum number of typos for which correction +// is attempted. namespace CorrectTypo_has_reached_its_limit { -int flibberdy(); // no note here +int flibberdy(); // expected-note{{'flibberdy' declared here}} int no_correction() { - return gibberdy(); // expected-error-re{{use of undeclared identifier 'gibberdy'$}} + return hibberdy() + // expected-error{{use of undeclared identifier 'hibberdy'; did you mean 'flibberdy'?}} + gibberdy(); // expected-error-re{{use of undeclared identifier 'gibberdy'$}} }; }