Also be more proactive about checking a correction's visibility so that
a correction requiring a module import can be distinguished from the
original typo even if it looks identical. Otherwise the correction will
be excluded and the diagnostic about needing the module import won't be
emitted.
Note that no change was made to checkCorrectionVisibility other than
moving where it is at in SemaLookup.cpp.
---
include/clang/Sema/TypoCorrection.h | 24 +++++++--
lib/Sema/SemaLookup.cpp | 100 +++++++++++++++++++-----------------
2 files changed, 74 insertions(+), 50 deletions(-)
diff --git a/include/clang/Sema/TypoCorrection.h b/include/clang/Sema/TypoCorrection.h
index addbd65..73bfbeb 100644
--- a/include/clang/Sema/TypoCorrection.h
+++ b/include/clang/Sema/TypoCorrection.h
@@ -247,11 +247,12 @@ class CorrectionCandidateCallback {
public:
static const unsigned InvalidDistance = TypoCorrection::InvalidDistance;
- CorrectionCandidateCallback()
+ explicit CorrectionCandidateCallback(IdentifierInfo *Typo = nullptr,
+ NestedNameSpecifier *TypoNNS = nullptr)
: WantTypeSpecifiers(true), WantExpressionKeywords(true),
WantCXXNamedCasts(true), WantRemainingKeywords(true),
WantObjCSuper(false), IsObjCIvarLookup(false),
- IsAddressOfOperand(false) {}
+ IsAddressOfOperand(false), Typo(Typo), TypoNNS(TypoNNS) {}
virtual ~CorrectionCandidateCallback() {}
@@ -274,9 +275,14 @@ public:
/// the default RankCandidate returns either 0 or InvalidDistance depending
/// whether ValidateCandidate returns true or false.
virtual unsigned RankCandidate(const TypoCorrection &candidate) {
- return ValidateCandidate(candidate) ? 0 : InvalidDistance;
+ return (!MatchesTypo(candidate) && ValidateCandidate(candidate))
+ ? 0
+ : InvalidDistance;
}
+ void setTypoName(IdentifierInfo *II) { Typo = II; }
+ void setTypoNNS(NestedNameSpecifier *NNS) { TypoNNS = NNS; }
+
// Flags for context-dependent keywords.
// TODO: Expand these to apply to non-keywords or possibly remove them.
bool WantTypeSpecifiers;
@@ -288,6 +294,18 @@ public:
// when looking up results.
bool IsObjCIvarLookup;
bool IsAddressOfOperand;
+
+protected:
+ bool MatchesTypo(const TypoCorrection &candidate) {
+ return Typo && candidate.isResolved() && !candidate.requiresImport() &&
+ candidate.getCorrectionAsIdentifierInfo() == Typo &&
+ // FIXME: This probably does not return true when both
+ // NestedNameSpecifiers have the same textual representation.
+ candidate.getCorrectionSpecifier() == TypoNNS;
+ }
+
+ IdentifierInfo *Typo;
+ NestedNameSpecifier *TypoNNS;
};
/// @brief Simple template class for restricting typo correction candidates
diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp
index 64269a1..c78f524 100644
--- a/lib/Sema/SemaLookup.cpp
+++ b/lib/Sema/SemaLookup.cpp
@@ -3280,6 +3280,49 @@ static void LookupPotentialTypoResult(Sema &SemaRef,
bool isObjCIvarLookup,
bool FindHidden);
+/// \brief Check whether the declarations found for a typo correction are
+/// visible, and if none of them are, convert the correction to an 'import
+/// a module' correction.
+static void checkCorrectionVisibility(Sema &SemaRef, TypoCorrection &TC) {
+ if (TC.begin() == TC.end())
+ return;
+
+ TypoCorrection::decl_iterator DI = TC.begin(), DE = TC.end();
+
+ for (/**/; DI != DE; ++DI)
+ if (!LookupResult::isVisible(SemaRef, *DI))
+ break;
+ // Nothing to do if all decls are visible.
+ if (DI == DE)
+ return;
+
+ llvm::SmallVector<NamedDecl*, 4> NewDecls(TC.begin(), DI);
+ bool AnyVisibleDecls = !NewDecls.empty();
+
+ for (/**/; DI != DE; ++DI) {
+ NamedDecl *VisibleDecl = *DI;
+ if (!LookupResult::isVisible(SemaRef, *DI))
+ VisibleDecl = findAcceptableDecl(SemaRef, *DI);
+
+ if (VisibleDecl) {
+ if (!AnyVisibleDecls) {
+ // Found a visible decl, discard all hidden ones.
+ AnyVisibleDecls = true;
+ NewDecls.clear();
+ }
+ NewDecls.push_back(VisibleDecl);
+ } else if (!AnyVisibleDecls && !(*DI)->isModulePrivate())
+ NewDecls.push_back(*DI);
+ }
+
+ if (NewDecls.empty())
+ TC = TypoCorrection();
+ else {
+ TC.setCorrectionDecls(NewDecls);
+ TC.setRequiresImport(!AnyVisibleDecls);
+ }
+}
+
// Fill the supplied vector with the IdentifierInfo pointers for each piece of
// the given NestedNameSpecifier (i.e. given a NestedNameSpecifier "foo::bar::",
// fill the vector with the IdentifierInfo pointers for "foo" and "bar").
@@ -3389,9 +3432,11 @@ void TypoCorrectionConsumer::addCorrection(TypoCorrection Correction) {
return;
// If the correction is resolved but is not viable, ignore it.
- if (Correction.isResolved() &&
- !isCandidateViable(*CorrectionValidator, Correction))
- return;
+ if (Correction.isResolved()) {
+ checkCorrectionVisibility(SemaRef, Correction);
+ if (!Correction || !isCandidateViable(*CorrectionValidator, Correction))
+ return;
+ }
TypoResultList &CList =
CorrectionResults[Correction.getEditDistance(false)][Name];
@@ -3465,7 +3510,7 @@ TypoCorrection &TypoCorrectionConsumer::getNextCorrection() {
}
TypoCorrection TC = RI->second.pop_back_val();
- if (TC.isResolved() || resolveCorrection(TC)) {
+ if (TC.isResolved() || TC.requiresImport() || resolveCorrection(TC)) {
ValidatedCorrections.push_back(TC);
return ValidatedCorrections[CurrentTCIndex];
}
@@ -3513,6 +3558,7 @@ retry_lookup:
// Store all of the Decls for overloaded symbols
for (auto *TRD : Result)
Candidate.addCorrectionDecl(TRD);
+ checkCorrectionVisibility(SemaRef, Candidate);
if (!isCandidateViable(*CorrectionValidator, Candidate)) {
if (SearchNamespaces)
QualifiedResults.push_back(Candidate);
@@ -3941,49 +3987,6 @@ static void AddKeywordsToConsumer(Sema &SemaRef,
}
}
-/// \brief Check whether the declarations found for a typo correction are
-/// visible, and if none of them are, convert the correction to an 'import
-/// a module' correction.
-static void checkCorrectionVisibility(Sema &SemaRef, TypoCorrection &TC) {
- if (TC.begin() == TC.end())
- return;
-
- TypoCorrection::decl_iterator DI = TC.begin(), DE = TC.end();
-
- for (/**/; DI != DE; ++DI)
- if (!LookupResult::isVisible(SemaRef, *DI))
- break;
- // Nothing to do if all decls are visible.
- if (DI == DE)
- return;
-
- llvm::SmallVector<NamedDecl*, 4> NewDecls(TC.begin(), DI);
- bool AnyVisibleDecls = !NewDecls.empty();
-
- for (/**/; DI != DE; ++DI) {
- NamedDecl *VisibleDecl = *DI;
- if (!LookupResult::isVisible(SemaRef, *DI))
- VisibleDecl = findAcceptableDecl(SemaRef, *DI);
-
- if (VisibleDecl) {
- if (!AnyVisibleDecls) {
- // Found a visible decl, discard all hidden ones.
- AnyVisibleDecls = true;
- NewDecls.clear();
- }
- NewDecls.push_back(VisibleDecl);
- } else if (!AnyVisibleDecls && !(*DI)->isModulePrivate())
- NewDecls.push_back(*DI);
- }
-
- if (NewDecls.empty())
- TC = TypoCorrection();
- else {
- TC.setCorrectionDecls(NewDecls);
- TC.setRequiresImport(!AnyVisibleDecls);
- }
-}
-
std::unique_ptr<TypoCorrectionConsumer> Sema::makeTypoCorrectionConsumer(
const DeclarationNameInfo &TypoName, Sema::LookupNameKind LookupKind,
Scope *S, CXXScopeSpec *SS,
@@ -4397,6 +4400,9 @@ bool CorrectionCandidateCallback::ValidateCandidate(const TypoCorrection &candid
if (!candidate.isResolved())
return true;
+ if (MatchesTypo(candidate))
+ return false;
+
if (candidate.isKeyword())
return WantTypeSpecifiers || WantExpressionKeywords || WantCXXNamedCasts ||
WantRemainingKeywords || WantObjCSuper;
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits