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