Index: include/clang/AST/DeclCXX.h =================================================================== --- include/clang/AST/DeclCXX.h +++ include/clang/AST/DeclCXX.h @@ -2158,6 +2158,9 @@ /// of this initializer in the original sources, counting from 0. unsigned SourceOrder : 13; + /// Whether this initializer was typo-corrected. + unsigned IsTypoCorrected : 1; + public: /// \brief Creates a new base-class initializer. explicit @@ -2312,6 +2315,11 @@ /// \brief Get the initializer. Expr *getInit() const { return static_cast(Init); } + + /// True iff the initializer was constructed during typo-correction. + bool isTypoCorrected() const { return IsTypoCorrected; } + + void setIsTypoCorrected(bool V = true) { IsTypoCorrected = V; } }; /// Description of a constructor that was inherited from a base class. Index: include/clang/AST/Expr.h =================================================================== --- include/clang/AST/Expr.h +++ include/clang/AST/Expr.h @@ -850,6 +850,11 @@ return skipRValueSubobjectAdjustments(CommaLHSs, Adjustments); } + /// True iff the expression was constructed during typo-correction. + bool isTypoCorrected() const; + + void setIsTypoCorrected(bool V = true); + static bool classof(const Stmt *T) { return T->getStmtClass() >= firstExprConstant && T->getStmtClass() <= lastExprConstant; @@ -1013,6 +1018,7 @@ DeclRefExprBits.HadMultipleCandidates = 0; DeclRefExprBits.RefersToEnclosingVariableOrCapture = RefersToEnclosingVariableOrCapture; + DeclRefExprBits.IsTypoCorrected = 0; computeDependence(D->getASTContext()); } @@ -1166,6 +1172,13 @@ return DeclRefExprBits.RefersToEnclosingVariableOrCapture; } + /// True iff the expression was constructed during typo-correction. + bool isTypoCorrected() const { return DeclRefExprBits.IsTypoCorrected; } + + void setIsTypoCorrected(bool V = true) { + DeclRefExprBits.IsTypoCorrected = V; + } + static bool classof(const Stmt *T) { return T->getStmtClass() == DeclRefExprClass; } @@ -2447,6 +2460,7 @@ IsArrow(isarrow), HasQualifierOrFoundDecl(false), HasTemplateKWAndArgsInfo(false), HadMultipleCandidates(false) { assert(memberdecl->getDeclName() == NameInfo.getName()); + MemberExprBits.IsTypoCorrected = 0; } // NOTE: this constructor should be used only when it is known that @@ -2462,7 +2476,9 @@ Base(base), MemberDecl(memberdecl), MemberDNLoc(), MemberLoc(l), OperatorLoc(operatorloc), IsArrow(isarrow), HasQualifierOrFoundDecl(false), HasTemplateKWAndArgsInfo(false), - HadMultipleCandidates(false) {} + HadMultipleCandidates(false) { + MemberExprBits.IsTypoCorrected = 0; + } static MemberExpr *Create(const ASTContext &C, Expr *base, bool isarrow, SourceLocation OperatorLoc, @@ -2617,6 +2633,11 @@ return LO.AppleKext || !hasQualifier(); } + /// True iff the expression was constructed during typo-correction. + bool isTypoCorrected() const { return MemberExprBits.IsTypoCorrected; } + + void setIsTypoCorrected(bool V = true) { MemberExprBits.IsTypoCorrected = V; } + static bool classof(const Stmt *T) { return T->getStmtClass() == MemberExprClass; } Index: include/clang/AST/ExprObjC.h =================================================================== --- include/clang/AST/ExprObjC.h +++ include/clang/AST/ExprObjC.h @@ -487,20 +487,23 @@ bool IsFreeIvar:1; // True if ivar reference has no base (self assumed). public: - ObjCIvarRefExpr(ObjCIvarDecl *d, QualType t, - SourceLocation l, SourceLocation oploc, - Expr *base, - bool arrow = false, bool freeIvar = false) : - Expr(ObjCIvarRefExprClass, t, VK_LValue, - d->isBitField() ? OK_BitField : OK_Ordinary, - /*TypeDependent=*/false, base->isValueDependent(), - base->isInstantiationDependent(), - base->containsUnexpandedParameterPack()), - D(d), Base(base), Loc(l), OpLoc(oploc), - IsArrow(arrow), IsFreeIvar(freeIvar) {} + ObjCIvarRefExpr(ObjCIvarDecl *d, QualType t, SourceLocation l, + SourceLocation oploc, Expr *base, bool arrow = false, + bool freeIvar = false) + : Expr(ObjCIvarRefExprClass, t, VK_LValue, + d->isBitField() ? OK_BitField : OK_Ordinary, + /*TypeDependent=*/false, base->isValueDependent(), + base->isInstantiationDependent(), + base->containsUnexpandedParameterPack()), + D(d), Base(base), Loc(l), OpLoc(oploc), IsArrow(arrow), + IsFreeIvar(freeIvar) { + ObjCIvarRefExprBits.IsTypoCorrected = 0; + } explicit ObjCIvarRefExpr(EmptyShell Empty) - : Expr(ObjCIvarRefExprClass, Empty) {} + : Expr(ObjCIvarRefExprClass, Empty) { + ObjCIvarRefExprBits.IsTypoCorrected = 0; + } ObjCIvarDecl *getDecl() { return D; } const ObjCIvarDecl *getDecl() const { return D; } @@ -526,6 +529,13 @@ SourceLocation getOpLoc() const { return OpLoc; } void setOpLoc(SourceLocation L) { OpLoc = L; } + /// True iff the expression was constructed during typo-correction. + bool isTypoCorrected() const { return ObjCIvarRefExprBits.IsTypoCorrected; } + + void setIsTypoCorrected(bool V = true) { + ObjCIvarRefExprBits.IsTypoCorrected = V; + } + static bool classof(const Stmt *T) { return T->getStmtClass() == ObjCIvarRefExprClass; } @@ -580,6 +590,7 @@ PropertyOrGetter(PD, false), SetterAndMethodRefFlags(), IdLoc(l), ReceiverLoc(), Receiver(base) { assert(t->isSpecificPlaceholderType(BuiltinType::PseudoObject)); + ObjCPropertyRefExprBits.IsTypoCorrected = 0; } ObjCPropertyRefExpr(ObjCPropertyDecl *PD, QualType t, @@ -591,6 +602,7 @@ PropertyOrGetter(PD, false), SetterAndMethodRefFlags(), IdLoc(l), ReceiverLoc(sl), Receiver(st.getTypePtr()) { assert(t->isSpecificPlaceholderType(BuiltinType::PseudoObject)); + ObjCPropertyRefExprBits.IsTypoCorrected = 0; } ObjCPropertyRefExpr(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter, @@ -602,6 +614,7 @@ PropertyOrGetter(Getter, true), SetterAndMethodRefFlags(Setter, 0), IdLoc(IdLoc), ReceiverLoc(), Receiver(Base) { assert(T->isSpecificPlaceholderType(BuiltinType::PseudoObject)); + ObjCPropertyRefExprBits.IsTypoCorrected = 0; } ObjCPropertyRefExpr(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter, @@ -612,6 +625,7 @@ PropertyOrGetter(Getter, true), SetterAndMethodRefFlags(Setter, 0), IdLoc(IdLoc), ReceiverLoc(SuperLoc), Receiver(SuperTy.getTypePtr()) { assert(T->isSpecificPlaceholderType(BuiltinType::PseudoObject)); + ObjCPropertyRefExprBits.IsTypoCorrected = 0; } ObjCPropertyRefExpr(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter, @@ -622,10 +636,13 @@ PropertyOrGetter(Getter, true), SetterAndMethodRefFlags(Setter, 0), IdLoc(IdLoc), ReceiverLoc(ReceiverLoc), Receiver(Receiver) { assert(T->isSpecificPlaceholderType(BuiltinType::PseudoObject)); + ObjCPropertyRefExprBits.IsTypoCorrected = 0; } explicit ObjCPropertyRefExpr(EmptyShell Empty) - : Expr(ObjCPropertyRefExprClass, Empty) {} + : Expr(ObjCPropertyRefExprClass, Empty) { + ObjCPropertyRefExprBits.IsTypoCorrected = 0; + } bool isImplicitProperty() const { return PropertyOrGetter.getInt(); } bool isExplicitProperty() const { return !PropertyOrGetter.getInt(); } @@ -708,6 +725,15 @@ } SourceLocation getLocEnd() const LLVM_READONLY { return IdLoc; } + /// True iff the expression was constructed during typo-correction. + bool isTypoCorrected() const { + return ObjCPropertyRefExprBits.IsTypoCorrected; + } + + void setIsTypoCorrected(bool V = true) { + ObjCPropertyRefExprBits.IsTypoCorrected = V; + } + static bool classof(const Stmt *T) { return T->getStmtClass() == ObjCPropertyRefExprClass; } Index: include/clang/AST/Stmt.h =================================================================== --- include/clang/AST/Stmt.h +++ include/clang/AST/Stmt.h @@ -177,6 +177,31 @@ unsigned HasFoundDecl : 1; unsigned HadMultipleCandidates : 1; unsigned RefersToEnclosingVariableOrCapture : 1; + unsigned IsTypoCorrected : 1; + }; + + class MemberExprBitfields { + friend class MemberExpr; + friend class ASTStmtReader; + unsigned : NumExprBits; + + unsigned IsTypoCorrected : 1; + }; + + class ObjCIvarRefExprBitfields { + friend class ObjCIvarRefExpr; + friend class ASTStmtReader; + unsigned : NumExprBits; + + unsigned IsTypoCorrected : 1; + }; + + class ObjCPropertyRefExprBitfields { + friend class ObjCPropertyRefExpr; + friend class ASTStmtReader; + unsigned : NumExprBits; + + unsigned IsTypoCorrected : 1; }; class CastExprBitfields { @@ -270,6 +295,9 @@ FloatingLiteralBitfields FloatingLiteralBits; UnaryExprOrTypeTraitExprBitfields UnaryExprOrTypeTraitExprBits; DeclRefExprBitfields DeclRefExprBits; + MemberExprBitfields MemberExprBits; + ObjCIvarRefExprBitfields ObjCIvarRefExprBits; + ObjCPropertyRefExprBitfields ObjCPropertyRefExprBits; CastExprBitfields CastExprBits; CallExprBitfields CallExprBits; ExprWithCleanupsBitfields ExprWithCleanupsBits; Index: lib/AST/DeclCXX.cpp =================================================================== --- lib/AST/DeclCXX.cpp +++ lib/AST/DeclCXX.cpp @@ -1946,43 +1946,33 @@ SourceLocation L, Expr *Init, SourceLocation R, SourceLocation EllipsisLoc) - : Initializee(TInfo), MemberOrEllipsisLocation(EllipsisLoc), Init(Init), - LParenLoc(L), RParenLoc(R), IsDelegating(false), IsVirtual(IsVirtual), - IsWritten(false), SourceOrder(0) -{ -} + : Initializee(TInfo), MemberOrEllipsisLocation(EllipsisLoc), Init(Init), + LParenLoc(L), RParenLoc(R), IsDelegating(false), IsVirtual(IsVirtual), + IsWritten(false), SourceOrder(0), IsTypoCorrected(false) {} -CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context, - FieldDecl *Member, +CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context, FieldDecl *Member, SourceLocation MemberLoc, SourceLocation L, Expr *Init, SourceLocation R) - : Initializee(Member), MemberOrEllipsisLocation(MemberLoc), Init(Init), - LParenLoc(L), RParenLoc(R), IsDelegating(false), IsVirtual(false), - IsWritten(false), SourceOrder(0) -{ -} + : Initializee(Member), MemberOrEllipsisLocation(MemberLoc), Init(Init), + LParenLoc(L), RParenLoc(R), IsDelegating(false), IsVirtual(false), + IsWritten(false), SourceOrder(0), IsTypoCorrected(false) {} CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context, IndirectFieldDecl *Member, SourceLocation MemberLoc, SourceLocation L, Expr *Init, SourceLocation R) - : Initializee(Member), MemberOrEllipsisLocation(MemberLoc), Init(Init), - LParenLoc(L), RParenLoc(R), IsDelegating(false), IsVirtual(false), - IsWritten(false), SourceOrder(0) -{ -} + : Initializee(Member), MemberOrEllipsisLocation(MemberLoc), Init(Init), + LParenLoc(L), RParenLoc(R), IsDelegating(false), IsVirtual(false), + IsWritten(false), SourceOrder(0), IsTypoCorrected(false) {} CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context, - TypeSourceInfo *TInfo, - SourceLocation L, Expr *Init, - SourceLocation R) - : Initializee(TInfo), MemberOrEllipsisLocation(), Init(Init), - LParenLoc(L), RParenLoc(R), IsDelegating(true), IsVirtual(false), - IsWritten(false), SourceOrder(0) -{ -} + TypeSourceInfo *TInfo, SourceLocation L, + Expr *Init, SourceLocation R) + : Initializee(TInfo), MemberOrEllipsisLocation(), Init(Init), LParenLoc(L), + RParenLoc(R), IsDelegating(true), IsVirtual(false), IsWritten(false), + SourceOrder(0), IsTypoCorrected(false) {} TypeLoc CXXCtorInitializer::getBaseClassLoc() const { if (isBaseInitializer()) Index: lib/AST/Expr.cpp =================================================================== --- lib/AST/Expr.cpp +++ lib/AST/Expr.cpp @@ -226,6 +226,29 @@ llvm_unreachable("unknown expression kind"); } +bool Expr::isTypoCorrected() const { + if (const DeclRefExpr *DRE = dyn_cast(this)) + return DRE->isTypoCorrected(); + if (const auto *ME = dyn_cast(this)) + return ME->isTypoCorrected(); + if (const auto *IVar = dyn_cast(this)) + return IVar->isTypoCorrected(); + if (const auto *PRef = dyn_cast(this)) + return PRef->isTypoCorrected(); + return false; +} + +void Expr::setIsTypoCorrected(bool V) { + if (auto *DRE = dyn_cast(this)) + DRE->setIsTypoCorrected(V); + else if (auto *ME = dyn_cast(this)) + ME->setIsTypoCorrected(V); + else if (auto *IVar = dyn_cast(this)) + IVar->setIsTypoCorrected(V); + else if (auto *PRef = dyn_cast(this)) + PRef->setIsTypoCorrected(V); +} + //===----------------------------------------------------------------------===// // Primary Expressions. //===----------------------------------------------------------------------===// @@ -369,6 +392,7 @@ = (TemplateArgs || TemplateKWLoc.isValid()) ? 1 : 0; DeclRefExprBits.RefersToEnclosingVariableOrCapture = RefersToEnclosingVariableOrCapture; + DeclRefExprBits.IsTypoCorrected = 0; if (TemplateArgs) { bool Dependent = false; bool InstantiationDependent = false; Index: lib/Sema/SemaDecl.cpp =================================================================== --- lib/Sema/SemaDecl.cpp +++ lib/Sema/SemaDecl.cpp @@ -887,6 +887,7 @@ bool SecondTry = false; bool IsFilteredTemplateName = false; + bool IsTypoCorrected = false; Corrected: switch (Result.getResultKind()) { @@ -983,9 +984,12 @@ if (ObjCIvarDecl *Ivar = Result.getAsSingle()) { Result.clear(); ExprResult E(LookupInObjCMethod(Result, S, Ivar->getIdentifier())); + if (E.isUsable()) + E.get()->setIsTypoCorrected(); return E; } + IsTypoCorrected = true; goto Corrected; } } @@ -1144,12 +1148,19 @@ return ParsedType::make(T); } - if (FirstDecl->isCXXClassMember()) - return BuildPossibleImplicitMemberExpr(SS, SourceLocation(), Result, - nullptr, S); + if (FirstDecl->isCXXClassMember()) { + ExprResult ME = BuildPossibleImplicitMemberExpr(SS, SourceLocation(), + Result, nullptr, S); + if (IsTypoCorrected && ME.isUsable()) + ME.get()->setIsTypoCorrected(); + return ME; + } bool ADL = UseArgumentDependentLookup(SS, Result, NextToken.is(tok::l_paren)); - return BuildDeclarationNameExpr(SS, Result, ADL); + ExprResult DNE = BuildDeclarationNameExpr(SS, Result, ADL); + if (IsTypoCorrected && DNE.isUsable()) + DNE.get()->setIsTypoCorrected(); + return DNE; } Sema::TemplateNameKindForDiagnostics Index: lib/Sema/SemaDeclCXX.cpp =================================================================== --- lib/Sema/SemaDeclCXX.cpp +++ lib/Sema/SemaDeclCXX.cpp @@ -3807,7 +3807,10 @@ diagnoseTypo(Corr, PDiag(diag::err_mem_init_not_member_or_class_suggest) << MemberOrBase << true); - return BuildMemberInitializer(Member, Init, IdLoc); + MemInitResult MI = BuildMemberInitializer(Member, Init, IdLoc); + if (MI.isUsable()) + MI.get()->setIsTypoCorrected(); + return MI; } else if (TypeDecl *Type = Corr.getCorrectionDeclAs()) { const CXXBaseSpecifier *DirectBaseSpec; const CXXBaseSpecifier *VirtualBaseSpec; Index: lib/Sema/SemaExprCXX.cpp =================================================================== --- lib/Sema/SemaExprCXX.cpp +++ lib/Sema/SemaExprCXX.cpp @@ -7231,8 +7231,12 @@ } } - return SemaRef.BuildDeclarationNameExpr(NewSS, R, /*NeedsADL*/ false, - /*AcceptInvalidDecl*/ true); + ExprResult Result = + SemaRef.BuildDeclarationNameExpr(NewSS, R, /*NeedsADL*/ false, + /*AcceptInvalidDecl*/ true); + if (Result.isUsable()) + Result.get()->setIsTypoCorrected(); + return Result; } namespace { Index: lib/Sema/SemaExprMember.cpp =================================================================== --- lib/Sema/SemaExprMember.cpp +++ lib/Sema/SemaExprMember.cpp @@ -720,9 +720,12 @@ for (NamedDecl *ND : TC) R.addDecl(ND); R.resolveKind(); - return SemaRef.BuildMemberReferenceExpr( + ExprResult CorrectedME = SemaRef.BuildMemberReferenceExpr( BaseExpr, BaseExpr->getType(), OpLoc, IsArrow, SS, SourceLocation(), nullptr, R, nullptr, nullptr); + if (CorrectedME.isUsable()) + CorrectedME.get()->setIsTypoCorrected(); + return CorrectedME; }, Sema::CTK_ErrorRecovery, DC); @@ -1364,6 +1367,7 @@ ObjCInterfaceDecl *ClassDeclared = nullptr; ObjCIvarDecl *IV = IDecl->lookupInstanceVariable(Member, ClassDeclared); + bool IsTypoCorrected = false; if (!IV) { // Attempt to correct for typos in ivar names. auto Validator = llvm::make_unique>(); @@ -1376,6 +1380,7 @@ Corrected, S.PDiag(diag::err_typecheck_member_reference_ivar_suggest) << IDecl->getDeclName() << MemberName); + IsTypoCorrected = true; // Figure out the class that declares the ivar. assert(!ClassDeclared); @@ -1481,6 +1486,8 @@ if (!S.Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, MemberLoc)) S.recordUseOfEvaluatedWeak(Result); } + if (IsTypoCorrected) + Result->setIsTypoCorrected(); return Result; } Index: lib/Sema/SemaExprObjC.cpp =================================================================== --- lib/Sema/SemaExprObjC.cpp +++ lib/Sema/SemaExprObjC.cpp @@ -1903,9 +1903,12 @@ } else { diagnoseTypo(Corrected, PDiag(diag::err_property_not_found_suggest) << MemberName << QualType(OPT, 0)); - return HandleExprPropertyRefExpr(OPT, BaseExpr, OpLoc, - TypoResult, MemberLoc, - SuperLoc, SuperType, Super); + ExprResult CorrectPRE = + HandleExprPropertyRefExpr(OPT, BaseExpr, OpLoc, TypoResult, MemberLoc, + SuperLoc, SuperType, Super); + if (CorrectPRE.isUsable()) + CorrectPRE.get()->setIsTypoCorrected(); + return CorrectPRE; } } ObjCInterfaceDecl *ClassDeclared; Index: lib/Sema/SemaOverload.cpp =================================================================== --- lib/Sema/SemaOverload.cpp +++ lib/Sema/SemaOverload.cpp @@ -11694,6 +11694,8 @@ if (NewFn.isInvalid()) return ExprError(); + if (AllowTypoCorrection) + NewFn.get()->setIsTypoCorrected(); // This shouldn't cause an infinite loop because we're giving it // an expression with viable lookup results, which should never Index: lib/Sema/SemaPseudoObject.cpp =================================================================== --- lib/Sema/SemaPseudoObject.cpp +++ lib/Sema/SemaPseudoObject.cpp @@ -59,17 +59,22 @@ if (refExpr->isClassReceiver() || refExpr->isSuperReceiver()) return refExpr; + ObjCPropertyRefExpr *Result; if (refExpr->isExplicitProperty()) { - return new (S.Context) ObjCPropertyRefExpr( + Result = new (S.Context) ObjCPropertyRefExpr( refExpr->getExplicitProperty(), refExpr->getType(), refExpr->getValueKind(), refExpr->getObjectKind(), refExpr->getLocation(), SpecificCallback(refExpr->getBase(), 0)); + } else { + Result = new (S.Context) ObjCPropertyRefExpr( + refExpr->getImplicitPropertyGetter(), + refExpr->getImplicitPropertySetter(), refExpr->getType(), + refExpr->getValueKind(), refExpr->getObjectKind(), + refExpr->getLocation(), SpecificCallback(refExpr->getBase(), 0)); } - return new (S.Context) ObjCPropertyRefExpr( - refExpr->getImplicitPropertyGetter(), - refExpr->getImplicitPropertySetter(), refExpr->getType(), - refExpr->getValueKind(), refExpr->getObjectKind(), - refExpr->getLocation(), SpecificCallback(refExpr->getBase(), 0)); + if (refExpr->isTypoCorrected()) + Result->setIsTypoCorrected(); + return Result; } Expr *rebuildObjCSubscriptRefExpr(ObjCSubscriptRefExpr *refExpr) { assert(refExpr->getBaseExpr()); Index: lib/Sema/SemaTemplateInstantiateDecl.cpp =================================================================== --- lib/Sema/SemaTemplateInstantiateDecl.cpp +++ lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -4594,6 +4594,8 @@ AnyErrors = true; New->setInvalidDecl(); } else { + if (Init->isTypoCorrected()) + NewInit.get()->setIsTypoCorrected(); NewInits.push_back(NewInit.get()); } } Index: lib/Sema/TreeTransform.h =================================================================== --- lib/Sema/TreeTransform.h +++ lib/Sema/TreeTransform.h @@ -8896,8 +8896,11 @@ return ExprError(); } - return getDerived().RebuildDeclRefExpr(QualifierLoc, ND, NameInfo, - TemplateArgs); + ExprResult Result = + getDerived().RebuildDeclRefExpr(QualifierLoc, ND, NameInfo, TemplateArgs); + if (E->isTypoCorrected() && Result.isUsable()) + Result.getAs()->setIsTypoCorrected(); + return Result; } template @@ -9325,16 +9328,14 @@ return ExprError(); } - return getDerived().RebuildMemberExpr(Base.get(), FakeOperatorLoc, - E->isArrow(), - QualifierLoc, - TemplateKWLoc, - MemberNameInfo, - Member, - FoundDecl, - (E->hasExplicitTemplateArgs() - ? &TransArgs : nullptr), - FirstQualifierInScope); + ExprResult Result = getDerived().RebuildMemberExpr( + Base.get(), FakeOperatorLoc, E->isArrow(), QualifierLoc, TemplateKWLoc, + MemberNameInfo, Member, FoundDecl, + (E->hasExplicitTemplateArgs() ? &TransArgs : nullptr), + FirstQualifierInScope); + if (E->isTypoCorrected() && Result.isUsable()) + E->setIsTypoCorrected(); + return Result; } template @@ -11994,9 +11995,12 @@ Base.get() == E->getBase()) return E; - return getDerived().RebuildObjCIvarRefExpr(Base.get(), E->getDecl(), - E->getLocation(), - E->isArrow(), E->isFreeIvar()); + ExprResult Result = getDerived().RebuildObjCIvarRefExpr( + Base.get(), E->getDecl(), E->getLocation(), E->isArrow(), + E->isFreeIvar()); + if (E->isTypoCorrected() && Result.isUsable()) + Result.getAs()->setIsTypoCorrected(); + return Result; } template @@ -12019,16 +12023,18 @@ Base.get() == E->getBase()) return E; + ExprResult Result; if (E->isExplicitProperty()) - return getDerived().RebuildObjCPropertyRefExpr(Base.get(), - E->getExplicitProperty(), - E->getLocation()); - - return getDerived().RebuildObjCPropertyRefExpr(Base.get(), - SemaRef.Context.PseudoObjectTy, - E->getImplicitPropertyGetter(), - E->getImplicitPropertySetter(), - E->getLocation()); + Result = getDerived().RebuildObjCPropertyRefExpr( + Base.get(), E->getExplicitProperty(), E->getLocation()); + else + Result = getDerived().RebuildObjCPropertyRefExpr( + Base.get(), SemaRef.Context.PseudoObjectTy, + E->getImplicitPropertyGetter(), E->getImplicitPropertySetter(), + E->getLocation()); + if (E->isTypoCorrected() && Result.isUsable()) + Result.getAs()->setIsTypoCorrected(); + return Result; } template Index: lib/Serialization/ASTReader.cpp =================================================================== --- lib/Serialization/ASTReader.cpp +++ lib/Serialization/ASTReader.cpp @@ -8714,6 +8714,8 @@ unsigned SourceOrder = Record[Idx++]; BOMInit->setSourceOrder(SourceOrder); } + if (/*IsTypoCorrected*/ Record[Idx++]) + Init->setIsTypoCorrected(); CtorInitializers[i] = BOMInit; } Index: lib/Serialization/ASTReaderStmt.cpp =================================================================== --- lib/Serialization/ASTReaderStmt.cpp +++ lib/Serialization/ASTReaderStmt.cpp @@ -462,6 +462,7 @@ E->DeclRefExprBits.HasTemplateKWAndArgsInfo = Record.readInt(); E->DeclRefExprBits.HadMultipleCandidates = Record.readInt(); E->DeclRefExprBits.RefersToEnclosingVariableOrCapture = Record.readInt(); + E->DeclRefExprBits.IsTypoCorrected = Record.readInt(); unsigned NumTemplateArgs = 0; if (E->hasTemplateKWAndArgsInfo()) NumTemplateArgs = Record.readInt(); @@ -1040,11 +1041,13 @@ E->setBase(Record.readSubExpr()); E->setIsArrow(Record.readInt()); E->setIsFreeIvar(Record.readInt()); + E->setIsTypoCorrected(Record.readInt()); } void ASTStmtReader::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) { VisitExpr(E); unsigned MethodRefFlags = Record.readInt(); + E->setIsTypoCorrected(Record.readInt()); bool Implicit = Record.readInt() != 0; if (Implicit) { ObjCMethodDecl *Getter = ReadDeclAs(); @@ -3232,6 +3235,7 @@ assert(Record.getIdx() == 0); NestedNameSpecifierLoc QualifierLoc; + bool IsTypoCorrected = Record.readInt(); if (Record.readInt()) { // HasQualifier. QualifierLoc = Record.readNestedNameSpecifierLoc(); } @@ -3268,6 +3272,8 @@ TemplateKWLoc, MemberD, FoundDecl, MemberNameInfo, HasTemplateKWAndArgsInfo ? &ArgInfo : nullptr, T, VK, OK); + if (IsTypoCorrected) + cast(S)->setIsTypoCorrected(); Record.readDeclarationNameLoc(cast(S)->MemberDNLoc, MemberD->getDeclName()); if (HadMultipleCandidates) Index: lib/Serialization/ASTWriter.cpp =================================================================== --- lib/Serialization/ASTWriter.cpp +++ lib/Serialization/ASTWriter.cpp @@ -5882,6 +5882,7 @@ Writer.push_back(Init->isWritten()); if (Init->isWritten()) Writer.push_back(Init->getSourceOrder()); + Writer.push_back(Init->isTypoCorrected()); } return Writer.Emit(serialization::DECL_CXX_CTOR_INITIALIZERS); Index: lib/Serialization/ASTWriterDecl.cpp =================================================================== --- lib/Serialization/ASTWriterDecl.cpp +++ lib/Serialization/ASTWriterDecl.cpp @@ -2102,6 +2102,7 @@ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //HadMultipleCandidates Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // RefersToEnclosingVariableOrCapture + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsTypoCorrected Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclRef Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Location DeclRefExprAbbrev = Stream.EmitAbbrev(std::move(Abv)); Index: lib/Serialization/ASTWriterStmt.cpp =================================================================== --- lib/Serialization/ASTWriterStmt.cpp +++ lib/Serialization/ASTWriterStmt.cpp @@ -402,6 +402,7 @@ Record.push_back(E->hasTemplateKWAndArgsInfo()); Record.push_back(E->hadMultipleCandidates()); Record.push_back(E->refersToEnclosingVariableOrCapture()); + Record.push_back(E->isTypoCorrected()); if (E->hasTemplateKWAndArgsInfo()) { unsigned NumTemplateArgs = E->getNumTemplateArgs(); @@ -593,6 +594,7 @@ void ASTStmtWriter::VisitMemberExpr(MemberExpr *E) { // Don't call VisitExpr, we'll write everything here. + Record.push_back(E->isTypoCorrected()); Record.push_back(E->hasQualifier()); if (E->hasQualifier()) Record.AddNestedNameSpecifierLoc(E->getQualifierLoc()); @@ -1030,12 +1032,14 @@ Record.AddStmt(E->getBase()); Record.push_back(E->isArrow()); Record.push_back(E->isFreeIvar()); + Record.push_back(E->isTypoCorrected()); Code = serialization::EXPR_OBJC_IVAR_REF_EXPR; } void ASTStmtWriter::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) { VisitExpr(E); Record.push_back(E->SetterAndMethodRefFlags.getInt()); + Record.push_back(E->isTypoCorrected()); Record.push_back(E->isImplicitProperty()); if (E->isImplicitProperty()) { Record.AddDeclRef(E->getImplicitPropertyGetter()); Index: test/Index/typo-annotate-tokens.mm =================================================================== --- /dev/null +++ test/Index/typo-annotate-tokens.mm @@ -0,0 +1,33 @@ +// RUN: c-index-test -test-annotate-tokens=%s:1:1:33:1 %s -fspell-checking | FileCheck %s + +struct Structure {}; + +Structure *test555() { + Structure *myOwnStringOrig = 0; + return myOwnStringNew; // CHECK: Identifier: "myOwnStringNew" {{\[}}[[@LINE]]:10 - [[@LINE]]:24{{\]}} ReturnStmt= +} + +class AClass { +public: + int MyField; + void MyMethod(); + + void anotherMethod(); + + AClass() : MyFild(0) {} // CHECK: Identifier: "MyFild" {{\[}}[[@LINE]]:14 - [[@LINE]]:20{{\]}} CXXConstructor=AClass +}; + +void AClass::anotherMethod() { + MYField = 0; // CHECK: Identifier: "MYField" {{\[}}[[@LINE]]:3 - [[@LINE]]:10{{\]}} BinaryOperator= + MYMethod(); // CHECK: Identifier: "MYMethod" {{\[}}[[@LINE]]:3 - [[@LINE]]:11{{\]}} CallExpr=MyMethod +} + +@interface MyInterface + +@property int MyProperty; + +@end + +void foo(MyInterface *I) { + I.MyProprty = 0; // CHECK: Identifier: "MyProprty" {{\[}}[[@LINE]]:5 - [[@LINE]]:14{{\]}} BinaryOperator= +} Index: test/Index/typo-file-refs.cpp =================================================================== --- /dev/null +++ test/Index/typo-file-refs.cpp @@ -0,0 +1,45 @@ +struct Structure {}; + +Structure *test555() { + Structure *myOwnStringOrig = 0; + return myOwnStringNew; +} + +class AClass { +public: + int MyField; + void MyMethod(); + + void anotherMethod(); + + AClass() : MyFild(0) {} +}; + +void AClass::anotherMethod() { + MYField = 0; + MYMethod(); +} + +void refMember(AClass *C) { + C->MyFild = 1; + C->MyMethd(); +} + +// RUN: c-index-test \ + +// RUN: -file-refs-at=%s:4:14 \ +// CHECK: VarDecl=myOwnStringOrig:4:14 (Definition) +// CHECK-NEXT: VarDecl=myOwnStringOrig:4:14 (Definition) =[4:14 - 4:29] +// CHECK-NOT: DeclRefExpr=myOwnStringOrig + +// RUN: -file-refs-at=%s:10:7 \ +// CHECK-NEXT: FieldDecl=MyField:10:7 (Definition) +// CHECK-NEXT: FieldDecl=MyField:10:7 (Definition) =[10:7 - 10:14] +// CHECK-NOT: =MyField + +// RUN: -file-refs-at=%s:11:8 \ +// CHECK-NEXT: CXXMethod=MyMethod:11:8 +// CHECK-NEXT: CXXMethod=MyMethod:11:8 =[11:8 - 11:16] +// CHECK-NOT: MemberRefExpr=MyMethod + +// RUN: %s -fspell-checking | FileCheck %s Index: test/Index/typo-file-refs.m =================================================================== --- /dev/null +++ test/Index/typo-file-refs.m @@ -0,0 +1,76 @@ +struct Structure { + int MyCField; +}; + +void testMember(struct Structure *x) { + x->MyField = 0; +} + +@interface MyInterface + +@property int MyProperty; + +- (int)MyImplicit; +- (void)setMyImplicit:(int)x; + +@property (class) int MyClassProperty; + +- (void)MyMethod; + +@end + +@implementation MyInterface { + int MyIVar; +} + +- (void) method { + MyiVar = 0; + self->MyiVar = 1; + + self.MyProprty = 0; + int x = self.MyProprty; + + int y = self.MyImplict; + self.MyImplict = 2; + + MyInterface.MyClassProprty = 0; + int z = MyInterface.MyClassProprty; + + [self MyMethd]; +} + +@end + +// RUN: c-index-test \ + +// RUN: -file-refs-at=%s:2:7 \ +// CHECK: FieldDecl=MyCField:2:7 (Definition) +// CHECK-NEXT: FieldDecl=MyCField:2:7 (Definition) =[2:7 - 2:15] +// CHECK-NOT: MemberRefExpr=MyCField + +// RUN: -file-refs-at=%s:23:7 \ +// CHECK-NEXT: ObjCIvarDecl=MyIVar:23:7 (Definition) +// CHECK-NEXT: ObjCIvarDecl=MyIVar:23:7 (Definition) =[23:7 - 23:13] +// CHECK-NOT: MemberRefExpr=MyIVar + +// RUN: -file-refs-at=%s:11:15 \ +// CHECK-NEXT: ObjCPropertyDecl=MyProperty:11:15 +// CHECK-NEXT: ObjCPropertyDecl=MyProperty:11:15 =[11:15 - 11:25] +// CHECK-NOT: MemberRefExpr=MyProperty + +// RUN: -file-refs-at=%s:13:8 \ +// CHECK-NEXT: ObjCInstanceMethodDecl=MyImplicit:13:8 +// CHECK-NEXT: ObjCInstanceMethodDecl=MyImplicit:13:8 =[13:8 - 13:18] +// CHECK-NOT: MyImplicit + +// RUN: -file-refs-at=%s:16:23 \ +// CHECK-NEXT: ObjCPropertyDecl=MyClassProperty:16:23 [class,] +// CHECK-NEXT: ObjCPropertyDecl=MyClassProperty:16:23 [class,] =[16:23 - 16:38] +// CHECK-NOT: MyClassProperty + +// RUN: -file-refs-at=%s:18:9 \ +// CHECK-NEXT: ObjCInstanceMethodDecl=MyMethod:18:9 +// CHECK-NEXT: ObjCInstanceMethodDecl=MyMethod:18:9 =[18:9 - 18:17] +// CHECK-NOT: MyMethod + +// RUN: %s -fspell-checking | FileCheck %s Index: tools/libclang/CIndex.cpp =================================================================== --- tools/libclang/CIndex.cpp +++ tools/libclang/CIndex.cpp @@ -847,13 +847,15 @@ // Visit the initializers in source order for (unsigned I = 0, N = WrittenInits.size(); I != N; ++I) { CXXCtorInitializer *Init = WrittenInits[I]; - if (Init->isAnyMemberInitializer()) { - if (Visit(MakeCursorMemberRef(Init->getAnyMember(), - Init->getMemberLocation(), TU))) - return true; - } else if (TypeSourceInfo *TInfo = Init->getTypeSourceInfo()) { - if (Visit(TInfo->getTypeLoc())) - return true; + if (VisitTypoCorrected | !Init->isTypoCorrected()) { + if (Init->isAnyMemberInitializer()) { + if (Visit(MakeCursorMemberRef(Init->getAnyMember(), + Init->getMemberLocation(), TU))) + return true; + } else if (TypeSourceInfo *TInfo = Init->getTypeSourceInfo()) { + if (Visit(TInfo->getTypeLoc())) + return true; + } } // Visit the initializer value. @@ -6483,17 +6485,18 @@ public: AnnotateTokensWorker(CXToken *tokens, CXCursor *cursors, unsigned numTokens, CXTranslationUnit TU, SourceRange RegionOfInterest) - : Tokens(tokens), Cursors(cursors), - NumTokens(numTokens), TokIdx(0), PreprocessingTokIdx(0), - AnnotateVis(TU, - AnnotateTokensVisitor, this, - /*VisitPreprocessorLast=*/true, - /*VisitIncludedEntities=*/false, - RegionOfInterest, - /*VisitDeclsOnly=*/false, - AnnotateTokensPostChildrenVisitor), - SrcMgr(cxtu::getASTUnit(TU)->getSourceManager()), - HasContextSensitiveKeywords(false) { } + : Tokens(tokens), Cursors(cursors), NumTokens(numTokens), TokIdx(0), + PreprocessingTokIdx(0), + AnnotateVis(TU, AnnotateTokensVisitor, this, + /*VisitPreprocessorLast=*/true, + /*VisitIncludedEntities=*/false, RegionOfInterest, + /*VisitDeclsOnly=*/false, + AnnotateTokensPostChildrenVisitor), + SrcMgr(cxtu::getASTUnit(TU)->getSourceManager()), + HasContextSensitiveKeywords(false) { + // Don't annotate typo-corrected references. + AnnotateVis.setVisitTypoCorrected(false); + } void VisitChildren(CXCursor C) { AnnotateVis.VisitChildren(C); } enum CXChildVisitResult Visit(CXCursor cursor, CXCursor parent); @@ -6720,6 +6723,9 @@ // MyCXXClass foo; // Make sure we don't annotate 'foo' as a CallExpr cursor. if (clang_isExpression(cursorK) && MoreTokens()) { const Expr *E = getCursorExpr(cursor); + // Avoid annotating typo-corrected references. + if (E->isTypoCorrected()) + return CXChildVisit_Continue; if (const Decl *D = getCursorParentDecl(cursor)) { const unsigned I = NextToken(); if (E->getLocStart().isValid() && D->getLocation().isValid() && Index: tools/libclang/CIndexHigh.cpp =================================================================== --- tools/libclang/CIndexHigh.cpp +++ tools/libclang/CIndexHigh.cpp @@ -169,7 +169,9 @@ if (clang_isExpression(cursor.kind)) { if (cursor.kind == CXCursor_DeclRefExpr || cursor.kind == CXCursor_MemberRefExpr) { - // continue.. + // Avoid visiting typo-corrected references. + if (cxcursor::getCursorExpr(cursor)->isTypoCorrected()) + return CXChildVisit_Continue; } else if (cursor.kind == CXCursor_ObjCMessageExpr && cxcursor::getSelectorIdentifierIndex(cursor) != -1) { @@ -228,8 +230,11 @@ Visitor); if (const DeclContext *DC = Dcl->getParentFunctionOrMethod()) { - return clang_visitChildren(cxcursor::MakeCXCursor(cast(DC), TU), - findFileIdRefVisit, &data); + CursorVisitor CursorVis(TU, findFileIdRefVisit, &data, + /*VisitPreprocessorLast=*/false); + // Don't include the typo-corrected references. + CursorVis.setVisitTypoCorrected(false); + return CursorVis.VisitChildren(cxcursor::MakeCXCursor(cast(DC), TU)); } SourceRange Range(SM.getLocForStartOfFile(FID), SM.getLocForEndOfFile(FID)); @@ -239,6 +244,8 @@ /*VisitIncludedEntities=*/false, Range, /*VisitDeclsOnly=*/true); + // Don't include the typo-corrected references. + FindIdRefsVisitor.setVisitTypoCorrected(false); return FindIdRefsVisitor.visitFileRegion(); } Index: tools/libclang/CursorVisitor.h =================================================================== --- tools/libclang/CursorVisitor.h +++ tools/libclang/CursorVisitor.h @@ -96,6 +96,9 @@ /// record entries. bool VisitDeclsOnly; + /// \brief Whether we should visit typo-corrected references. + bool VisitTypoCorrected = true; + // FIXME: Eventually remove. This part of a hack to support proper // iteration over all Decls contained lexically within an ObjC container. DeclContext::decl_iterator *DI_current; @@ -187,6 +190,8 @@ return VisitIncludedEntities; } + void setVisitTypoCorrected(bool V = true) { VisitTypoCorrected = V; } + template bool visitPreprocessedEntities(InputIterator First, InputIterator Last, PreprocessingRecord &PPRec,