arphaman created this revision.
This patch adds a new boolean field to the `DeclRefExpr`, `MemberExpr`,
`CXXCtorInitializer`, `ObjCIvarRefExpr`, `ObjCPropertyRefExpr` nodes which is
set to true when these nodes have been produced during typo-correction.
This is useful for Clang-based tooling as it can distinguish between true
references and the typo-corrected references. The initial tooling support uses
the flag to prevent token annotation for typo-corrected references and to
prevent finding typo-corrected references during single TU reference search.
Repository:
rL LLVM
https://reviews.llvm.org/D38708
Files:
include/clang/AST/DeclCXX.h
include/clang/AST/Expr.h
include/clang/AST/ExprObjC.h
include/clang/AST/Stmt.h
lib/AST/DeclCXX.cpp
lib/AST/Expr.cpp
lib/Sema/SemaDecl.cpp
lib/Sema/SemaDeclCXX.cpp
lib/Sema/SemaExprCXX.cpp
lib/Sema/SemaExprMember.cpp
lib/Sema/SemaExprObjC.cpp
lib/Sema/SemaOverload.cpp
lib/Sema/SemaPseudoObject.cpp
lib/Sema/SemaTemplateInstantiateDecl.cpp
lib/Sema/TreeTransform.h
lib/Serialization/ASTReader.cpp
lib/Serialization/ASTReaderStmt.cpp
lib/Serialization/ASTWriter.cpp
lib/Serialization/ASTWriterDecl.cpp
lib/Serialization/ASTWriterStmt.cpp
test/Index/typo-annotate-tokens.mm
test/Index/typo-file-refs.cpp
test/Index/typo-file-refs.m
tools/libclang/CIndex.cpp
tools/libclang/CIndexHigh.cpp
tools/libclang/CursorVisitor.h
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<typename InputIterator>
bool visitPreprocessedEntities(InputIterator First, InputIterator Last,
PreprocessingRecord &PPRec,
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<Decl>(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<Decl>(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/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: 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: 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-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: 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: 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/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/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<ObjCMethodDecl>();
@@ -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<MemberExpr>(S)->setIsTypoCorrected();
Record.readDeclarationNameLoc(cast<MemberExpr>(S)->MemberDNLoc,
MemberD->getDeclName());
if (HadMultipleCandidates)
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/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<DeclRefExpr>()->setIsTypoCorrected();
+ return Result;
}
template<typename Derived>
@@ -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<typename Derived>
@@ -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<ObjCIvarRefExpr>()->setIsTypoCorrected();
+ return Result;
}
template<typename Derived>
@@ -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<ObjCPropertyRefExpr>()->setIsTypoCorrected();
+ return Result;
}
template<typename Derived>
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/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/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/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/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<DeclFilterCCC<ObjCIvarDecl>>();
@@ -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/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/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<TypeDecl>()) {
const CXXBaseSpecifier *DirectBaseSpec;
const CXXBaseSpecifier *VirtualBaseSpec;
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<ObjCIvarDecl>()) {
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/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<DeclRefExpr>(this))
+ return DRE->isTypoCorrected();
+ if (const auto *ME = dyn_cast<MemberExpr>(this))
+ return ME->isTypoCorrected();
+ if (const auto *IVar = dyn_cast<ObjCIvarRefExpr>(this))
+ return IVar->isTypoCorrected();
+ if (const auto *PRef = dyn_cast<ObjCPropertyRefExpr>(this))
+ return PRef->isTypoCorrected();
+ return false;
+}
+
+void Expr::setIsTypoCorrected(bool V) {
+ if (auto *DRE = dyn_cast<DeclRefExpr>(this))
+ DRE->setIsTypoCorrected(V);
+ else if (auto *ME = dyn_cast<MemberExpr>(this))
+ ME->setIsTypoCorrected(V);
+ else if (auto *IVar = dyn_cast<ObjCIvarRefExpr>(this))
+ IVar->setIsTypoCorrected(V);
+ else if (auto *PRef = dyn_cast<ObjCPropertyRefExpr>(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/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: 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: 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/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/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<Expr*>(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.
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits