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