CIndexHigh.cpp revision c6f5c6a58d34833d1fe458a518d5f59462926c7b
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"
11aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis#include "CXCursor.h"
12aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis#include "CXSourceLocation.h"
13aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis#include "CXTranslationUnit.h"
14c6f5c6a58d34833d1fe458a518d5f59462926c7bArgyrios Kyrtzidis#include "CLog.h"
15aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis#include "clang/AST/DeclObjC.h"
16f59edb96b2d0bfe612b732f19519ab84bb995bd4Chandler Carruth#include "clang/Frontend/ASTUnit.h"
17aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
18aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidisusing namespace clang;
19e2079cf54ded1eda9e35d215aef6628373368276Argyrios Kyrtzidisusing namespace cxcursor;
20c6f5c6a58d34833d1fe458a518d5f59462926c7bArgyrios Kyrtzidisusing namespace cxindex;
21aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
22aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidisstatic void getTopOverriddenMethods(CXTranslationUnit TU,
23aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis                                    Decl *D,
24aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis                                    SmallVectorImpl<Decl *> &Methods) {
2516ed0e6fda74800595cb98d11969fc4afcc00bacArgyrios Kyrtzidis  if (!D)
2616ed0e6fda74800595cb98d11969fc4afcc00bacArgyrios Kyrtzidis    return;
27aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  if (!isa<ObjCMethodDecl>(D) && !isa<CXXMethodDecl>(D))
28aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    return;
29aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
30aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  SmallVector<CXCursor, 8> Overridden;
31aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  cxcursor::getOverriddenCursors(cxcursor::MakeCXCursor(D, TU), Overridden);
32aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
33aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  if (Overridden.empty()) {
34aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    Methods.push_back(D->getCanonicalDecl());
35aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    return;
36aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  }
37aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
38aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  for (SmallVector<CXCursor, 8>::iterator
39aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis         I = Overridden.begin(), E = Overridden.end(); I != E; ++I)
40aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    getTopOverriddenMethods(TU, cxcursor::getCursorDecl(*I), Methods);
41aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis}
42aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
43aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidisnamespace {
44aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
45aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidisstruct FindFileIdRefVisitData {
46aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  CXTranslationUnit TU;
47aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  FileID FID;
48aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  Decl *Dcl;
49aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  int SelectorIdIdx;
50aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  CXCursorAndRangeVisitor visitor;
51aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
52aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  typedef SmallVector<Decl *, 8> TopMethodsTy;
53aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  TopMethodsTy TopMethods;
54aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
55aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  FindFileIdRefVisitData(CXTranslationUnit TU, FileID FID,
56aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis                         Decl *D, int selectorIdIdx,
57aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis                         CXCursorAndRangeVisitor visitor)
58aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    : TU(TU), FID(FID), SelectorIdIdx(selectorIdIdx), visitor(visitor) {
59aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    Dcl = getCanonical(D);
60aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    getTopOverriddenMethods(TU, Dcl, TopMethods);
61aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  }
62aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
63aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  ASTContext &getASTContext() const {
64aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    return static_cast<ASTUnit *>(TU->TUData)->getASTContext();
65aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  }
66aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
67aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  /// \brief We are looking to find all semantically relevant identifiers,
68aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  /// so the definition of "canonical" here is different than in the AST, e.g.
69aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  ///
70aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  /// \code
71aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  ///   class C {
72aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  ///     C() {}
73aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  ///   };
74aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  /// \endcode
75aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  ///
76aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  /// we consider the canonical decl of the constructor decl to be the class
77aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  /// itself, so both 'C' can be highlighted.
78aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  Decl *getCanonical(Decl *D) const {
79e368a641a03617983dabb1e092d880e1089f576aArgyrios Kyrtzidis    if (!D)
80e368a641a03617983dabb1e092d880e1089f576aArgyrios Kyrtzidis      return 0;
81e368a641a03617983dabb1e092d880e1089f576aArgyrios Kyrtzidis
82aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    D = D->getCanonicalDecl();
83aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
84e368a641a03617983dabb1e092d880e1089f576aArgyrios Kyrtzidis    if (ObjCImplDecl *ImplD = dyn_cast<ObjCImplDecl>(D)) {
85e368a641a03617983dabb1e092d880e1089f576aArgyrios Kyrtzidis      if (ImplD->getClassInterface())
86e368a641a03617983dabb1e092d880e1089f576aArgyrios Kyrtzidis        return getCanonical(ImplD->getClassInterface());
87e368a641a03617983dabb1e092d880e1089f576aArgyrios Kyrtzidis
88e368a641a03617983dabb1e092d880e1089f576aArgyrios Kyrtzidis    } else if (CXXConstructorDecl *CXXCtorD = dyn_cast<CXXConstructorDecl>(D)) {
89aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis      return getCanonical(CXXCtorD->getParent());
90e368a641a03617983dabb1e092d880e1089f576aArgyrios Kyrtzidis    }
91aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
92aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    return D;
93aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  }
94aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
95aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  bool isHit(Decl *D) const {
96e368a641a03617983dabb1e092d880e1089f576aArgyrios Kyrtzidis    if (!D)
97e368a641a03617983dabb1e092d880e1089f576aArgyrios Kyrtzidis      return false;
98e368a641a03617983dabb1e092d880e1089f576aArgyrios Kyrtzidis
99aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    D = getCanonical(D);
100aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    if (D == Dcl)
101aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis      return true;
102aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
103aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    if (isa<ObjCMethodDecl>(D) || isa<CXXMethodDecl>(D))
104aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis      return isOverriddingMethod(D);
105aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
106aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    return false;
107aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  }
108aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
109aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidisprivate:
110aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  bool isOverriddingMethod(Decl *D) const {
111aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    if (std::find(TopMethods.begin(), TopMethods.end(), D) !=
112aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis          TopMethods.end())
113aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis      return true;
114aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
115aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    TopMethodsTy methods;
116aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    getTopOverriddenMethods(TU, D, methods);
117aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    for (TopMethodsTy::iterator
118aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis           I = methods.begin(), E = methods.end(); I != E; ++I) {
119aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis      if (std::find(TopMethods.begin(), TopMethods.end(), *I) !=
120aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis            TopMethods.end())
121aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis        return true;
122aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    }
123aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
124aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    return false;
125aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  }
126aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis};
127aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
128aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis} // end anonymous namespace.
129aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
130aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis/// \brief For a macro \arg Loc, returns the file spelling location and sets
131aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis/// to \arg isMacroArg whether the spelling resides inside a macro definition or
132aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis/// a macro argument.
133aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidisstatic SourceLocation getFileSpellingLoc(SourceManager &SM,
134aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis                                         SourceLocation Loc,
135aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis                                         bool &isMacroArg) {
136aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  assert(Loc.isMacroID());
137aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  SourceLocation SpellLoc = SM.getImmediateSpellingLoc(Loc);
138aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  if (SpellLoc.isMacroID())
139aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    return getFileSpellingLoc(SM, SpellLoc, isMacroArg);
140aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
141aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  isMacroArg = SM.isMacroArgExpansion(Loc);
142aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  return SpellLoc;
143aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis}
144aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
145aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidisstatic enum CXChildVisitResult findFileIdRefVisit(CXCursor cursor,
146aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis                                                  CXCursor parent,
147aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis                                                  CXClientData client_data) {
148aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  CXCursor declCursor = clang_getCursorReferenced(cursor);
149aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  if (!clang_isDeclaration(declCursor.kind))
150aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    return CXChildVisit_Recurse;
151aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
152aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  Decl *D = cxcursor::getCursorDecl(declCursor);
15316ed0e6fda74800595cb98d11969fc4afcc00bacArgyrios Kyrtzidis  if (!D)
15416ed0e6fda74800595cb98d11969fc4afcc00bacArgyrios Kyrtzidis    return CXChildVisit_Continue;
15516ed0e6fda74800595cb98d11969fc4afcc00bacArgyrios Kyrtzidis
156aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  FindFileIdRefVisitData *data = (FindFileIdRefVisitData *)client_data;
157aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  if (data->isHit(D)) {
158aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    cursor = cxcursor::getSelectorIdentifierCursor(data->SelectorIdIdx, cursor);
159aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
160aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    // We are looking for identifiers to highlight so for objc methods (and
161aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    // not a parameter) we can only highlight the selector identifiers.
162aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    if ((cursor.kind == CXCursor_ObjCClassMethodDecl ||
163aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis         cursor.kind == CXCursor_ObjCInstanceMethodDecl) &&
164aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis         cxcursor::getSelectorIdentifierIndex(cursor) == -1)
165aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis      return CXChildVisit_Recurse;
166aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
167aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    if (clang_isExpression(cursor.kind)) {
168aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis      if (cursor.kind == CXCursor_DeclRefExpr ||
169aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis          cursor.kind == CXCursor_MemberRefExpr) {
170aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis        // continue..
171aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
172aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis      } else if (cursor.kind == CXCursor_ObjCMessageExpr &&
173aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis                 cxcursor::getSelectorIdentifierIndex(cursor) != -1) {
174aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis        // continue..
175aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
176aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis      } else
177aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis        return CXChildVisit_Recurse;
178aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    }
179aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
180aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    SourceLocation
181aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis      Loc = cxloc::translateSourceLocation(clang_getCursorLocation(cursor));
182aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    SourceLocation SelIdLoc = cxcursor::getSelectorIdentifierLoc(cursor);
183aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    if (SelIdLoc.isValid())
184aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis      Loc = SelIdLoc;
185aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
186b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis    ASTContext &Ctx = data->getASTContext();
187b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis    SourceManager &SM = Ctx.getSourceManager();
188aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    bool isInMacroDef = false;
189aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    if (Loc.isMacroID()) {
190aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis      bool isMacroArg;
191aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis      Loc = getFileSpellingLoc(SM, Loc, isMacroArg);
192aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis      isInMacroDef = !isMacroArg;
193aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    }
194aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
195aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    // We are looking for identifiers in a specific file.
196aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc);
197aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    if (LocInfo.first != data->FID)
198aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis      return CXChildVisit_Recurse;
199aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
200aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    if (isInMacroDef) {
201aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis      // FIXME: For a macro definition make sure that all expansions
202aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis      // of it expand to the same reference before allowing to point to it.
203b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis      return CXChildVisit_Recurse;
204aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    }
205aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
206aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    data->visitor.visit(data->visitor.context, cursor,
207b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis                        cxloc::translateSourceRange(Ctx, Loc));
208aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  }
209aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  return CXChildVisit_Recurse;
210aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis}
211aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
212aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidisstatic void findIdRefsInFile(CXTranslationUnit TU, CXCursor declCursor,
213aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis                           const FileEntry *File,
214aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis                           CXCursorAndRangeVisitor Visitor) {
215aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  assert(clang_isDeclaration(declCursor.kind));
216aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  ASTUnit *Unit = static_cast<ASTUnit*>(TU->TUData);
217aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  SourceManager &SM = Unit->getSourceManager();
218aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
219aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  FileID FID = SM.translateFile(File);
220aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  Decl *Dcl = cxcursor::getCursorDecl(declCursor);
221e368a641a03617983dabb1e092d880e1089f576aArgyrios Kyrtzidis  if (!Dcl)
222e368a641a03617983dabb1e092d880e1089f576aArgyrios Kyrtzidis    return;
223e368a641a03617983dabb1e092d880e1089f576aArgyrios Kyrtzidis
224aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  FindFileIdRefVisitData data(TU, FID, Dcl,
225aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis                              cxcursor::getSelectorIdentifierIndex(declCursor),
226aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis                              Visitor);
227aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
228aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  if (DeclContext *DC = Dcl->getParentFunctionOrMethod()) {
229aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    clang_visitChildren(cxcursor::MakeCXCursor(cast<Decl>(DC), TU),
230aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis                        findFileIdRefVisit, &data);
231aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    return;
232aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  }
233aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
234e2079cf54ded1eda9e35d215aef6628373368276Argyrios Kyrtzidis  SourceRange Range(SM.getLocForStartOfFile(FID), SM.getLocForEndOfFile(FID));
235e2079cf54ded1eda9e35d215aef6628373368276Argyrios Kyrtzidis  CursorVisitor FindIdRefsVisitor(TU,
236e2079cf54ded1eda9e35d215aef6628373368276Argyrios Kyrtzidis                                  findFileIdRefVisit, &data,
237e2079cf54ded1eda9e35d215aef6628373368276Argyrios Kyrtzidis                                  /*VisitPreprocessorLast=*/true,
238e2079cf54ded1eda9e35d215aef6628373368276Argyrios Kyrtzidis                                  /*VisitIncludedEntities=*/false,
239b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis                                  Range,
240b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis                                  /*VisitDeclsOnly=*/true);
241e2079cf54ded1eda9e35d215aef6628373368276Argyrios Kyrtzidis  FindIdRefsVisitor.visitFileRegion();
242aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis}
243aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
244b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidisnamespace {
245b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis
246b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidisstruct FindFileMacroRefVisitData {
247b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis  ASTUnit &Unit;
248b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis  const FileEntry *File;
249b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis  const IdentifierInfo *Macro;
250b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis  CXCursorAndRangeVisitor visitor;
251b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis
252b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis  FindFileMacroRefVisitData(ASTUnit &Unit, const FileEntry *File,
253b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis                            const IdentifierInfo *Macro,
254b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis                            CXCursorAndRangeVisitor visitor)
255b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis    : Unit(Unit), File(File), Macro(Macro), visitor(visitor) { }
256b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis
257b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis  ASTContext &getASTContext() const {
258b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis    return Unit.getASTContext();
259b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis  }
260b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis};
261b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis
262b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis} // anonymous namespace
263b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis
264b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidisstatic enum CXChildVisitResult findFileMacroRefVisit(CXCursor cursor,
265b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis                                                     CXCursor parent,
266b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis                                                     CXClientData client_data) {
267b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis  const IdentifierInfo *Macro = 0;
268b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis  if (cursor.kind == CXCursor_MacroDefinition)
269b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis    Macro = getCursorMacroDefinition(cursor)->getName();
270b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis  else if (cursor.kind == CXCursor_MacroExpansion)
271664b06f9bd2ea83443ddc8553feba8ba48880752Argyrios Kyrtzidis    Macro = getCursorMacroExpansion(cursor).getName();
272b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis  if (!Macro)
273b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis    return CXChildVisit_Continue;
274b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis
275b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis  FindFileMacroRefVisitData *data = (FindFileMacroRefVisitData *)client_data;
276b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis  if (data->Macro != Macro)
277b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis    return CXChildVisit_Continue;
278b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis
279b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis  SourceLocation
280b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis    Loc = cxloc::translateSourceLocation(clang_getCursorLocation(cursor));
281b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis
282b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis  ASTContext &Ctx = data->getASTContext();
283b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis  SourceManager &SM = Ctx.getSourceManager();
284b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis  bool isInMacroDef = false;
285b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis  if (Loc.isMacroID()) {
286b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis    bool isMacroArg;
287b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis    Loc = getFileSpellingLoc(SM, Loc, isMacroArg);
288b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis    isInMacroDef = !isMacroArg;
289b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis  }
290b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis
291b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis  // We are looking for identifiers in a specific file.
292b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis  std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc);
293b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis  if (SM.getFileEntryForID(LocInfo.first) != data->File)
294b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis    return CXChildVisit_Continue;
295b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis
296b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis  if (isInMacroDef) {
297b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis    // FIXME: For a macro definition make sure that all expansions
298b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis    // of it expand to the same reference before allowing to point to it.
299b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis    return CXChildVisit_Continue;
300b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis  }
301b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis
302b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis  data->visitor.visit(data->visitor.context, cursor,
303b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis                      cxloc::translateSourceRange(Ctx, Loc));
304b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis  return CXChildVisit_Continue;
305b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis}
306b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis
307b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidisstatic void findMacroRefsInFile(CXTranslationUnit TU, CXCursor Cursor,
308b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis                                const FileEntry *File,
309b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis                                CXCursorAndRangeVisitor Visitor) {
310b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis  if (Cursor.kind != CXCursor_MacroDefinition &&
311b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis      Cursor.kind != CXCursor_MacroExpansion)
312b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis    return;
313b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis
314b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis  ASTUnit *Unit = static_cast<ASTUnit*>(TU->TUData);
315b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis  SourceManager &SM = Unit->getSourceManager();
316b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis
317b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis  FileID FID = SM.translateFile(File);
318b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis  const IdentifierInfo *Macro = 0;
319b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis  if (Cursor.kind == CXCursor_MacroDefinition)
320b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis    Macro = getCursorMacroDefinition(Cursor)->getName();
321b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis  else
322664b06f9bd2ea83443ddc8553feba8ba48880752Argyrios Kyrtzidis    Macro = getCursorMacroExpansion(Cursor).getName();
323b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis  if (!Macro)
324b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis    return;
325b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis
326b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis  FindFileMacroRefVisitData data(*Unit, File, Macro, Visitor);
327b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis
328b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis  SourceRange Range(SM.getLocForStartOfFile(FID), SM.getLocForEndOfFile(FID));
329b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis  CursorVisitor FindMacroRefsVisitor(TU,
330b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis                                  findFileMacroRefVisit, &data,
331b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis                                  /*VisitPreprocessorLast=*/false,
332b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis                                  /*VisitIncludedEntities=*/false,
333b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis                                  Range);
334b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis  FindMacroRefsVisitor.visitPreprocessedEntitiesInRegion();
335b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis}
336b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis
337aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
338aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis//===----------------------------------------------------------------------===//
339aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis// libclang public APIs.
340aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis//===----------------------------------------------------------------------===//
341aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
342aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidisextern "C" {
343aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
344aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidisvoid clang_findReferencesInFile(CXCursor cursor, CXFile file,
345aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis                                CXCursorAndRangeVisitor visitor) {
346c6f5c6a58d34833d1fe458a518d5f59462926c7bArgyrios Kyrtzidis  LogRef Log = Logger::make(__func__);
347aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
348aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  if (clang_Cursor_isNull(cursor)) {
349c6f5c6a58d34833d1fe458a518d5f59462926c7bArgyrios Kyrtzidis    if (Log)
350c6f5c6a58d34833d1fe458a518d5f59462926c7bArgyrios Kyrtzidis      *Log << "Null cursor";
351aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    return;
352aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  }
3534451746d8f658b51eaf15dd24664a488457063a9Argyrios Kyrtzidis  if (cursor.kind == CXCursor_NoDeclFound) {
354c6f5c6a58d34833d1fe458a518d5f59462926c7bArgyrios Kyrtzidis    if (Log)
355c6f5c6a58d34833d1fe458a518d5f59462926c7bArgyrios Kyrtzidis      *Log << "Got CXCursor_NoDeclFound";
3564451746d8f658b51eaf15dd24664a488457063a9Argyrios Kyrtzidis    return;
3574451746d8f658b51eaf15dd24664a488457063a9Argyrios Kyrtzidis  }
358aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  if (!file) {
359c6f5c6a58d34833d1fe458a518d5f59462926c7bArgyrios Kyrtzidis    if (Log)
360c6f5c6a58d34833d1fe458a518d5f59462926c7bArgyrios Kyrtzidis      *Log << "Null file";
361aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    return;
362aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  }
363aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  if (!visitor.visit) {
364c6f5c6a58d34833d1fe458a518d5f59462926c7bArgyrios Kyrtzidis    if (Log)
365c6f5c6a58d34833d1fe458a518d5f59462926c7bArgyrios Kyrtzidis      *Log << "Null visitor";
366aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    return;
367aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  }
368aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
3695c2a1f741e133fcad4782b855a18d3b220243b11Argyrios Kyrtzidis  ASTUnit *CXXUnit = cxcursor::getCursorASTUnit(cursor);
3705c2a1f741e133fcad4782b855a18d3b220243b11Argyrios Kyrtzidis  if (!CXXUnit)
3715c2a1f741e133fcad4782b855a18d3b220243b11Argyrios Kyrtzidis    return;
3725c2a1f741e133fcad4782b855a18d3b220243b11Argyrios Kyrtzidis
3735c2a1f741e133fcad4782b855a18d3b220243b11Argyrios Kyrtzidis  ASTUnit::ConcurrencyCheck Check(*CXXUnit);
3745c2a1f741e133fcad4782b855a18d3b220243b11Argyrios Kyrtzidis
375b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis  if (cursor.kind == CXCursor_MacroDefinition ||
376b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis      cursor.kind == CXCursor_MacroExpansion) {
377b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis    findMacroRefsInFile(cxcursor::getCursorTU(cursor),
378b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis                        cursor,
379b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis                        static_cast<const FileEntry *>(file),
380b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis                        visitor);
381b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis    return;
382b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis  }
383b49e728a4d1a84b72f3aebf60ff494684f9cb004Argyrios Kyrtzidis
384aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  // We are interested in semantics of identifiers so for C++ constructor exprs
385aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  // prefer type references, e.g.:
386aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  //
387aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  //  return MyStruct();
388aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  //
389aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  // for 'MyStruct' we'll have a cursor pointing at the constructor decl but
390aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  // we are actually interested in the type declaration.
391aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  cursor = cxcursor::getTypeRefCursor(cursor);
392aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
393aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  CXCursor refCursor = clang_getCursorReferenced(cursor);
394aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
395aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  if (!clang_isDeclaration(refCursor.kind)) {
396c6f5c6a58d34833d1fe458a518d5f59462926c7bArgyrios Kyrtzidis    if (Log)
397c6f5c6a58d34833d1fe458a518d5f59462926c7bArgyrios Kyrtzidis      *Log << "cursor is not referencing a declaration";
398aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    return;
399aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  }
400aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
401aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  findIdRefsInFile(cxcursor::getCursorTU(cursor),
402aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis                   refCursor,
403aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis                   static_cast<const FileEntry *>(file),
404aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis                   visitor);
405aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis}
406aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
407aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidisstatic enum CXVisitorResult _visitCursorAndRange(void *context,
408aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis                                                 CXCursor cursor,
409aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis                                                 CXSourceRange range) {
410aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  CXCursorAndRangeVisitorBlock block = (CXCursorAndRangeVisitorBlock)context;
411aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  return INVOKE_BLOCK2(block, cursor, range);
412aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis}
413aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
414aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidisvoid clang_findReferencesInFileWithBlock(CXCursor cursor,
415aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis                                         CXFile file,
416aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis                                         CXCursorAndRangeVisitorBlock block) {
417aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  CXCursorAndRangeVisitor visitor = { block,
418aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis                                      block ? _visitCursorAndRange : 0 };
419aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  return clang_findReferencesInFile(cursor, file, visitor);
420aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis}
421aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
422aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis} // end: extern "C"
423aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
424