From: Kaelyn Takata Date: Wed, 5 Nov 2014 00:09:29 +0000 (+0000) Subject: Filter out non-static class members when correcting non-member-references. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4da35811cd29ff0b8982de5c024d1350e6068c87;p=clang Filter out non-static class members when correcting non-member-references. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@221319 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Parse/ParseTentative.cpp b/lib/Parse/ParseTentative.cpp index 4b1375dfc1..944e88722f 100644 --- a/lib/Parse/ParseTentative.cpp +++ b/lib/Parse/ParseTentative.cpp @@ -1006,6 +1006,28 @@ bool Parser::isTentativelyDeclared(IdentifierInfo *II) { != TentativelyDeclaredIdentifiers.end(); } +namespace { +class TentativeParseCCC : public CorrectionCandidateCallback { +public: + TentativeParseCCC(const Token &Next) { + WantRemainingKeywords = false; + WantTypeSpecifiers = Next.is(tok::l_paren) || Next.is(tok::r_paren) || + Next.is(tok::greater) || Next.is(tok::l_brace) || + Next.is(tok::identifier); + } + + bool ValidateCandidate(const TypoCorrection &Candidate) override { + // Reject any candidate that only resolves to instance members since they + // aren't viable as standalone identifiers instead of member references. + if (Candidate.isResolved() && !Candidate.isKeyword() && + std::all_of(Candidate.begin(), Candidate.end(), + [](NamedDecl *ND) { return ND->isCXXInstanceMember(); })) + return false; + + return CorrectionCandidateCallback::ValidateCandidate(Candidate); + } +}; +} /// isCXXDeclarationSpecifier - Returns TPResult::True if it is a declaration /// specifier, TPResult::False if it is not, TPResult::Ambiguous if it could /// be either a decl-specifier or a function-style cast, and TPResult::Error @@ -1131,14 +1153,8 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult, // a parse error one way or another. In that case, tell the caller that // this is ambiguous. Typo-correct to type and expression keywords and // to types and identifiers, in order to try to recover from errors. - auto TypoCorrection = llvm::make_unique(); - TypoCorrection->WantRemainingKeywords = false; - TypoCorrection->WantTypeSpecifiers = - Next.is(tok::l_paren) || Next.is(tok::r_paren) || - Next.is(tok::greater) || Next.is(tok::l_brace) || - Next.is(tok::identifier); switch (TryAnnotateName(false /* no nested name specifier */, - std::move(TypoCorrection))) { + llvm::make_unique(Next))) { case ANK_Error: return TPResult::Error; case ANK_TentativeDecl: diff --git a/test/SemaCXX/typo-correction-pt2.cpp b/test/SemaCXX/typo-correction-pt2.cpp index de12da77d1..5d3f1236ac 100644 --- a/test/SemaCXX/typo-correction-pt2.cpp +++ b/test/SemaCXX/typo-correction-pt2.cpp @@ -319,3 +319,16 @@ int bar() { Test::SomeSettings some_settings; // expected-error {{no type named 'SomeSettings' in 'testCXXDeclarationSpecifierParsing::Test'; did you mean 'test::SomeSettings'?}} } } + +namespace testNonStaticMemberHandling { +struct Foo { + bool usesMetadata; // expected-note {{'usesMetadata' declared here}} +}; +int test(Foo f) { + if (UsesMetadata) // expected-error-re {{use of undeclared identifier 'UsesMetadata'{{$}}}} + return 5; + if (f.UsesMetadata) // expected-error {{no member named 'UsesMetadata' in 'testNonStaticMemberHandling::Foo'; did you mean 'usesMetadata'?}} + return 11; + return 0; +} +};