summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema
diff options
context:
space:
mode:
authorKaelyn Takata <rikka@google.com>2014-11-20 22:06:30 +0000
committerKaelyn Takata <rikka@google.com>2014-11-20 22:06:30 +0000
commit3f9794f288d89d33fe42e89cdf57371784bf0258 (patch)
treef813c8dfbd6d2cd9d0874f123f7fb7f66007b3b1 /clang/lib/Sema
parent6fc91a9d5e7d151890c7fc344e1999b8b11f34c2 (diff)
downloadbcm5719-llvm-3f9794f288d89d33fe42e89cdf57371784bf0258.tar.gz
bcm5719-llvm-3f9794f288d89d33fe42e89cdf57371784bf0258.zip
Factor out the default recovery handling.
The default handling is extended to properly create member expressions and Objective-C ivar references. Also detect and reject cases where multiple corrections have identical correction distances and are valid, instead of suggesting the first one that is found. llvm-svn: 222462
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r--clang/lib/Sema/SemaExprCXX.cpp91
1 files changed, 77 insertions, 14 deletions
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 02a657fd257..abd5b9d471b 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -5920,6 +5920,60 @@ static void CheckIfAnyEnclosingLambdasMustCaptureAnyPotentialCaptures(
CurrentLSI->clearPotentialCaptures();
}
+static ExprResult attemptRecovery(Sema &SemaRef,
+ const TypoCorrectionConsumer &Consumer,
+ TypoCorrection TC) {
+ LookupResult R(SemaRef, Consumer.getLookupResult().getLookupNameInfo(),
+ Consumer.getLookupResult().getLookupKind());
+ const CXXScopeSpec *SS = Consumer.getSS();
+ CXXScopeSpec NewSS;
+
+ // Use an approprate CXXScopeSpec for building the expr.
+ if (auto *NNS = TC.getCorrectionSpecifier())
+ NewSS.MakeTrivial(SemaRef.Context, NNS, TC.getCorrectionRange());
+ else if (SS && !TC.WillReplaceSpecifier())
+ NewSS = *SS;
+
+ if (auto *ND = TC.getCorrectionDecl()) {
+ R.addDecl(ND);
+ if (ND->isCXXClassMember()) {
+ // Figure out the correct naming class to ad to the LookupResult.
+ CXXRecordDecl *Record = nullptr;
+ if (auto *NNS = TC.getCorrectionSpecifier())
+ Record = NNS->getAsType()->getAsCXXRecordDecl();
+ if (!Record)
+ Record = cast<CXXRecordDecl>(ND->getDeclContext()->getRedeclContext());
+ R.setNamingClass(Record);
+
+ // Detect and handle the case where the decl might be an implicit
+ // member.
+ bool MightBeImplicitMember;
+ if (!Consumer.isAddressOfOperand())
+ MightBeImplicitMember = true;
+ else if (!NewSS.isEmpty())
+ MightBeImplicitMember = false;
+ else if (R.isOverloadedResult())
+ MightBeImplicitMember = false;
+ else if (R.isUnresolvableResult())
+ MightBeImplicitMember = true;
+ else
+ MightBeImplicitMember = isa<FieldDecl>(ND) ||
+ isa<IndirectFieldDecl>(ND) ||
+ isa<MSPropertyDecl>(ND);
+
+ if (MightBeImplicitMember)
+ return SemaRef.BuildPossibleImplicitMemberExpr(
+ NewSS, /*TemplateKWLoc*/ SourceLocation(), R,
+ /*TemplateArgs*/ nullptr);
+ } else if (auto *Ivar = dyn_cast<ObjCIvarDecl>(ND)) {
+ return SemaRef.LookupInObjCMethod(R, Consumer.getScope(),
+ Ivar->getIdentifier());
+ }
+ }
+
+ return SemaRef.BuildDeclarationNameExpr(NewSS, R, false);
+}
+
namespace {
class TransformTypos : public TreeTransform<TransformTypos> {
typedef TreeTransform<TransformTypos> BaseTransform;
@@ -6049,21 +6103,30 @@ public:
// For the first TypoExpr and an uncached TypoExpr, find the next likely
// typo correction and return it.
while (TypoCorrection TC = State.Consumer->getNextCorrection()) {
- ExprResult NE;
- if (State.RecoveryHandler) {
- NE = State.RecoveryHandler(SemaRef, E, TC);
- } else {
- LookupResult R(SemaRef,
- State.Consumer->getLookupResult().getLookupNameInfo(),
- State.Consumer->getLookupResult().getLookupKind());
- if (!TC.isKeyword())
- R.addDecl(TC.getCorrectionDecl());
- NE = SemaRef.BuildDeclarationNameExpr(CXXScopeSpec(), R, false);
- }
- assert(!NE.isUnset() &&
- "Typo was transformed into a valid-but-null ExprResult");
- if (!NE.isInvalid())
+ ExprResult NE = State.RecoveryHandler ?
+ State.RecoveryHandler(SemaRef, E, TC) :
+ attemptRecovery(SemaRef, *State.Consumer, TC);
+ if (!NE.isInvalid()) {
+ // Check whether there is a second viable correction with the same edit
+ // distance--in which case do not suggest anything since both are
+ // equally good candidates for correcting the typo.
+ Sema::SFINAETrap LocalTrap(SemaRef);
+ TypoCorrection Next;
+ while ((Next = State.Consumer->peekNextCorrection()) &&
+ Next.getEditDistance(false) == TC.getEditDistance(false)) {
+ ExprResult Res =
+ State.RecoveryHandler
+ ? State.RecoveryHandler(SemaRef, E, Next)
+ : attemptRecovery(SemaRef, *State.Consumer, Next);
+ if (!Res.isInvalid()) {
+ NE = ExprError();
+ State.Consumer->getNextCorrection();
+ }
+ }
+ assert(!NE.isUnset() &&
+ "Typo was transformed into a valid-but-null ExprResult");
return CacheEntry = NE;
+ }
}
return CacheEntry = ExprError();
}
OpenPOWER on IntegriCloud