summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaelyn Takata <rikka@google.com>2015-01-16 22:11:04 +0000
committerKaelyn Takata <rikka@google.com>2015-01-16 22:11:04 +0000
commitae9e97c9d6aeeacc07b48a15b49852d1681a2fc1 (patch)
tree27dfef9643c4906b16ae55441f3d2508c38335d2
parent76723d733bdac9e9f68a0a0b4388d470bfd5e3a0 (diff)
downloadbcm5719-llvm-ae9e97c9d6aeeacc07b48a15b49852d1681a2fc1.tar.gz
bcm5719-llvm-ae9e97c9d6aeeacc07b48a15b49852d1681a2fc1.zip
Fix a case where delayed typo correction should have resolved an
ambiguity but wasn't. In the new test case, "click" wasn't being corrected properly because Sema::ClassifyName would call CorrectTypo for "click" then later Sema::DiagnoseEmptyLookup would call CorrectTypoDelayed for the same use of "click" (the former by the parser needing to determine what the identifier is so it knows how to parse the statement, i.e. is it the beginning of a declaration or an expression). CorrectTypo would record that typo correction for "click" failed and CorrectTypoDelayed would see that and not even try to correct the typo, even though in this case CorrectTypo failed due to an ambiguity (both "Click" and "clock" having an edit distance of one from "click") that could be resolved with more information. The fix is two-fold: 1) Have CorrectTypo not record failed corrections if the reason for the failure was two or more corrections with the same edit distance, and 2) Make the CorrectionCandidateCallback used by Parser::ParseCastExpression reject FunctionDecl candidates when the next token after the identifier is a ".", "=", or "->" since functions cannot be assigned to and do not have members that can be referenced. The reason for two correction spots is that from r222549 until r224375 landed, the first correction attempt would fail completely but the second would suggest "clock" while having the note point to the declaration of "Click". llvm-svn: 226334
-rw-r--r--clang/lib/Parse/ParseExpr.cpp23
-rw-r--r--clang/lib/Sema/SemaLookup.cpp6
-rw-r--r--clang/test/SemaCXX/typo-correction-delayed.cpp10
3 files changed, 30 insertions, 9 deletions
diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp
index d0d97de84c1..4c83bd8a77b 100644
--- a/clang/lib/Parse/ParseExpr.cpp
+++ b/clang/lib/Parse/ParseExpr.cpp
@@ -446,8 +446,8 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
namespace {
class CastExpressionIdValidator : public CorrectionCandidateCallback {
public:
- CastExpressionIdValidator(bool AllowTypes, bool AllowNonTypes)
- : AllowNonTypes(AllowNonTypes) {
+ CastExpressionIdValidator(Token Next, bool AllowTypes, bool AllowNonTypes)
+ : NextToken(Next), AllowNonTypes(AllowNonTypes) {
WantTypeSpecifiers = WantFunctionLikeCasts = AllowTypes;
}
@@ -458,11 +458,24 @@ class CastExpressionIdValidator : public CorrectionCandidateCallback {
if (isa<TypeDecl>(ND))
return WantTypeSpecifiers;
- return AllowNonTypes &&
- CorrectionCandidateCallback::ValidateCandidate(candidate);
+
+ if (!AllowNonTypes || !CorrectionCandidateCallback::ValidateCandidate(candidate))
+ return false;
+
+ if (!(NextToken.is(tok::equal) || NextToken.is(tok::arrow) ||
+ NextToken.is(tok::period)))
+ return true;
+
+ for (auto *C : candidate) {
+ NamedDecl *ND = C->getUnderlyingDecl();
+ if (isa<ValueDecl>(ND) && !isa<FunctionDecl>(ND))
+ return true;
+ }
+ return false;
}
private:
+ Token NextToken;
bool AllowNonTypes;
};
}
@@ -908,7 +921,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
SourceLocation TemplateKWLoc;
Token Replacement;
auto Validator = llvm::make_unique<CastExpressionIdValidator>(
- isTypeCast != NotTypeCast, isTypeCast != IsTypeCast);
+ Tok, isTypeCast != NotTypeCast, isTypeCast != IsTypeCast);
Validator->IsAddressOfOperand = isAddressOfOperand;
Validator->WantRemainingKeywords = Tok.isNot(tok::r_paren);
Name.setIdentifier(&II, ILoc);
diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index 3445264461f..c4fe0589c4b 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -4284,7 +4284,7 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
// Record the failure's location if needed and return an empty correction. If
// this was an unqualified lookup and we believe the callback object did not
// filter out possible corrections, also cache the failure for the typo.
- return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure);
+ return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure && !SecondBestTC);
}
/// \brief Try to "correct" a typo in the source code by finding
@@ -4337,9 +4337,7 @@ TypoExpr *Sema::CorrectTypoDelayed(
TypoCorrection Empty;
auto Consumer = makeTypoCorrectionConsumer(
TypoName, LookupKind, S, SS, std::move(CCC), MemberContext,
- EnteringContext, OPT,
- /*SearchModules=*/(Mode == CTK_ErrorRecovery) && getLangOpts().Modules &&
- getLangOpts().ModulesSearchAll);
+ EnteringContext, OPT, Mode == CTK_ErrorRecovery);
if (!Consumer || Consumer->empty())
return nullptr;
diff --git a/clang/test/SemaCXX/typo-correction-delayed.cpp b/clang/test/SemaCXX/typo-correction-delayed.cpp
index e028faad251..454a8b365c3 100644
--- a/clang/test/SemaCXX/typo-correction-delayed.cpp
+++ b/clang/test/SemaCXX/typo-correction-delayed.cpp
@@ -157,3 +157,13 @@ namespace PR22092 {
a = b ? : 0; // expected-error {{C++ requires a type specifier for all declarations}} \
// expected-error-re {{use of undeclared identifier 'b'{{$}}}}
}
+
+extern long clock (void);
+struct Pointer {
+ void set_xpos(int);
+ void set_ypos(int);
+};
+void MovePointer(Pointer &Click, int x, int y) { // expected-note 2 {{'Click' declared here}}
+ click.set_xpos(x); // expected-error {{use of undeclared identifier 'click'; did you mean 'Click'?}}
+ click.set_ypos(x); // expected-error {{use of undeclared identifier 'click'; did you mean 'Click'?}}
+}
OpenPOWER on IntegriCloud