Teach the cursor visitor to walk statements and expressions, including

a few important subkinds. Now we're cookin' with gas!


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@94116 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Douglas Gregor 2010-01-21 23:27:09 +00:00
Родитель b5c775575b
Коммит a59e390ed6
2 изменённых файлов: 74 добавлений и 23 удалений

Просмотреть файл

@ -87,3 +87,15 @@ int main (int argc, const char * argv[]) {
// CHECK: c-index-api-loadTU-test.m:49:13: VarDecl=d:49:13 (Definition) [Extent=49:13:49:13] // CHECK: c-index-api-loadTU-test.m:49:13: VarDecl=d:49:13 (Definition) [Extent=49:13:49:13]
// CHECK: c-index-api-loadTU-test.m:49:2: TypeRef=id:0:0 [Extent=49:2:49:3] // CHECK: c-index-api-loadTU-test.m:49:2: TypeRef=id:0:0 [Extent=49:2:49:3]
// CHECK: c-index-api-loadTU-test.m:49:6: ObjCProtocolRef=Proto:24:1 [Extent=49:6:49:10] // CHECK: c-index-api-loadTU-test.m:49:6: ObjCProtocolRef=Proto:24:1 [Extent=49:6:49:10]
// CHECK: c-index-api-loadTU-test.m:50:2: DeclRefExpr=d:49:13 [Extent=50:2:50:2]
// CHECK: c-index-api-loadTU-test.m:50:6: DeclRefExpr=c:48:12 [Extent=50:6:50:6]
// CHECK: c-index-api-loadTU-test.m:51:2: ObjCMessageExpr=pMethod:25:1 [Extent=51:2:51:12]
// CHECK: c-index-api-loadTU-test.m:51:3: DeclRefExpr=d:49:13 [Extent=51:3:51:3]
// CHECK: c-index-api-loadTU-test.m:52:2: ObjCMessageExpr=catMethodWithFloat::20:1 [Extent=52:2:52:43]
// CHECK: c-index-api-loadTU-test.m:52:3: DeclRefExpr=bee:46:8 [Extent=52:3:52:5]
// CHECK: c-index-api-loadTU-test.m:52:26: ObjCMessageExpr=floatMethod:21:1 [Extent=52:26:52:42]
// CHECK: c-index-api-loadTU-test.m:52:27: DeclRefExpr=bee:46:8 [Extent=52:27:52:29]
// CHECK: c-index-api-loadTU-test.m:53:3: CallExpr=main:45:5 [Extent=53:3:53:36]
// CHECK: c-index-api-loadTU-test.m:53:3: DeclRefExpr=main:45:5 [Extent=53:3:53:6]
// CHECK: c-index-api-loadTU-test.m:53:8: DeclRefExpr=someEnum:42:3 [Extent=53:8:53:15]
// CHECK: c-index-api-loadTU-test.m:53:33: DeclRefExpr=bee:46:8 [Extent=53:33:53:35]

Просмотреть файл

@ -142,7 +142,8 @@ namespace {
// Cursor visitor. // Cursor visitor.
class CursorVisitor : public DeclVisitor<CursorVisitor, bool>, class CursorVisitor : public DeclVisitor<CursorVisitor, bool>,
public TypeLocVisitor<CursorVisitor, bool> public TypeLocVisitor<CursorVisitor, bool>,
public StmtVisitor<CursorVisitor, bool>
{ {
ASTUnit *TU; ASTUnit *TU;
CXCursor Parent; CXCursor Parent;
@ -157,6 +158,7 @@ class CursorVisitor : public DeclVisitor<CursorVisitor, bool>,
using DeclVisitor<CursorVisitor, bool>::Visit; using DeclVisitor<CursorVisitor, bool>::Visit;
using TypeLocVisitor<CursorVisitor, bool>::Visit; using TypeLocVisitor<CursorVisitor, bool>::Visit;
using StmtVisitor<CursorVisitor, bool>::Visit;
public: public:
CursorVisitor(ASTUnit *TU, CXCursorVisitor Visitor, CXClientData ClientData, CursorVisitor(ASTUnit *TU, CXCursorVisitor Visitor, CXClientData ClientData,
@ -178,6 +180,7 @@ public:
bool VisitTranslationUnitDecl(TranslationUnitDecl *D); bool VisitTranslationUnitDecl(TranslationUnitDecl *D);
bool VisitDeclaratorDecl(DeclaratorDecl *DD); bool VisitDeclaratorDecl(DeclaratorDecl *DD);
bool VisitFunctionDecl(FunctionDecl *ND); bool VisitFunctionDecl(FunctionDecl *ND);
bool VisitObjCContainerDecl(ObjCContainerDecl *D);
bool VisitObjCCategoryDecl(ObjCCategoryDecl *ND); bool VisitObjCCategoryDecl(ObjCCategoryDecl *ND);
bool VisitObjCInterfaceDecl(ObjCInterfaceDecl *D); bool VisitObjCInterfaceDecl(ObjCInterfaceDecl *D);
bool VisitObjCMethodDecl(ObjCMethodDecl *ND); bool VisitObjCMethodDecl(ObjCMethodDecl *ND);
@ -205,6 +208,10 @@ public:
// implemented // implemented
bool VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL); bool VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL);
bool VisitTypeOfTypeLoc(TypeOfTypeLoc TL); bool VisitTypeOfTypeLoc(TypeOfTypeLoc TL);
// Statement visitors
bool VisitStmt(Stmt *S);
bool VisitDeclStmt(DeclStmt *S);
}; };
} // end anonymous namespace } // end anonymous namespace
@ -247,6 +254,11 @@ bool CursorVisitor::Visit(CXCursor Cursor) {
/// \returns true if the visitation should be aborted, false if it /// \returns true if the visitation should be aborted, false if it
/// should continue. /// should continue.
bool CursorVisitor::VisitChildren(CXCursor Cursor) { bool CursorVisitor::VisitChildren(CXCursor Cursor) {
if (clang_isReference(Cursor.kind)) {
// By definition, references have no children.
return false;
}
// Set the Parent field to Cursor, then back to its old value once we're // Set the Parent field to Cursor, then back to its old value once we're
// done. // done.
class SetParentRAII { class SetParentRAII {
@ -276,6 +288,11 @@ bool CursorVisitor::VisitChildren(CXCursor Cursor) {
return Visit(D); return Visit(D);
} }
if (clang_isStatement(Cursor.kind))
return Visit(getCursorStmt(Cursor));
if (clang_isExpression(Cursor.kind))
return Visit(getCursorExpr(Cursor));
if (clang_isTranslationUnit(Cursor.kind)) { if (clang_isTranslationUnit(Cursor.kind)) {
ASTUnit *CXXUnit = getCursorASTUnit(Cursor); ASTUnit *CXXUnit = getCursorASTUnit(Cursor);
if (!CXXUnit->isMainFileAST() && CXXUnit->getOnlyLocalDecls()) { if (!CXXUnit->isMainFileAST() && CXXUnit->getOnlyLocalDecls()) {
@ -292,9 +309,8 @@ bool CursorVisitor::VisitChildren(CXCursor Cursor) {
return false; return false;
} }
// Nothing to visit at the moment. // Nothing to visit at the moment.
// FIXME: Traverse statements, declarations, etc. here.
return false; return false;
} }
@ -325,21 +341,17 @@ bool CursorVisitor::VisitFunctionDecl(FunctionDecl *ND) {
if (VisitDeclaratorDecl(ND)) if (VisitDeclaratorDecl(ND))
return true; return true;
// FIXME: This is wrong. We want to visit the body as a statement. if (ND->isThisDeclarationADefinition() &&
if (ND->isThisDeclarationADefinition()) { Visit(MakeCXCursor(ND->getBody(), StmtParent, TU)))
return VisitDeclContext(ND); return true;
#if 0
// Not currently needed.
CompoundStmt *Body = dyn_cast<CompoundStmt>(ND->getBody());
CRefVisitor RVisit(CDecl, Callback, CData);
RVisit.Visit(Body);
#endif
}
return false; return false;
} }
bool CursorVisitor::VisitObjCContainerDecl(ObjCContainerDecl *D) {
return VisitDeclContext(D);
}
bool CursorVisitor::VisitObjCCategoryDecl(ObjCCategoryDecl *ND) { bool CursorVisitor::VisitObjCCategoryDecl(ObjCCategoryDecl *ND) {
if (Visit(MakeCursorObjCClassRef(ND->getClassInterface(), ND->getLocation(), if (Visit(MakeCursorObjCClassRef(ND->getClassInterface(), ND->getLocation(),
TU))) TU)))
@ -351,7 +363,7 @@ bool CursorVisitor::VisitObjCCategoryDecl(ObjCCategoryDecl *ND) {
if (Visit(MakeCursorObjCProtocolRef(*I, *PL, TU))) if (Visit(MakeCursorObjCProtocolRef(*I, *PL, TU)))
return true; return true;
return VisitDeclContext(ND); return VisitObjCContainerDecl(ND);
} }
bool CursorVisitor::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { bool CursorVisitor::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
@ -368,13 +380,23 @@ bool CursorVisitor::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
if (Visit(MakeCursorObjCProtocolRef(*I, *PL, TU))) if (Visit(MakeCursorObjCProtocolRef(*I, *PL, TU)))
return true; return true;
return VisitDeclContext(D); return VisitObjCContainerDecl(D);
} }
bool CursorVisitor::VisitObjCMethodDecl(ObjCMethodDecl *ND) { bool CursorVisitor::VisitObjCMethodDecl(ObjCMethodDecl *ND) {
// FIXME: Wrong in the same way that VisitFunctionDecl is wrong. // FIXME: We really need a TypeLoc covering Objective-C method declarations.
if (ND->getBody()) // At the moment, we don't have information about locations in the return
return VisitDeclContext(ND); // type.
for (ObjCMethodDecl::param_iterator P = ND->param_begin(),
PEnd = ND->param_end();
P != PEnd; ++P) {
if (Visit(MakeCXCursor(*P, TU)))
return true;
}
if (ND->isThisDeclarationADefinition() &&
Visit(MakeCXCursor(ND->getBody(), StmtParent, TU)))
return true;
return false; return false;
} }
@ -386,7 +408,7 @@ bool CursorVisitor::VisitObjCProtocolDecl(ObjCProtocolDecl *PID) {
if (Visit(MakeCursorObjCProtocolRef(*I, *PL, TU))) if (Visit(MakeCursorObjCProtocolRef(*I, *PL, TU)))
return true; return true;
return VisitDeclContext(PID); return VisitObjCContainerDecl(PID);
} }
bool CursorVisitor::VisitTagDecl(TagDecl *D) { bool CursorVisitor::VisitTagDecl(TagDecl *D) {
@ -517,9 +539,6 @@ bool CursorVisitor::VisitFunctionTypeLoc(FunctionTypeLoc TL) {
if (Visit(TL.getResultLoc())) if (Visit(TL.getResultLoc()))
return true; return true;
// FIXME: For function definitions, this means that we'll end up
// visiting the parameters twice, because VisitFunctionDecl is
// walking the DeclContext.
for (unsigned I = 0, N = TL.getNumArgs(); I != N; ++I) for (unsigned I = 0, N = TL.getNumArgs(); I != N; ++I)
if (Visit(MakeCXCursor(TL.getArg(I), TU))) if (Visit(MakeCXCursor(TL.getArg(I), TU)))
return true; return true;
@ -548,6 +567,26 @@ bool CursorVisitor::VisitTypeOfTypeLoc(TypeOfTypeLoc TL) {
return false; return false;
} }
bool CursorVisitor::VisitStmt(Stmt *S) {
for (Stmt::child_iterator Child = S->child_begin(), ChildEnd = S->child_end();
Child != ChildEnd; ++Child) {
if (Visit(MakeCXCursor(*Child, StmtParent, TU)))
return true;
}
return false;
}
bool CursorVisitor::VisitDeclStmt(DeclStmt *S) {
for (DeclStmt::decl_iterator D = S->decl_begin(), DEnd = S->decl_end();
D != DEnd; ++D) {
if (Visit(MakeCXCursor(*D, TU)))
return true;
}
return false;
}
CXString CIndexer::createCXString(const char *String, bool DupString){ CXString CIndexer::createCXString(const char *String, bool DupString){
CXString Str; CXString Str;
if (DupString) { if (DupString) {