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