[cfe-commits] r157823 - in /cfe/trunk: lib/Sema/SemaLookup.cpp test/SemaCXX/typo-correction.cpp
Kaelyn Uhrain
rikka at google.com
Fri Jun 1 11:11:17 PDT 2012
Author: rikka
Date: Fri Jun 1 13:11:16 2012
New Revision: 157823
URL: http://llvm.org/viewvc/llvm-project?rev=157823&view=rev
Log:
Don't allow multiple correction candidates that have the same identifier
but different nested name specifiers to quietly clobber each other so
only one remains if they do not refer to the same NamedDecl. Fixes
PR12951.
Modified:
cfe/trunk/lib/Sema/SemaLookup.cpp
cfe/trunk/test/SemaCXX/typo-correction.cpp
Modified: cfe/trunk/lib/Sema/SemaLookup.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLookup.cpp?rev=157823&r1=157822&r2=157823&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaLookup.cpp (original)
+++ cfe/trunk/lib/Sema/SemaLookup.cpp Fri Jun 1 13:11:16 2012
@@ -3147,7 +3147,8 @@
namespace {
-typedef llvm::StringMap<TypoCorrection, llvm::BumpPtrAllocator> TypoResultsMap;
+typedef llvm::SmallVector<TypoCorrection, 1> TypoResultList;
+typedef llvm::StringMap<TypoResultList, llvm::BumpPtrAllocator> TypoResultsMap;
typedef std::map<unsigned, TypoResultsMap> TypoEditDistanceMap;
static const unsigned MaxTypoDistanceResultSets = 5;
@@ -3186,7 +3187,7 @@
unsigned size() const { return CorrectionResults.size(); }
bool empty() const { return CorrectionResults.empty(); }
- TypoCorrection &operator[](StringRef Name) {
+ TypoResultList &operator[](StringRef Name) {
return CorrectionResults.begin()->second[Name];
}
@@ -3256,16 +3257,28 @@
void TypoCorrectionConsumer::addCorrection(TypoCorrection Correction) {
StringRef Name = Correction.getCorrectionAsIdentifierInfo()->getName();
- TypoResultsMap &Map = CorrectionResults[Correction.getEditDistance(false)];
+ TypoResultList &CList =
+ CorrectionResults[Correction.getEditDistance(false)][Name];
- TypoCorrection &CurrentCorrection = Map[Name];
- if (!CurrentCorrection ||
- // FIXME: The following should be rolled up into an operator< on
- // TypoCorrection with a more principled definition.
- CurrentCorrection.isKeyword() < Correction.isKeyword() ||
- Correction.getAsString(SemaRef.getLangOpts()) <
- CurrentCorrection.getAsString(SemaRef.getLangOpts()))
- CurrentCorrection = Correction;
+ if (!CList.empty() && !CList.back().isResolved())
+ CList.pop_back();
+ if (NamedDecl *NewND = Correction.getCorrectionDecl()) {
+ std::string CorrectionStr = Correction.getAsString(SemaRef.getLangOpts());
+ for (TypoResultList::iterator RI = CList.begin(), RIEnd = CList.end();
+ RI != RIEnd; ++RI) {
+ // If the Correction refers to a decl already in the result list,
+ // replace the existing result if the string representation of Correction
+ // comes before the current result alphabetically, then stop as there is
+ // nothing more to be done to add Correction to the candidate set.
+ if (RI->getCorrectionDecl() == NewND) {
+ if (CorrectionStr < RI->getAsString(SemaRef.getLangOpts()))
+ *RI = Correction;
+ return;
+ }
+ }
+ }
+ if (CList.empty() || Correction.isResolved())
+ CList.push_back(Correction);
while (CorrectionResults.size() > MaxTypoDistanceResultSets)
erase(llvm::prior(CorrectionResults.end()));
@@ -3862,16 +3875,30 @@
// If the item already has been looked up or is a keyword, keep it.
// If a validator callback object was given, drop the correction
// unless it passes validation.
- if (I->second.isResolved()) {
+ bool Viable = false;
+ for (TypoResultList::iterator RI = I->second.begin(), RIEnd = I->second.end();
+ RI != RIEnd; /* Increment in loop. */) {
+ TypoResultList::iterator Prev = RI;
+ ++RI;
+ if (Prev->isResolved()) {
+ if (!isCandidateViable(CCC, *Prev))
+ I->second.erase(Prev);
+ else
+ Viable = true;
+ }
+ }
+ if (Viable || I->second.empty()) {
TypoCorrectionConsumer::result_iterator Prev = I;
++I;
- if (!isCandidateViable(CCC, Prev->second))
+ if (!Viable)
DI->second.erase(Prev);
continue;
}
+ assert(I->second.size() == 1 && "Expected a single unresolved candidate");
// Perform name lookup on this name.
- IdentifierInfo *Name = I->second.getCorrectionAsIdentifierInfo();
+ TypoCorrection &Candidate = I->second.front();
+ IdentifierInfo *Name = Candidate.getCorrectionAsIdentifierInfo();
LookupPotentialTypoResult(*this, TmpRes, Name, S, SS, MemberContext,
EnteringContext, CCC.IsObjCIvarLookup);
@@ -3879,7 +3906,7 @@
case LookupResult::NotFound:
case LookupResult::NotFoundInCurrentInstantiation:
case LookupResult::FoundUnresolvedValue:
- QualifiedResults.push_back(I->second);
+ QualifiedResults.push_back(Candidate);
// We didn't find this name in our scope, or didn't like what we found;
// ignore it.
{
@@ -3900,18 +3927,18 @@
for (LookupResult::iterator TRD = TmpRes.begin(),
TRDEnd = TmpRes.end();
TRD != TRDEnd; ++TRD)
- I->second.addCorrectionDecl(*TRD);
+ Candidate.addCorrectionDecl(*TRD);
++I;
- if (!isCandidateViable(CCC, Prev->second))
+ if (!isCandidateViable(CCC, Candidate))
DI->second.erase(Prev);
break;
}
case LookupResult::Found: {
TypoCorrectionConsumer::result_iterator Prev = I;
- I->second.setCorrectionDecl(TmpRes.getAsSingle<NamedDecl>());
+ Candidate.setCorrectionDecl(TmpRes.getAsSingle<NamedDecl>());
++I;
- if (!isCandidateViable(CCC, Prev->second))
+ if (!isCandidateViable(CCC, Candidate))
DI->second.erase(Prev);
break;
}
@@ -3998,8 +4025,9 @@
// If only a single name remains, return that result.
if (BestResults.size() == 1) {
- const llvm::StringMapEntry<TypoCorrection> &Correction = *(BestResults.begin());
- const TypoCorrection &Result = Correction.second;
+ const TypoResultList &CorrectionList = BestResults.begin()->second;
+ const TypoCorrection &Result = CorrectionList.front();
+ if (CorrectionList.size() != 1) return TypoCorrection();
// Don't correct to a keyword that's the same as the typo; the keyword
// wasn't actually in scope.
@@ -4017,7 +4045,7 @@
// some instances of CTC_Unknown, while WantRemainingKeywords is true
// for CTC_Unknown but not for CTC_ObjCMessageReceiver.
&& CCC.WantObjCSuper && !CCC.WantRemainingKeywords
- && BestResults["super"].isKeyword()) {
+ && BestResults["super"].front().isKeyword()) {
// Prefer 'super' when we're completing in a message-receiver
// context.
@@ -4027,9 +4055,9 @@
// Record the correction for unqualified lookup.
if (IsUnqualifiedLookup)
- UnqualifiedTyposCorrected[Typo] = BestResults["super"];
+ UnqualifiedTyposCorrected[Typo] = BestResults["super"].front();
- return BestResults["super"];
+ return BestResults["super"].front();
}
// If this was an unqualified lookup and we believe the callback object did
Modified: cfe/trunk/test/SemaCXX/typo-correction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/typo-correction.cpp?rev=157823&r1=157822&r2=157823&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/typo-correction.cpp (original)
+++ cfe/trunk/test/SemaCXX/typo-correction.cpp Fri Jun 1 13:11:16 2012
@@ -197,3 +197,12 @@
unsinged : 4; // expected-error{{did you mean 'unsigned'}}
};
}
+
+namespace PR12951 {
+// If there are two corrections that have the same identifier and edit distance
+// and only differ by their namespaces, don't suggest either as a correction
+// since both are equally likely corrections.
+namespace foobar { struct Thing {}; }
+namespace bazquux { struct Thing {}; }
+void f() { Thing t; } // expected-error{{unknown type name 'Thing'}}
+}
More information about the cfe-commits
mailing list