1aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis//===- CIndexHigh.cpp - Higher level API functions ------------------------===// 2aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis// 3aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis// The LLVM Compiler Infrastructure 4aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis// 5aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis// This file is distributed under the University of Illinois Open Source 6aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis// License. See LICENSE.TXT for details. 7aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis// 8aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis//===----------------------------------------------------------------------===// 9aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis 10e2079cf54ded1eda9e35d215aef6628373368276Argyrios Kyrtzidis#include "CursorVisitor.h" 11b1ba0efc3d1dc1daa5d82c40bc504e1f368c4fa0Chandler Carruth#include "CLog.h" 12aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis#include "CXCursor.h" 13aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis#include "CXSourceLocation.h" 14aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis#include "CXTranslationUnit.h" 15aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis#include "clang/AST/DeclObjC.h" 16f59edb96b2d0bfe612b732f19519ab84bb995bd4Chandler Carruth#include "clang/Frontend/ASTUnit.h" 17acbe4ba0bec71346e77a2f7360e8920212a07c81Dmitri Gribenko#include "llvm/Support/Compiler.h" 18aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis 19aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidisusing namespace clang; 20e2079cf54ded1eda9e35d215aef6628373368276Argyrios Kyrtzidisusing namespace cxcursor; 21c6f5c6a58d34833d1fe458a518d5f59462926c7bArgyrios Kyrtzidisusing namespace cxindex; 22aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis 23aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidisstatic void getTopOverriddenMethods(CXTranslationUnit TU, 24e22339c44bb28d71a2cc97c840d3da0c4bdb4909Dmitri Gribenko const Decl *D, 25e22339c44bb28d71a2cc97c840d3da0c4bdb4909Dmitri Gribenko SmallVectorImpl<const Decl *> &Methods) { 2616ed0e6fda74800595cb98d11969fc4afcc00bacArgyrios Kyrtzidis if (!D) 2716ed0e6fda74800595cb98d11969fc4afcc00bacArgyrios Kyrtzidis return; 28aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis if (!isa<ObjCMethodDecl>(D) && !isa<CXXMethodDecl>(D)) 29aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis return; 30aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis 31aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis SmallVector<CXCursor, 8> Overridden; 32aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis cxcursor::getOverriddenCursors(cxcursor::MakeCXCursor(D, TU), Overridden); 33aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis 34aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis if (Overridden.empty()) { 35aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis Methods.push_back(D->getCanonicalDecl()); 36aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis return; 37aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis } 38aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis 3909d19efaa147762f84aed55efa7930bb3616a4e5Craig Topper for (SmallVectorImpl<CXCursor>::iterator 40aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis I = Overridden.begin(), E = Overridden.end(); I != E; ++I) 41aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis getTopOverriddenMethods(TU, cxcursor::getCursorDecl(*I), Methods); 42aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis} 43aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis 44aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidisnamespace { 45aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis 46aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidisstruct FindFileIdRefVisitData { 47aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis CXTranslationUnit TU; 48aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis FileID FID; 49e22339c44bb28d71a2cc97c840d3da0c4bdb4909Dmitri Gribenko const Decl *Dcl; 50aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis int SelectorIdIdx; 51aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis CXCursorAndRangeVisitor visitor; 52aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis 53e22339c44bb28d71a2cc97c840d3da0c4bdb4909Dmitri Gribenko typedef SmallVector<const Decl *, 8> TopMethodsTy; 54aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis TopMethodsTy TopMethods; 55aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis 56aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis FindFileIdRefVisitData(CXTranslationUnit TU, FileID FID, 57e22339c44bb28d71a2cc97c840d3da0c4bdb4909Dmitri Gribenko const Decl *D, int selectorIdIdx, 58aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis CXCursorAndRangeVisitor visitor) 59aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis : TU(TU), FID(FID), SelectorIdIdx(selectorIdIdx), visitor(visitor) { 60aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis Dcl = getCanonical(D); 61aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis getTopOverriddenMethods(TU, Dcl, TopMethods); 62aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis } 63aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis 64aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis ASTContext &getASTContext() const { 655694feb5ccd6eb862cb600b55753cecc13794471Dmitri Gribenko return cxtu::getASTUnit(TU)->getASTContext(); 66aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis } 67aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis 68aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis /// \brief We are looking to find all semantically relevant identifiers, 69aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis /// so the definition of "canonical" here is different than in the AST, e.g. 70aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis /// 71aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis /// \code 72aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis /// class C { 73aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis /// C() {} 74aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis /// }; 75aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis /// \endcode 76aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis /// 77aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis /// we consider the canonical decl of the constructor decl to be the class 78aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis /// itself, so both 'C' can be highlighted. 79e22339c44bb28d71a2cc97c840d3da0c4bdb4909Dmitri Gribenko const Decl *getCanonical(const Decl *D) const { 80e368a641a03617983dabb1e092d880e1089f576aArgyrios Kyrtzidis if (!D) 81c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines return nullptr; 82e368a641a03617983dabb1e092d880e1089f576aArgyrios Kyrtzidis 83aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis D = D->getCanonicalDecl(); 84aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis 85e22339c44bb28d71a2cc97c840d3da0c4bdb4909Dmitri Gribenko if (const ObjCImplDecl *ImplD = dyn_cast<ObjCImplDecl>(D)) { 86e368a641a03617983dabb1e092d880e1089f576aArgyrios Kyrtzidis if (ImplD->getClassInterface()) 87e368a641a03617983dabb1e092d880e1089f576aArgyrios Kyrtzidis return getCanonical(ImplD->getClassInterface()); 88e368a641a03617983dabb1e092d880e1089f576aArgyrios Kyrtzidis 89e22339c44bb28d71a2cc97c840d3da0c4bdb4909Dmitri Gribenko } else if (const CXXConstructorDecl *CXXCtorD = 90e22339c44bb28d71a2cc97c840d3da0c4bdb4909Dmitri Gribenko dyn_cast<CXXConstructorDecl>(D)) { 91aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis return getCanonical(CXXCtorD->getParent()); 92e368a641a03617983dabb1e092d880e1089f576aArgyrios Kyrtzidis } 93aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis 94aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis return D; 95aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis } 96aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis 97e22339c44bb28d71a2cc97c840d3da0c4bdb4909Dmitri Gribenko bool isHit(const Decl *D) const { 98e368a641a03617983dabb1e092d880e1089f576aArgyrios Kyrtzidis if (!D) 99e368a641a03617983dabb1e092d880e1089f576aArgyrios Kyrtzidis return false; 100e368a641a03617983dabb1e092d880e1089f576aArgyrios Kyrtzidis 101aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis D = getCanonical(D); 102aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis if (D == Dcl) 103aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis return true; 104aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis 105aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis if (isa<ObjCMethodDecl>(D) || isa<CXXMethodDecl>(D)) 106aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis return isOverriddingMethod(D); 107aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis 108aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis return false; 109aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis } 110aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis 111aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidisprivate: 112e22339c44bb28d71a2cc97c840d3da0c4bdb4909Dmitri Gribenko bool isOverriddingMethod(const Decl *D) const { 113aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis if (std::find(TopMethods.begin(), TopMethods.end(), D) != 114aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis TopMethods.end()) 115aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis return true; 116aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis 117aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis TopMethodsTy methods; 118aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis getTopOverriddenMethods(TU, D, methods); 119aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis for (TopMethodsTy::iterator 120aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis I = methods.begin(), E = methods.end(); I != E; ++I) { 121aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis if (std::find(TopMethods.begin(), TopMethods.end(), *I) != 122aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis TopMethods.end()) 123aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis return true; 124aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis } 125aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis 126aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis return false; 127aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis } 128aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis}; 129aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis 130aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis} // end anonymous namespace. 131aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis 132aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis/// \brief For a macro \arg Loc, returns the file spelling location and sets 133aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis/// to \arg isMacroArg whether the spelling resides inside a macro definition or 134aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis/// a macro argument. 135aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidisstatic SourceLocation getFileSpellingLoc(SourceManager &SM, 136aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis SourceLocation Loc, 137aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis bool &isMacroArg) { 138aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis assert(Loc.isMacroID()); 139aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis SourceLocation SpellLoc = SM.getImmediateSpellingLoc(Loc); 140aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis if (SpellLoc.isMacroID()) 141aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis return getFileSpellingLoc(SM, SpellLoc, isMacroArg); 142aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis 143aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis isMacroArg = SM.isMacroArgExpansion(Loc); 144aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis return SpellLoc; 145aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis} 146aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis 147aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidisstatic enum CXChildVisitResult findFileIdRefVisit(CXCursor cursor, 148aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis CXCursor parent, 149aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis CXClientData client_data) { 150aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis CXCursor declCursor = clang_getCursorReferenced(cursor); 151aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis if (!clang_isDeclaration(declCursor.kind)) 152aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis return CXChildVisit_Recurse; 153aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis 154e22339c44bb28d71a2cc97c840d3da0c4bdb4909Dmitri Gribenko const Decl *D = cxcursor::getCursorDecl(declCursor); 15516ed0e6fda74800595cb98d11969fc4afcc00bacArgyrios Kyrtzidis if (!D) 15616ed0e6fda74800595cb98d11969fc4afcc00bacArgyrios Kyrtzidis return CXChildVisit_Continue; 15716ed0e6fda74800595cb98d11969fc4afcc00bacArgyrios Kyrtzidis 158aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis FindFileIdRefVisitData *data = (FindFileIdRefVisitData *)client_data; 159aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis if (data->isHit(D)) { 160aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis cursor = cxcursor::getSelectorIdentifierCursor(data->SelectorIdIdx, cursor); 161aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis 162aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis // We are looking for identifiers to highlight so for objc methods (and 163aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis // not a parameter) we can only highlight the selector identifiers. 164aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis if ((cursor.kind == CXCursor_ObjCClassMethodDecl || 165aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis cursor.kind == CXCursor_ObjCInstanceMethodDecl) && 166aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis cxcursor::getSelectorIdentifierIndex(cursor) == -1) 167aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis return CXChildVisit_Recurse; 168aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis 169aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis if (clang_isExpression(cursor.kind)) { 170aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis if (cursor.kind == CXCursor_DeclRefExpr || 171aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis cursor.kind == CXCursor_MemberRefExpr) { 172aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis // continue.. 173aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis 174aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis } else if (cursor.kind == CXCursor_ObjCMessageExpr && 175aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis cxcursor::getSelectorIdentifierIndex(cursor) != -1) { 176aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis // continue.. 177aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis 178aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis } else 179aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis return CXChildVisit_Recurse; 180aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis } 181aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis 182aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis SourceLocation 183aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis Loc = cxloc::translateSourceLocation(clang_getCursorLocation(cursor)); 184aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis SourceLocation SelIdLoc = cxcursor::getSelectorIdentifierLoc(cursor); 185aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis if (SelIdLoc.isValid()) 186aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis Loc = SelIdLoc; 187aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis 188b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis ASTContext &Ctx = data->getASTContext(); 189b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis SourceManager &SM = Ctx.getSourceManager(); 190aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis bool isInMacroDef = false; 191aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis if (Loc.isMacroID()) { 192aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis bool isMacroArg; 193aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis Loc = getFileSpellingLoc(SM, Loc, isMacroArg); 194aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis isInMacroDef = !isMacroArg; 195aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis } 196aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis 197aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis // We are looking for identifiers in a specific file. 198aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc); 199aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis if (LocInfo.first != data->FID) 200aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis return CXChildVisit_Recurse; 201aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis 202aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis if (isInMacroDef) { 203aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis // FIXME: For a macro definition make sure that all expansions 204aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis // of it expand to the same reference before allowing to point to it. 205b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis return CXChildVisit_Recurse; 206aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis } 207aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis 208029c8f37e32b08bad4c757848a695d199fe5c813Argyrios Kyrtzidis if (data->visitor.visit(data->visitor.context, cursor, 209029c8f37e32b08bad4c757848a695d199fe5c813Argyrios Kyrtzidis cxloc::translateSourceRange(Ctx, Loc)) == CXVisit_Break) 210029c8f37e32b08bad4c757848a695d199fe5c813Argyrios Kyrtzidis return CXChildVisit_Break; 211aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis } 212aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis return CXChildVisit_Recurse; 213aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis} 214aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis 215389dc5603fa10b508a38f668a7830c6d877b6542Argyrios Kyrtzidisstatic bool findIdRefsInFile(CXTranslationUnit TU, CXCursor declCursor, 216389dc5603fa10b508a38f668a7830c6d877b6542Argyrios Kyrtzidis const FileEntry *File, 217389dc5603fa10b508a38f668a7830c6d877b6542Argyrios Kyrtzidis CXCursorAndRangeVisitor Visitor) { 218aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis assert(clang_isDeclaration(declCursor.kind)); 2195694feb5ccd6eb862cb600b55753cecc13794471Dmitri Gribenko SourceManager &SM = cxtu::getASTUnit(TU)->getSourceManager(); 220aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis 221aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis FileID FID = SM.translateFile(File); 222e22339c44bb28d71a2cc97c840d3da0c4bdb4909Dmitri Gribenko const Decl *Dcl = cxcursor::getCursorDecl(declCursor); 223e368a641a03617983dabb1e092d880e1089f576aArgyrios Kyrtzidis if (!Dcl) 224389dc5603fa10b508a38f668a7830c6d877b6542Argyrios Kyrtzidis return false; 225e368a641a03617983dabb1e092d880e1089f576aArgyrios Kyrtzidis 226aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis FindFileIdRefVisitData data(TU, FID, Dcl, 227aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis cxcursor::getSelectorIdentifierIndex(declCursor), 228aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis Visitor); 229aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis 230e22339c44bb28d71a2cc97c840d3da0c4bdb4909Dmitri Gribenko if (const DeclContext *DC = Dcl->getParentFunctionOrMethod()) { 231389dc5603fa10b508a38f668a7830c6d877b6542Argyrios Kyrtzidis return clang_visitChildren(cxcursor::MakeCXCursor(cast<Decl>(DC), TU), 232389dc5603fa10b508a38f668a7830c6d877b6542Argyrios Kyrtzidis findFileIdRefVisit, &data); 233aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis } 234aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis 235e2079cf54ded1eda9e35d215aef6628373368276Argyrios Kyrtzidis SourceRange Range(SM.getLocForStartOfFile(FID), SM.getLocForEndOfFile(FID)); 236e2079cf54ded1eda9e35d215aef6628373368276Argyrios Kyrtzidis CursorVisitor FindIdRefsVisitor(TU, 237e2079cf54ded1eda9e35d215aef6628373368276Argyrios Kyrtzidis findFileIdRefVisit, &data, 238e2079cf54ded1eda9e35d215aef6628373368276Argyrios Kyrtzidis /*VisitPreprocessorLast=*/true, 239e2079cf54ded1eda9e35d215aef6628373368276Argyrios Kyrtzidis /*VisitIncludedEntities=*/false, 240b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis Range, 241b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis /*VisitDeclsOnly=*/true); 242389dc5603fa10b508a38f668a7830c6d877b6542Argyrios Kyrtzidis return FindIdRefsVisitor.visitFileRegion(); 243aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis} 244aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis 245b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidisnamespace { 246b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis 247b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidisstruct FindFileMacroRefVisitData { 248b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis ASTUnit &Unit; 249b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis const FileEntry *File; 250b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis const IdentifierInfo *Macro; 251b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis CXCursorAndRangeVisitor visitor; 252b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis 253b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis FindFileMacroRefVisitData(ASTUnit &Unit, const FileEntry *File, 254b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis const IdentifierInfo *Macro, 255b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis CXCursorAndRangeVisitor visitor) 256b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis : Unit(Unit), File(File), Macro(Macro), visitor(visitor) { } 257b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis 258b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis ASTContext &getASTContext() const { 259b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis return Unit.getASTContext(); 260b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis } 261b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis}; 262b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis 263b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis} // anonymous namespace 264b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis 265b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidisstatic enum CXChildVisitResult findFileMacroRefVisit(CXCursor cursor, 266b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis CXCursor parent, 267b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis CXClientData client_data) { 268c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines const IdentifierInfo *Macro = nullptr; 269b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis if (cursor.kind == CXCursor_MacroDefinition) 270b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis Macro = getCursorMacroDefinition(cursor)->getName(); 271b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis else if (cursor.kind == CXCursor_MacroExpansion) 272664b06f9bd2ea83443ddc8553feba8ba48880752Argyrios Kyrtzidis Macro = getCursorMacroExpansion(cursor).getName(); 273b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis if (!Macro) 274b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis return CXChildVisit_Continue; 275b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis 276b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis FindFileMacroRefVisitData *data = (FindFileMacroRefVisitData *)client_data; 277b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis if (data->Macro != Macro) 278b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis return CXChildVisit_Continue; 279b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis 280b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis SourceLocation 281b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis Loc = cxloc::translateSourceLocation(clang_getCursorLocation(cursor)); 282b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis 283b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis ASTContext &Ctx = data->getASTContext(); 284b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis SourceManager &SM = Ctx.getSourceManager(); 285b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis bool isInMacroDef = false; 286b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis if (Loc.isMacroID()) { 287b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis bool isMacroArg; 288b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis Loc = getFileSpellingLoc(SM, Loc, isMacroArg); 289b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis isInMacroDef = !isMacroArg; 290b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis } 291b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis 292b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis // We are looking for identifiers in a specific file. 293b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc); 294b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis if (SM.getFileEntryForID(LocInfo.first) != data->File) 295b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis return CXChildVisit_Continue; 296b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis 297b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis if (isInMacroDef) { 298b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis // FIXME: For a macro definition make sure that all expansions 299b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis // of it expand to the same reference before allowing to point to it. 300b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis return CXChildVisit_Continue; 301b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis } 302b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis 303029c8f37e32b08bad4c757848a695d199fe5c813Argyrios Kyrtzidis if (data->visitor.visit(data->visitor.context, cursor, 304029c8f37e32b08bad4c757848a695d199fe5c813Argyrios Kyrtzidis cxloc::translateSourceRange(Ctx, Loc)) == CXVisit_Break) 305029c8f37e32b08bad4c757848a695d199fe5c813Argyrios Kyrtzidis return CXChildVisit_Break; 306b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis return CXChildVisit_Continue; 307b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis} 308b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis 309389dc5603fa10b508a38f668a7830c6d877b6542Argyrios Kyrtzidisstatic bool findMacroRefsInFile(CXTranslationUnit TU, CXCursor Cursor, 310b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis const FileEntry *File, 311b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis CXCursorAndRangeVisitor Visitor) { 312b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis if (Cursor.kind != CXCursor_MacroDefinition && 313b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis Cursor.kind != CXCursor_MacroExpansion) 314389dc5603fa10b508a38f668a7830c6d877b6542Argyrios Kyrtzidis return false; 315b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis 3165694feb5ccd6eb862cb600b55753cecc13794471Dmitri Gribenko ASTUnit *Unit = cxtu::getASTUnit(TU); 317b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis SourceManager &SM = Unit->getSourceManager(); 318b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis 319b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis FileID FID = SM.translateFile(File); 320c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines const IdentifierInfo *Macro = nullptr; 321b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis if (Cursor.kind == CXCursor_MacroDefinition) 322b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis Macro = getCursorMacroDefinition(Cursor)->getName(); 323b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis else 324664b06f9bd2ea83443ddc8553feba8ba48880752Argyrios Kyrtzidis Macro = getCursorMacroExpansion(Cursor).getName(); 325b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis if (!Macro) 326389dc5603fa10b508a38f668a7830c6d877b6542Argyrios Kyrtzidis return false; 327b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis 328b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis FindFileMacroRefVisitData data(*Unit, File, Macro, Visitor); 329b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis 330b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis SourceRange Range(SM.getLocForStartOfFile(FID), SM.getLocForEndOfFile(FID)); 331b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis CursorVisitor FindMacroRefsVisitor(TU, 332b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis findFileMacroRefVisit, &data, 333b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis /*VisitPreprocessorLast=*/false, 334b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis /*VisitIncludedEntities=*/false, 335b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis Range); 336389dc5603fa10b508a38f668a7830c6d877b6542Argyrios Kyrtzidis return FindMacroRefsVisitor.visitPreprocessedEntitiesInRegion(); 337b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis} 338b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis 339ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidisnamespace { 340ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis 341ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidisstruct FindFileIncludesVisitor { 342ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis ASTUnit &Unit; 343ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis const FileEntry *File; 344ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis CXCursorAndRangeVisitor visitor; 345ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis 346ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis FindFileIncludesVisitor(ASTUnit &Unit, const FileEntry *File, 347ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis CXCursorAndRangeVisitor visitor) 348ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis : Unit(Unit), File(File), visitor(visitor) { } 349ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis 350ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis ASTContext &getASTContext() const { 351ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis return Unit.getASTContext(); 352ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis } 353ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis 354ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis enum CXChildVisitResult visit(CXCursor cursor, CXCursor parent) { 355ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis if (cursor.kind != CXCursor_InclusionDirective) 356ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis return CXChildVisit_Continue; 357ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis 358ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis SourceLocation 359ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis Loc = cxloc::translateSourceLocation(clang_getCursorLocation(cursor)); 360ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis 361ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis ASTContext &Ctx = getASTContext(); 362ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis SourceManager &SM = Ctx.getSourceManager(); 363ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis 364ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis // We are looking for includes in a specific file. 365ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc); 366ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis if (SM.getFileEntryForID(LocInfo.first) != File) 367ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis return CXChildVisit_Continue; 368ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis 369ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis if (visitor.visit(visitor.context, cursor, 370ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis cxloc::translateSourceRange(Ctx, Loc)) == CXVisit_Break) 371ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis return CXChildVisit_Break; 372ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis return CXChildVisit_Continue; 373ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis } 374ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis 375ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis static enum CXChildVisitResult visit(CXCursor cursor, CXCursor parent, 376ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis CXClientData client_data) { 377ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis return static_cast<FindFileIncludesVisitor*>(client_data)-> 378ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis visit(cursor, parent); 379ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis } 380ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis}; 381ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis 382ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis} // anonymous namespace 383ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis 384389dc5603fa10b508a38f668a7830c6d877b6542Argyrios Kyrtzidisstatic bool findIncludesInFile(CXTranslationUnit TU, const FileEntry *File, 385ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis CXCursorAndRangeVisitor Visitor) { 386ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis assert(TU && File && Visitor.visit); 387ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis 388ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis ASTUnit *Unit = cxtu::getASTUnit(TU); 389ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis SourceManager &SM = Unit->getSourceManager(); 390ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis 391ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis FileID FID = SM.translateFile(File); 392ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis 393ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis FindFileIncludesVisitor IncludesVisitor(*Unit, File, Visitor); 394ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis 395ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis SourceRange Range(SM.getLocForStartOfFile(FID), SM.getLocForEndOfFile(FID)); 396ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis CursorVisitor InclusionCursorsVisitor(TU, 397ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis FindFileIncludesVisitor::visit, 398ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis &IncludesVisitor, 399ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis /*VisitPreprocessorLast=*/false, 400ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis /*VisitIncludedEntities=*/false, 401ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis Range); 402389dc5603fa10b508a38f668a7830c6d877b6542Argyrios Kyrtzidis return InclusionCursorsVisitor.visitPreprocessedEntitiesInRegion(); 403ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis} 404ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis 405aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis 406aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis//===----------------------------------------------------------------------===// 407aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis// libclang public APIs. 408aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis//===----------------------------------------------------------------------===// 409aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis 410aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidisextern "C" { 411aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis 4126f09c3d69f6272b101ff795562dffead1c0bd9deArgyrios KyrtzidisCXResult clang_findReferencesInFile(CXCursor cursor, CXFile file, 4136f09c3d69f6272b101ff795562dffead1c0bd9deArgyrios Kyrtzidis CXCursorAndRangeVisitor visitor) { 414acbe4ba0bec71346e77a2f7360e8920212a07c81Dmitri Gribenko LogRef Log = Logger::make(LLVM_FUNCTION_NAME); 415aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis 416aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis if (clang_Cursor_isNull(cursor)) { 417c6f5c6a58d34833d1fe458a518d5f59462926c7bArgyrios Kyrtzidis if (Log) 418c6f5c6a58d34833d1fe458a518d5f59462926c7bArgyrios Kyrtzidis *Log << "Null cursor"; 4196f09c3d69f6272b101ff795562dffead1c0bd9deArgyrios Kyrtzidis return CXResult_Invalid; 420aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis } 4214451746d8f658b51eaf15dd24664a488457063a9Argyrios Kyrtzidis if (cursor.kind == CXCursor_NoDeclFound) { 422c6f5c6a58d34833d1fe458a518d5f59462926c7bArgyrios Kyrtzidis if (Log) 423c6f5c6a58d34833d1fe458a518d5f59462926c7bArgyrios Kyrtzidis *Log << "Got CXCursor_NoDeclFound"; 4246f09c3d69f6272b101ff795562dffead1c0bd9deArgyrios Kyrtzidis return CXResult_Invalid; 4254451746d8f658b51eaf15dd24664a488457063a9Argyrios Kyrtzidis } 426aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis if (!file) { 427c6f5c6a58d34833d1fe458a518d5f59462926c7bArgyrios Kyrtzidis if (Log) 428c6f5c6a58d34833d1fe458a518d5f59462926c7bArgyrios Kyrtzidis *Log << "Null file"; 4296f09c3d69f6272b101ff795562dffead1c0bd9deArgyrios Kyrtzidis return CXResult_Invalid; 430aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis } 431aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis if (!visitor.visit) { 432c6f5c6a58d34833d1fe458a518d5f59462926c7bArgyrios Kyrtzidis if (Log) 433c6f5c6a58d34833d1fe458a518d5f59462926c7bArgyrios Kyrtzidis *Log << "Null visitor"; 4346f09c3d69f6272b101ff795562dffead1c0bd9deArgyrios Kyrtzidis return CXResult_Invalid; 435aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis } 436aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis 437b70e7a83ee55e463d52d175bd68dece2bfd084f4Argyrios Kyrtzidis if (Log) 438b70e7a83ee55e463d52d175bd68dece2bfd084f4Argyrios Kyrtzidis *Log << cursor << " @" << static_cast<const FileEntry *>(file); 439b70e7a83ee55e463d52d175bd68dece2bfd084f4Argyrios Kyrtzidis 4405c2a1f741e133fcad4782b855a18d3b220243b11Argyrios Kyrtzidis ASTUnit *CXXUnit = cxcursor::getCursorASTUnit(cursor); 4415c2a1f741e133fcad4782b855a18d3b220243b11Argyrios Kyrtzidis if (!CXXUnit) 4426f09c3d69f6272b101ff795562dffead1c0bd9deArgyrios Kyrtzidis return CXResult_Invalid; 4435c2a1f741e133fcad4782b855a18d3b220243b11Argyrios Kyrtzidis 4445c2a1f741e133fcad4782b855a18d3b220243b11Argyrios Kyrtzidis ASTUnit::ConcurrencyCheck Check(*CXXUnit); 4455c2a1f741e133fcad4782b855a18d3b220243b11Argyrios Kyrtzidis 446b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis if (cursor.kind == CXCursor_MacroDefinition || 447b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis cursor.kind == CXCursor_MacroExpansion) { 448389dc5603fa10b508a38f668a7830c6d877b6542Argyrios Kyrtzidis if (findMacroRefsInFile(cxcursor::getCursorTU(cursor), 449389dc5603fa10b508a38f668a7830c6d877b6542Argyrios Kyrtzidis cursor, 450389dc5603fa10b508a38f668a7830c6d877b6542Argyrios Kyrtzidis static_cast<const FileEntry *>(file), 451389dc5603fa10b508a38f668a7830c6d877b6542Argyrios Kyrtzidis visitor)) 4526f09c3d69f6272b101ff795562dffead1c0bd9deArgyrios Kyrtzidis return CXResult_VisitBreak; 4536f09c3d69f6272b101ff795562dffead1c0bd9deArgyrios Kyrtzidis return CXResult_Success; 454b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis } 455b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis 456aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis // We are interested in semantics of identifiers so for C++ constructor exprs 457aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis // prefer type references, e.g.: 458aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis // 459aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis // return MyStruct(); 460aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis // 461aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis // for 'MyStruct' we'll have a cursor pointing at the constructor decl but 462aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis // we are actually interested in the type declaration. 463aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis cursor = cxcursor::getTypeRefCursor(cursor); 464aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis 465aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis CXCursor refCursor = clang_getCursorReferenced(cursor); 466aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis 467aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis if (!clang_isDeclaration(refCursor.kind)) { 468c6f5c6a58d34833d1fe458a518d5f59462926c7bArgyrios Kyrtzidis if (Log) 469c6f5c6a58d34833d1fe458a518d5f59462926c7bArgyrios Kyrtzidis *Log << "cursor is not referencing a declaration"; 4706f09c3d69f6272b101ff795562dffead1c0bd9deArgyrios Kyrtzidis return CXResult_Invalid; 471aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis } 472aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis 473389dc5603fa10b508a38f668a7830c6d877b6542Argyrios Kyrtzidis if (findIdRefsInFile(cxcursor::getCursorTU(cursor), 474389dc5603fa10b508a38f668a7830c6d877b6542Argyrios Kyrtzidis refCursor, 475389dc5603fa10b508a38f668a7830c6d877b6542Argyrios Kyrtzidis static_cast<const FileEntry *>(file), 476389dc5603fa10b508a38f668a7830c6d877b6542Argyrios Kyrtzidis visitor)) 4776f09c3d69f6272b101ff795562dffead1c0bd9deArgyrios Kyrtzidis return CXResult_VisitBreak; 4786f09c3d69f6272b101ff795562dffead1c0bd9deArgyrios Kyrtzidis return CXResult_Success; 479aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis} 480aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis 4816f09c3d69f6272b101ff795562dffead1c0bd9deArgyrios KyrtzidisCXResult clang_findIncludesInFile(CXTranslationUnit TU, CXFile file, 482389dc5603fa10b508a38f668a7830c6d877b6542Argyrios Kyrtzidis CXCursorAndRangeVisitor visitor) { 483651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (cxtu::isNotUsableTU(TU)) { 484651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines LOG_BAD_TU(TU); 4856f09c3d69f6272b101ff795562dffead1c0bd9deArgyrios Kyrtzidis return CXResult_Invalid; 486ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis } 487651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 488651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines LogRef Log = Logger::make(LLVM_FUNCTION_NAME); 489ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis if (!file) { 490ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis if (Log) 491ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis *Log << "Null file"; 4926f09c3d69f6272b101ff795562dffead1c0bd9deArgyrios Kyrtzidis return CXResult_Invalid; 493ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis } 494ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis if (!visitor.visit) { 495ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis if (Log) 496ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis *Log << "Null visitor"; 4976f09c3d69f6272b101ff795562dffead1c0bd9deArgyrios Kyrtzidis return CXResult_Invalid; 498ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis } 499ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis 500ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis if (Log) 501ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis *Log << TU << " @" << static_cast<const FileEntry *>(file); 502ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis 503ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis ASTUnit *CXXUnit = cxtu::getASTUnit(TU); 504ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis if (!CXXUnit) 5056f09c3d69f6272b101ff795562dffead1c0bd9deArgyrios Kyrtzidis return CXResult_Invalid; 506ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis 507ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis ASTUnit::ConcurrencyCheck Check(*CXXUnit); 508ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis 509389dc5603fa10b508a38f668a7830c6d877b6542Argyrios Kyrtzidis if (findIncludesInFile(TU, static_cast<const FileEntry *>(file), visitor)) 5106f09c3d69f6272b101ff795562dffead1c0bd9deArgyrios Kyrtzidis return CXResult_VisitBreak; 5116f09c3d69f6272b101ff795562dffead1c0bd9deArgyrios Kyrtzidis return CXResult_Success; 512ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis} 513ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis 514aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidisstatic enum CXVisitorResult _visitCursorAndRange(void *context, 515aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis CXCursor cursor, 516aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis CXSourceRange range) { 517aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis CXCursorAndRangeVisitorBlock block = (CXCursorAndRangeVisitorBlock)context; 518aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis return INVOKE_BLOCK2(block, cursor, range); 519aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis} 520aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis 5216f09c3d69f6272b101ff795562dffead1c0bd9deArgyrios KyrtzidisCXResult clang_findReferencesInFileWithBlock(CXCursor cursor, 5226f09c3d69f6272b101ff795562dffead1c0bd9deArgyrios Kyrtzidis CXFile file, 5236f09c3d69f6272b101ff795562dffead1c0bd9deArgyrios Kyrtzidis CXCursorAndRangeVisitorBlock block) { 524aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis CXCursorAndRangeVisitor visitor = { block, 525c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines block ? _visitCursorAndRange : nullptr }; 526aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis return clang_findReferencesInFile(cursor, file, visitor); 527aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis} 528aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis 5296f09c3d69f6272b101ff795562dffead1c0bd9deArgyrios KyrtzidisCXResult clang_findIncludesInFileWithBlock(CXTranslationUnit TU, 5306f09c3d69f6272b101ff795562dffead1c0bd9deArgyrios Kyrtzidis CXFile file, 5316f09c3d69f6272b101ff795562dffead1c0bd9deArgyrios Kyrtzidis CXCursorAndRangeVisitorBlock block) { 532ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis CXCursorAndRangeVisitor visitor = { block, 533c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines block ? _visitCursorAndRange : nullptr }; 534ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis return clang_findIncludesInFile(TU, file, visitor); 535ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis} 536ee2d5fd7a3bd42bce387db094d27a479617c3e67Argyrios Kyrtzidis 537aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis} // end: extern "C" 538aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis 539