forked from OSchip/llvm-project
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). llvm-svn: 191544
This commit is contained in:
parent
0e23844f57
commit
3dfff19658
|
@ -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<FieldDecl>())
|
||||
return isa<ObjCIvarDecl>(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.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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'$}}
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue