From: Douglas Gregor Date: Mon, 18 Jan 2010 23:41:10 +0000 (+0000) Subject: Teach clang_getCursorLocation() to return the locations of references X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f46034af49435a4d1a0085a4738343122aeb6521;p=clang Teach clang_getCursorLocation() to return the locations of references rather than the locations that refer to. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@93812 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/tools/CIndex/CIndex.cpp b/tools/CIndex/CIndex.cpp index ba0e2607c6..e48581ac0a 100644 --- a/tools/CIndex/CIndex.cpp +++ b/tools/CIndex/CIndex.cpp @@ -350,58 +350,6 @@ void CDeclVisitor::VisitVarDecl(VarDecl *ND) { Call(CXCursor_VarDecl, ND); } -static SourceLocation getLocationFromCursor(CXCursor C, - SourceManager &SourceMgr, - NamedDecl *ND) { - if (clang_isReference(C.kind)) { - - if (Decl *D = getCursorReferringDecl(C)) - return D->getLocation(); - - switch (C.kind) { - case CXCursor_ObjCClassRef: - return getCursorObjCClassRef(C).second; - case CXCursor_ObjCSuperClassRef: - return getCursorObjCSuperClassRef(C).second; - case CXCursor_ObjCProtocolRef: - return getCursorObjCProtocolRef(C).second; - case CXCursor_ObjCSelectorRef: { - ObjCMessageExpr *OME = dyn_cast(getCursorStmt(C)); - assert(OME && "getLocationFromCursor(): Missing message expr"); - return OME->getLeftLoc(); /* FIXME: should be a range */ - } - case CXCursor_VarRef: - case CXCursor_FunctionRef: - case CXCursor_EnumConstantRef: { - DeclRefExpr *DRE = dyn_cast(getCursorStmt(C)); - assert(DRE && "getLocationFromCursor(): Missing decl ref expr"); - return DRE->getLocation(); - } - default: - return SourceLocation(); - } - } else { // We have a declaration or a definition. - SourceLocation SLoc; - switch (ND->getKind()) { - case Decl::ObjCInterface: { - SLoc = dyn_cast(ND)->getClassLoc(); - break; - } - case Decl::ObjCProtocol: { - SLoc = ND->getLocation(); /* FIXME: need to get the name location. */ - break; - } - default: { - SLoc = ND->getLocation(); - break; - } - } - if (SLoc.isInvalid()) - return SourceLocation(); - return SourceMgr.getSpellingLoc(SLoc); // handles macro instantiations. - } -} - CXString CIndexer::createCXString(const char *String, bool DupString){ CXString Str; if (DupString) { @@ -791,12 +739,12 @@ CXString clang_getCursorSpelling(CXCursor C) { } case CXCursor_ObjCProtocolRef: { ObjCProtocolDecl *OID = getCursorObjCProtocolRef(C).first; - assert(OID && "getLocationFromCursor(): Missing protocol decl"); + assert(OID && "getCursorSpelling(): Missing protocol decl"); return CIndexer::createCXString(OID->getIdentifier()->getNameStart()); } case CXCursor_ObjCSelectorRef: { ObjCMessageExpr *OME = dyn_cast(getCursorStmt(C)); - assert(OME && "getLocationFromCursor(): Missing message expr"); + assert(OME && "getCursorSpelling(): Missing message expr"); return CIndexer::createCXString(OME->getSelector().getAsString().c_str(), true); } @@ -804,7 +752,7 @@ CXString clang_getCursorSpelling(CXCursor C) { case CXCursor_FunctionRef: case CXCursor_EnumConstantRef: { DeclRefExpr *DRE = dyn_cast(getCursorStmt(C)); - assert(DRE && "getLocationFromCursor(): Missing decl ref expr"); + assert(DRE && "getCursorSpelling(): Missing decl ref expr"); return CIndexer::createCXString(DRE->getDecl()->getIdentifier() ->getNameStart()); } @@ -888,9 +836,11 @@ CXCursor clang_getCursor(CXTranslationUnit CTUnit, const char *source_name, if (Dcl) { if (Stm) { if (DeclRefExpr *DRE = dyn_cast(Stm)) - return MakeCXCursor(TranslateDeclRefExpr(DRE), Dcl, Stm); + return MakeCXCursor(TranslateDeclRefExpr(DRE), Dcl, Stm, + CXXUnit->getASTContext()); else if (ObjCMessageExpr *MExp = dyn_cast(Stm)) - return MakeCXCursor(CXCursor_ObjCSelectorRef, Dcl, MExp); + return MakeCXCursor(CXCursor_ObjCSelectorRef, Dcl, MExp, + CXXUnit->getASTContext()); // Fall through...treat as a decl, not a ref. } if (ALoc.isNamedRef()) { @@ -952,8 +902,51 @@ CXDecl clang_getCursorDecl(CXCursor C) { CXSourceLocation clang_getCursorLocation(CXCursor C) { if (clang_isReference(C.kind)) { - // FIXME: Return the location of the reference, not of the underlying - // declaration (which may not even exist!). + switch (C.kind) { + case CXCursor_ObjCSuperClassRef: { + std::pair P + = getCursorObjCSuperClassRef(C); + SourceManager &SM = P.first->getASTContext().getSourceManager(); + return translateSourceLocation(SM, P.second); + } + + case CXCursor_ObjCProtocolRef: { + std::pair P + = getCursorObjCProtocolRef(C); + SourceManager &SM = P.first->getASTContext().getSourceManager(); + return translateSourceLocation(SM, P.second); + } + + case CXCursor_ObjCClassRef: { + std::pair P + = getCursorObjCClassRef(C); + SourceManager &SM = P.first->getASTContext().getSourceManager(); + return translateSourceLocation(SM, P.second); + } + + case CXCursor_ObjCSelectorRef: + case CXCursor_ObjCIvarRef: + case CXCursor_VarRef: + case CXCursor_FunctionRef: + case CXCursor_EnumConstantRef: + case CXCursor_MemberRef: { + Expr *E = getCursorExpr(C); + SourceManager &SM = getCursorContext(C).getSourceManager(); + if (ObjCMessageExpr *Msg = dyn_cast(E)) + return translateSourceLocation(SM, /*FIXME:*/Msg->getLeftLoc()); + if (DeclRefExpr *DRE = dyn_cast(E)) + return translateSourceLocation(SM, DRE->getLocation()); + if (MemberExpr *Member = dyn_cast(E)) + return translateSourceLocation(SM, Member->getMemberLoc()); + if (ObjCIvarRefExpr *Ivar = dyn_cast(E)) + return translateSourceLocation(SM, Ivar->getLocation()); + return translateSourceLocation(SM, E->getLocStart()); + } + + default: + // FIXME: Need a way to enumerate all non-reference cases. + llvm_unreachable("Missed a reference kind"); + } } if (!getCursorDecl(C)) { @@ -961,10 +954,12 @@ CXSourceLocation clang_getCursorLocation(CXCursor C) { return empty; } - NamedDecl *ND = static_cast(getCursorDecl(C)); - SourceManager &SM = ND->getASTContext().getSourceManager(); - - return translateSourceLocation(SM, getLocationFromCursor(C, SM, ND)); + Decl *D = getCursorDecl(C); + SourceManager &SM = D->getASTContext().getSourceManager(); + SourceLocation Loc = D->getLocation(); + if (ObjCInterfaceDecl *Class = dyn_cast(D)) + Loc = Class->getClassLoc(); + return translateSourceLocation(SM, Loc); } void clang_getDefinitionSpellingAndExtent(CXCursor C, diff --git a/tools/CIndex/CXCursor.cpp b/tools/CIndex/CXCursor.cpp index 945e1ac3c7..747b1a1390 100644 --- a/tools/CIndex/CXCursor.cpp +++ b/tools/CIndex/CXCursor.cpp @@ -26,9 +26,10 @@ CXCursor cxcursor::MakeCXCursor(CXCursorKind K, Decl *D) { return C; } -CXCursor cxcursor::MakeCXCursor(CXCursorKind K, Decl *D, Stmt *S) { +CXCursor cxcursor::MakeCXCursor(CXCursorKind K, Decl *D, Stmt *S, + ASTContext &Context) { assert(clang_isReference(K)); - CXCursor C = { K, { D, S, 0 } }; + CXCursor C = { K, { D, S, &Context } }; return C; } @@ -140,8 +141,52 @@ Stmt *cxcursor::getCursorStmt(CXCursor Cursor) { return (Stmt *)Cursor.data[1]; } -Decl *cxcursor::getCursorReferringDecl(CXCursor Cursor) { - return (Decl *)Cursor.data[2]; +ASTContext &cxcursor::getCursorContext(CXCursor Cursor) { + switch (Cursor.kind) { + case CXCursor_TypedefDecl: + case CXCursor_StructDecl: + case CXCursor_UnionDecl: + case CXCursor_ClassDecl: + case CXCursor_EnumDecl: + case CXCursor_FieldDecl: + case CXCursor_EnumConstantDecl: + case CXCursor_FunctionDecl: + case CXCursor_VarDecl: + case CXCursor_ParmDecl: + case CXCursor_ObjCInterfaceDecl: + case CXCursor_ObjCCategoryDecl: + case CXCursor_ObjCProtocolDecl: + case CXCursor_ObjCPropertyDecl: + case CXCursor_ObjCIvarDecl: + case CXCursor_ObjCInstanceMethodDecl: + case CXCursor_ObjCClassMethodDecl: + case CXCursor_FunctionDefn: + case CXCursor_ObjCClassDefn: + case CXCursor_ObjCCategoryDefn: + case CXCursor_ObjCInstanceMethodDefn: + case CXCursor_ObjCClassMethodDefn: + return static_cast(Cursor.data[0])->getASTContext(); + + case CXCursor_ObjCSuperClassRef: + case CXCursor_ObjCProtocolRef: + case CXCursor_ObjCClassRef: + return static_cast(Cursor.data[0])->getASTContext(); + + case CXCursor_ObjCSelectorRef: + case CXCursor_ObjCIvarRef: + case CXCursor_VarRef: + case CXCursor_FunctionRef: + case CXCursor_EnumConstantRef: + case CXCursor_MemberRef: + return *static_cast(Cursor.data[2]); + + case CXCursor_InvalidFile: + case CXCursor_NoDeclFound: + case CXCursor_NotImplemented: + llvm_unreachable("No context in an invalid cursor"); + } + + llvm_unreachable("No context available"); } bool cxcursor::operator==(CXCursor X, CXCursor Y) { diff --git a/tools/CIndex/CXCursor.h b/tools/CIndex/CXCursor.h index ff474edade..a924a0e7ba 100644 --- a/tools/CIndex/CXCursor.h +++ b/tools/CIndex/CXCursor.h @@ -20,6 +20,7 @@ namespace clang { +class ASTContext; class Decl; class Expr; class NamedDecl; @@ -30,7 +31,8 @@ class Stmt; namespace cxcursor { CXCursor MakeCXCursor(CXCursorKind K, clang::Decl *D); -CXCursor MakeCXCursor(CXCursorKind K, clang::Decl *D, clang::Stmt *S); +CXCursor MakeCXCursor(CXCursorKind K, clang::Decl *D, clang::Stmt *S, + ASTContext &Context); CXCursor MakeCXCursor(clang::Decl *D); /// \brief Create an Objective-C superclass reference at the given location. @@ -61,7 +63,7 @@ std::pair Decl *getCursorDecl(CXCursor Cursor); Expr *getCursorExpr(CXCursor Cursor); Stmt *getCursorStmt(CXCursor Cursor); -Decl *getCursorReferringDecl(CXCursor Cursor); +ASTContext &getCursorContext(CXCursor Cursor); bool operator==(CXCursor X, CXCursor Y);