Allow typo correction to try removing nested name specifiers.
The removal is tried by retrying the failed lookup of a correction
candidate with either the MemberContext or SS (CXXScopeSpecifier) or
both set to NULL if they weren't already. If the candidate identifier
is then looked up successfully, make a note in the candidate that the
SourceRange should include any existing nested name specifier even if
the candidate isn't adding a different one (i.e. the candidate has a
NULL NestedNameSpecifier).
Also tweak the diagnostic messages to differentiate between a suggestion
that just replaces the identifer but leaves the existing nested name
specifier intact and one that replaces the entire qualified identifier,
in cases where the suggested replacement is unqualified.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@185487 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 8e86389..162b5b8 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -422,22 +422,29 @@
CorrectedQuotedStr = "the keyword " + CorrectedQuotedStr;
Diag(IILoc, diag::err_unknown_typename_suggest)
<< II << CorrectedQuotedStr
- << FixItHint::CreateReplacement(SourceRange(IILoc), CorrectedStr);
+ << FixItHint::CreateReplacement(Corrected.getCorrectionRange(),
+ CorrectedStr);
II = NewII;
} else {
NamedDecl *Result = Corrected.getCorrectionDecl();
// We found a similarly-named type or interface; suggest that.
- if (!SS || !SS->isSet())
+ if (!SS || !SS->isSet()) {
Diag(IILoc, diag::err_unknown_typename_suggest)
<< II << CorrectedQuotedStr
- << FixItHint::CreateReplacement(SourceRange(IILoc), CorrectedStr);
- else if (DeclContext *DC = computeDeclContext(*SS, false))
- Diag(IILoc, diag::err_unknown_nested_typename_suggest)
- << II << DC << CorrectedQuotedStr << SS->getRange()
<< FixItHint::CreateReplacement(Corrected.getCorrectionRange(),
CorrectedStr);
- else
+ } else if (DeclContext *DC = computeDeclContext(*SS, false)) {
+ bool droppedSpecifier = Corrected.WillReplaceSpecifier() &&
+ II->getName().equals(CorrectedStr);
+ Diag(IILoc, diag::err_unknown_nested_typename_suggest)
+ << II << DC << droppedSpecifier << CorrectedQuotedStr
+ << SS->getRange()
+ << FixItHint::CreateReplacement(Corrected.getCorrectionRange(),
+ CorrectedStr);
+ }
+ else {
llvm_unreachable("could not have corrected a typo here");
+ }
Diag(Result->getLocation(), diag::note_previous_decl)
<< CorrectedQuotedStr;
@@ -680,16 +687,19 @@
QualifiedDiag = diag::err_unknown_nested_typename_suggest;
}
- if (SS.isEmpty())
+ if (SS.isEmpty()) {
Diag(NameLoc, UnqualifiedDiag)
<< Name << CorrectedQuotedStr
<< FixItHint::CreateReplacement(NameLoc, CorrectedStr);
- else // FIXME: is this even reachable? Test it.
+ } else {// FIXME: is this even reachable? Test it.
+ bool droppedSpecifier = Corrected.WillReplaceSpecifier() &&
+ Name->getName().equals(CorrectedStr);
Diag(NameLoc, QualifiedDiag)
- << Name << computeDeclContext(SS, false) << CorrectedQuotedStr
- << SS.getRange()
+ << Name << computeDeclContext(SS, false) << droppedSpecifier
+ << CorrectedQuotedStr << SS.getRange()
<< FixItHint::CreateReplacement(Corrected.getCorrectionRange(),
CorrectedStr);
+ }
// Update the name, so that the caller has the new name.
Name = Corrected.getCorrectionAsIdentifierInfo();