blob: 98edd521ef4bf2b032628feab996f1c47ef3812e [file] [log] [blame]
Ted Kremenekd2fa5662009-08-26 22:36:44 +00001//===- CIndex.cpp - Clang-C Source Indexing Library -----------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
Daniel Dunbar0d7dd222009-11-30 20:42:43 +00007//
Ted Kremenekd2fa5662009-08-26 22:36:44 +00008//===----------------------------------------------------------------------===//
9//
Ted Kremenekab188932010-01-05 19:32:54 +000010// This file implements the main API hooks in the Clang-C Source Indexing
11// library.
Ted Kremenekd2fa5662009-08-26 22:36:44 +000012//
13//===----------------------------------------------------------------------===//
14
Ted Kremenekab188932010-01-05 19:32:54 +000015#include "CIndexer.h"
Ted Kremenek16c440a2010-01-15 20:35:54 +000016#include "CXCursor.h"
Ted Kremenek0a90d322010-11-17 23:24:11 +000017#include "CXTranslationUnit.h"
Ted Kremeneked122732010-11-16 01:56:27 +000018#include "CXString.h"
Ted Kremenek95f33552010-08-26 01:42:22 +000019#include "CXType.h"
Ted Kremeneka297de22010-01-25 22:34:44 +000020#include "CXSourceLocation.h"
Douglas Gregor5352ac02010-01-28 00:27:43 +000021#include "CIndexDiagnostic.h"
Ted Kremenekab188932010-01-05 19:32:54 +000022
Ted Kremenek04bb7162010-01-22 22:44:15 +000023#include "clang/Basic/Version.h"
Douglas Gregor936ea3b2010-01-28 00:56:43 +000024
Steve Naroff50398192009-08-28 15:28:48 +000025#include "clang/AST/DeclVisitor.h"
Steve Narofffb570422009-09-22 19:25:29 +000026#include "clang/AST/StmtVisitor.h"
Douglas Gregor7d0d40e2010-01-21 16:28:34 +000027#include "clang/AST/TypeLocVisitor.h"
Benjamin Kramerb846deb2010-04-12 19:45:50 +000028#include "clang/Basic/Diagnostic.h"
29#include "clang/Frontend/ASTUnit.h"
30#include "clang/Frontend/CompilerInstance.h"
Douglas Gregor936ea3b2010-01-28 00:56:43 +000031#include "clang/Frontend/FrontendDiagnostic.h"
Ted Kremenekd8210652010-01-06 23:43:31 +000032#include "clang/Lex/Lexer.h"
Benjamin Kramerb846deb2010-04-12 19:45:50 +000033#include "clang/Lex/PreprocessingRecord.h"
Douglas Gregor33e9abd2010-01-22 19:49:59 +000034#include "clang/Lex/Preprocessor.h"
Douglas Gregora67e03f2010-09-09 21:42:20 +000035#include "llvm/ADT/STLExtras.h"
Ted Kremenekd8c370c2010-11-02 23:10:24 +000036#include "llvm/ADT/Optional.h"
Douglas Gregorf5251602011-03-08 17:10:18 +000037#include "llvm/ADT/StringSwitch.h"
Ted Kremenekd8c370c2010-11-02 23:10:24 +000038#include "clang/Analysis/Support/SaveAndRestore.h"
Daniel Dunbarc7df4f32010-08-18 18:43:14 +000039#include "llvm/Support/CrashRecoveryContext.h"
Daniel Dunbar48615ff2010-10-08 19:30:33 +000040#include "llvm/Support/PrettyStackTrace.h"
Douglas Gregor02465752009-10-16 21:24:31 +000041#include "llvm/Support/MemoryBuffer.h"
Douglas Gregor358559d2010-10-02 22:49:11 +000042#include "llvm/Support/raw_ostream.h"
Douglas Gregor7a07fcb2010-08-09 21:00:09 +000043#include "llvm/Support/Timer.h"
Michael J. Spencer03013fa2010-11-29 18:12:39 +000044#include "llvm/Support/Mutex.h"
45#include "llvm/Support/Program.h"
46#include "llvm/Support/Signals.h"
47#include "llvm/Support/Threading.h"
Ted Kremenek37f1ea02010-11-15 23:11:54 +000048#include "llvm/Support/Compiler.h"
Ted Kremenekfc062212009-10-19 21:44:57 +000049
Steve Naroff50398192009-08-28 15:28:48 +000050using namespace clang;
Ted Kremenek16c440a2010-01-15 20:35:54 +000051using namespace clang::cxcursor;
Ted Kremenekee4db4f2010-02-17 00:41:08 +000052using namespace clang::cxstring;
Steve Naroff50398192009-08-28 15:28:48 +000053
Ted Kremeneka60ed472010-11-16 08:15:36 +000054static CXTranslationUnit MakeCXTranslationUnit(ASTUnit *TU) {
55 if (!TU)
56 return 0;
57 CXTranslationUnit D = new CXTranslationUnitImpl();
58 D->TUData = TU;
59 D->StringPool = createCXStringPool();
60 return D;
61}
62
Douglas Gregor33e9abd2010-01-22 19:49:59 +000063/// \brief The result of comparing two source ranges.
64enum RangeComparisonResult {
65 /// \brief Either the ranges overlap or one of the ranges is invalid.
66 RangeOverlap,
Ted Kremenekf0e23e82010-02-17 00:41:40 +000067
Douglas Gregor33e9abd2010-01-22 19:49:59 +000068 /// \brief The first range ends before the second range starts.
69 RangeBefore,
Ted Kremenekf0e23e82010-02-17 00:41:40 +000070
Douglas Gregor33e9abd2010-01-22 19:49:59 +000071 /// \brief The first range starts after the second range ends.
72 RangeAfter
73};
74
Ted Kremenekf0e23e82010-02-17 00:41:40 +000075/// \brief Compare two source ranges to determine their relative position in
Douglas Gregor33e9abd2010-01-22 19:49:59 +000076/// the translation unit.
Ted Kremenekf0e23e82010-02-17 00:41:40 +000077static RangeComparisonResult RangeCompare(SourceManager &SM,
78 SourceRange R1,
Douglas Gregor33e9abd2010-01-22 19:49:59 +000079 SourceRange R2) {
80 assert(R1.isValid() && "First range is invalid?");
81 assert(R2.isValid() && "Second range is invalid?");
Douglas Gregora8e5c5b2010-07-22 20:22:31 +000082 if (R1.getEnd() != R2.getBegin() &&
Daniel Dunbard52864b2010-02-14 10:02:57 +000083 SM.isBeforeInTranslationUnit(R1.getEnd(), R2.getBegin()))
Douglas Gregor33e9abd2010-01-22 19:49:59 +000084 return RangeBefore;
Douglas Gregora8e5c5b2010-07-22 20:22:31 +000085 if (R2.getEnd() != R1.getBegin() &&
Daniel Dunbard52864b2010-02-14 10:02:57 +000086 SM.isBeforeInTranslationUnit(R2.getEnd(), R1.getBegin()))
Douglas Gregor33e9abd2010-01-22 19:49:59 +000087 return RangeAfter;
88 return RangeOverlap;
89}
90
Ted Kremenekfbd84ca2010-05-05 00:55:23 +000091/// \brief Determine if a source location falls within, before, or after a
92/// a given source range.
93static RangeComparisonResult LocationCompare(SourceManager &SM,
94 SourceLocation L, SourceRange R) {
95 assert(R.isValid() && "First range is invalid?");
96 assert(L.isValid() && "Second range is invalid?");
Douglas Gregora8e5c5b2010-07-22 20:22:31 +000097 if (L == R.getBegin() || L == R.getEnd())
Ted Kremenekfbd84ca2010-05-05 00:55:23 +000098 return RangeOverlap;
Ted Kremenekfbd84ca2010-05-05 00:55:23 +000099 if (SM.isBeforeInTranslationUnit(L, R.getBegin()))
100 return RangeBefore;
101 if (SM.isBeforeInTranslationUnit(R.getEnd(), L))
102 return RangeAfter;
103 return RangeOverlap;
104}
105
Daniel Dunbar76dd3c22010-02-14 01:47:29 +0000106/// \brief Translate a Clang source range into a CIndex source range.
107///
108/// Clang internally represents ranges where the end location points to the
109/// start of the token at the end. However, for external clients it is more
110/// useful to have a CXSourceRange be a proper half-open interval. This routine
111/// does the appropriate translation.
Ted Kremenekf0e23e82010-02-17 00:41:40 +0000112CXSourceRange cxloc::translateSourceRange(const SourceManager &SM,
Daniel Dunbar76dd3c22010-02-14 01:47:29 +0000113 const LangOptions &LangOpts,
Chris Lattner0a76aae2010-06-18 22:45:06 +0000114 const CharSourceRange &R) {
Daniel Dunbar76dd3c22010-02-14 01:47:29 +0000115 // We want the last character in this location, so we will adjust the
Douglas Gregor6a5a23f2010-03-19 21:51:54 +0000116 // location accordingly.
Daniel Dunbar76dd3c22010-02-14 01:47:29 +0000117 SourceLocation EndLoc = R.getEnd();
Douglas Gregora9b06d42010-11-09 06:24:54 +0000118 if (EndLoc.isValid() && EndLoc.isMacroID())
Douglas Gregorffcd9852011-04-20 21:16:21 +0000119 EndLoc = SM.getInstantiationRange(EndLoc).second;
Chris Lattner0a76aae2010-06-18 22:45:06 +0000120 if (R.isTokenRange() && !EndLoc.isInvalid() && EndLoc.isFileID()) {
Douglas Gregor6a5a23f2010-03-19 21:51:54 +0000121 unsigned Length = Lexer::MeasureTokenLength(EndLoc, SM, LangOpts);
Daniel Dunbar76dd3c22010-02-14 01:47:29 +0000122 EndLoc = EndLoc.getFileLocWithOffset(Length);
123 }
124
125 CXSourceRange Result = { { (void *)&SM, (void *)&LangOpts },
126 R.getBegin().getRawEncoding(),
127 EndLoc.getRawEncoding() };
128 return Result;
129}
Douglas Gregor1db19de2010-01-19 21:36:55 +0000130
Ted Kremenek8a8da7d2010-01-06 03:42:32 +0000131//===----------------------------------------------------------------------===//
Douglas Gregor33e9abd2010-01-22 19:49:59 +0000132// Cursor visitor.
Ted Kremenek8a8da7d2010-01-06 03:42:32 +0000133//===----------------------------------------------------------------------===//
134
Steve Naroff89922f82009-08-31 00:59:03 +0000135namespace {
Ted Kremenekc0e1d922010-11-11 08:05:18 +0000136
137class VisitorJob {
138public:
Ted Kremenekcdb4caf2010-11-12 21:34:12 +0000139 enum Kind { DeclVisitKind, StmtVisitKind, MemberExprPartsKind,
Ted Kremeneke4979cc2010-11-13 00:58:18 +0000140 TypeLocVisitKind, OverloadExprPartsKind,
Ted Kremenek60608ec2010-11-17 00:50:47 +0000141 DeclRefExprPartsKind, LabelRefVisitKind,
Ted Kremenekf64d8032010-11-18 00:02:32 +0000142 ExplicitTemplateArgsVisitKind,
143 NestedNameSpecifierVisitKind,
Douglas Gregorf3db29f2011-02-25 18:19:59 +0000144 NestedNameSpecifierLocVisitKind,
Ted Kremenekcdba6592010-11-18 00:42:18 +0000145 DeclarationNameInfoVisitKind,
Douglas Gregor94d96292011-01-19 20:34:17 +0000146 MemberRefVisitKind, SizeOfPackExprPartsKind };
Ted Kremenekc0e1d922010-11-11 08:05:18 +0000147protected:
Ted Kremenekf64d8032010-11-18 00:02:32 +0000148 void *data[3];
Ted Kremenekc0e1d922010-11-11 08:05:18 +0000149 CXCursor parent;
150 Kind K;
Ted Kremenekf64d8032010-11-18 00:02:32 +0000151 VisitorJob(CXCursor C, Kind k, void *d1, void *d2 = 0, void *d3 = 0)
152 : parent(C), K(k) {
153 data[0] = d1;
154 data[1] = d2;
155 data[2] = d3;
156 }
Ted Kremenekc0e1d922010-11-11 08:05:18 +0000157public:
158 Kind getKind() const { return K; }
159 const CXCursor &getParent() const { return parent; }
160 static bool classof(VisitorJob *VJ) { return true; }
161};
162
163typedef llvm::SmallVector<VisitorJob, 10> VisitorWorkList;
164
Douglas Gregorb1373d02010-01-20 20:59:29 +0000165// Cursor visitor.
Douglas Gregor7d0d40e2010-01-21 16:28:34 +0000166class CursorVisitor : public DeclVisitor<CursorVisitor, bool>,
Ted Kremenekcdba6592010-11-18 00:42:18 +0000167 public TypeLocVisitor<CursorVisitor, bool>
Douglas Gregor7d0d40e2010-01-21 16:28:34 +0000168{
Douglas Gregor33e9abd2010-01-22 19:49:59 +0000169 /// \brief The translation unit we are traversing.
Ted Kremeneka60ed472010-11-16 08:15:36 +0000170 CXTranslationUnit TU;
171 ASTUnit *AU;
Ted Kremenekf0e23e82010-02-17 00:41:40 +0000172
Douglas Gregor33e9abd2010-01-22 19:49:59 +0000173 /// \brief The parent cursor whose children we are traversing.
Douglas Gregorb1373d02010-01-20 20:59:29 +0000174 CXCursor Parent;
Ted Kremenekf0e23e82010-02-17 00:41:40 +0000175
Douglas Gregor33e9abd2010-01-22 19:49:59 +0000176 /// \brief The declaration that serves at the parent of any statement or
177 /// expression nodes.
Douglas Gregorf20dfbc2010-01-21 17:29:07 +0000178 Decl *StmtParent;
Ted Kremenekf0e23e82010-02-17 00:41:40 +0000179
Douglas Gregor33e9abd2010-01-22 19:49:59 +0000180 /// \brief The visitor function.
Douglas Gregorb1373d02010-01-20 20:59:29 +0000181 CXCursorVisitor Visitor;
Ted Kremenekf0e23e82010-02-17 00:41:40 +0000182
Douglas Gregor33e9abd2010-01-22 19:49:59 +0000183 /// \brief The opaque client data, to be passed along to the visitor.
Douglas Gregorb1373d02010-01-20 20:59:29 +0000184 CXClientData ClientData;
Ted Kremenekf0e23e82010-02-17 00:41:40 +0000185
Douglas Gregor7d1d49d2009-10-16 20:01:17 +0000186 // MaxPCHLevel - the maximum PCH level of declarations that we will pass on
187 // to the visitor. Declarations with a PCH level greater than this value will
188 // be suppressed.
189 unsigned MaxPCHLevel;
Douglas Gregor33e9abd2010-01-22 19:49:59 +0000190
Douglas Gregor04a9eb32011-03-16 23:23:30 +0000191 /// \brief Whether we should visit the preprocessing record entries last,
192 /// after visiting other declarations.
193 bool VisitPreprocessorLast;
194
Douglas Gregor33e9abd2010-01-22 19:49:59 +0000195 /// \brief When valid, a source range to which the cursor should restrict
196 /// its search.
197 SourceRange RegionOfInterest;
Ted Kremenekf0e23e82010-02-17 00:41:40 +0000198
Ted Kremenekd8c370c2010-11-02 23:10:24 +0000199 // FIXME: Eventually remove. This part of a hack to support proper
200 // iteration over all Decls contained lexically within an ObjC container.
201 DeclContext::decl_iterator *DI_current;
202 DeclContext::decl_iterator DE_current;
203
Ted Kremenekd1ded662010-11-15 23:31:32 +0000204 // Cache of pre-allocated worklists for data-recursion walk of Stmts.
205 llvm::SmallVector<VisitorWorkList*, 5> WorkListFreeList;
206 llvm::SmallVector<VisitorWorkList*, 5> WorkListCache;
207
Douglas Gregorb1373d02010-01-20 20:59:29 +0000208 using DeclVisitor<CursorVisitor, bool>::Visit;
Douglas Gregor7d0d40e2010-01-21 16:28:34 +0000209 using TypeLocVisitor<CursorVisitor, bool>::Visit;
Ted Kremenekf0e23e82010-02-17 00:41:40 +0000210
211 /// \brief Determine whether this particular source range comes before, comes
212 /// after, or overlaps the region of interest.
Douglas Gregor33e9abd2010-01-22 19:49:59 +0000213 ///
Daniel Dunbard52864b2010-02-14 10:02:57 +0000214 /// \param R a half-open source range retrieved from the abstract syntax tree.
Ted Kremenekf0e23e82010-02-17 00:41:40 +0000215 RangeComparisonResult CompareRegionOfInterest(SourceRange R);
216
Ted Kremenek0f91f6a2010-05-13 00:25:00 +0000217 class SetParentRAII {
218 CXCursor &Parent;
219 Decl *&StmtParent;
220 CXCursor OldParent;
221
222 public:
223 SetParentRAII(CXCursor &Parent, Decl *&StmtParent, CXCursor NewParent)
224 : Parent(Parent), StmtParent(StmtParent), OldParent(Parent)
225 {
226 Parent = NewParent;
227 if (clang_isDeclaration(Parent.kind))
228 StmtParent = getCursorDecl(Parent);
229 }
230
231 ~SetParentRAII() {
232 Parent = OldParent;
233 if (clang_isDeclaration(Parent.kind))
234 StmtParent = getCursorDecl(Parent);
235 }
236 };
237
Steve Naroff89922f82009-08-31 00:59:03 +0000238public:
Ted Kremeneka60ed472010-11-16 08:15:36 +0000239 CursorVisitor(CXTranslationUnit TU, CXCursorVisitor Visitor,
240 CXClientData ClientData,
Ted Kremenekf0e23e82010-02-17 00:41:40 +0000241 unsigned MaxPCHLevel,
Douglas Gregor04a9eb32011-03-16 23:23:30 +0000242 bool VisitPreprocessorLast,
Douglas Gregor33e9abd2010-01-22 19:49:59 +0000243 SourceRange RegionOfInterest = SourceRange())
Ted Kremeneka60ed472010-11-16 08:15:36 +0000244 : TU(TU), AU(static_cast<ASTUnit*>(TU->TUData)),
245 Visitor(Visitor), ClientData(ClientData),
Douglas Gregor04a9eb32011-03-16 23:23:30 +0000246 MaxPCHLevel(MaxPCHLevel), VisitPreprocessorLast(VisitPreprocessorLast),
247 RegionOfInterest(RegionOfInterest), DI_current(0)
Douglas Gregorb1373d02010-01-20 20:59:29 +0000248 {
249 Parent.kind = CXCursor_NoDeclFound;
250 Parent.data[0] = 0;
251 Parent.data[1] = 0;
252 Parent.data[2] = 0;
Douglas Gregorf20dfbc2010-01-21 17:29:07 +0000253 StmtParent = 0;
Douglas Gregorb1373d02010-01-20 20:59:29 +0000254 }
Ted Kremenekf0e23e82010-02-17 00:41:40 +0000255
Ted Kremenekd1ded662010-11-15 23:31:32 +0000256 ~CursorVisitor() {
257 // Free the pre-allocated worklists for data-recursion.
258 for (llvm::SmallVectorImpl<VisitorWorkList*>::iterator
259 I = WorkListCache.begin(), E = WorkListCache.end(); I != E; ++I) {
260 delete *I;
261 }
262 }
263
Ted Kremeneka60ed472010-11-16 08:15:36 +0000264 ASTUnit *getASTUnit() const { return static_cast<ASTUnit*>(TU->TUData); }
265 CXTranslationUnit getTU() const { return TU; }
Ted Kremenekab979612010-11-11 08:05:23 +0000266
Douglas Gregor33e9abd2010-01-22 19:49:59 +0000267 bool Visit(CXCursor Cursor, bool CheckedRegionOfInterest = false);
Douglas Gregor788f5a12010-03-20 00:41:21 +0000268
269 std::pair<PreprocessingRecord::iterator, PreprocessingRecord::iterator>
270 getPreprocessedEntities();
271
Douglas Gregorb1373d02010-01-20 20:59:29 +0000272 bool VisitChildren(CXCursor Parent);
Ted Kremenekf0e23e82010-02-17 00:41:40 +0000273
Douglas Gregor7d0d40e2010-01-21 16:28:34 +0000274 // Declaration visitors
Richard Smith162e1c12011-04-15 14:24:37 +0000275 bool VisitTypeAliasDecl(TypeAliasDecl *D);
Ted Kremenek09dfa372010-02-18 05:46:33 +0000276 bool VisitAttributes(Decl *D);
Ted Kremenek1ee6cad2010-04-11 21:47:37 +0000277 bool VisitBlockDecl(BlockDecl *B);
Ted Kremenek3064ef92010-08-27 21:34:58 +0000278 bool VisitCXXRecordDecl(CXXRecordDecl *D);
Ted Kremenekd8c370c2010-11-02 23:10:24 +0000279 llvm::Optional<bool> shouldVisitCursor(CXCursor C);
Douglas Gregorb1373d02010-01-20 20:59:29 +0000280 bool VisitDeclContext(DeclContext *DC);
Ted Kremenek4540c9c2010-02-18 18:47:08 +0000281 bool VisitTranslationUnitDecl(TranslationUnitDecl *D);
282 bool VisitTypedefDecl(TypedefDecl *D);
Ted Kremenek79758f62010-02-18 22:36:18 +0000283 bool VisitTagDecl(TagDecl *D);
Douglas Gregor0ab1e9f2010-09-01 17:32:36 +0000284 bool VisitClassTemplateSpecializationDecl(ClassTemplateSpecializationDecl *D);
Douglas Gregor74dbe642010-08-31 19:31:58 +0000285 bool VisitClassTemplatePartialSpecializationDecl(
286 ClassTemplatePartialSpecializationDecl *D);
Douglas Gregorfe72e9c2010-08-31 17:01:39 +0000287 bool VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D);
Ted Kremenek79758f62010-02-18 22:36:18 +0000288 bool VisitEnumConstantDecl(EnumConstantDecl *D);
289 bool VisitDeclaratorDecl(DeclaratorDecl *DD);
290 bool VisitFunctionDecl(FunctionDecl *ND);
291 bool VisitFieldDecl(FieldDecl *D);
Ted Kremenek4540c9c2010-02-18 18:47:08 +0000292 bool VisitVarDecl(VarDecl *);
Douglas Gregor84b51d72010-09-01 20:16:53 +0000293 bool VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D);
Douglas Gregorfe72e9c2010-08-31 17:01:39 +0000294 bool VisitFunctionTemplateDecl(FunctionTemplateDecl *D);
Douglas Gregor39d6f072010-08-31 19:02:00 +0000295 bool VisitClassTemplateDecl(ClassTemplateDecl *D);
Douglas Gregor84b51d72010-09-01 20:16:53 +0000296 bool VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D);
Ted Kremenek79758f62010-02-18 22:36:18 +0000297 bool VisitObjCMethodDecl(ObjCMethodDecl *ND);
298 bool VisitObjCContainerDecl(ObjCContainerDecl *D);
299 bool VisitObjCCategoryDecl(ObjCCategoryDecl *ND);
300 bool VisitObjCProtocolDecl(ObjCProtocolDecl *PID);
Ted Kremenek23173d72010-05-18 21:09:07 +0000301 bool VisitObjCPropertyDecl(ObjCPropertyDecl *PD);
Ted Kremenek79758f62010-02-18 22:36:18 +0000302 bool VisitObjCInterfaceDecl(ObjCInterfaceDecl *D);
303 bool VisitObjCImplDecl(ObjCImplDecl *D);
304 bool VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D);
305 bool VisitObjCImplementationDecl(ObjCImplementationDecl *D);
Ted Kremenek79758f62010-02-18 22:36:18 +0000306 // FIXME: ObjCCompatibleAliasDecl requires aliased-class locations.
307 bool VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D);
308 bool VisitObjCClassDecl(ObjCClassDecl *D);
Douglas Gregora4ffd852010-11-17 01:03:52 +0000309 bool VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *PD);
Ted Kremeneka0536d82010-05-07 01:04:29 +0000310 bool VisitLinkageSpecDecl(LinkageSpecDecl *D);
Ted Kremenek8f06e0e2010-05-06 23:38:21 +0000311 bool VisitNamespaceDecl(NamespaceDecl *D);
Douglas Gregor69319002010-08-31 23:48:11 +0000312 bool VisitNamespaceAliasDecl(NamespaceAliasDecl *D);
Douglas Gregor0a35bce2010-09-01 03:07:18 +0000313 bool VisitUsingDirectiveDecl(UsingDirectiveDecl *D);
Douglas Gregor7e242562010-09-01 19:52:22 +0000314 bool VisitUsingDecl(UsingDecl *D);
315 bool VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D);
316 bool VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
Douglas Gregor0a35bce2010-09-01 03:07:18 +0000317
Douglas Gregor01829d32010-08-31 14:41:23 +0000318 // Name visitor
319 bool VisitDeclarationNameInfo(DeclarationNameInfo Name);
Douglas Gregorc5ade2e2010-09-02 17:35:32 +0000320 bool VisitNestedNameSpecifier(NestedNameSpecifier *NNS, SourceRange Range);
Douglas Gregordc355712011-02-25 00:36:19 +0000321 bool VisitNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS);
Douglas Gregor01829d32010-08-31 14:41:23 +0000322
Douglas Gregorfe72e9c2010-08-31 17:01:39 +0000323 // Template visitors
324 bool VisitTemplateParameters(const TemplateParameterList *Params);
Douglas Gregor0b36e612010-08-31 20:37:03 +0000325 bool VisitTemplateName(TemplateName Name, SourceLocation Loc);
Douglas Gregorfe72e9c2010-08-31 17:01:39 +0000326 bool VisitTemplateArgumentLoc(const TemplateArgumentLoc &TAL);
327
Douglas Gregor7d0d40e2010-01-21 16:28:34 +0000328 // Type visitors
Douglas Gregor01829d32010-08-31 14:41:23 +0000329 bool VisitQualifiedTypeLoc(QualifiedTypeLoc TL);
Douglas Gregorf20dfbc2010-01-21 17:29:07 +0000330 bool VisitBuiltinTypeLoc(BuiltinTypeLoc TL);
Douglas Gregor7d0d40e2010-01-21 16:28:34 +0000331 bool VisitTypedefTypeLoc(TypedefTypeLoc TL);
Douglas Gregorf20dfbc2010-01-21 17:29:07 +0000332 bool VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc TL);
333 bool VisitTagTypeLoc(TagTypeLoc TL);
Douglas Gregorfe72e9c2010-08-31 17:01:39 +0000334 bool VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL);
Douglas Gregorf20dfbc2010-01-21 17:29:07 +0000335 bool VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL);
John McCallc12c5bb2010-05-15 11:32:37 +0000336 bool VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL);
Douglas Gregorf20dfbc2010-01-21 17:29:07 +0000337 bool VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL);
Abramo Bagnara075f8f12010-12-10 16:29:40 +0000338 bool VisitParenTypeLoc(ParenTypeLoc TL);
Douglas Gregorf20dfbc2010-01-21 17:29:07 +0000339 bool VisitPointerTypeLoc(PointerTypeLoc TL);
340 bool VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL);
341 bool VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL);
342 bool VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL);
343 bool VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL);
Douglas Gregor01829d32010-08-31 14:41:23 +0000344 bool VisitFunctionTypeLoc(FunctionTypeLoc TL, bool SkipResultType = false);
Douglas Gregorf20dfbc2010-01-21 17:29:07 +0000345 bool VisitArrayTypeLoc(ArrayTypeLoc TL);
Douglas Gregorfe72e9c2010-08-31 17:01:39 +0000346 bool VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL);
Douglas Gregor2332c112010-01-21 20:48:56 +0000347 // FIXME: Implement visitors here when the unimplemented TypeLocs get
348 // implemented
349 bool VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL);
Douglas Gregor7536dd52010-12-20 02:24:11 +0000350 bool VisitPackExpansionTypeLoc(PackExpansionTypeLoc TL);
Douglas Gregor2332c112010-01-21 20:48:56 +0000351 bool VisitTypeOfTypeLoc(TypeOfTypeLoc TL);
Douglas Gregor2494dd02011-03-01 01:34:45 +0000352 bool VisitDependentNameTypeLoc(DependentNameTypeLoc TL);
Douglas Gregor94fdffa2011-03-01 20:11:18 +0000353 bool VisitDependentTemplateSpecializationTypeLoc(
354 DependentTemplateSpecializationTypeLoc TL);
Douglas Gregor9e876872011-03-01 18:12:44 +0000355 bool VisitElaboratedTypeLoc(ElaboratedTypeLoc TL);
Douglas Gregor2494dd02011-03-01 01:34:45 +0000356
Ted Kremenekc0e1d922010-11-11 08:05:18 +0000357 // Data-recursive visitor functions.
358 bool IsInRegionOfInterest(CXCursor C);
359 bool RunVisitorWorkList(VisitorWorkList &WL);
360 void EnqueueWorkList(VisitorWorkList &WL, Stmt *S);
Ted Kremenekcdba6592010-11-18 00:42:18 +0000361 LLVM_ATTRIBUTE_NOINLINE bool Visit(Stmt *S);
Steve Naroff89922f82009-08-31 00:59:03 +0000362};
Ted Kremenekf0e23e82010-02-17 00:41:40 +0000363
Ted Kremenekab188932010-01-05 19:32:54 +0000364} // end anonymous namespace
Benjamin Kramer5e4bc592009-10-18 16:11:04 +0000365
Douglas Gregora8e5c5b2010-07-22 20:22:31 +0000366static SourceRange getRawCursorExtent(CXCursor C);
Douglas Gregor66537982010-11-17 17:14:07 +0000367static SourceRange getFullCursorExtent(CXCursor C, SourceManager &SrcMgr);
368
Douglas Gregora8e5c5b2010-07-22 20:22:31 +0000369
Douglas Gregor33e9abd2010-01-22 19:49:59 +0000370RangeComparisonResult CursorVisitor::CompareRegionOfInterest(SourceRange R) {
Ted Kremeneka60ed472010-11-16 08:15:36 +0000371 return RangeCompare(AU->getSourceManager(), R, RegionOfInterest);
Douglas Gregor33e9abd2010-01-22 19:49:59 +0000372}
373
Douglas Gregorb1373d02010-01-20 20:59:29 +0000374/// \brief Visit the given cursor and, if requested by the visitor,
375/// its children.
376///
Douglas Gregor33e9abd2010-01-22 19:49:59 +0000377/// \param Cursor the cursor to visit.
378///
379/// \param CheckRegionOfInterest if true, then the caller already checked that
380/// this cursor is within the region of interest.
381///
Douglas Gregorb1373d02010-01-20 20:59:29 +0000382/// \returns true if the visitation should be aborted, false if it
383/// should continue.
Douglas Gregor33e9abd2010-01-22 19:49:59 +0000384bool CursorVisitor::Visit(CXCursor Cursor, bool CheckedRegionOfInterest) {
Douglas Gregorb1373d02010-01-20 20:59:29 +0000385 if (clang_isInvalid(Cursor.kind))
386 return false;
Ted Kremenekf0e23e82010-02-17 00:41:40 +0000387
Douglas Gregorb1373d02010-01-20 20:59:29 +0000388 if (clang_isDeclaration(Cursor.kind)) {
389 Decl *D = getCursorDecl(Cursor);
390 assert(D && "Invalid declaration cursor");
391 if (D->getPCHLevel() > MaxPCHLevel)
392 return false;
393
394 if (D->isImplicit())
395 return false;
396 }
397
Douglas Gregor33e9abd2010-01-22 19:49:59 +0000398 // If we have a range of interest, and this cursor doesn't intersect with it,
399 // we're done.
400 if (RegionOfInterest.isValid() && !CheckedRegionOfInterest) {
Douglas Gregora8e5c5b2010-07-22 20:22:31 +0000401 SourceRange Range = getRawCursorExtent(Cursor);
Daniel Dunbarf408f322010-02-14 08:32:05 +0000402 if (Range.isInvalid() || CompareRegionOfInterest(Range))
Douglas Gregor33e9abd2010-01-22 19:49:59 +0000403 return false;
404 }
Ted Kremenekf0e23e82010-02-17 00:41:40 +0000405
Douglas Gregorb1373d02010-01-20 20:59:29 +0000406 switch (Visitor(Cursor, Parent, ClientData)) {
407 case CXChildVisit_Break:
408 return true;
409
410 case CXChildVisit_Continue:
411 return false;
412
413 case CXChildVisit_Recurse:
414 return VisitChildren(Cursor);
415 }
416
Douglas Gregorfd643772010-01-25 16:45:46 +0000417 return false;
Douglas Gregorb1373d02010-01-20 20:59:29 +0000418}
419
Douglas Gregor788f5a12010-03-20 00:41:21 +0000420std::pair<PreprocessingRecord::iterator, PreprocessingRecord::iterator>
421CursorVisitor::getPreprocessedEntities() {
422 PreprocessingRecord &PPRec
Ted Kremeneka60ed472010-11-16 08:15:36 +0000423 = *AU->getPreprocessor().getPreprocessingRecord();
Douglas Gregor788f5a12010-03-20 00:41:21 +0000424
425 bool OnlyLocalDecls
Douglas Gregor32038bb2010-12-21 19:07:48 +0000426 = !AU->isMainFileAST() && AU->getOnlyLocalDecls();
427
428 if (OnlyLocalDecls && RegionOfInterest.isValid()) {
429 // If we would only look at local declarations but we have a region of
430 // interest, check whether that region of interest is in the main file.
431 // If not, we should traverse all declarations.
432 // FIXME: My kingdom for a proper binary search approach to finding
433 // cursors!
434 std::pair<FileID, unsigned> Location
435 = AU->getSourceManager().getDecomposedInstantiationLoc(
436 RegionOfInterest.getBegin());
437 if (Location.first != AU->getSourceManager().getMainFileID())
438 OnlyLocalDecls = false;
439 }
Douglas Gregor788f5a12010-03-20 00:41:21 +0000440
Douglas Gregor89d99802010-11-30 06:16:57 +0000441 PreprocessingRecord::iterator StartEntity, EndEntity;
442 if (OnlyLocalDecls) {
443 StartEntity = AU->pp_entity_begin();
444 EndEntity = AU->pp_entity_end();
445 } else {
446 StartEntity = PPRec.begin();
447 EndEntity = PPRec.end();
448 }
449
Douglas Gregor788f5a12010-03-20 00:41:21 +0000450 // There is no region of interest; we have to walk everything.
451 if (RegionOfInterest.isInvalid())
Douglas Gregor89d99802010-11-30 06:16:57 +0000452 return std::make_pair(StartEntity, EndEntity);
Douglas Gregor788f5a12010-03-20 00:41:21 +0000453
454 // Find the file in which the region of interest lands.
Ted Kremeneka60ed472010-11-16 08:15:36 +0000455 SourceManager &SM = AU->getSourceManager();
Douglas Gregor788f5a12010-03-20 00:41:21 +0000456 std::pair<FileID, unsigned> Begin
457 = SM.getDecomposedInstantiationLoc(RegionOfInterest.getBegin());
458 std::pair<FileID, unsigned> End
459 = SM.getDecomposedInstantiationLoc(RegionOfInterest.getEnd());
460
461 // The region of interest spans files; we have to walk everything.
462 if (Begin.first != End.first)
Douglas Gregor89d99802010-11-30 06:16:57 +0000463 return std::make_pair(StartEntity, EndEntity);
Douglas Gregor788f5a12010-03-20 00:41:21 +0000464
465 ASTUnit::PreprocessedEntitiesByFileMap &ByFileMap
Ted Kremeneka60ed472010-11-16 08:15:36 +0000466 = AU->getPreprocessedEntitiesByFile();
Douglas Gregor788f5a12010-03-20 00:41:21 +0000467 if (ByFileMap.empty()) {
468 // Build the mapping from files to sets of preprocessed entities.
Douglas Gregor89d99802010-11-30 06:16:57 +0000469 for (PreprocessingRecord::iterator E = StartEntity; E != EndEntity; ++E) {
Douglas Gregor788f5a12010-03-20 00:41:21 +0000470 std::pair<FileID, unsigned> P
471 = SM.getDecomposedInstantiationLoc((*E)->getSourceRange().getBegin());
Douglas Gregor89d99802010-11-30 06:16:57 +0000472
Douglas Gregor788f5a12010-03-20 00:41:21 +0000473 ByFileMap[P.first].push_back(*E);
474 }
475 }
476
477 return std::make_pair(ByFileMap[Begin.first].begin(),
478 ByFileMap[Begin.first].end());
479}
480
Douglas Gregorb1373d02010-01-20 20:59:29 +0000481/// \brief Visit the children of the given cursor.
Ted Kremeneka60ed472010-11-16 08:15:36 +0000482///
Douglas Gregorb1373d02010-01-20 20:59:29 +0000483/// \returns true if the visitation should be aborted, false if it
484/// should continue.
Ted Kremenekf0e23e82010-02-17 00:41:40 +0000485bool CursorVisitor::VisitChildren(CXCursor Cursor) {
Douglas Gregorc314aa42011-03-02 19:17:03 +0000486 if (clang_isReference(Cursor.kind) &&
487 Cursor.kind != CXCursor_CXXBaseSpecifier) {
Douglas Gregora59e3902010-01-21 23:27:09 +0000488 // By definition, references have no children.
489 return false;
490 }
Ted Kremenekf0e23e82010-02-17 00:41:40 +0000491
492 // Set the Parent field to Cursor, then back to its old value once we're
Douglas Gregorb1373d02010-01-20 20:59:29 +0000493 // done.
Ted Kremenek0f91f6a2010-05-13 00:25:00 +0000494 SetParentRAII SetParent(Parent, StmtParent, Cursor);
Ted Kremenekf0e23e82010-02-17 00:41:40 +0000495
Douglas Gregorb1373d02010-01-20 20:59:29 +0000496 if (clang_isDeclaration(Cursor.kind)) {
497 Decl *D = getCursorDecl(Cursor);
Douglas Gregor06d9b1a2011-04-14 21:41:34 +0000498 if (!D)
499 return false;
500
Ted Kremenek539311e2010-02-18 18:47:01 +0000501 return VisitAttributes(D) || Visit(D);
Douglas Gregorb1373d02010-01-20 20:59:29 +0000502 }
Ted Kremenekf0e23e82010-02-17 00:41:40 +0000503
Douglas Gregor06d9b1a2011-04-14 21:41:34 +0000504 if (clang_isStatement(Cursor.kind)) {
505 if (Stmt *S = getCursorStmt(Cursor))
506 return Visit(S);
507
508 return false;
509 }
510
511 if (clang_isExpression(Cursor.kind)) {
512 if (Expr *E = getCursorExpr(Cursor))
513 return Visit(E);
514
515 return false;
516 }
Ted Kremenekf0e23e82010-02-17 00:41:40 +0000517
Douglas Gregorb1373d02010-01-20 20:59:29 +0000518 if (clang_isTranslationUnit(Cursor.kind)) {
Ted Kremeneka60ed472010-11-16 08:15:36 +0000519 CXTranslationUnit tu = getCursorTU(Cursor);
520 ASTUnit *CXXUnit = static_cast<ASTUnit*>(tu->TUData);
Douglas Gregor04a9eb32011-03-16 23:23:30 +0000521
522 int VisitOrder[2] = { VisitPreprocessorLast, !VisitPreprocessorLast };
523 for (unsigned I = 0; I != 2; ++I) {
524 if (VisitOrder[I]) {
525 if (!CXXUnit->isMainFileAST() && CXXUnit->getOnlyLocalDecls() &&
526 RegionOfInterest.isInvalid()) {
527 for (ASTUnit::top_level_iterator TL = CXXUnit->top_level_begin(),
528 TLEnd = CXXUnit->top_level_end();
529 TL != TLEnd; ++TL) {
530 if (Visit(MakeCXCursor(*TL, tu), true))
531 return true;
532 }
533 } else if (VisitDeclContext(
534 CXXUnit->getASTContext().getTranslationUnitDecl()))
Douglas Gregor7b691f332010-01-20 21:13:59 +0000535 return true;
Douglas Gregor04a9eb32011-03-16 23:23:30 +0000536 continue;
Douglas Gregor7b691f332010-01-20 21:13:59 +0000537 }
Bob Wilson3178cb62010-03-19 03:57:57 +0000538
Douglas Gregor04a9eb32011-03-16 23:23:30 +0000539 // Walk the preprocessing record.
540 if (CXXUnit->getPreprocessor().getPreprocessingRecord()) {
541 // FIXME: Once we have the ability to deserialize a preprocessing record,
542 // do so.
543 PreprocessingRecord::iterator E, EEnd;
544 for (llvm::tie(E, EEnd) = getPreprocessedEntities(); E != EEnd; ++E) {
545 if (MacroInstantiation *MI = dyn_cast<MacroInstantiation>(*E)) {
546 if (Visit(MakeMacroInstantiationCursor(MI, tu)))
547 return true;
548
549 continue;
550 }
Douglas Gregor788f5a12010-03-20 00:41:21 +0000551
Douglas Gregor04a9eb32011-03-16 23:23:30 +0000552 if (MacroDefinition *MD = dyn_cast<MacroDefinition>(*E)) {
553 if (Visit(MakeMacroDefinitionCursor(MD, tu)))
554 return true;
555
556 continue;
557 }
Douglas Gregor0396f462010-03-19 05:22:59 +0000558
Douglas Gregor04a9eb32011-03-16 23:23:30 +0000559 if (InclusionDirective *ID = dyn_cast<InclusionDirective>(*E)) {
560 if (Visit(MakeInclusionDirectiveCursor(ID, tu)))
561 return true;
562
563 continue;
564 }
Douglas Gregorecdcb882010-10-20 22:00:55 +0000565 }
Douglas Gregor0396f462010-03-19 05:22:59 +0000566 }
567 }
Douglas Gregor04a9eb32011-03-16 23:23:30 +0000568
Douglas Gregor7b691f332010-01-20 21:13:59 +0000569 return false;
Douglas Gregorb1373d02010-01-20 20:59:29 +0000570 }
Ted Kremenekf0e23e82010-02-17 00:41:40 +0000571
Douglas Gregorc314aa42011-03-02 19:17:03 +0000572 if (Cursor.kind == CXCursor_CXXBaseSpecifier) {
573 if (CXXBaseSpecifier *Base = getCursorCXXBaseSpecifier(Cursor)) {
574 if (TypeSourceInfo *BaseTSInfo = Base->getTypeSourceInfo()) {
575 return Visit(BaseTSInfo->getTypeLoc());
576 }
577 }
578 }
579
Douglas Gregorb1373d02010-01-20 20:59:29 +0000580 // Nothing to visit at the moment.
Douglas Gregorb1373d02010-01-20 20:59:29 +0000581 return false;
582}
583
Ted Kremenek1ee6cad2010-04-11 21:47:37 +0000584bool CursorVisitor::VisitBlockDecl(BlockDecl *B) {
Douglas Gregor13c8ccb2011-04-22 23:49:24 +0000585 if (TypeSourceInfo *TSInfo = B->getSignatureAsWritten())
586 if (Visit(TSInfo->getTypeLoc()))
587 return true;
Ted Kremenek1ee6cad2010-04-11 21:47:37 +0000588
Ted Kremenek664cffd2010-07-22 11:30:19 +0000589 if (Stmt *Body = B->getBody())
590 return Visit(MakeCXCursor(Body, StmtParent, TU));
591
592 return false;
Ted Kremenek1ee6cad2010-04-11 21:47:37 +0000593}
594
Ted Kremenekd8c370c2010-11-02 23:10:24 +0000595llvm::Optional<bool> CursorVisitor::shouldVisitCursor(CXCursor Cursor) {
596 if (RegionOfInterest.isValid()) {
Douglas Gregor66537982010-11-17 17:14:07 +0000597 SourceRange Range = getFullCursorExtent(Cursor, AU->getSourceManager());
Ted Kremenekd8c370c2010-11-02 23:10:24 +0000598 if (Range.isInvalid())
599 return llvm::Optional<bool>();
Douglas Gregor66537982010-11-17 17:14:07 +0000600
Ted Kremenekd8c370c2010-11-02 23:10:24 +0000601 switch (CompareRegionOfInterest(Range)) {
602 case RangeBefore:
603 // This declaration comes before the region of interest; skip it.
604 return llvm::Optional<bool>();
605
606 case RangeAfter:
607 // This declaration comes after the region of interest; we're done.
608 return false;
609
610 case RangeOverlap:
611 // This declaration overlaps the region of interest; visit it.
612 break;
613 }
614 }
615 return true;
616}
617
618bool CursorVisitor::VisitDeclContext(DeclContext *DC) {
619 DeclContext::decl_iterator I = DC->decls_begin(), E = DC->decls_end();
620
621 // FIXME: Eventually remove. This part of a hack to support proper
622 // iteration over all Decls contained lexically within an ObjC container.
623 SaveAndRestore<DeclContext::decl_iterator*> DI_saved(DI_current, &I);
624 SaveAndRestore<DeclContext::decl_iterator> DE_saved(DE_current, E);
625
626 for ( ; I != E; ++I) {
Ted Kremenek23173d72010-05-18 21:09:07 +0000627 Decl *D = *I;
628 if (D->getLexicalDeclContext() != DC)
629 continue;
Ted Kremenek23173d72010-05-18 21:09:07 +0000630 CXCursor Cursor = MakeCXCursor(D, TU);
Ted Kremenekd8c370c2010-11-02 23:10:24 +0000631 const llvm::Optional<bool> &V = shouldVisitCursor(Cursor);
632 if (!V.hasValue())
633 continue;
634 if (!V.getValue())
635 return false;
Daniel Dunbard52864b2010-02-14 10:02:57 +0000636 if (Visit(Cursor, true))
Douglas Gregorb1373d02010-01-20 20:59:29 +0000637 return true;
638 }
Douglas Gregorb1373d02010-01-20 20:59:29 +0000639 return false;
Ted Kremenekdd6bcc52010-01-13 00:22:49 +0000640}
641
Douglas Gregor1ef2fc12010-01-22 00:50:27 +0000642bool CursorVisitor::VisitTranslationUnitDecl(TranslationUnitDecl *D) {
643 llvm_unreachable("Translation units are visited directly by Visit()");
644 return false;
645}
646
Richard Smith162e1c12011-04-15 14:24:37 +0000647bool CursorVisitor::VisitTypeAliasDecl(TypeAliasDecl *D) {
648 if (TypeSourceInfo *TSInfo = D->getTypeSourceInfo())
649 return Visit(TSInfo->getTypeLoc());
650
651 return false;
652}
653
Douglas Gregor1ef2fc12010-01-22 00:50:27 +0000654bool CursorVisitor::VisitTypedefDecl(TypedefDecl *D) {
655 if (TypeSourceInfo *TSInfo = D->getTypeSourceInfo())
656 return Visit(TSInfo->getTypeLoc());
Ted Kremenekf0e23e82010-02-17 00:41:40 +0000657
Douglas Gregor1ef2fc12010-01-22 00:50:27 +0000658 return false;
659}
660
661bool CursorVisitor::VisitTagDecl(TagDecl *D) {
662 return VisitDeclContext(D);
663}
664
Douglas Gregor0ab1e9f2010-09-01 17:32:36 +0000665bool CursorVisitor::VisitClassTemplateSpecializationDecl(
666 ClassTemplateSpecializationDecl *D) {
667 bool ShouldVisitBody = false;
668 switch (D->getSpecializationKind()) {
669 case TSK_Undeclared:
670 case TSK_ImplicitInstantiation:
671 // Nothing to visit
672 return false;
673
674 case TSK_ExplicitInstantiationDeclaration:
675 case TSK_ExplicitInstantiationDefinition:
676 break;
677
678 case TSK_ExplicitSpecialization:
679 ShouldVisitBody = true;
680 break;
681 }
682
683 // Visit the template arguments used in the specialization.
684 if (TypeSourceInfo *SpecType = D->getTypeAsWritten()) {
685 TypeLoc TL = SpecType->getTypeLoc();
686 if (TemplateSpecializationTypeLoc *TSTLoc
687 = dyn_cast<TemplateSpecializationTypeLoc>(&TL)) {
688 for (unsigned I = 0, N = TSTLoc->getNumArgs(); I != N; ++I)
689 if (VisitTemplateArgumentLoc(TSTLoc->getArgLoc(I)))
690 return true;
691 }
692 }
693
694 if (ShouldVisitBody && VisitCXXRecordDecl(D))
695 return true;
696
697 return false;
698}
699
Douglas Gregor74dbe642010-08-31 19:31:58 +0000700bool CursorVisitor::VisitClassTemplatePartialSpecializationDecl(
701 ClassTemplatePartialSpecializationDecl *D) {
702 // FIXME: Visit the "outer" template parameter lists on the TagDecl
703 // before visiting these template parameters.
704 if (VisitTemplateParameters(D->getTemplateParameters()))
705 return true;
706
707 // Visit the partial specialization arguments.
708 const TemplateArgumentLoc *TemplateArgs = D->getTemplateArgsAsWritten();
709 for (unsigned I = 0, N = D->getNumTemplateArgsAsWritten(); I != N; ++I)
710 if (VisitTemplateArgumentLoc(TemplateArgs[I]))
711 return true;
712
713 return VisitCXXRecordDecl(D);
714}
715
Douglas Gregorfe72e9c2010-08-31 17:01:39 +0000716bool CursorVisitor::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
Douglas Gregor84b51d72010-09-01 20:16:53 +0000717 // Visit the default argument.
718 if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited())
719 if (TypeSourceInfo *DefArg = D->getDefaultArgumentInfo())
720 if (Visit(DefArg->getTypeLoc()))
721 return true;
722
Douglas Gregorfe72e9c2010-08-31 17:01:39 +0000723 return false;
724}
725
Douglas Gregor1ef2fc12010-01-22 00:50:27 +0000726bool CursorVisitor::VisitEnumConstantDecl(EnumConstantDecl *D) {
727 if (Expr *Init = D->getInitExpr())
728 return Visit(MakeCXCursor(Init, StmtParent, TU));
729 return false;
730}
731
Douglas Gregor7d0d40e2010-01-21 16:28:34 +0000732bool CursorVisitor::VisitDeclaratorDecl(DeclaratorDecl *DD) {
733 if (TypeSourceInfo *TSInfo = DD->getTypeSourceInfo())
734 if (Visit(TSInfo->getTypeLoc()))
735 return true;
736
Douglas Gregorc22b5ff2011-02-25 02:25:35 +0000737 // Visit the nested-name-specifier, if present.
738 if (NestedNameSpecifierLoc QualifierLoc = DD->getQualifierLoc())
739 if (VisitNestedNameSpecifierLoc(QualifierLoc))
740 return true;
741
Douglas Gregor7d0d40e2010-01-21 16:28:34 +0000742 return false;
743}
744
Douglas Gregora67e03f2010-09-09 21:42:20 +0000745/// \brief Compare two base or member initializers based on their source order.
Sean Huntcbb67482011-01-08 20:30:50 +0000746static int CompareCXXCtorInitializers(const void* Xp, const void *Yp) {
747 CXXCtorInitializer const * const *X
748 = static_cast<CXXCtorInitializer const * const *>(Xp);
749 CXXCtorInitializer const * const *Y
750 = static_cast<CXXCtorInitializer const * const *>(Yp);
Douglas Gregora67e03f2010-09-09 21:42:20 +0000751
752 if ((*X)->getSourceOrder() < (*Y)->getSourceOrder())
753 return -1;
754 else if ((*X)->getSourceOrder() > (*Y)->getSourceOrder())
755 return 1;
756 else
757 return 0;
758}
759
Douglas Gregorb1373d02010-01-20 20:59:29 +0000760bool CursorVisitor::VisitFunctionDecl(FunctionDecl *ND) {
Douglas Gregor01829d32010-08-31 14:41:23 +0000761 if (TypeSourceInfo *TSInfo = ND->getTypeSourceInfo()) {
762 // Visit the function declaration's syntactic components in the order
763 // written. This requires a bit of work.
Abramo Bagnara723df242010-12-14 22:11:44 +0000764 TypeLoc TL = TSInfo->getTypeLoc().IgnoreParens();
Douglas Gregor01829d32010-08-31 14:41:23 +0000765 FunctionTypeLoc *FTL = dyn_cast<FunctionTypeLoc>(&TL);
766
767 // If we have a function declared directly (without the use of a typedef),
768 // visit just the return type. Otherwise, just visit the function's type
769 // now.
770 if ((FTL && !isa<CXXConversionDecl>(ND) && Visit(FTL->getResultLoc())) ||
771 (!FTL && Visit(TL)))
772 return true;
773
Douglas Gregorc5ade2e2010-09-02 17:35:32 +0000774 // Visit the nested-name-specifier, if present.
Douglas Gregorc22b5ff2011-02-25 02:25:35 +0000775 if (NestedNameSpecifierLoc QualifierLoc = ND->getQualifierLoc())
776 if (VisitNestedNameSpecifierLoc(QualifierLoc))
Douglas Gregorc5ade2e2010-09-02 17:35:32 +0000777 return true;
Douglas Gregor01829d32010-08-31 14:41:23 +0000778
779 // Visit the declaration name.
780 if (VisitDeclarationNameInfo(ND->getNameInfo()))
781 return true;
782
783 // FIXME: Visit explicitly-specified template arguments!
784
785 // Visit the function parameters, if we have a function type.
786 if (FTL && VisitFunctionTypeLoc(*FTL, true))
787 return true;
788
789 // FIXME: Attributes?
790 }
791
Francois Pichet8387e2a2011-04-22 22:18:13 +0000792 if (ND->isThisDeclarationADefinition() && !ND->isLateTemplateParsed()) {
Douglas Gregora67e03f2010-09-09 21:42:20 +0000793 if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(ND)) {
794 // Find the initializers that were written in the source.
Sean Huntcbb67482011-01-08 20:30:50 +0000795 llvm::SmallVector<CXXCtorInitializer *, 4> WrittenInits;
Douglas Gregora67e03f2010-09-09 21:42:20 +0000796 for (CXXConstructorDecl::init_iterator I = Constructor->init_begin(),
797 IEnd = Constructor->init_end();
798 I != IEnd; ++I) {
799 if (!(*I)->isWritten())
800 continue;
801
802 WrittenInits.push_back(*I);
803 }
804
805 // Sort the initializers in source order
806 llvm::array_pod_sort(WrittenInits.begin(), WrittenInits.end(),
Sean Huntcbb67482011-01-08 20:30:50 +0000807 &CompareCXXCtorInitializers);
Douglas Gregora67e03f2010-09-09 21:42:20 +0000808
809 // Visit the initializers in source order
810 for (unsigned I = 0, N = WrittenInits.size(); I != N; ++I) {
Sean Huntcbb67482011-01-08 20:30:50 +0000811 CXXCtorInitializer *Init = WrittenInits[I];
Francois Pichet00eb3f92010-12-04 09:14:42 +0000812 if (Init->isAnyMemberInitializer()) {
813 if (Visit(MakeCursorMemberRef(Init->getAnyMember(),
Douglas Gregora67e03f2010-09-09 21:42:20 +0000814 Init->getMemberLocation(), TU)))
815 return true;
816 } else if (TypeSourceInfo *BaseInfo = Init->getBaseClassInfo()) {
817 if (Visit(BaseInfo->getTypeLoc()))
818 return true;
819 }
820
821 // Visit the initializer value.
822 if (Expr *Initializer = Init->getInit())
823 if (Visit(MakeCXCursor(Initializer, ND, TU)))
824 return true;
825 }
826 }
827
828 if (Visit(MakeCXCursor(ND->getBody(), StmtParent, TU)))
829 return true;
830 }
Ted Kremenekf0e23e82010-02-17 00:41:40 +0000831
Douglas Gregorb1373d02010-01-20 20:59:29 +0000832 return false;
833}
Ted Kremenekdd6bcc52010-01-13 00:22:49 +0000834
Douglas Gregor1ef2fc12010-01-22 00:50:27 +0000835bool CursorVisitor::VisitFieldDecl(FieldDecl *D) {
836 if (VisitDeclaratorDecl(D))
837 return true;
Ted Kremenekf0e23e82010-02-17 00:41:40 +0000838
Douglas Gregor1ef2fc12010-01-22 00:50:27 +0000839 if (Expr *BitWidth = D->getBitWidth())
840 return Visit(MakeCXCursor(BitWidth, StmtParent, TU));
Ted Kremenekf0e23e82010-02-17 00:41:40 +0000841
Douglas Gregor1ef2fc12010-01-22 00:50:27 +0000842 return false;
843}
844
845bool CursorVisitor::VisitVarDecl(VarDecl *D) {
846 if (VisitDeclaratorDecl(D))
847 return true;
Ted Kremenekf0e23e82010-02-17 00:41:40 +0000848
Douglas Gregor1ef2fc12010-01-22 00:50:27 +0000849 if (Expr *Init = D->getInit())
850 return Visit(MakeCXCursor(Init, StmtParent, TU));
Ted Kremenekf0e23e82010-02-17 00:41:40 +0000851
Douglas Gregor1ef2fc12010-01-22 00:50:27 +0000852 return false;
853}
854
Douglas Gregor84b51d72010-09-01 20:16:53 +0000855bool CursorVisitor::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) {
856 if (VisitDeclaratorDecl(D))
857 return true;
858
859 if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited())
860 if (Expr *DefArg = D->getDefaultArgument())
861 return Visit(MakeCXCursor(DefArg, StmtParent, TU));
862
863 return false;
864}
865
Douglas Gregorfe72e9c2010-08-31 17:01:39 +0000866bool CursorVisitor::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
867 // FIXME: Visit the "outer" template parameter lists on the FunctionDecl
868 // before visiting these template parameters.
869 if (VisitTemplateParameters(D->getTemplateParameters()))
870 return true;
871
872 return VisitFunctionDecl(D->getTemplatedDecl());
873}
874
Douglas Gregor39d6f072010-08-31 19:02:00 +0000875bool CursorVisitor::VisitClassTemplateDecl(ClassTemplateDecl *D) {
876 // FIXME: Visit the "outer" template parameter lists on the TagDecl
877 // before visiting these template parameters.
878 if (VisitTemplateParameters(D->getTemplateParameters()))
879 return true;
880
881 return VisitCXXRecordDecl(D->getTemplatedDecl());
882}
883
Douglas Gregor84b51d72010-09-01 20:16:53 +0000884bool CursorVisitor::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) {
885 if (VisitTemplateParameters(D->getTemplateParameters()))
886 return true;
887
888 if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited() &&
889 VisitTemplateArgumentLoc(D->getDefaultArgument()))
890 return true;
891
892 return false;
893}
894
Douglas Gregor1ef2fc12010-01-22 00:50:27 +0000895bool CursorVisitor::VisitObjCMethodDecl(ObjCMethodDecl *ND) {
Douglas Gregor4bc1cb62010-03-08 14:59:44 +0000896 if (TypeSourceInfo *TSInfo = ND->getResultTypeSourceInfo())
897 if (Visit(TSInfo->getTypeLoc()))
898 return true;
899
Ted Kremenekf0e23e82010-02-17 00:41:40 +0000900 for (ObjCMethodDecl::param_iterator P = ND->param_begin(),
Douglas Gregor1ef2fc12010-01-22 00:50:27 +0000901 PEnd = ND->param_end();
902 P != PEnd; ++P) {
903 if (Visit(MakeCXCursor(*P, TU)))
904 return true;
905 }
Ted Kremenekf0e23e82010-02-17 00:41:40 +0000906
Douglas Gregor1ef2fc12010-01-22 00:50:27 +0000907 if (ND->isThisDeclarationADefinition() &&
908 Visit(MakeCXCursor(ND->getBody(), StmtParent, TU)))
909 return true;
Ted Kremenekf0e23e82010-02-17 00:41:40 +0000910
Douglas Gregor1ef2fc12010-01-22 00:50:27 +0000911 return false;
912}
913
Ted Kremenekd8c370c2010-11-02 23:10:24 +0000914namespace {
915 struct ContainerDeclsSort {
916 SourceManager &SM;
917 ContainerDeclsSort(SourceManager &sm) : SM(sm) {}
918 bool operator()(Decl *A, Decl *B) {
919 SourceLocation L_A = A->getLocStart();
920 SourceLocation L_B = B->getLocStart();
921 assert(L_A.isValid() && L_B.isValid());
922 return SM.isBeforeInTranslationUnit(L_A, L_B);
923 }
924 };
925}
926
Douglas Gregora59e3902010-01-21 23:27:09 +0000927bool CursorVisitor::VisitObjCContainerDecl(ObjCContainerDecl *D) {
Ted Kremenekd8c370c2010-11-02 23:10:24 +0000928 // FIXME: Eventually convert back to just 'VisitDeclContext()'. Essentially
929 // an @implementation can lexically contain Decls that are not properly
930 // nested in the AST. When we identify such cases, we need to retrofit
931 // this nesting here.
932 if (!DI_current)
933 return VisitDeclContext(D);
934
935 // Scan the Decls that immediately come after the container
936 // in the current DeclContext. If any fall within the
937 // container's lexical region, stash them into a vector
938 // for later processing.
939 llvm::SmallVector<Decl *, 24> DeclsInContainer;
940 SourceLocation EndLoc = D->getSourceRange().getEnd();
Ted Kremeneka60ed472010-11-16 08:15:36 +0000941 SourceManager &SM = AU->getSourceManager();
Ted Kremenekd8c370c2010-11-02 23:10:24 +0000942 if (EndLoc.isValid()) {
943 DeclContext::decl_iterator next = *DI_current;
944 while (++next != DE_current) {
945 Decl *D_next = *next;
946 if (!D_next)
947 break;
948 SourceLocation L = D_next->getLocStart();
949 if (!L.isValid())
950 break;
951 if (SM.isBeforeInTranslationUnit(L, EndLoc)) {
952 *DI_current = next;
953 DeclsInContainer.push_back(D_next);
954 continue;
955 }
956 break;
957 }
958 }
959
960 // The common case.
961 if (DeclsInContainer.empty())
962 return VisitDeclContext(D);
963
964 // Get all the Decls in the DeclContext, and sort them with the
965 // additional ones we've collected. Then visit them.
966 for (DeclContext::decl_iterator I = D->decls_begin(), E = D->decls_end();
967 I!=E; ++I) {
968 Decl *subDecl = *I;
Ted Kremenek0582c892010-11-02 23:17:51 +0000969 if (!subDecl || subDecl->getLexicalDeclContext() != D ||
970 subDecl->getLocStart().isInvalid())
Ted Kremenekd8c370c2010-11-02 23:10:24 +0000971 continue;
972 DeclsInContainer.push_back(subDecl);
973 }
974
975 // Now sort the Decls so that they appear in lexical order.
976 std::sort(DeclsInContainer.begin(), DeclsInContainer.end(),
977 ContainerDeclsSort(SM));
978
979 // Now visit the decls.
980 for (llvm::SmallVectorImpl<Decl*>::iterator I = DeclsInContainer.begin(),
981 E = DeclsInContainer.end(); I != E; ++I) {
982 CXCursor Cursor = MakeCXCursor(*I, TU);
983 const llvm::Optional<bool> &V = shouldVisitCursor(Cursor);
984 if (!V.hasValue())
985 continue;
986 if (!V.getValue())
987 return false;
988 if (Visit(Cursor, true))
989 return true;
990 }
991 return false;
Douglas Gregora59e3902010-01-21 23:27:09 +0000992}
993
Douglas Gregorb1373d02010-01-20 20:59:29 +0000994bool CursorVisitor::VisitObjCCategoryDecl(ObjCCategoryDecl *ND) {
Douglas Gregorb2cd4872010-01-20 23:57:43 +0000995 if (Visit(MakeCursorObjCClassRef(ND->getClassInterface(), ND->getLocation(),
996 TU)))
Douglas Gregorb1373d02010-01-20 20:59:29 +0000997 return true;
Ted Kremenekf0e23e82010-02-17 00:41:40 +0000998
Douglas Gregor78db0cd2010-01-16 15:44:18 +0000999 ObjCCategoryDecl::protocol_loc_iterator PL = ND->protocol_loc_begin();
1000 for (ObjCCategoryDecl::protocol_iterator I = ND->protocol_begin(),
1001 E = ND->protocol_end(); I != E; ++I, ++PL)
Douglas Gregorb2cd4872010-01-20 23:57:43 +00001002 if (Visit(MakeCursorObjCProtocolRef(*I, *PL, TU)))
Douglas Gregorb1373d02010-01-20 20:59:29 +00001003 return true;
Ted Kremenekf0e23e82010-02-17 00:41:40 +00001004
Douglas Gregora59e3902010-01-21 23:27:09 +00001005 return VisitObjCContainerDecl(ND);
Ted Kremenekdd6bcc52010-01-13 00:22:49 +00001006}
1007
Douglas Gregor1ef2fc12010-01-22 00:50:27 +00001008bool CursorVisitor::VisitObjCProtocolDecl(ObjCProtocolDecl *PID) {
1009 ObjCProtocolDecl::protocol_loc_iterator PL = PID->protocol_loc_begin();
1010 for (ObjCProtocolDecl::protocol_iterator I = PID->protocol_begin(),
1011 E = PID->protocol_end(); I != E; ++I, ++PL)
1012 if (Visit(MakeCursorObjCProtocolRef(*I, *PL, TU)))
1013 return true;
Ted Kremenekf0e23e82010-02-17 00:41:40 +00001014
Douglas Gregor1ef2fc12010-01-22 00:50:27 +00001015 return VisitObjCContainerDecl(PID);
1016}
1017
Ted Kremenek23173d72010-05-18 21:09:07 +00001018bool CursorVisitor::VisitObjCPropertyDecl(ObjCPropertyDecl *PD) {
Douglas Gregor83cb9422010-09-09 17:09:21 +00001019 if (PD->getTypeSourceInfo() && Visit(PD->getTypeSourceInfo()->getTypeLoc()))
John McCallfc929202010-06-04 22:33:30 +00001020 return true;
1021
Ted Kremenek23173d72010-05-18 21:09:07 +00001022 // FIXME: This implements a workaround with @property declarations also being
1023 // installed in the DeclContext for the @interface. Eventually this code
1024 // should be removed.
1025 ObjCCategoryDecl *CDecl = dyn_cast<ObjCCategoryDecl>(PD->getDeclContext());
1026 if (!CDecl || !CDecl->IsClassExtension())
1027 return false;
1028
1029 ObjCInterfaceDecl *ID = CDecl->getClassInterface();
1030 if (!ID)
1031 return false;
1032
1033 IdentifierInfo *PropertyId = PD->getIdentifier();
1034 ObjCPropertyDecl *prevDecl =
1035 ObjCPropertyDecl::findPropertyDecl(cast<DeclContext>(ID), PropertyId);
1036
1037 if (!prevDecl)
1038 return false;
1039
1040 // Visit synthesized methods since they will be skipped when visiting
1041 // the @interface.
1042 if (ObjCMethodDecl *MD = prevDecl->getGetterMethodDecl())
Ted Kremeneka054fb42010-09-21 20:52:59 +00001043 if (MD->isSynthesized() && MD->getLexicalDeclContext() == CDecl)
Ted Kremenek23173d72010-05-18 21:09:07 +00001044 if (Visit(MakeCXCursor(MD, TU)))
1045 return true;
1046
1047 if (ObjCMethodDecl *MD = prevDecl->getSetterMethodDecl())
Ted Kremeneka054fb42010-09-21 20:52:59 +00001048 if (MD->isSynthesized() && MD->getLexicalDeclContext() == CDecl)
Ted Kremenek23173d72010-05-18 21:09:07 +00001049 if (Visit(MakeCXCursor(MD, TU)))
1050 return true;
1051
1052 return false;
1053}
1054
Douglas Gregorb1373d02010-01-20 20:59:29 +00001055bool CursorVisitor::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
Ted Kremenekdd6bcc52010-01-13 00:22:49 +00001056 // Issue callbacks for super class.
Douglas Gregorb1373d02010-01-20 20:59:29 +00001057 if (D->getSuperClass() &&
1058 Visit(MakeCursorObjCSuperClassRef(D->getSuperClass(),
Ted Kremenekf0e23e82010-02-17 00:41:40 +00001059 D->getSuperClassLoc(),
Douglas Gregorb2cd4872010-01-20 23:57:43 +00001060 TU)))
Douglas Gregorb1373d02010-01-20 20:59:29 +00001061 return true;
Ted Kremenekf0e23e82010-02-17 00:41:40 +00001062
Douglas Gregor78db0cd2010-01-16 15:44:18 +00001063 ObjCInterfaceDecl::protocol_loc_iterator PL = D->protocol_loc_begin();
1064 for (ObjCInterfaceDecl::protocol_iterator I = D->protocol_begin(),
1065 E = D->protocol_end(); I != E; ++I, ++PL)
Douglas Gregorb2cd4872010-01-20 23:57:43 +00001066 if (Visit(MakeCursorObjCProtocolRef(*I, *PL, TU)))
Douglas Gregorb1373d02010-01-20 20:59:29 +00001067 return true;
Ted Kremenekf0e23e82010-02-17 00:41:40 +00001068
Douglas Gregora59e3902010-01-21 23:27:09 +00001069 return VisitObjCContainerDecl(D);
Ted Kremenekdd6bcc52010-01-13 00:22:49 +00001070}
1071
Douglas Gregor1ef2fc12010-01-22 00:50:27 +00001072bool CursorVisitor::VisitObjCImplDecl(ObjCImplDecl *D) {
1073 return VisitObjCContainerDecl(D);
Ted Kremenekdd6bcc52010-01-13 00:22:49 +00001074}
1075
Douglas Gregor1ef2fc12010-01-22 00:50:27 +00001076bool CursorVisitor::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) {
Ted Kremenekebfa3392010-03-19 20:39:03 +00001077 // 'ID' could be null when dealing with invalid code.
1078 if (ObjCInterfaceDecl *ID = D->getClassInterface())
1079 if (Visit(MakeCursorObjCClassRef(ID, D->getLocation(), TU)))
1080 return true;
Ted Kremenekf0e23e82010-02-17 00:41:40 +00001081
Douglas Gregor1ef2fc12010-01-22 00:50:27 +00001082 return VisitObjCImplDecl(D);
1083}
1084
1085bool CursorVisitor::VisitObjCImplementationDecl(ObjCImplementationDecl *D) {
1086#if 0
1087 // Issue callbacks for super class.
1088 // FIXME: No source location information!
1089 if (D->getSuperClass() &&
1090 Visit(MakeCursorObjCSuperClassRef(D->getSuperClass(),
Ted Kremenekf0e23e82010-02-17 00:41:40 +00001091 D->getSuperClassLoc(),
Douglas Gregor1ef2fc12010-01-22 00:50:27 +00001092 TU)))
1093 return true;
1094#endif
Ted Kremenekf0e23e82010-02-17 00:41:40 +00001095
Douglas Gregor1ef2fc12010-01-22 00:50:27 +00001096 return VisitObjCImplDecl(D);
1097}
1098
1099bool CursorVisitor::VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D) {
1100 ObjCForwardProtocolDecl::protocol_loc_iterator PL = D->protocol_loc_begin();
1101 for (ObjCForwardProtocolDecl::protocol_iterator I = D->protocol_begin(),
1102 E = D->protocol_end();
1103 I != E; ++I, ++PL)
Douglas Gregorb2cd4872010-01-20 23:57:43 +00001104 if (Visit(MakeCursorObjCProtocolRef(*I, *PL, TU)))
Douglas Gregorb1373d02010-01-20 20:59:29 +00001105 return true;
Ted Kremenekf0e23e82010-02-17 00:41:40 +00001106
1107 return false;
Ted Kremenekdd6bcc52010-01-13 00:22:49 +00001108}
1109
Douglas Gregor1ef2fc12010-01-22 00:50:27 +00001110bool CursorVisitor::VisitObjCClassDecl(ObjCClassDecl *D) {
1111 for (ObjCClassDecl::iterator C = D->begin(), CEnd = D->end(); C != CEnd; ++C)
1112 if (Visit(MakeCursorObjCClassRef(C->getInterface(), C->getLocation(), TU)))
1113 return true;
Ted Kremenekf0e23e82010-02-17 00:41:40 +00001114
Douglas Gregor1ef2fc12010-01-22 00:50:27 +00001115 return false;
Ted Kremenekdd6bcc52010-01-13 00:22:49 +00001116}
1117
Douglas Gregora4ffd852010-11-17 01:03:52 +00001118bool CursorVisitor::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *PD) {
1119 if (ObjCIvarDecl *Ivar = PD->getPropertyIvarDecl())
1120 return Visit(MakeCursorMemberRef(Ivar, PD->getPropertyIvarDeclLoc(), TU));
1121
1122 return false;
1123}
1124
Ted Kremenek8f06e0e2010-05-06 23:38:21 +00001125bool CursorVisitor::VisitNamespaceDecl(NamespaceDecl *D) {
1126 return VisitDeclContext(D);
1127}
1128
Douglas Gregor69319002010-08-31 23:48:11 +00001129bool CursorVisitor::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
Douglas Gregorc5ade2e2010-09-02 17:35:32 +00001130 // Visit nested-name-specifier.
Douglas Gregor0cfaf6a2011-02-25 17:08:07 +00001131 if (NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc())
1132 if (VisitNestedNameSpecifierLoc(QualifierLoc))
Douglas Gregorc5ade2e2010-09-02 17:35:32 +00001133 return true;
Douglas Gregor69319002010-08-31 23:48:11 +00001134
1135 return Visit(MakeCursorNamespaceRef(D->getAliasedNamespace(),
1136 D->getTargetNameLoc(), TU));
1137}
1138
Douglas Gregor7e242562010-09-01 19:52:22 +00001139bool CursorVisitor::VisitUsingDecl(UsingDecl *D) {
Douglas Gregorc5ade2e2010-09-02 17:35:32 +00001140 // Visit nested-name-specifier.
Douglas Gregordc355712011-02-25 00:36:19 +00001141 if (NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc()) {
1142 if (VisitNestedNameSpecifierLoc(QualifierLoc))
Douglas Gregorc5ade2e2010-09-02 17:35:32 +00001143 return true;
Douglas Gregordc355712011-02-25 00:36:19 +00001144 }
Douglas Gregor7e242562010-09-01 19:52:22 +00001145
Douglas Gregor1f60d9e2010-09-13 22:52:57 +00001146 if (Visit(MakeCursorOverloadedDeclRef(D, D->getLocation(), TU)))
1147 return true;
1148
Douglas Gregor7e242562010-09-01 19:52:22 +00001149 return VisitDeclarationNameInfo(D->getNameInfo());
1150}
1151
Douglas Gregor0a35bce2010-09-01 03:07:18 +00001152bool CursorVisitor::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
Douglas Gregorc5ade2e2010-09-02 17:35:32 +00001153 // Visit nested-name-specifier.
Douglas Gregordb992412011-02-25 16:33:46 +00001154 if (NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc())
1155 if (VisitNestedNameSpecifierLoc(QualifierLoc))
Douglas Gregorc5ade2e2010-09-02 17:35:32 +00001156 return true;
Douglas Gregor0a35bce2010-09-01 03:07:18 +00001157
1158 return Visit(MakeCursorNamespaceRef(D->getNominatedNamespaceAsWritten(),
1159 D->getIdentLocation(), TU));
1160}
1161
Douglas Gregor7e242562010-09-01 19:52:22 +00001162bool CursorVisitor::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) {
Douglas Gregorc5ade2e2010-09-02 17:35:32 +00001163 // Visit nested-name-specifier.
Douglas Gregordc355712011-02-25 00:36:19 +00001164 if (NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc()) {
1165 if (VisitNestedNameSpecifierLoc(QualifierLoc))
Douglas Gregorc5ade2e2010-09-02 17:35:32 +00001166 return true;
Douglas Gregordc355712011-02-25 00:36:19 +00001167 }
Douglas Gregorc5ade2e2010-09-02 17:35:32 +00001168
Douglas Gregor7e242562010-09-01 19:52:22 +00001169 return VisitDeclarationNameInfo(D->getNameInfo());
1170}
1171
1172bool CursorVisitor::VisitUnresolvedUsingTypenameDecl(
1173 UnresolvedUsingTypenameDecl *D) {
Douglas Gregorc5ade2e2010-09-02 17:35:32 +00001174 // Visit nested-name-specifier.
Douglas Gregordc355712011-02-25 00:36:19 +00001175 if (NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc())
1176 if (VisitNestedNameSpecifierLoc(QualifierLoc))
Douglas Gregorc5ade2e2010-09-02 17:35:32 +00001177 return true;
1178
Douglas Gregor7e242562010-09-01 19:52:22 +00001179 return false;
1180}
1181
Douglas Gregor01829d32010-08-31 14:41:23 +00001182bool CursorVisitor::VisitDeclarationNameInfo(DeclarationNameInfo Name) {
1183 switch (Name.getName().getNameKind()) {
1184 case clang::DeclarationName::Identifier:
1185 case clang::DeclarationName::CXXLiteralOperatorName:
1186 case clang::DeclarationName::CXXOperatorName:
1187 case clang::DeclarationName::CXXUsingDirective:
1188 return false;
1189
1190 case clang::DeclarationName::CXXConstructorName:
1191 case clang::DeclarationName::CXXDestructorName:
1192 case clang::DeclarationName::CXXConversionFunctionName:
1193 if (TypeSourceInfo *TSInfo = Name.getNamedTypeInfo())
1194 return Visit(TSInfo->getTypeLoc());
1195 return false;
1196
1197 case clang::DeclarationName::ObjCZeroArgSelector:
1198 case clang::DeclarationName::ObjCOneArgSelector:
1199 case clang::DeclarationName::ObjCMultiArgSelector:
1200 // FIXME: Per-identifier location info?
1201 return false;
1202 }
1203
1204 return false;
1205}
1206
Douglas Gregorc5ade2e2010-09-02 17:35:32 +00001207bool CursorVisitor::VisitNestedNameSpecifier(NestedNameSpecifier *NNS,
1208 SourceRange Range) {
1209 // FIXME: This whole routine is a hack to work around the lack of proper
1210 // source information in nested-name-specifiers (PR5791). Since we do have
1211 // a beginning source location, we can visit the first component of the
1212 // nested-name-specifier, if it's a single-token component.
1213 if (!NNS)
1214 return false;
1215
1216 // Get the first component in the nested-name-specifier.
1217 while (NestedNameSpecifier *Prefix = NNS->getPrefix())
1218 NNS = Prefix;
1219
1220 switch (NNS->getKind()) {
1221 case NestedNameSpecifier::Namespace:
Douglas Gregorc5ade2e2010-09-02 17:35:32 +00001222 return Visit(MakeCursorNamespaceRef(NNS->getAsNamespace(), Range.getBegin(),
1223 TU));
1224
Douglas Gregor14aba762011-02-24 02:36:08 +00001225 case NestedNameSpecifier::NamespaceAlias:
1226 return Visit(MakeCursorNamespaceRef(NNS->getAsNamespaceAlias(),
1227 Range.getBegin(), TU));
1228
Douglas Gregorc5ade2e2010-09-02 17:35:32 +00001229 case NestedNameSpecifier::TypeSpec: {
1230 // If the type has a form where we know that the beginning of the source
1231 // range matches up with a reference cursor. Visit the appropriate reference
1232 // cursor.
John McCallf4c73712011-01-19 06:33:43 +00001233 const Type *T = NNS->getAsType();
Douglas Gregorc5ade2e2010-09-02 17:35:32 +00001234 if (const TypedefType *Typedef = dyn_cast<TypedefType>(T))
1235 return Visit(MakeCursorTypeRef(Typedef->getDecl(), Range.getBegin(), TU));
1236 if (const TagType *Tag = dyn_cast<TagType>(T))
1237 return Visit(MakeCursorTypeRef(Tag->getDecl(), Range.getBegin(), TU));
1238 if (const TemplateSpecializationType *TST
1239 = dyn_cast<TemplateSpecializationType>(T))
1240 return VisitTemplateName(TST->getTemplateName(), Range.getBegin());
1241 break;
1242 }
1243
1244 case NestedNameSpecifier::TypeSpecWithTemplate:
1245 case NestedNameSpecifier::Global:
1246 case NestedNameSpecifier::Identifier:
1247 break;
1248 }
1249
1250 return false;
1251}
1252
Douglas Gregordc355712011-02-25 00:36:19 +00001253bool
1254CursorVisitor::VisitNestedNameSpecifierLoc(NestedNameSpecifierLoc Qualifier) {
1255 llvm::SmallVector<NestedNameSpecifierLoc, 4> Qualifiers;
1256 for (; Qualifier; Qualifier = Qualifier.getPrefix())
1257 Qualifiers.push_back(Qualifier);
1258
1259 while (!Qualifiers.empty()) {
1260 NestedNameSpecifierLoc Q = Qualifiers.pop_back_val();
1261 NestedNameSpecifier *NNS = Q.getNestedNameSpecifier();
1262 switch (NNS->getKind()) {
1263 case NestedNameSpecifier::Namespace:
1264 if (Visit(MakeCursorNamespaceRef(NNS->getAsNamespace(),
Douglas Gregorc22b5ff2011-02-25 02:25:35 +00001265 Q.getLocalBeginLoc(),
Douglas Gregordc355712011-02-25 00:36:19 +00001266 TU)))
1267 return true;
1268
1269 break;
1270
1271 case NestedNameSpecifier::NamespaceAlias:
1272 if (Visit(MakeCursorNamespaceRef(NNS->getAsNamespaceAlias(),
Douglas Gregorc22b5ff2011-02-25 02:25:35 +00001273 Q.getLocalBeginLoc(),
Douglas Gregordc355712011-02-25 00:36:19 +00001274 TU)))
1275 return true;
1276
1277 break;
1278
1279 case NestedNameSpecifier::TypeSpec:
1280 case NestedNameSpecifier::TypeSpecWithTemplate:
1281 if (Visit(Q.getTypeLoc()))
1282 return true;
1283
1284 break;
1285
1286 case NestedNameSpecifier::Global:
1287 case NestedNameSpecifier::Identifier:
1288 break;
1289 }
1290 }
1291
1292 return false;
1293}
1294
Douglas Gregorfe72e9c2010-08-31 17:01:39 +00001295bool CursorVisitor::VisitTemplateParameters(
1296 const TemplateParameterList *Params) {
1297 if (!Params)
1298 return false;
1299
1300 for (TemplateParameterList::const_iterator P = Params->begin(),
1301 PEnd = Params->end();
1302 P != PEnd; ++P) {
1303 if (Visit(MakeCXCursor(*P, TU)))
1304 return true;
1305 }
1306
1307 return false;
1308}
1309
Douglas Gregor0b36e612010-08-31 20:37:03 +00001310bool CursorVisitor::VisitTemplateName(TemplateName Name, SourceLocation Loc) {
1311 switch (Name.getKind()) {
1312 case TemplateName::Template:
1313 return Visit(MakeCursorTemplateRef(Name.getAsTemplateDecl(), Loc, TU));
1314
1315 case TemplateName::OverloadedTemplate:
Douglas Gregor1f60d9e2010-09-13 22:52:57 +00001316 // Visit the overloaded template set.
1317 if (Visit(MakeCursorOverloadedDeclRef(Name, Loc, TU)))
1318 return true;
1319
Douglas Gregor0b36e612010-08-31 20:37:03 +00001320 return false;
1321
1322 case TemplateName::DependentTemplate:
1323 // FIXME: Visit nested-name-specifier.
1324 return false;
1325
1326 case TemplateName::QualifiedTemplate:
1327 // FIXME: Visit nested-name-specifier.
1328 return Visit(MakeCursorTemplateRef(
1329 Name.getAsQualifiedTemplateName()->getDecl(),
1330 Loc, TU));
Douglas Gregor1aee05d2011-01-15 06:45:20 +00001331
1332 case TemplateName::SubstTemplateTemplateParmPack:
1333 return Visit(MakeCursorTemplateRef(
1334 Name.getAsSubstTemplateTemplateParmPack()->getParameterPack(),
1335 Loc, TU));
Douglas Gregor0b36e612010-08-31 20:37:03 +00001336 }
1337
1338 return false;
1339}
1340
Douglas Gregorfe72e9c2010-08-31 17:01:39 +00001341bool CursorVisitor::VisitTemplateArgumentLoc(const TemplateArgumentLoc &TAL) {
1342 switch (TAL.getArgument().getKind()) {
1343 case TemplateArgument::Null:
1344 case TemplateArgument::Integral:
Douglas Gregor87dd6972010-12-20 16:52:59 +00001345 case TemplateArgument::Pack:
Douglas Gregorfe72e9c2010-08-31 17:01:39 +00001346 return false;
1347
Douglas Gregorfe72e9c2010-08-31 17:01:39 +00001348 case TemplateArgument::Type:
1349 if (TypeSourceInfo *TSInfo = TAL.getTypeSourceInfo())
1350 return Visit(TSInfo->getTypeLoc());
1351 return false;
1352
1353 case TemplateArgument::Declaration:
1354 if (Expr *E = TAL.getSourceDeclExpression())
1355 return Visit(MakeCXCursor(E, StmtParent, TU));
1356 return false;
1357
1358 case TemplateArgument::Expression:
1359 if (Expr *E = TAL.getSourceExpression())
1360 return Visit(MakeCXCursor(E, StmtParent, TU));
1361 return false;
1362
1363 case TemplateArgument::Template:
Douglas Gregora7fc9012011-01-05 18:58:31 +00001364 case TemplateArgument::TemplateExpansion:
Douglas Gregorb6744ef2011-03-02 17:09:35 +00001365 if (VisitNestedNameSpecifierLoc(TAL.getTemplateQualifierLoc()))
1366 return true;
1367
Douglas Gregora7fc9012011-01-05 18:58:31 +00001368 return VisitTemplateName(TAL.getArgument().getAsTemplateOrTemplatePattern(),
Douglas Gregor0b36e612010-08-31 20:37:03 +00001369 TAL.getTemplateNameLoc());
Douglas Gregorfe72e9c2010-08-31 17:01:39 +00001370 }
1371
1372 return false;
1373}
1374
Ted Kremeneka0536d82010-05-07 01:04:29 +00001375bool CursorVisitor::VisitLinkageSpecDecl(LinkageSpecDecl *D) {
1376 return VisitDeclContext(D);
1377}
1378
Douglas Gregor01829d32010-08-31 14:41:23 +00001379bool CursorVisitor::VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {
1380 return Visit(TL.getUnqualifiedLoc());
1381}
1382
Douglas Gregorf20dfbc2010-01-21 17:29:07 +00001383bool CursorVisitor::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) {
Ted Kremeneka60ed472010-11-16 08:15:36 +00001384 ASTContext &Context = AU->getASTContext();
Douglas Gregorf20dfbc2010-01-21 17:29:07 +00001385
1386 // Some builtin types (such as Objective-C's "id", "sel", and
1387 // "Class") have associated declarations. Create cursors for those.
1388 QualType VisitType;
1389 switch (TL.getType()->getAs<BuiltinType>()->getKind()) {
Ted Kremenek6b3b5142010-02-18 22:32:43 +00001390 case BuiltinType::Void:
Douglas Gregorf20dfbc2010-01-21 17:29:07 +00001391 case BuiltinType::Bool:
Ted Kremenek6b3b5142010-02-18 22:32:43 +00001392 case BuiltinType::Char_U:
1393 case BuiltinType::UChar:
Douglas Gregorf20dfbc2010-01-21 17:29:07 +00001394 case BuiltinType::Char16:
1395 case BuiltinType::Char32:
Ted Kremenek6b3b5142010-02-18 22:32:43 +00001396 case BuiltinType::UShort:
Douglas Gregorf20dfbc2010-01-21 17:29:07 +00001397 case BuiltinType::UInt:
1398 case BuiltinType::ULong:
1399 case BuiltinType::ULongLong:
Ted Kremenek6b3b5142010-02-18 22:32:43 +00001400 case BuiltinType::UInt128:
1401 case BuiltinType::Char_S:
1402 case BuiltinType::SChar:
Chris Lattner3f59c972010-12-25 23:25:43 +00001403 case BuiltinType::WChar_U:
1404 case BuiltinType::WChar_S:
Ted Kremenek6b3b5142010-02-18 22:32:43 +00001405 case BuiltinType::Short:
1406 case BuiltinType::Int:
1407 case BuiltinType::Long:
1408 case BuiltinType::LongLong:
1409 case BuiltinType::Int128:
1410 case BuiltinType::Float:
1411 case BuiltinType::Double:
1412 case BuiltinType::LongDouble:
1413 case BuiltinType::NullPtr:
1414 case BuiltinType::Overload:
1415 case BuiltinType::Dependent:
John McCall1de4d4e2011-04-07 08:22:57 +00001416 case BuiltinType::UnknownAny:
Douglas Gregorf20dfbc2010-01-21 17:29:07 +00001417 break;
Ted Kremenek6b3b5142010-02-18 22:32:43 +00001418
Ted Kremenekc4174cc2010-02-18 18:52:18 +00001419 case BuiltinType::ObjCId:
1420 VisitType = Context.getObjCIdType();
1421 break;
Ted Kremenek6b3b5142010-02-18 22:32:43 +00001422
1423 case BuiltinType::ObjCClass:
1424 VisitType = Context.getObjCClassType();
1425 break;
1426
Douglas Gregorf20dfbc2010-01-21 17:29:07 +00001427 case BuiltinType::ObjCSel:
1428 VisitType = Context.getObjCSelType();
1429 break;
1430 }
1431
1432 if (!VisitType.isNull()) {
1433 if (const TypedefType *Typedef = VisitType->getAs<TypedefType>())
Ted Kremenekf0e23e82010-02-17 00:41:40 +00001434 return Visit(MakeCursorTypeRef(Typedef->getDecl(), TL.getBuiltinLoc(),
Douglas Gregorf20dfbc2010-01-21 17:29:07 +00001435 TU));
1436 }
1437
1438 return false;
1439}
1440
Douglas Gregor7d0d40e2010-01-21 16:28:34 +00001441bool CursorVisitor::VisitTypedefTypeLoc(TypedefTypeLoc TL) {
Richard Smith162e1c12011-04-15 14:24:37 +00001442 return Visit(MakeCursorTypeRef(TL.getTypedefNameDecl(), TL.getNameLoc(), TU));
Douglas Gregor7d0d40e2010-01-21 16:28:34 +00001443}
1444
Douglas Gregorf20dfbc2010-01-21 17:29:07 +00001445bool CursorVisitor::VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc TL) {
1446 return Visit(MakeCursorTypeRef(TL.getDecl(), TL.getNameLoc(), TU));
1447}
1448
1449bool CursorVisitor::VisitTagTypeLoc(TagTypeLoc TL) {
1450 return Visit(MakeCursorTypeRef(TL.getDecl(), TL.getNameLoc(), TU));
1451}
1452
Douglas Gregorfe72e9c2010-08-31 17:01:39 +00001453bool CursorVisitor::VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) {
Douglas Gregor1f60d9e2010-09-13 22:52:57 +00001454 // FIXME: We can't visit the template type parameter, because there's
Douglas Gregorfe72e9c2010-08-31 17:01:39 +00001455 // no context information with which we can match up the depth/index in the
1456 // type to the appropriate
1457 return false;
1458}
1459
Douglas Gregorf20dfbc2010-01-21 17:29:07 +00001460bool CursorVisitor::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
1461 if (Visit(MakeCursorObjCClassRef(TL.getIFaceDecl(), TL.getNameLoc(), TU)))
1462 return true;
1463
John McCallc12c5bb2010-05-15 11:32:37 +00001464 return false;
1465}
1466
1467bool CursorVisitor::VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) {
1468 if (TL.hasBaseTypeAsWritten() && Visit(TL.getBaseLoc()))
1469 return true;
1470
Douglas Gregorf20dfbc2010-01-21 17:29:07 +00001471 for (unsigned I = 0, N = TL.getNumProtocols(); I != N; ++I) {
1472 if (Visit(MakeCursorObjCProtocolRef(TL.getProtocol(I), TL.getProtocolLoc(I),
1473 TU)))
1474 return true;
1475 }
1476
1477 return false;
1478}
1479
1480bool CursorVisitor::VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) {
John McCallc12c5bb2010-05-15 11:32:37 +00001481 return Visit(TL.getPointeeLoc());
Douglas Gregorf20dfbc2010-01-21 17:29:07 +00001482}
1483
Abramo Bagnara075f8f12010-12-10 16:29:40 +00001484bool CursorVisitor::VisitParenTypeLoc(ParenTypeLoc TL) {
1485 return Visit(TL.getInnerLoc());
1486}
1487
Douglas Gregorf20dfbc2010-01-21 17:29:07 +00001488bool CursorVisitor::VisitPointerTypeLoc(PointerTypeLoc TL) {
1489 return Visit(TL.getPointeeLoc());
1490}
1491
1492bool CursorVisitor::VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL) {
1493 return Visit(TL.getPointeeLoc());
1494}
1495
1496bool CursorVisitor::VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) {
1497 return Visit(TL.getPointeeLoc());
1498}
1499
1500bool CursorVisitor::VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL) {
Ted Kremenekf0e23e82010-02-17 00:41:40 +00001501 return Visit(TL.getPointeeLoc());
Douglas Gregorf20dfbc2010-01-21 17:29:07 +00001502}
1503
1504bool CursorVisitor::VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL) {
Ted Kremenekf0e23e82010-02-17 00:41:40 +00001505 return Visit(TL.getPointeeLoc());
Douglas Gregorf20dfbc2010-01-21 17:29:07 +00001506}
1507
Douglas Gregor01829d32010-08-31 14:41:23 +00001508bool CursorVisitor::VisitFunctionTypeLoc(FunctionTypeLoc TL,
1509 bool SkipResultType) {
1510 if (!SkipResultType && Visit(TL.getResultLoc()))
Douglas Gregorf20dfbc2010-01-21 17:29:07 +00001511 return true;
1512
Douglas Gregorf20dfbc2010-01-21 17:29:07 +00001513 for (unsigned I = 0, N = TL.getNumArgs(); I != N; ++I)
Ted Kremenek5dbacb42010-04-07 00:27:13 +00001514 if (Decl *D = TL.getArg(I))
1515 if (Visit(MakeCXCursor(D, TU)))
1516 return true;
Douglas Gregorf20dfbc2010-01-21 17:29:07 +00001517
1518 return false;
1519}
1520
1521bool CursorVisitor::VisitArrayTypeLoc(ArrayTypeLoc TL) {
1522 if (Visit(TL.getElementLoc()))
1523 return true;
1524
1525 if (Expr *Size = TL.getSizeExpr())
1526 return Visit(MakeCXCursor(Size, StmtParent, TU));
1527
1528 return false;
1529}
1530
Douglas Gregorfe72e9c2010-08-31 17:01:39 +00001531bool CursorVisitor::VisitTemplateSpecializationTypeLoc(
1532 TemplateSpecializationTypeLoc TL) {
Douglas Gregor0b36e612010-08-31 20:37:03 +00001533 // Visit the template name.
1534 if (VisitTemplateName(TL.getTypePtr()->getTemplateName(),
1535 TL.getTemplateNameLoc()))
1536 return true;
Douglas Gregorfe72e9c2010-08-31 17:01:39 +00001537
1538 // Visit the template arguments.
1539 for (unsigned I = 0, N = TL.getNumArgs(); I != N; ++I)
1540 if (VisitTemplateArgumentLoc(TL.getArgLoc(I)))
1541 return true;
1542
1543 return false;
1544}
1545
Douglas Gregor2332c112010-01-21 20:48:56 +00001546bool CursorVisitor::VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) {
1547 return Visit(MakeCXCursor(TL.getUnderlyingExpr(), StmtParent, TU));
1548}
1549
1550bool CursorVisitor::VisitTypeOfTypeLoc(TypeOfTypeLoc TL) {
1551 if (TypeSourceInfo *TSInfo = TL.getUnderlyingTInfo())
1552 return Visit(TSInfo->getTypeLoc());
1553
1554 return false;
1555}
1556
Douglas Gregor2494dd02011-03-01 01:34:45 +00001557bool CursorVisitor::VisitDependentNameTypeLoc(DependentNameTypeLoc TL) {
1558 if (VisitNestedNameSpecifierLoc(TL.getQualifierLoc()))
1559 return true;
1560
1561 return false;
1562}
1563
Douglas Gregor94fdffa2011-03-01 20:11:18 +00001564bool CursorVisitor::VisitDependentTemplateSpecializationTypeLoc(
1565 DependentTemplateSpecializationTypeLoc TL) {
1566 // Visit the nested-name-specifier, if there is one.
1567 if (TL.getQualifierLoc() &&
1568 VisitNestedNameSpecifierLoc(TL.getQualifierLoc()))
1569 return true;
1570
1571 // Visit the template arguments.
1572 for (unsigned I = 0, N = TL.getNumArgs(); I != N; ++I)
1573 if (VisitTemplateArgumentLoc(TL.getArgLoc(I)))
1574 return true;
1575
1576 return false;
1577}
1578
Douglas Gregor9e876872011-03-01 18:12:44 +00001579bool CursorVisitor::VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) {
1580 if (VisitNestedNameSpecifierLoc(TL.getQualifierLoc()))
1581 return true;
1582
1583 return Visit(TL.getNamedTypeLoc());
1584}
1585
Douglas Gregor7536dd52010-12-20 02:24:11 +00001586bool CursorVisitor::VisitPackExpansionTypeLoc(PackExpansionTypeLoc TL) {
1587 return Visit(TL.getPatternLoc());
1588}
1589
Ted Kremenek3064ef92010-08-27 21:34:58 +00001590bool CursorVisitor::VisitCXXRecordDecl(CXXRecordDecl *D) {
Douglas Gregorc22b5ff2011-02-25 02:25:35 +00001591 // Visit the nested-name-specifier, if present.
1592 if (NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc())
1593 if (VisitNestedNameSpecifierLoc(QualifierLoc))
1594 return true;
1595
Ted Kremenek3064ef92010-08-27 21:34:58 +00001596 if (D->isDefinition()) {
1597 for (CXXRecordDecl::base_class_iterator I = D->bases_begin(),
1598 E = D->bases_end(); I != E; ++I) {
1599 if (Visit(cxcursor::MakeCursorCXXBaseSpecifier(I, TU)))
1600 return true;
1601 }
1602 }
1603
1604 return VisitTagDecl(D);
1605}
1606
Ted Kremenek09dfa372010-02-18 05:46:33 +00001607bool CursorVisitor::VisitAttributes(Decl *D) {
Sean Huntcf807c42010-08-18 23:23:40 +00001608 for (AttrVec::const_iterator i = D->attr_begin(), e = D->attr_end();
1609 i != e; ++i)
1610 if (Visit(MakeCXCursor(*i, D, TU)))
Ted Kremenek09dfa372010-02-18 05:46:33 +00001611 return true;
1612
1613 return false;
1614}
1615
Ted Kremenekc0e1d922010-11-11 08:05:18 +00001616//===----------------------------------------------------------------------===//
1617// Data-recursive visitor methods.
1618//===----------------------------------------------------------------------===//
1619
Ted Kremenek28a71942010-11-13 00:36:47 +00001620namespace {
Ted Kremenek035dc412010-11-13 00:36:50 +00001621#define DEF_JOB(NAME, DATA, KIND)\
1622class NAME : public VisitorJob {\
1623public:\
1624 NAME(DATA *d, CXCursor parent) : VisitorJob(parent, VisitorJob::KIND, d) {} \
1625 static bool classof(const VisitorJob *VJ) { return VJ->getKind() == KIND; }\
Ted Kremenekf64d8032010-11-18 00:02:32 +00001626 DATA *get() const { return static_cast<DATA*>(data[0]); }\
Ted Kremenek035dc412010-11-13 00:36:50 +00001627};
1628
1629DEF_JOB(StmtVisit, Stmt, StmtVisitKind)
1630DEF_JOB(MemberExprParts, MemberExpr, MemberExprPartsKind)
Ted Kremeneke4979cc2010-11-13 00:58:18 +00001631DEF_JOB(DeclRefExprParts, DeclRefExpr, DeclRefExprPartsKind)
Ted Kremenek035dc412010-11-13 00:36:50 +00001632DEF_JOB(OverloadExprParts, OverloadExpr, OverloadExprPartsKind)
Ted Kremenek60608ec2010-11-17 00:50:47 +00001633DEF_JOB(ExplicitTemplateArgsVisit, ExplicitTemplateArgumentList,
1634 ExplicitTemplateArgsVisitKind)
Douglas Gregor94d96292011-01-19 20:34:17 +00001635DEF_JOB(SizeOfPackExprParts, SizeOfPackExpr, SizeOfPackExprPartsKind)
Ted Kremenek035dc412010-11-13 00:36:50 +00001636#undef DEF_JOB
1637
1638class DeclVisit : public VisitorJob {
1639public:
1640 DeclVisit(Decl *d, CXCursor parent, bool isFirst) :
1641 VisitorJob(parent, VisitorJob::DeclVisitKind,
1642 d, isFirst ? (void*) 1 : (void*) 0) {}
1643 static bool classof(const VisitorJob *VJ) {
Ted Kremenek82f3c502010-11-15 22:23:26 +00001644 return VJ->getKind() == DeclVisitKind;
Ted Kremenek035dc412010-11-13 00:36:50 +00001645 }
Ted Kremenekf64d8032010-11-18 00:02:32 +00001646 Decl *get() const { return static_cast<Decl*>(data[0]); }
1647 bool isFirst() const { return data[1] ? true : false; }
Ted Kremenek035dc412010-11-13 00:36:50 +00001648};
Ted Kremenek035dc412010-11-13 00:36:50 +00001649class TypeLocVisit : public VisitorJob {
1650public:
1651 TypeLocVisit(TypeLoc tl, CXCursor parent) :
1652 VisitorJob(parent, VisitorJob::TypeLocVisitKind,
1653 tl.getType().getAsOpaquePtr(), tl.getOpaqueData()) {}
1654
1655 static bool classof(const VisitorJob *VJ) {
1656 return VJ->getKind() == TypeLocVisitKind;
1657 }
1658
Ted Kremenek82f3c502010-11-15 22:23:26 +00001659 TypeLoc get() const {
Ted Kremenekf64d8032010-11-18 00:02:32 +00001660 QualType T = QualType::getFromOpaquePtr(data[0]);
1661 return TypeLoc(T, data[1]);
Ted Kremenek035dc412010-11-13 00:36:50 +00001662 }
1663};
1664
Ted Kremenekae1fd6f2010-11-17 00:50:45 +00001665class LabelRefVisit : public VisitorJob {
1666public:
Chris Lattnerad8dcf42011-02-17 07:39:24 +00001667 LabelRefVisit(LabelDecl *LD, SourceLocation labelLoc, CXCursor parent)
1668 : VisitorJob(parent, VisitorJob::LabelRefVisitKind, LD,
Jeffrey Yasskindec09842011-01-18 02:00:16 +00001669 labelLoc.getPtrEncoding()) {}
Ted Kremenekae1fd6f2010-11-17 00:50:45 +00001670
1671 static bool classof(const VisitorJob *VJ) {
1672 return VJ->getKind() == VisitorJob::LabelRefVisitKind;
1673 }
Chris Lattnerad8dcf42011-02-17 07:39:24 +00001674 LabelDecl *get() const { return static_cast<LabelDecl*>(data[0]); }
Ted Kremenekae1fd6f2010-11-17 00:50:45 +00001675 SourceLocation getLoc() const {
Jeffrey Yasskindec09842011-01-18 02:00:16 +00001676 return SourceLocation::getFromPtrEncoding(data[1]); }
Ted Kremenekf64d8032010-11-18 00:02:32 +00001677};
1678class NestedNameSpecifierVisit : public VisitorJob {
1679public:
1680 NestedNameSpecifierVisit(NestedNameSpecifier *NS, SourceRange R,
1681 CXCursor parent)
1682 : VisitorJob(parent, VisitorJob::NestedNameSpecifierVisitKind,
Jeffrey Yasskindec09842011-01-18 02:00:16 +00001683 NS, R.getBegin().getPtrEncoding(),
1684 R.getEnd().getPtrEncoding()) {}
Ted Kremenekf64d8032010-11-18 00:02:32 +00001685 static bool classof(const VisitorJob *VJ) {
1686 return VJ->getKind() == VisitorJob::NestedNameSpecifierVisitKind;
1687 }
1688 NestedNameSpecifier *get() const {
1689 return static_cast<NestedNameSpecifier*>(data[0]);
1690 }
1691 SourceRange getSourceRange() const {
1692 SourceLocation A =
1693 SourceLocation::getFromRawEncoding((unsigned)(uintptr_t) data[1]);
1694 SourceLocation B =
1695 SourceLocation::getFromRawEncoding((unsigned)(uintptr_t) data[2]);
1696 return SourceRange(A, B);
1697 }
1698};
Douglas Gregorf3db29f2011-02-25 18:19:59 +00001699
1700class NestedNameSpecifierLocVisit : public VisitorJob {
1701public:
1702 NestedNameSpecifierLocVisit(NestedNameSpecifierLoc Qualifier, CXCursor parent)
1703 : VisitorJob(parent, VisitorJob::NestedNameSpecifierLocVisitKind,
1704 Qualifier.getNestedNameSpecifier(),
1705 Qualifier.getOpaqueData()) { }
1706
1707 static bool classof(const VisitorJob *VJ) {
1708 return VJ->getKind() == VisitorJob::NestedNameSpecifierLocVisitKind;
1709 }
1710
1711 NestedNameSpecifierLoc get() const {
1712 return NestedNameSpecifierLoc(static_cast<NestedNameSpecifier*>(data[0]),
1713 data[1]);
1714 }
1715};
1716
Ted Kremenekf64d8032010-11-18 00:02:32 +00001717class DeclarationNameInfoVisit : public VisitorJob {
1718public:
1719 DeclarationNameInfoVisit(Stmt *S, CXCursor parent)
1720 : VisitorJob(parent, VisitorJob::DeclarationNameInfoVisitKind, S) {}
1721 static bool classof(const VisitorJob *VJ) {
1722 return VJ->getKind() == VisitorJob::DeclarationNameInfoVisitKind;
1723 }
1724 DeclarationNameInfo get() const {
1725 Stmt *S = static_cast<Stmt*>(data[0]);
1726 switch (S->getStmtClass()) {
1727 default:
1728 llvm_unreachable("Unhandled Stmt");
1729 case Stmt::CXXDependentScopeMemberExprClass:
1730 return cast<CXXDependentScopeMemberExpr>(S)->getMemberNameInfo();
1731 case Stmt::DependentScopeDeclRefExprClass:
1732 return cast<DependentScopeDeclRefExpr>(S)->getNameInfo();
1733 }
1734 }
Ted Kremenekae1fd6f2010-11-17 00:50:45 +00001735};
Ted Kremenekcdba6592010-11-18 00:42:18 +00001736class MemberRefVisit : public VisitorJob {
1737public:
1738 MemberRefVisit(FieldDecl *D, SourceLocation L, CXCursor parent)
1739 : VisitorJob(parent, VisitorJob::MemberRefVisitKind, D,
Jeffrey Yasskindec09842011-01-18 02:00:16 +00001740 L.getPtrEncoding()) {}
Ted Kremenekcdba6592010-11-18 00:42:18 +00001741 static bool classof(const VisitorJob *VJ) {
1742 return VJ->getKind() == VisitorJob::MemberRefVisitKind;
1743 }
1744 FieldDecl *get() const {
1745 return static_cast<FieldDecl*>(data[0]);
1746 }
1747 SourceLocation getLoc() const {
1748 return SourceLocation::getFromRawEncoding((unsigned)(uintptr_t) data[1]);
1749 }
1750};
Ted Kremenek28a71942010-11-13 00:36:47 +00001751class EnqueueVisitor : public StmtVisitor<EnqueueVisitor, void> {
1752 VisitorWorkList &WL;
1753 CXCursor Parent;
1754public:
1755 EnqueueVisitor(VisitorWorkList &wl, CXCursor parent)
1756 : WL(wl), Parent(parent) {}
1757
Ted Kremenekae1fd6f2010-11-17 00:50:45 +00001758 void VisitAddrLabelExpr(AddrLabelExpr *E);
Ted Kremenek73d15c42010-11-13 01:09:29 +00001759 void VisitBlockExpr(BlockExpr *B);
Ted Kremenek28a71942010-11-13 00:36:47 +00001760 void VisitCompoundLiteralExpr(CompoundLiteralExpr *E);
Ted Kremenek083c7e22010-11-13 05:38:03 +00001761 void VisitCompoundStmt(CompoundStmt *S);
Ted Kremenek11b8e3e2010-11-13 05:55:53 +00001762 void VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) { /* Do nothing. */ }
Ted Kremenekf64d8032010-11-18 00:02:32 +00001763 void VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E);
Ted Kremenek11b8e3e2010-11-13 05:55:53 +00001764 void VisitCXXNewExpr(CXXNewExpr *E);
Ted Kremenek6d0a00d2010-11-17 02:18:35 +00001765 void VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E);
Ted Kremenek28a71942010-11-13 00:36:47 +00001766 void VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E);
Ted Kremenekcdba6592010-11-18 00:42:18 +00001767 void VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E);
Ted Kremenek73d15c42010-11-13 01:09:29 +00001768 void VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E);
Ted Kremenekb8dd1ca2010-11-17 00:50:41 +00001769 void VisitCXXTypeidExpr(CXXTypeidExpr *E);
Ted Kremenek55b933a2010-11-17 00:50:36 +00001770 void VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr *E);
Ted Kremenek1e7e8772010-11-17 00:50:52 +00001771 void VisitCXXUuidofExpr(CXXUuidofExpr *E);
Ted Kremeneke4979cc2010-11-13 00:58:18 +00001772 void VisitDeclRefExpr(DeclRefExpr *D);
Ted Kremenek035dc412010-11-13 00:36:50 +00001773 void VisitDeclStmt(DeclStmt *S);
Ted Kremenekf64d8032010-11-18 00:02:32 +00001774 void VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E);
Ted Kremenekcdba6592010-11-18 00:42:18 +00001775 void VisitDesignatedInitExpr(DesignatedInitExpr *E);
Ted Kremenek28a71942010-11-13 00:36:47 +00001776 void VisitExplicitCastExpr(ExplicitCastExpr *E);
1777 void VisitForStmt(ForStmt *FS);
Ted Kremenekae1fd6f2010-11-17 00:50:45 +00001778 void VisitGotoStmt(GotoStmt *GS);
Ted Kremenek28a71942010-11-13 00:36:47 +00001779 void VisitIfStmt(IfStmt *If);
1780 void VisitInitListExpr(InitListExpr *IE);
1781 void VisitMemberExpr(MemberExpr *M);
Ted Kremenekcdba6592010-11-18 00:42:18 +00001782 void VisitOffsetOfExpr(OffsetOfExpr *E);
Ted Kremenek73d15c42010-11-13 01:09:29 +00001783 void VisitObjCEncodeExpr(ObjCEncodeExpr *E);
Ted Kremenek28a71942010-11-13 00:36:47 +00001784 void VisitObjCMessageExpr(ObjCMessageExpr *M);
1785 void VisitOverloadExpr(OverloadExpr *E);
Peter Collingbournef4e3cfb2011-03-11 19:24:49 +00001786 void VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E);
Ted Kremenek28a71942010-11-13 00:36:47 +00001787 void VisitStmt(Stmt *S);
1788 void VisitSwitchStmt(SwitchStmt *S);
1789 void VisitWhileStmt(WhileStmt *W);
Ted Kremenek2939b6f2010-11-17 00:50:50 +00001790 void VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E);
Francois Pichet6ad6f282010-12-07 00:08:36 +00001791 void VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *E);
Ted Kremenek28a71942010-11-13 00:36:47 +00001792 void VisitUnresolvedMemberExpr(UnresolvedMemberExpr *U);
Ted Kremenek9d3bf792010-11-17 00:50:43 +00001793 void VisitVAArgExpr(VAArgExpr *E);
Douglas Gregor94d96292011-01-19 20:34:17 +00001794 void VisitSizeOfPackExpr(SizeOfPackExpr *E);
Douglas Gregoree8aff02011-01-04 17:33:58 +00001795
Ted Kremenek28a71942010-11-13 00:36:47 +00001796private:
Ted Kremenekf64d8032010-11-18 00:02:32 +00001797 void AddDeclarationNameInfo(Stmt *S);
1798 void AddNestedNameSpecifier(NestedNameSpecifier *NS, SourceRange R);
Douglas Gregorf3db29f2011-02-25 18:19:59 +00001799 void AddNestedNameSpecifierLoc(NestedNameSpecifierLoc Qualifier);
Ted Kremenek60608ec2010-11-17 00:50:47 +00001800 void AddExplicitTemplateArgs(const ExplicitTemplateArgumentList *A);
Ted Kremenekcdba6592010-11-18 00:42:18 +00001801 void AddMemberRef(FieldDecl *D, SourceLocation L);
Ted Kremenek28a71942010-11-13 00:36:47 +00001802 void AddStmt(Stmt *S);
Ted Kremenek035dc412010-11-13 00:36:50 +00001803 void AddDecl(Decl *D, bool isFirst = true);
Ted Kremenek28a71942010-11-13 00:36:47 +00001804 void AddTypeLoc(TypeSourceInfo *TI);
1805 void EnqueueChildren(Stmt *S);
1806};
1807} // end anonyous namespace
1808
Ted Kremenekf64d8032010-11-18 00:02:32 +00001809void EnqueueVisitor::AddDeclarationNameInfo(Stmt *S) {
1810 // 'S' should always be non-null, since it comes from the
1811 // statement we are visiting.
1812 WL.push_back(DeclarationNameInfoVisit(S, Parent));
1813}
1814void EnqueueVisitor::AddNestedNameSpecifier(NestedNameSpecifier *N,
1815 SourceRange R) {
1816 if (N)
1817 WL.push_back(NestedNameSpecifierVisit(N, R, Parent));
1818}
Douglas Gregorf3db29f2011-02-25 18:19:59 +00001819
1820void
1821EnqueueVisitor::AddNestedNameSpecifierLoc(NestedNameSpecifierLoc Qualifier) {
1822 if (Qualifier)
1823 WL.push_back(NestedNameSpecifierLocVisit(Qualifier, Parent));
1824}
1825
Ted Kremenek28a71942010-11-13 00:36:47 +00001826void EnqueueVisitor::AddStmt(Stmt *S) {
1827 if (S)
1828 WL.push_back(StmtVisit(S, Parent));
1829}
Ted Kremenek035dc412010-11-13 00:36:50 +00001830void EnqueueVisitor::AddDecl(Decl *D, bool isFirst) {
Ted Kremenek28a71942010-11-13 00:36:47 +00001831 if (D)
Ted Kremenek035dc412010-11-13 00:36:50 +00001832 WL.push_back(DeclVisit(D, Parent, isFirst));
Ted Kremenek28a71942010-11-13 00:36:47 +00001833}
Ted Kremenek60608ec2010-11-17 00:50:47 +00001834void EnqueueVisitor::
1835 AddExplicitTemplateArgs(const ExplicitTemplateArgumentList *A) {
1836 if (A)
1837 WL.push_back(ExplicitTemplateArgsVisit(
1838 const_cast<ExplicitTemplateArgumentList*>(A), Parent));
1839}
Ted Kremenekcdba6592010-11-18 00:42:18 +00001840void EnqueueVisitor::AddMemberRef(FieldDecl *D, SourceLocation L) {
1841 if (D)
1842 WL.push_back(MemberRefVisit(D, L, Parent));
1843}
Ted Kremenek28a71942010-11-13 00:36:47 +00001844void EnqueueVisitor::AddTypeLoc(TypeSourceInfo *TI) {
1845 if (TI)
1846 WL.push_back(TypeLocVisit(TI->getTypeLoc(), Parent));
1847 }
1848void EnqueueVisitor::EnqueueChildren(Stmt *S) {
Ted Kremeneka6b70432010-11-12 21:34:09 +00001849 unsigned size = WL.size();
John McCall7502c1d2011-02-13 04:07:26 +00001850 for (Stmt::child_range Child = S->children(); Child; ++Child) {
Ted Kremenek28a71942010-11-13 00:36:47 +00001851 AddStmt(*Child);
Ted Kremeneka6b70432010-11-12 21:34:09 +00001852 }
1853 if (size == WL.size())
1854 return;
1855 // Now reverse the entries we just added. This will match the DFS
1856 // ordering performed by the worklist.
1857 VisitorWorkList::iterator I = WL.begin() + size, E = WL.end();
1858 std::reverse(I, E);
1859}
Ted Kremenekae1fd6f2010-11-17 00:50:45 +00001860void EnqueueVisitor::VisitAddrLabelExpr(AddrLabelExpr *E) {
1861 WL.push_back(LabelRefVisit(E->getLabel(), E->getLabelLoc(), Parent));
1862}
Ted Kremenek73d15c42010-11-13 01:09:29 +00001863void EnqueueVisitor::VisitBlockExpr(BlockExpr *B) {
1864 AddDecl(B->getBlockDecl());
1865}
Ted Kremenek28a71942010-11-13 00:36:47 +00001866void EnqueueVisitor::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
1867 EnqueueChildren(E);
1868 AddTypeLoc(E->getTypeSourceInfo());
1869}
Ted Kremenek083c7e22010-11-13 05:38:03 +00001870void EnqueueVisitor::VisitCompoundStmt(CompoundStmt *S) {
1871 for (CompoundStmt::reverse_body_iterator I = S->body_rbegin(),
1872 E = S->body_rend(); I != E; ++I) {
1873 AddStmt(*I);
1874 }
Ted Kremenek11b8e3e2010-11-13 05:55:53 +00001875}
Ted Kremenekf64d8032010-11-18 00:02:32 +00001876void EnqueueVisitor::
1877VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E) {
1878 AddExplicitTemplateArgs(E->getOptionalExplicitTemplateArgs());
1879 AddDeclarationNameInfo(E);
Douglas Gregor7c3179c2011-02-28 18:50:33 +00001880 if (NestedNameSpecifierLoc QualifierLoc = E->getQualifierLoc())
1881 AddNestedNameSpecifierLoc(QualifierLoc);
Ted Kremenekf64d8032010-11-18 00:02:32 +00001882 if (!E->isImplicitAccess())
1883 AddStmt(E->getBase());
1884}
Ted Kremenek11b8e3e2010-11-13 05:55:53 +00001885void EnqueueVisitor::VisitCXXNewExpr(CXXNewExpr *E) {
1886 // Enqueue the initializer or constructor arguments.
1887 for (unsigned I = E->getNumConstructorArgs(); I > 0; --I)
1888 AddStmt(E->getConstructorArg(I-1));
1889 // Enqueue the array size, if any.
1890 AddStmt(E->getArraySize());
1891 // Enqueue the allocated type.
1892 AddTypeLoc(E->getAllocatedTypeSourceInfo());
1893 // Enqueue the placement arguments.
1894 for (unsigned I = E->getNumPlacementArgs(); I > 0; --I)
1895 AddStmt(E->getPlacementArg(I-1));
1896}
Ted Kremenek28a71942010-11-13 00:36:47 +00001897void EnqueueVisitor::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *CE) {
Ted Kremenek8b8d8c92010-11-13 05:55:56 +00001898 for (unsigned I = CE->getNumArgs(); I > 1 /* Yes, this is 1 */; --I)
1899 AddStmt(CE->getArg(I-1));
Ted Kremenek28a71942010-11-13 00:36:47 +00001900 AddStmt(CE->getCallee());
1901 AddStmt(CE->getArg(0));
1902}
Ted Kremenekcdba6592010-11-18 00:42:18 +00001903void EnqueueVisitor::VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E) {
1904 // Visit the name of the type being destroyed.
1905 AddTypeLoc(E->getDestroyedTypeInfo());
1906 // Visit the scope type that looks disturbingly like the nested-name-specifier
1907 // but isn't.
1908 AddTypeLoc(E->getScopeTypeInfo());
1909 // Visit the nested-name-specifier.
Douglas Gregorf3db29f2011-02-25 18:19:59 +00001910 if (NestedNameSpecifierLoc QualifierLoc = E->getQualifierLoc())
1911 AddNestedNameSpecifierLoc(QualifierLoc);
Ted Kremenekcdba6592010-11-18 00:42:18 +00001912 // Visit base expression.
1913 AddStmt(E->getBase());
1914}
Ted Kremenek6d0a00d2010-11-17 02:18:35 +00001915void EnqueueVisitor::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E) {
1916 AddTypeLoc(E->getTypeSourceInfo());
1917}
Ted Kremenek73d15c42010-11-13 01:09:29 +00001918void EnqueueVisitor::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E) {
1919 EnqueueChildren(E);
1920 AddTypeLoc(E->getTypeSourceInfo());
1921}
Ted Kremenekb8dd1ca2010-11-17 00:50:41 +00001922void EnqueueVisitor::VisitCXXTypeidExpr(CXXTypeidExpr *E) {
1923 EnqueueChildren(E);
1924 if (E->isTypeOperand())
1925 AddTypeLoc(E->getTypeOperandSourceInfo());
1926}
Ted Kremenek55b933a2010-11-17 00:50:36 +00001927
1928void EnqueueVisitor::VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr
1929 *E) {
1930 EnqueueChildren(E);
1931 AddTypeLoc(E->getTypeSourceInfo());
1932}
Ted Kremenek1e7e8772010-11-17 00:50:52 +00001933void EnqueueVisitor::VisitCXXUuidofExpr(CXXUuidofExpr *E) {
1934 EnqueueChildren(E);
1935 if (E->isTypeOperand())
1936 AddTypeLoc(E->getTypeOperandSourceInfo());
1937}
Ted Kremeneke4979cc2010-11-13 00:58:18 +00001938void EnqueueVisitor::VisitDeclRefExpr(DeclRefExpr *DR) {
Ted Kremenek60608ec2010-11-17 00:50:47 +00001939 if (DR->hasExplicitTemplateArgs()) {
1940 AddExplicitTemplateArgs(&DR->getExplicitTemplateArgs());
1941 }
Ted Kremeneke4979cc2010-11-13 00:58:18 +00001942 WL.push_back(DeclRefExprParts(DR, Parent));
1943}
Ted Kremenekf64d8032010-11-18 00:02:32 +00001944void EnqueueVisitor::VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) {
1945 AddExplicitTemplateArgs(E->getOptionalExplicitTemplateArgs());
1946 AddDeclarationNameInfo(E);
Douglas Gregor00cf3cc2011-02-25 20:49:16 +00001947 AddNestedNameSpecifierLoc(E->getQualifierLoc());
Ted Kremenekf64d8032010-11-18 00:02:32 +00001948}
Ted Kremenek035dc412010-11-13 00:36:50 +00001949void EnqueueVisitor::VisitDeclStmt(DeclStmt *S) {
1950 unsigned size = WL.size();
1951 bool isFirst = true;
1952 for (DeclStmt::decl_iterator D = S->decl_begin(), DEnd = S->decl_end();
1953 D != DEnd; ++D) {
1954 AddDecl(*D, isFirst);
1955 isFirst = false;
1956 }
1957 if (size == WL.size())
1958 return;
1959 // Now reverse the entries we just added. This will match the DFS
1960 // ordering performed by the worklist.
1961 VisitorWorkList::iterator I = WL.begin() + size, E = WL.end();
1962 std::reverse(I, E);
1963}
Ted Kremenekcdba6592010-11-18 00:42:18 +00001964void EnqueueVisitor::VisitDesignatedInitExpr(DesignatedInitExpr *E) {
1965 AddStmt(E->getInit());
1966 typedef DesignatedInitExpr::Designator Designator;
1967 for (DesignatedInitExpr::reverse_designators_iterator
1968 D = E->designators_rbegin(), DEnd = E->designators_rend();
1969 D != DEnd; ++D) {
1970 if (D->isFieldDesignator()) {
1971 if (FieldDecl *Field = D->getField())
1972 AddMemberRef(Field, D->getFieldLoc());
1973 continue;
1974 }
1975 if (D->isArrayDesignator()) {
1976 AddStmt(E->getArrayIndex(*D));
1977 continue;
1978 }
1979 assert(D->isArrayRangeDesignator() && "Unknown designator kind");
1980 AddStmt(E->getArrayRangeEnd(*D));
1981 AddStmt(E->getArrayRangeStart(*D));
1982 }
1983}
Ted Kremenek28a71942010-11-13 00:36:47 +00001984void EnqueueVisitor::VisitExplicitCastExpr(ExplicitCastExpr *E) {
1985 EnqueueChildren(E);
1986 AddTypeLoc(E->getTypeInfoAsWritten());
1987}
1988void EnqueueVisitor::VisitForStmt(ForStmt *FS) {
1989 AddStmt(FS->getBody());
1990 AddStmt(FS->getInc());
1991 AddStmt(FS->getCond());
1992 AddDecl(FS->getConditionVariable());
1993 AddStmt(FS->getInit());
1994}
Ted Kremenekae1fd6f2010-11-17 00:50:45 +00001995void EnqueueVisitor::VisitGotoStmt(GotoStmt *GS) {
1996 WL.push_back(LabelRefVisit(GS->getLabel(), GS->getLabelLoc(), Parent));
1997}
Ted Kremenek28a71942010-11-13 00:36:47 +00001998void EnqueueVisitor::VisitIfStmt(IfStmt *If) {
1999 AddStmt(If->getElse());
2000 AddStmt(If->getThen());
2001 AddStmt(If->getCond());
2002 AddDecl(If->getConditionVariable());
2003}
2004void EnqueueVisitor::VisitInitListExpr(InitListExpr *IE) {
2005 // We care about the syntactic form of the initializer list, only.
2006 if (InitListExpr *Syntactic = IE->getSyntacticForm())
2007 IE = Syntactic;
2008 EnqueueChildren(IE);
2009}
2010void EnqueueVisitor::VisitMemberExpr(MemberExpr *M) {
Douglas Gregor89629a72010-11-17 17:15:08 +00002011 WL.push_back(MemberExprParts(M, Parent));
2012
2013 // If the base of the member access expression is an implicit 'this', don't
2014 // visit it.
2015 // FIXME: If we ever want to show these implicit accesses, this will be
2016 // unfortunate. However, clang_getCursor() relies on this behavior.
Douglas Gregor75e85042011-03-02 21:06:53 +00002017 if (!M->isImplicitAccess())
2018 AddStmt(M->getBase());
Ted Kremenek28a71942010-11-13 00:36:47 +00002019}
Ted Kremenek73d15c42010-11-13 01:09:29 +00002020void EnqueueVisitor::VisitObjCEncodeExpr(ObjCEncodeExpr *E) {
2021 AddTypeLoc(E->getEncodedTypeSourceInfo());
2022}
Ted Kremenek28a71942010-11-13 00:36:47 +00002023void EnqueueVisitor::VisitObjCMessageExpr(ObjCMessageExpr *M) {
2024 EnqueueChildren(M);
2025 AddTypeLoc(M->getClassReceiverTypeInfo());
2026}
Ted Kremenekcdba6592010-11-18 00:42:18 +00002027void EnqueueVisitor::VisitOffsetOfExpr(OffsetOfExpr *E) {
2028 // Visit the components of the offsetof expression.
2029 for (unsigned N = E->getNumComponents(), I = N; I > 0; --I) {
2030 typedef OffsetOfExpr::OffsetOfNode OffsetOfNode;
2031 const OffsetOfNode &Node = E->getComponent(I-1);
2032 switch (Node.getKind()) {
2033 case OffsetOfNode::Array:
2034 AddStmt(E->getIndexExpr(Node.getArrayExprIndex()));
2035 break;
2036 case OffsetOfNode::Field:
Abramo Bagnara06dec892011-03-12 09:45:03 +00002037 AddMemberRef(Node.getField(), Node.getSourceRange().getEnd());
Ted Kremenekcdba6592010-11-18 00:42:18 +00002038 break;
2039 case OffsetOfNode::Identifier:
2040 case OffsetOfNode::Base:
2041 continue;
2042 }
2043 }
2044 // Visit the type into which we're computing the offset.
2045 AddTypeLoc(E->getTypeSourceInfo());
2046}
Ted Kremenek28a71942010-11-13 00:36:47 +00002047void EnqueueVisitor::VisitOverloadExpr(OverloadExpr *E) {
Ted Kremenek60608ec2010-11-17 00:50:47 +00002048 AddExplicitTemplateArgs(E->getOptionalExplicitTemplateArgs());
Ted Kremenek60458782010-11-12 21:34:16 +00002049 WL.push_back(OverloadExprParts(E, Parent));
2050}
Peter Collingbournef4e3cfb2011-03-11 19:24:49 +00002051void EnqueueVisitor::VisitUnaryExprOrTypeTraitExpr(
2052 UnaryExprOrTypeTraitExpr *E) {
Ted Kremenek6d0a00d2010-11-17 02:18:35 +00002053 EnqueueChildren(E);
2054 if (E->isArgumentType())
2055 AddTypeLoc(E->getArgumentTypeInfo());
2056}
Ted Kremenek28a71942010-11-13 00:36:47 +00002057void EnqueueVisitor::VisitStmt(Stmt *S) {
2058 EnqueueChildren(S);
2059}
2060void EnqueueVisitor::VisitSwitchStmt(SwitchStmt *S) {
2061 AddStmt(S->getBody());
2062 AddStmt(S->getCond());
2063 AddDecl(S->getConditionVariable());
2064}
Ted Kremenekfafa75a2010-11-17 00:50:39 +00002065
Ted Kremenek28a71942010-11-13 00:36:47 +00002066void EnqueueVisitor::VisitWhileStmt(WhileStmt *W) {
2067 AddStmt(W->getBody());
2068 AddStmt(W->getCond());
2069 AddDecl(W->getConditionVariable());
2070}
Ted Kremenek2939b6f2010-11-17 00:50:50 +00002071void EnqueueVisitor::VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E) {
2072 AddTypeLoc(E->getQueriedTypeSourceInfo());
2073}
Francois Pichet6ad6f282010-12-07 00:08:36 +00002074
2075void EnqueueVisitor::VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *E) {
Francois Pichet6ad6f282010-12-07 00:08:36 +00002076 AddTypeLoc(E->getRhsTypeSourceInfo());
Francois Pichet0a03a3f2010-12-08 09:11:05 +00002077 AddTypeLoc(E->getLhsTypeSourceInfo());
Francois Pichet6ad6f282010-12-07 00:08:36 +00002078}
2079
Ted Kremenek28a71942010-11-13 00:36:47 +00002080void EnqueueVisitor::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *U) {
2081 VisitOverloadExpr(U);
2082 if (!U->isImplicitAccess())
2083 AddStmt(U->getBase());
2084}
Ted Kremenek9d3bf792010-11-17 00:50:43 +00002085void EnqueueVisitor::VisitVAArgExpr(VAArgExpr *E) {
2086 AddStmt(E->getSubExpr());
2087 AddTypeLoc(E->getWrittenTypeInfo());
2088}
Douglas Gregor94d96292011-01-19 20:34:17 +00002089void EnqueueVisitor::VisitSizeOfPackExpr(SizeOfPackExpr *E) {
2090 WL.push_back(SizeOfPackExprParts(E, Parent));
2091}
Ted Kremenek60458782010-11-12 21:34:16 +00002092
Ted Kremenekc0e1d922010-11-11 08:05:18 +00002093void CursorVisitor::EnqueueWorkList(VisitorWorkList &WL, Stmt *S) {
Ted Kremenek28a71942010-11-13 00:36:47 +00002094 EnqueueVisitor(WL, MakeCXCursor(S, StmtParent, TU)).Visit(S);
Ted Kremenekc0e1d922010-11-11 08:05:18 +00002095}
2096
2097bool CursorVisitor::IsInRegionOfInterest(CXCursor C) {
2098 if (RegionOfInterest.isValid()) {
2099 SourceRange Range = getRawCursorExtent(C);
2100 if (Range.isInvalid() || CompareRegionOfInterest(Range))
2101 return false;
2102 }
2103 return true;
2104}
2105
2106bool CursorVisitor::RunVisitorWorkList(VisitorWorkList &WL) {
2107 while (!WL.empty()) {
2108 // Dequeue the worklist item.
Ted Kremenek82f3c502010-11-15 22:23:26 +00002109 VisitorJob LI = WL.back();
2110 WL.pop_back();
2111
Ted Kremenekc0e1d922010-11-11 08:05:18 +00002112 // Set the Parent field, then back to its old value once we're done.
2113 SetParentRAII SetParent(Parent, StmtParent, LI.getParent());
2114
2115 switch (LI.getKind()) {
Ted Kremenekf1107452010-11-12 18:26:56 +00002116 case VisitorJob::DeclVisitKind: {
Ted Kremenek82f3c502010-11-15 22:23:26 +00002117 Decl *D = cast<DeclVisit>(&LI)->get();
Ted Kremenekf1107452010-11-12 18:26:56 +00002118 if (!D)
2119 continue;
2120
2121 // For now, perform default visitation for Decls.
Ted Kremenek82f3c502010-11-15 22:23:26 +00002122 if (Visit(MakeCXCursor(D, TU, cast<DeclVisit>(&LI)->isFirst())))
Ted Kremenekf1107452010-11-12 18:26:56 +00002123 return true;
2124
2125 continue;
2126 }
Ted Kremenek60608ec2010-11-17 00:50:47 +00002127 case VisitorJob::ExplicitTemplateArgsVisitKind: {
2128 const ExplicitTemplateArgumentList *ArgList =
2129 cast<ExplicitTemplateArgsVisit>(&LI)->get();
2130 for (const TemplateArgumentLoc *Arg = ArgList->getTemplateArgs(),
2131 *ArgEnd = Arg + ArgList->NumTemplateArgs;
2132 Arg != ArgEnd; ++Arg) {
2133 if (VisitTemplateArgumentLoc(*Arg))
2134 return true;
2135 }
2136 continue;
2137 }
Ted Kremenekcdb4caf2010-11-12 21:34:12 +00002138 case VisitorJob::TypeLocVisitKind: {
2139 // Perform default visitation for TypeLocs.
Ted Kremenek82f3c502010-11-15 22:23:26 +00002140 if (Visit(cast<TypeLocVisit>(&LI)->get()))
Ted Kremenekcdb4caf2010-11-12 21:34:12 +00002141 return true;
2142 continue;
2143 }
Ted Kremenekae1fd6f2010-11-17 00:50:45 +00002144 case VisitorJob::LabelRefVisitKind: {
Chris Lattnerad8dcf42011-02-17 07:39:24 +00002145 LabelDecl *LS = cast<LabelRefVisit>(&LI)->get();
Ted Kremeneke7455012011-02-23 04:54:51 +00002146 if (LabelStmt *stmt = LS->getStmt()) {
2147 if (Visit(MakeCursorLabelRef(stmt, cast<LabelRefVisit>(&LI)->getLoc(),
2148 TU))) {
2149 return true;
2150 }
2151 }
Ted Kremenekae1fd6f2010-11-17 00:50:45 +00002152 continue;
2153 }
Douglas Gregorf3db29f2011-02-25 18:19:59 +00002154
Ted Kremenekf64d8032010-11-18 00:02:32 +00002155 case VisitorJob::NestedNameSpecifierVisitKind: {
2156 NestedNameSpecifierVisit *V = cast<NestedNameSpecifierVisit>(&LI);
2157 if (VisitNestedNameSpecifier(V->get(), V->getSourceRange()))
2158 return true;
2159 continue;
2160 }
Douglas Gregorf3db29f2011-02-25 18:19:59 +00002161
2162 case VisitorJob::NestedNameSpecifierLocVisitKind: {
2163 NestedNameSpecifierLocVisit *V = cast<NestedNameSpecifierLocVisit>(&LI);
2164 if (VisitNestedNameSpecifierLoc(V->get()))
2165 return true;
2166 continue;
2167 }
2168
Ted Kremenekf64d8032010-11-18 00:02:32 +00002169 case VisitorJob::DeclarationNameInfoVisitKind: {
2170 if (VisitDeclarationNameInfo(cast<DeclarationNameInfoVisit>(&LI)
2171 ->get()))
2172 return true;
2173 continue;
2174 }
Ted Kremenekcdba6592010-11-18 00:42:18 +00002175 case VisitorJob::MemberRefVisitKind: {
2176 MemberRefVisit *V = cast<MemberRefVisit>(&LI);
2177 if (Visit(MakeCursorMemberRef(V->get(), V->getLoc(), TU)))
2178 return true;
2179 continue;
2180 }
Ted Kremenekc0e1d922010-11-11 08:05:18 +00002181 case VisitorJob::StmtVisitKind: {
Ted Kremenek82f3c502010-11-15 22:23:26 +00002182 Stmt *S = cast<StmtVisit>(&LI)->get();
Ted Kremenek8c269ac2010-11-11 23:11:43 +00002183 if (!S)
2184 continue;
2185
Ted Kremenekf1107452010-11-12 18:26:56 +00002186 // Update the current cursor.
Ted Kremenekc0e1d922010-11-11 08:05:18 +00002187 CXCursor Cursor = MakeCXCursor(S, StmtParent, TU);
Ted Kremenekcdba6592010-11-18 00:42:18 +00002188 if (!IsInRegionOfInterest(Cursor))
2189 continue;
2190 switch (Visitor(Cursor, Parent, ClientData)) {
2191 case CXChildVisit_Break: return true;
2192 case CXChildVisit_Continue: break;
2193 case CXChildVisit_Recurse:
2194 EnqueueWorkList(WL, S);
Ted Kremenek82f3c502010-11-15 22:23:26 +00002195 break;
Ted Kremenekc0e1d922010-11-11 08:05:18 +00002196 }
Ted Kremenek82f3c502010-11-15 22:23:26 +00002197 continue;
Ted Kremenekc0e1d922010-11-11 08:05:18 +00002198 }
2199 case VisitorJob::MemberExprPartsKind: {
2200 // Handle the other pieces in the MemberExpr besides the base.
Ted Kremenek82f3c502010-11-15 22:23:26 +00002201 MemberExpr *M = cast<MemberExprParts>(&LI)->get();
Ted Kremenekc0e1d922010-11-11 08:05:18 +00002202
2203 // Visit the nested-name-specifier
Douglas Gregor40d96a62011-02-28 21:54:11 +00002204 if (NestedNameSpecifierLoc QualifierLoc = M->getQualifierLoc())
2205 if (VisitNestedNameSpecifierLoc(QualifierLoc))
Ted Kremenekc0e1d922010-11-11 08:05:18 +00002206 return true;
2207
2208 // Visit the declaration name.
2209 if (VisitDeclarationNameInfo(M->getMemberNameInfo()))
2210 return true;
2211
2212 // Visit the explicitly-specified template arguments, if any.
2213 if (M->hasExplicitTemplateArgs()) {
2214 for (const TemplateArgumentLoc *Arg = M->getTemplateArgs(),
2215 *ArgEnd = Arg + M->getNumTemplateArgs();
2216 Arg != ArgEnd; ++Arg) {
2217 if (VisitTemplateArgumentLoc(*Arg))
2218 return true;
2219 }
2220 }
2221 continue;
2222 }
Ted Kremeneke4979cc2010-11-13 00:58:18 +00002223 case VisitorJob::DeclRefExprPartsKind: {
Ted Kremenek82f3c502010-11-15 22:23:26 +00002224 DeclRefExpr *DR = cast<DeclRefExprParts>(&LI)->get();
Ted Kremeneke4979cc2010-11-13 00:58:18 +00002225 // Visit nested-name-specifier, if present.
Douglas Gregor40d96a62011-02-28 21:54:11 +00002226 if (NestedNameSpecifierLoc QualifierLoc = DR->getQualifierLoc())
2227 if (VisitNestedNameSpecifierLoc(QualifierLoc))
Ted Kremeneke4979cc2010-11-13 00:58:18 +00002228 return true;
2229 // Visit declaration name.
2230 if (VisitDeclarationNameInfo(DR->getNameInfo()))
2231 return true;
Ted Kremeneke4979cc2010-11-13 00:58:18 +00002232 continue;
2233 }
Ted Kremenek60458782010-11-12 21:34:16 +00002234 case VisitorJob::OverloadExprPartsKind: {
Ted Kremenek82f3c502010-11-15 22:23:26 +00002235 OverloadExpr *O = cast<OverloadExprParts>(&LI)->get();
Ted Kremenek60458782010-11-12 21:34:16 +00002236 // Visit the nested-name-specifier.
Douglas Gregor4c9be892011-02-28 20:01:57 +00002237 if (NestedNameSpecifierLoc QualifierLoc = O->getQualifierLoc())
2238 if (VisitNestedNameSpecifierLoc(QualifierLoc))
Ted Kremenek60458782010-11-12 21:34:16 +00002239 return true;
2240 // Visit the declaration name.
2241 if (VisitDeclarationNameInfo(O->getNameInfo()))
2242 return true;
2243 // Visit the overloaded declaration reference.
2244 if (Visit(MakeCursorOverloadedDeclRef(O, TU)))
2245 return true;
Ted Kremenek60458782010-11-12 21:34:16 +00002246 continue;
2247 }
Douglas Gregor94d96292011-01-19 20:34:17 +00002248 case VisitorJob::SizeOfPackExprPartsKind: {
2249 SizeOfPackExpr *E = cast<SizeOfPackExprParts>(&LI)->get();
2250 NamedDecl *Pack = E->getPack();
2251 if (isa<TemplateTypeParmDecl>(Pack)) {
2252 if (Visit(MakeCursorTypeRef(cast<TemplateTypeParmDecl>(Pack),
2253 E->getPackLoc(), TU)))
2254 return true;
2255
2256 continue;
2257 }
2258
2259 if (isa<TemplateTemplateParmDecl>(Pack)) {
2260 if (Visit(MakeCursorTemplateRef(cast<TemplateTemplateParmDecl>(Pack),
2261 E->getPackLoc(), TU)))
2262 return true;
2263
2264 continue;
2265 }
2266
2267 // Non-type template parameter packs and function parameter packs are
2268 // treated like DeclRefExpr cursors.
2269 continue;
2270 }
Ted Kremenekc0e1d922010-11-11 08:05:18 +00002271 }
2272 }
2273 return false;
2274}
2275
Ted Kremenekcdba6592010-11-18 00:42:18 +00002276bool CursorVisitor::Visit(Stmt *S) {
Ted Kremenekd1ded662010-11-15 23:31:32 +00002277 VisitorWorkList *WL = 0;
2278 if (!WorkListFreeList.empty()) {
2279 WL = WorkListFreeList.back();
2280 WL->clear();
2281 WorkListFreeList.pop_back();
2282 }
2283 else {
2284 WL = new VisitorWorkList();
2285 WorkListCache.push_back(WL);
2286 }
2287 EnqueueWorkList(*WL, S);
2288 bool result = RunVisitorWorkList(*WL);
2289 WorkListFreeList.push_back(WL);
2290 return result;
Ted Kremenekc0e1d922010-11-11 08:05:18 +00002291}
2292
2293//===----------------------------------------------------------------------===//
2294// Misc. API hooks.
2295//===----------------------------------------------------------------------===//
2296
Douglas Gregor8c8d5412010-09-24 21:18:36 +00002297static llvm::sys::Mutex EnableMultithreadingMutex;
2298static bool EnabledMultithreading;
2299
Benjamin Kramer5e4bc592009-10-18 16:11:04 +00002300extern "C" {
Douglas Gregor0a812cf2010-02-18 23:07:20 +00002301CXIndex clang_createIndex(int excludeDeclarationsFromPCH,
2302 int displayDiagnostics) {
Daniel Dunbar48615ff2010-10-08 19:30:33 +00002303 // Disable pretty stack trace functionality, which will otherwise be a very
2304 // poor citizen of the world and set up all sorts of signal handlers.
2305 llvm::DisablePrettyStackTrace = true;
2306
Daniel Dunbarc7df4f32010-08-18 18:43:14 +00002307 // We use crash recovery to make some of our APIs more reliable, implicitly
2308 // enable it.
2309 llvm::CrashRecoveryContext::Enable();
2310
Douglas Gregor8c8d5412010-09-24 21:18:36 +00002311 // Enable support for multithreading in LLVM.
2312 {
2313 llvm::sys::ScopedLock L(EnableMultithreadingMutex);
2314 if (!EnabledMultithreading) {
2315 llvm::llvm_start_multithreaded();
2316 EnabledMultithreading = true;
2317 }
2318 }
2319
Douglas Gregora030b7c2010-01-22 20:35:53 +00002320 CIndexer *CIdxr = new CIndexer();
Steve Naroffe56b4ba2009-10-20 14:46:24 +00002321 if (excludeDeclarationsFromPCH)
2322 CIdxr->setOnlyLocalDecls();
Douglas Gregor0a812cf2010-02-18 23:07:20 +00002323 if (displayDiagnostics)
2324 CIdxr->setDisplayDiagnostics();
Steve Naroffe56b4ba2009-10-20 14:46:24 +00002325 return CIdxr;
Steve Naroff600866c2009-08-27 19:51:58 +00002326}
2327
Daniel Dunbar9ebfa312009-12-01 03:14:51 +00002328void clang_disposeIndex(CXIndex CIdx) {
Douglas Gregor2b37c9e2010-01-29 00:47:48 +00002329 if (CIdx)
2330 delete static_cast<CIndexer *>(CIdx);
Steve Naroff2bd6b9f2009-09-17 18:33:27 +00002331}
2332
Ted Kremenekd2427dd2011-03-18 23:05:39 +00002333void clang_toggleCrashRecovery(unsigned isEnabled) {
2334 if (isEnabled)
2335 llvm::CrashRecoveryContext::Enable();
2336 else
2337 llvm::CrashRecoveryContext::Disable();
2338}
2339
Daniel Dunbar9ebfa312009-12-01 03:14:51 +00002340CXTranslationUnit clang_createTranslationUnit(CXIndex CIdx,
Douglas Gregora88084b2010-02-18 18:08:43 +00002341 const char *ast_filename) {
Douglas Gregor2b37c9e2010-01-29 00:47:48 +00002342 if (!CIdx)
2343 return 0;
Ted Kremenekf0e23e82010-02-17 00:41:40 +00002344
Douglas Gregor7d1d49d2009-10-16 20:01:17 +00002345 CIndexer *CXXIdx = static_cast<CIndexer *>(CIdx);
Argyrios Kyrtzidis389db162010-11-03 22:45:23 +00002346 FileSystemOptions FileSystemOpts;
2347 FileSystemOpts.WorkingDir = CXXIdx->getWorkingDirectory();
Daniel Dunbar0d7dd222009-11-30 20:42:43 +00002348
Douglas Gregor28019772010-04-05 23:52:57 +00002349 llvm::IntrusiveRefCntPtr<Diagnostic> Diags;
Ted Kremeneka60ed472010-11-16 08:15:36 +00002350 ASTUnit *TU = ASTUnit::LoadFromASTFile(ast_filename, Diags, FileSystemOpts,
Douglas Gregora88084b2010-02-18 18:08:43 +00002351 CXXIdx->getOnlyLocalDecls(),
2352 0, 0, true);
Ted Kremeneka60ed472010-11-16 08:15:36 +00002353 return MakeCXTranslationUnit(TU);
Steve Naroff600866c2009-08-27 19:51:58 +00002354}
2355
Douglas Gregorb1c031b2010-08-09 22:28:58 +00002356unsigned clang_defaultEditingTranslationUnitOptions() {
Douglas Gregor2a2c50b2010-09-27 05:49:58 +00002357 return CXTranslationUnit_PrecompiledPreamble |
Douglas Gregor99ba2022010-10-27 17:24:53 +00002358 CXTranslationUnit_CacheCompletionResults |
2359 CXTranslationUnit_CXXPrecompiledPreamble;
Douglas Gregorb1c031b2010-08-09 22:28:58 +00002360}
2361
Daniel Dunbar9ebfa312009-12-01 03:14:51 +00002362CXTranslationUnit
2363clang_createTranslationUnitFromSourceFile(CXIndex CIdx,
2364 const char *source_filename,
2365 int num_command_line_args,
Douglas Gregor2ef69442010-09-01 16:43:19 +00002366 const char * const *command_line_args,
Douglas Gregor4db64a42010-01-23 00:14:00 +00002367 unsigned num_unsaved_files,
Douglas Gregora88084b2010-02-18 18:08:43 +00002368 struct CXUnsavedFile *unsaved_files) {
Douglas Gregor5a430212010-07-21 18:52:53 +00002369 return clang_parseTranslationUnit(CIdx, source_filename,
2370 command_line_args, num_command_line_args,
2371 unsaved_files, num_unsaved_files,
2372 CXTranslationUnit_DetailedPreprocessingRecord);
2373}
Daniel Dunbar19ffd492010-08-18 18:43:17 +00002374
2375struct ParseTranslationUnitInfo {
2376 CXIndex CIdx;
2377 const char *source_filename;
Douglas Gregor2ef69442010-09-01 16:43:19 +00002378 const char *const *command_line_args;
Daniel Dunbar19ffd492010-08-18 18:43:17 +00002379 int num_command_line_args;
2380 struct CXUnsavedFile *unsaved_files;
2381 unsigned num_unsaved_files;
2382 unsigned options;
2383 CXTranslationUnit result;
2384};
Daniel Dunbarb1fd3452010-08-19 23:44:10 +00002385static void clang_parseTranslationUnit_Impl(void *UserData) {
Daniel Dunbar19ffd492010-08-18 18:43:17 +00002386 ParseTranslationUnitInfo *PTUI =
2387 static_cast<ParseTranslationUnitInfo*>(UserData);
2388 CXIndex CIdx = PTUI->CIdx;
2389 const char *source_filename = PTUI->source_filename;
Douglas Gregor2ef69442010-09-01 16:43:19 +00002390 const char * const *command_line_args = PTUI->command_line_args;
Daniel Dunbar19ffd492010-08-18 18:43:17 +00002391 int num_command_line_args = PTUI->num_command_line_args;
2392 struct CXUnsavedFile *unsaved_files = PTUI->unsaved_files;
2393 unsigned num_unsaved_files = PTUI->num_unsaved_files;
2394 unsigned options = PTUI->options;
2395 PTUI->result = 0;
Douglas Gregor5a430212010-07-21 18:52:53 +00002396
Douglas Gregor2b37c9e2010-01-29 00:47:48 +00002397 if (!CIdx)
Daniel Dunbar19ffd492010-08-18 18:43:17 +00002398 return;
Ted Kremenekf0e23e82010-02-17 00:41:40 +00002399
Steve Naroffe56b4ba2009-10-20 14:46:24 +00002400 CIndexer *CXXIdx = static_cast<CIndexer *>(CIdx);
2401
Douglas Gregor44c181a2010-07-23 00:33:23 +00002402 bool PrecompilePreamble = options & CXTranslationUnit_PrecompiledPreamble;
Douglas Gregordf95a132010-08-09 20:45:32 +00002403 bool CompleteTranslationUnit
2404 = ((options & CXTranslationUnit_Incomplete) == 0);
Douglas Gregor87c08a52010-08-13 22:48:40 +00002405 bool CacheCodeCompetionResults
2406 = options & CXTranslationUnit_CacheCompletionResults;
Douglas Gregor99ba2022010-10-27 17:24:53 +00002407 bool CXXPrecompilePreamble
2408 = options & CXTranslationUnit_CXXPrecompiledPreamble;
2409 bool CXXChainedPCH
2410 = options & CXTranslationUnit_CXXChainedPCH;
Douglas Gregor87c08a52010-08-13 22:48:40 +00002411
Douglas Gregor5352ac02010-01-28 00:27:43 +00002412 // Configure the diagnostics.
2413 DiagnosticOptions DiagOpts;
Ted Kremenek25a11e12011-03-22 01:15:24 +00002414 llvm::IntrusiveRefCntPtr<Diagnostic>
2415 Diags(CompilerInstance::createDiagnostics(DiagOpts, num_command_line_args,
2416 command_line_args));
Ted Kremenekf0e23e82010-02-17 00:41:40 +00002417
Ted Kremenek25a11e12011-03-22 01:15:24 +00002418 // Recover resources if we crash before exiting this function.
2419 llvm::CrashRecoveryContextCleanupRegistrar<Diagnostic,
2420 llvm::CrashRecoveryContextReleaseRefCleanup<Diagnostic> >
2421 DiagCleanup(Diags.getPtr());
2422
2423 llvm::OwningPtr<std::vector<ASTUnit::RemappedFile> >
2424 RemappedFiles(new std::vector<ASTUnit::RemappedFile>());
2425
2426 // Recover resources if we crash before exiting this function.
2427 llvm::CrashRecoveryContextCleanupRegistrar<
2428 std::vector<ASTUnit::RemappedFile> > RemappedCleanup(RemappedFiles.get());
2429
Douglas Gregor4db64a42010-01-23 00:14:00 +00002430 for (unsigned I = 0; I != num_unsaved_files; ++I) {
Chris Lattnera0a270c2010-04-05 22:42:27 +00002431 llvm::StringRef Data(unsaved_files[I].Contents, unsaved_files[I].Length);
Ted Kremenekf0e23e82010-02-17 00:41:40 +00002432 const llvm::MemoryBuffer *Buffer
Chris Lattnera0a270c2010-04-05 22:42:27 +00002433 = llvm::MemoryBuffer::getMemBufferCopy(Data, unsaved_files[I].Filename);
Ted Kremenek25a11e12011-03-22 01:15:24 +00002434 RemappedFiles->push_back(std::make_pair(unsaved_files[I].Filename,
2435 Buffer));
Douglas Gregor4db64a42010-01-23 00:14:00 +00002436 }
Ted Kremenekf0e23e82010-02-17 00:41:40 +00002437
Ted Kremenek25a11e12011-03-22 01:15:24 +00002438 llvm::OwningPtr<std::vector<const char *> >
2439 Args(new std::vector<const char*>());
2440
2441 // Recover resources if we crash before exiting this method.
2442 llvm::CrashRecoveryContextCleanupRegistrar<std::vector<const char*> >
2443 ArgsCleanup(Args.get());
2444
Douglas Gregor52ddc5d2010-07-09 18:39:07 +00002445 // Since the Clang C library is primarily used by batch tools dealing with
2446 // (often very broken) source code, where spell-checking can have a
2447 // significant negative impact on performance (particularly when
2448 // precompiled headers are involved), we disable it by default.
Douglas Gregorb10daed2010-10-11 16:52:23 +00002449 // Only do this if we haven't found a spell-checking-related argument.
2450 bool FoundSpellCheckingArgument = false;
2451 for (int I = 0; I != num_command_line_args; ++I) {
2452 if (strcmp(command_line_args[I], "-fno-spell-checking") == 0 ||
2453 strcmp(command_line_args[I], "-fspell-checking") == 0) {
2454 FoundSpellCheckingArgument = true;
2455 break;
Steve Naroffe56b4ba2009-10-20 14:46:24 +00002456 }
Douglas Gregorb10daed2010-10-11 16:52:23 +00002457 }
2458 if (!FoundSpellCheckingArgument)
Ted Kremenek25a11e12011-03-22 01:15:24 +00002459 Args->push_back("-fno-spell-checking");
Douglas Gregorb10daed2010-10-11 16:52:23 +00002460
Ted Kremenek25a11e12011-03-22 01:15:24 +00002461 Args->insert(Args->end(), command_line_args,
2462 command_line_args + num_command_line_args);
Douglas Gregord93256e2010-01-28 06:00:51 +00002463
Argyrios Kyrtzidisc8429552011-03-20 18:17:52 +00002464 // The 'source_filename' argument is optional. If the caller does not
2465 // specify it then it is assumed that the source file is specified
2466 // in the actual argument list.
2467 // Put the source file after command_line_args otherwise if '-x' flag is
2468 // present it will be unused.
2469 if (source_filename)
Ted Kremenek25a11e12011-03-22 01:15:24 +00002470 Args->push_back(source_filename);
Argyrios Kyrtzidisc8429552011-03-20 18:17:52 +00002471
Douglas Gregor44c181a2010-07-23 00:33:23 +00002472 // Do we need the detailed preprocessing record?
2473 if (options & CXTranslationUnit_DetailedPreprocessingRecord) {
Ted Kremenek25a11e12011-03-22 01:15:24 +00002474 Args->push_back("-Xclang");
2475 Args->push_back("-detailed-preprocessing-record");
Douglas Gregor44c181a2010-07-23 00:33:23 +00002476 }
2477
Argyrios Kyrtzidis026f6912010-11-18 21:47:04 +00002478 unsigned NumErrors = Diags->getClient()->getNumErrors();
Douglas Gregorb10daed2010-10-11 16:52:23 +00002479 llvm::OwningPtr<ASTUnit> Unit(
Ted Kremenek4ee99262011-03-22 20:16:19 +00002480 ASTUnit::LoadFromCommandLine(Args->size() ? &(*Args)[0] : 0
2481 /* vector::data() not portable */,
2482 Args->size() ? (&(*Args)[0] + Args->size()) :0,
Douglas Gregorb10daed2010-10-11 16:52:23 +00002483 Diags,
2484 CXXIdx->getClangResourcesPath(),
2485 CXXIdx->getOnlyLocalDecls(),
Douglas Gregore47be3e2010-11-11 00:39:14 +00002486 /*CaptureDiagnostics=*/true,
Ted Kremenek4ee99262011-03-22 20:16:19 +00002487 RemappedFiles->size() ? &(*RemappedFiles)[0]:0,
Ted Kremenek25a11e12011-03-22 01:15:24 +00002488 RemappedFiles->size(),
Argyrios Kyrtzidis299a4a92011-03-08 23:35:24 +00002489 /*RemappedFilesKeepOriginalName=*/true,
Douglas Gregorb10daed2010-10-11 16:52:23 +00002490 PrecompilePreamble,
2491 CompleteTranslationUnit,
Douglas Gregor99ba2022010-10-27 17:24:53 +00002492 CacheCodeCompetionResults,
2493 CXXPrecompilePreamble,
2494 CXXChainedPCH));
Ted Kremenekf0e23e82010-02-17 00:41:40 +00002495
Argyrios Kyrtzidis026f6912010-11-18 21:47:04 +00002496 if (NumErrors != Diags->getClient()->getNumErrors()) {
Douglas Gregorb10daed2010-10-11 16:52:23 +00002497 // Make sure to check that 'Unit' is non-NULL.
2498 if (CXXIdx->getDisplayDiagnostics() && Unit.get()) {
2499 for (ASTUnit::stored_diag_iterator D = Unit->stored_diag_begin(),
2500 DEnd = Unit->stored_diag_end();
2501 D != DEnd; ++D) {
2502 CXStoredDiagnostic Diag(*D, Unit->getASTContext().getLangOptions());
2503 CXString Msg = clang_formatDiagnostic(&Diag,
2504 clang_defaultDiagnosticDisplayOptions());
2505 fprintf(stderr, "%s\n", clang_getCString(Msg));
2506 clang_disposeString(Msg);
2507 }
Douglas Gregor274f1902010-02-22 23:17:23 +00002508#ifdef LLVM_ON_WIN32
Douglas Gregorb10daed2010-10-11 16:52:23 +00002509 // On Windows, force a flush, since there may be multiple copies of
2510 // stderr and stdout in the file system, all with different buffers
2511 // but writing to the same device.
2512 fflush(stderr);
2513#endif
2514 }
Douglas Gregora88084b2010-02-18 18:08:43 +00002515 }
Douglas Gregord93256e2010-01-28 06:00:51 +00002516
Ted Kremeneka60ed472010-11-16 08:15:36 +00002517 PTUI->result = MakeCXTranslationUnit(Unit.take());
Daniel Dunbar19ffd492010-08-18 18:43:17 +00002518}
2519CXTranslationUnit clang_parseTranslationUnit(CXIndex CIdx,
2520 const char *source_filename,
Douglas Gregor2ef69442010-09-01 16:43:19 +00002521 const char * const *command_line_args,
Daniel Dunbar19ffd492010-08-18 18:43:17 +00002522 int num_command_line_args,
Daniel Dunbar9e1ebdd2010-11-05 07:19:21 +00002523 struct CXUnsavedFile *unsaved_files,
Daniel Dunbar19ffd492010-08-18 18:43:17 +00002524 unsigned num_unsaved_files,
2525 unsigned options) {
2526 ParseTranslationUnitInfo PTUI = { CIdx, source_filename, command_line_args,
Daniel Dunbar9e1ebdd2010-11-05 07:19:21 +00002527 num_command_line_args, unsaved_files,
2528 num_unsaved_files, options, 0 };
Daniel Dunbar19ffd492010-08-18 18:43:17 +00002529 llvm::CrashRecoveryContext CRC;
2530
Daniel Dunbarbf44c3b2010-11-05 07:19:31 +00002531 if (!RunSafely(CRC, clang_parseTranslationUnit_Impl, &PTUI)) {
Daniel Dunbar60a45432010-08-23 22:35:34 +00002532 fprintf(stderr, "libclang: crash detected during parsing: {\n");
2533 fprintf(stderr, " 'source_filename' : '%s'\n", source_filename);
2534 fprintf(stderr, " 'command_line_args' : [");
2535 for (int i = 0; i != num_command_line_args; ++i) {
2536 if (i)
2537 fprintf(stderr, ", ");
2538 fprintf(stderr, "'%s'", command_line_args[i]);
2539 }
2540 fprintf(stderr, "],\n");
2541 fprintf(stderr, " 'unsaved_files' : [");
2542 for (unsigned i = 0; i != num_unsaved_files; ++i) {
2543 if (i)
2544 fprintf(stderr, ", ");
2545 fprintf(stderr, "('%s', '...', %ld)", unsaved_files[i].Filename,
2546 unsaved_files[i].Length);
2547 }
2548 fprintf(stderr, "],\n");
2549 fprintf(stderr, " 'options' : %d,\n", options);
2550 fprintf(stderr, "}\n");
2551
Daniel Dunbar19ffd492010-08-18 18:43:17 +00002552 return 0;
2553 }
2554
2555 return PTUI.result;
Steve Naroff5b7d8e22009-10-15 20:04:39 +00002556}
2557
Douglas Gregor19998442010-08-13 15:35:05 +00002558unsigned clang_defaultSaveOptions(CXTranslationUnit TU) {
2559 return CXSaveTranslationUnit_None;
2560}
2561
2562int clang_saveTranslationUnit(CXTranslationUnit TU, const char *FileName,
2563 unsigned options) {
Douglas Gregor7ae2faa2010-08-13 05:36:37 +00002564 if (!TU)
2565 return 1;
2566
Ted Kremeneka60ed472010-11-16 08:15:36 +00002567 return static_cast<ASTUnit *>(TU->TUData)->Save(FileName);
Douglas Gregor7ae2faa2010-08-13 05:36:37 +00002568}
Daniel Dunbar19ffd492010-08-18 18:43:17 +00002569
Daniel Dunbar9ebfa312009-12-01 03:14:51 +00002570void clang_disposeTranslationUnit(CXTranslationUnit CTUnit) {
Daniel Dunbarea94bbc2010-08-18 23:09:31 +00002571 if (CTUnit) {
2572 // If the translation unit has been marked as unsafe to free, just discard
2573 // it.
Ted Kremeneka60ed472010-11-16 08:15:36 +00002574 if (static_cast<ASTUnit *>(CTUnit->TUData)->isUnsafeToFree())
Daniel Dunbarea94bbc2010-08-18 23:09:31 +00002575 return;
2576
Ted Kremeneka60ed472010-11-16 08:15:36 +00002577 delete static_cast<ASTUnit *>(CTUnit->TUData);
2578 disposeCXStringPool(CTUnit->StringPool);
2579 delete CTUnit;
Daniel Dunbarea94bbc2010-08-18 23:09:31 +00002580 }
Steve Naroff2bd6b9f2009-09-17 18:33:27 +00002581}
Daniel Dunbar0d7dd222009-11-30 20:42:43 +00002582
Douglas Gregore1e13bf2010-08-11 15:58:42 +00002583unsigned clang_defaultReparseOptions(CXTranslationUnit TU) {
2584 return CXReparse_None;
2585}
2586
Daniel Dunbarea94bbc2010-08-18 23:09:31 +00002587struct ReparseTranslationUnitInfo {
2588 CXTranslationUnit TU;
2589 unsigned num_unsaved_files;
2590 struct CXUnsavedFile *unsaved_files;
2591 unsigned options;
2592 int result;
2593};
Douglas Gregor593b0c12010-09-23 18:47:53 +00002594
Daniel Dunbarb1fd3452010-08-19 23:44:10 +00002595static void clang_reparseTranslationUnit_Impl(void *UserData) {
Daniel Dunbarea94bbc2010-08-18 23:09:31 +00002596 ReparseTranslationUnitInfo *RTUI =
2597 static_cast<ReparseTranslationUnitInfo*>(UserData);
2598 CXTranslationUnit TU = RTUI->TU;
2599 unsigned num_unsaved_files = RTUI->num_unsaved_files;
2600 struct CXUnsavedFile *unsaved_files = RTUI->unsaved_files;
2601 unsigned options = RTUI->options;
2602 (void) options;
2603 RTUI->result = 1;
2604
Douglas Gregorabc563f2010-07-19 21:46:24 +00002605 if (!TU)
Daniel Dunbarea94bbc2010-08-18 23:09:31 +00002606 return;
Douglas Gregor593b0c12010-09-23 18:47:53 +00002607
Ted Kremeneka60ed472010-11-16 08:15:36 +00002608 ASTUnit *CXXUnit = static_cast<ASTUnit *>(TU->TUData);
Douglas Gregor593b0c12010-09-23 18:47:53 +00002609 ASTUnit::ConcurrencyCheck Check(*CXXUnit);
Douglas Gregorabc563f2010-07-19 21:46:24 +00002610
Ted Kremenek25a11e12011-03-22 01:15:24 +00002611 llvm::OwningPtr<std::vector<ASTUnit::RemappedFile> >
2612 RemappedFiles(new std::vector<ASTUnit::RemappedFile>());
2613
2614 // Recover resources if we crash before exiting this function.
2615 llvm::CrashRecoveryContextCleanupRegistrar<
2616 std::vector<ASTUnit::RemappedFile> > RemappedCleanup(RemappedFiles.get());
2617
Douglas Gregorabc563f2010-07-19 21:46:24 +00002618 for (unsigned I = 0; I != num_unsaved_files; ++I) {
2619 llvm::StringRef Data(unsaved_files[I].Contents, unsaved_files[I].Length);
2620 const llvm::MemoryBuffer *Buffer
Douglas Gregor1abc6bc2010-08-04 16:47:14 +00002621 = llvm::MemoryBuffer::getMemBufferCopy(Data, unsaved_files[I].Filename);
Ted Kremenek25a11e12011-03-22 01:15:24 +00002622 RemappedFiles->push_back(std::make_pair(unsaved_files[I].Filename,
2623 Buffer));
Douglas Gregorabc563f2010-07-19 21:46:24 +00002624 }
2625
Ted Kremenek4ee99262011-03-22 20:16:19 +00002626 if (!CXXUnit->Reparse(RemappedFiles->size() ? &(*RemappedFiles)[0] : 0,
2627 RemappedFiles->size()))
Douglas Gregor593b0c12010-09-23 18:47:53 +00002628 RTUI->result = 0;
Douglas Gregorabc563f2010-07-19 21:46:24 +00002629}
Douglas Gregor593b0c12010-09-23 18:47:53 +00002630
Daniel Dunbarea94bbc2010-08-18 23:09:31 +00002631int clang_reparseTranslationUnit(CXTranslationUnit TU,
2632 unsigned num_unsaved_files,
2633 struct CXUnsavedFile *unsaved_files,
2634 unsigned options) {
2635 ReparseTranslationUnitInfo RTUI = { TU, num_unsaved_files, unsaved_files,
2636 options, 0 };
2637 llvm::CrashRecoveryContext CRC;
2638
Daniel Dunbarbf44c3b2010-11-05 07:19:31 +00002639 if (!RunSafely(CRC, clang_reparseTranslationUnit_Impl, &RTUI)) {
Daniel Dunbarb1fd3452010-08-19 23:44:10 +00002640 fprintf(stderr, "libclang: crash detected during reparsing\n");
Ted Kremeneka60ed472010-11-16 08:15:36 +00002641 static_cast<ASTUnit *>(TU->TUData)->setUnsafeToFree(true);
Daniel Dunbarea94bbc2010-08-18 23:09:31 +00002642 return 1;
2643 }
2644
Ted Kremenek1dfb26a2010-10-29 01:06:50 +00002645
Daniel Dunbarea94bbc2010-08-18 23:09:31 +00002646 return RTUI.result;
2647}
2648
Douglas Gregordf95a132010-08-09 20:45:32 +00002649
Daniel Dunbar9ebfa312009-12-01 03:14:51 +00002650CXString clang_getTranslationUnitSpelling(CXTranslationUnit CTUnit) {
Douglas Gregor2b37c9e2010-01-29 00:47:48 +00002651 if (!CTUnit)
Ted Kremenekee4db4f2010-02-17 00:41:08 +00002652 return createCXString("");
Ted Kremenekf0e23e82010-02-17 00:41:40 +00002653
Ted Kremeneka60ed472010-11-16 08:15:36 +00002654 ASTUnit *CXXUnit = static_cast<ASTUnit *>(CTUnit->TUData);
Ted Kremenekee4db4f2010-02-17 00:41:08 +00002655 return createCXString(CXXUnit->getOriginalSourceFileName(), true);
Steve Naroffaf08ddc2009-09-03 15:49:00 +00002656}
Daniel Dunbar1eb79b52009-08-28 16:30:07 +00002657
Douglas Gregor7eaa8ae2010-01-20 00:23:15 +00002658CXCursor clang_getTranslationUnitCursor(CXTranslationUnit TU) {
Douglas Gregorb2cd4872010-01-20 23:57:43 +00002659 CXCursor Result = { CXCursor_TranslationUnit, { 0, 0, TU } };
Douglas Gregor7eaa8ae2010-01-20 00:23:15 +00002660 return Result;
2661}
2662
Ted Kremenekfb480492010-01-13 21:46:36 +00002663} // end: extern "C"
Steve Naroff600866c2009-08-27 19:51:58 +00002664
Ted Kremenekfb480492010-01-13 21:46:36 +00002665//===----------------------------------------------------------------------===//
Douglas Gregor1db19de2010-01-19 21:36:55 +00002666// CXSourceLocation and CXSourceRange Operations.
2667//===----------------------------------------------------------------------===//
2668
Douglas Gregorb9790342010-01-22 21:44:22 +00002669extern "C" {
2670CXSourceLocation clang_getNullLocation() {
Douglas Gregor5352ac02010-01-28 00:27:43 +00002671 CXSourceLocation Result = { { 0, 0 }, 0 };
Douglas Gregorb9790342010-01-22 21:44:22 +00002672 return Result;
2673}
2674
2675unsigned clang_equalLocations(CXSourceLocation loc1, CXSourceLocation loc2) {
Daniel Dunbar90a6b9e2010-01-30 23:58:27 +00002676 return (loc1.ptr_data[0] == loc2.ptr_data[0] &&
2677 loc1.ptr_data[1] == loc2.ptr_data[1] &&
2678 loc1.int_data == loc2.int_data);
Douglas Gregorb9790342010-01-22 21:44:22 +00002679}
2680
2681CXSourceLocation clang_getLocation(CXTranslationUnit tu,
2682 CXFile file,
2683 unsigned line,
2684 unsigned column) {
Douglas Gregor42748ec2010-04-30 19:45:53 +00002685 if (!tu || !file)
Douglas Gregorb9790342010-01-22 21:44:22 +00002686 return clang_getNullLocation();
Douglas Gregor42748ec2010-04-30 19:45:53 +00002687
Douglas Gregor86a4d0d2011-02-03 17:17:35 +00002688 bool Logging = ::getenv("LIBCLANG_LOGGING");
Ted Kremeneka60ed472010-11-16 08:15:36 +00002689 ASTUnit *CXXUnit = static_cast<ASTUnit *>(tu->TUData);
Douglas Gregor86a4d0d2011-02-03 17:17:35 +00002690 const FileEntry *File = static_cast<const FileEntry *>(file);
Douglas Gregorb9790342010-01-22 21:44:22 +00002691 SourceLocation SLoc
Douglas Gregor86a4d0d2011-02-03 17:17:35 +00002692 = CXXUnit->getSourceManager().getLocation(File, line, column);
2693 if (SLoc.isInvalid()) {
2694 if (Logging)
2695 llvm::errs() << "clang_getLocation(\"" << File->getName()
2696 << "\", " << line << ", " << column << ") = invalid\n";
2697 return clang_getNullLocation();
2698 }
2699
2700 if (Logging)
2701 llvm::errs() << "clang_getLocation(\"" << File->getName()
2702 << "\", " << line << ", " << column << ") = "
2703 << SLoc.getRawEncoding() << "\n";
David Chisnall83889a72010-10-15 17:07:39 +00002704
2705 return cxloc::translateSourceLocation(CXXUnit->getASTContext(), SLoc);
2706}
2707
2708CXSourceLocation clang_getLocationForOffset(CXTranslationUnit tu,
2709 CXFile file,
2710 unsigned offset) {
2711 if (!tu || !file)
2712 return clang_getNullLocation();
2713
Ted Kremeneka60ed472010-11-16 08:15:36 +00002714 ASTUnit *CXXUnit = static_cast<ASTUnit *>(tu->TUData);
David Chisnall83889a72010-10-15 17:07:39 +00002715 SourceLocation Start
2716 = CXXUnit->getSourceManager().getLocation(
2717 static_cast<const FileEntry *>(file),
2718 1, 1);
2719 if (Start.isInvalid()) return clang_getNullLocation();
2720
2721 SourceLocation SLoc = Start.getFileLocWithOffset(offset);
2722
2723 if (SLoc.isInvalid()) return clang_getNullLocation();
Ted Kremenekf0e23e82010-02-17 00:41:40 +00002724
Ted Kremenek1a9a0bc2010-06-28 23:54:17 +00002725 return cxloc::translateSourceLocation(CXXUnit->getASTContext(), SLoc);
Douglas Gregorb9790342010-01-22 21:44:22 +00002726}
2727
Douglas Gregor5352ac02010-01-28 00:27:43 +00002728CXSourceRange clang_getNullRange() {
2729 CXSourceRange Result = { { 0, 0 }, 0, 0 };
2730 return Result;
2731}
Daniel Dunbard52864b2010-02-14 10:02:57 +00002732
Douglas Gregor5352ac02010-01-28 00:27:43 +00002733CXSourceRange clang_getRange(CXSourceLocation begin, CXSourceLocation end) {
2734 if (begin.ptr_data[0] != end.ptr_data[0] ||
2735 begin.ptr_data[1] != end.ptr_data[1])
2736 return clang_getNullRange();
Ted Kremenekf0e23e82010-02-17 00:41:40 +00002737
2738 CXSourceRange Result = { { begin.ptr_data[0], begin.ptr_data[1] },
Douglas Gregor5352ac02010-01-28 00:27:43 +00002739 begin.int_data, end.int_data };
Douglas Gregorb9790342010-01-22 21:44:22 +00002740 return Result;
2741}
Ted Kremenek9d5a1652011-03-23 02:16:44 +00002742} // end: extern "C"
Douglas Gregorb9790342010-01-22 21:44:22 +00002743
Ted Kremenek9d5a1652011-03-23 02:16:44 +00002744static void createNullLocation(CXFile *file, unsigned *line,
2745 unsigned *column, unsigned *offset) {
2746 if (file)
2747 *file = 0;
2748 if (line)
2749 *line = 0;
2750 if (column)
2751 *column = 0;
2752 if (offset)
2753 *offset = 0;
2754 return;
2755}
2756
2757extern "C" {
Douglas Gregor46766dc2010-01-26 19:19:08 +00002758void clang_getInstantiationLocation(CXSourceLocation location,
2759 CXFile *file,
2760 unsigned *line,
2761 unsigned *column,
2762 unsigned *offset) {
Douglas Gregor1db19de2010-01-19 21:36:55 +00002763 SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data);
2764
Daniel Dunbarbb4a61a2010-02-14 01:47:36 +00002765 if (!location.ptr_data[0] || Loc.isInvalid()) {
Ted Kremenek9d5a1652011-03-23 02:16:44 +00002766 createNullLocation(file, line, column, offset);
Douglas Gregor46766dc2010-01-26 19:19:08 +00002767 return;
2768 }
2769
Daniel Dunbarbb4a61a2010-02-14 01:47:36 +00002770 const SourceManager &SM =
2771 *static_cast<const SourceManager*>(location.ptr_data[0]);
Douglas Gregor1db19de2010-01-19 21:36:55 +00002772 SourceLocation InstLoc = SM.getInstantiationLoc(Loc);
Douglas Gregor1db19de2010-01-19 21:36:55 +00002773
Ted Kremenek9d5a1652011-03-23 02:16:44 +00002774 // Check that the FileID is invalid on the instantiation location.
2775 // This can manifest in invalid code.
2776 FileID fileID = SM.getFileID(InstLoc);
Douglas Gregore23ac652011-04-20 00:21:03 +00002777 bool Invalid = false;
2778 const SrcMgr::SLocEntry &sloc = SM.getSLocEntry(fileID, &Invalid);
2779 if (!sloc.isFile() || Invalid) {
Ted Kremenek9d5a1652011-03-23 02:16:44 +00002780 createNullLocation(file, line, column, offset);
2781 return;
2782 }
2783
Douglas Gregor1db19de2010-01-19 21:36:55 +00002784 if (file)
Ted Kremenek9d5a1652011-03-23 02:16:44 +00002785 *file = (void *)SM.getFileEntryForSLocEntry(sloc);
Douglas Gregor1db19de2010-01-19 21:36:55 +00002786 if (line)
2787 *line = SM.getInstantiationLineNumber(InstLoc);
2788 if (column)
2789 *column = SM.getInstantiationColumnNumber(InstLoc);
Douglas Gregore69517c2010-01-26 03:07:15 +00002790 if (offset)
Douglas Gregor46766dc2010-01-26 19:19:08 +00002791 *offset = SM.getDecomposedLoc(InstLoc).second;
Douglas Gregore69517c2010-01-26 03:07:15 +00002792}
2793
Douglas Gregora9b06d42010-11-09 06:24:54 +00002794void clang_getSpellingLocation(CXSourceLocation location,
2795 CXFile *file,
2796 unsigned *line,
2797 unsigned *column,
2798 unsigned *offset) {
2799 SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data);
2800
2801 if (!location.ptr_data[0] || Loc.isInvalid()) {
2802 if (file)
2803 *file = 0;
2804 if (line)
2805 *line = 0;
2806 if (column)
2807 *column = 0;
2808 if (offset)
2809 *offset = 0;
2810 return;
2811 }
2812
2813 const SourceManager &SM =
2814 *static_cast<const SourceManager*>(location.ptr_data[0]);
2815 SourceLocation SpellLoc = Loc;
2816 if (SpellLoc.isMacroID()) {
2817 SourceLocation SimpleSpellingLoc = SM.getImmediateSpellingLoc(SpellLoc);
2818 if (SimpleSpellingLoc.isFileID() &&
2819 SM.getFileEntryForID(SM.getDecomposedLoc(SimpleSpellingLoc).first))
2820 SpellLoc = SimpleSpellingLoc;
2821 else
2822 SpellLoc = SM.getInstantiationLoc(SpellLoc);
2823 }
2824
2825 std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(SpellLoc);
2826 FileID FID = LocInfo.first;
2827 unsigned FileOffset = LocInfo.second;
2828
2829 if (file)
2830 *file = (void *)SM.getFileEntryForID(FID);
2831 if (line)
2832 *line = SM.getLineNumber(FID, FileOffset);
2833 if (column)
2834 *column = SM.getColumnNumber(FID, FileOffset);
2835 if (offset)
2836 *offset = FileOffset;
2837}
2838
Douglas Gregor1db19de2010-01-19 21:36:55 +00002839CXSourceLocation clang_getRangeStart(CXSourceRange range) {
Ted Kremenekf0e23e82010-02-17 00:41:40 +00002840 CXSourceLocation Result = { { range.ptr_data[0], range.ptr_data[1] },
Douglas Gregor5352ac02010-01-28 00:27:43 +00002841 range.begin_int_data };
Douglas Gregor1db19de2010-01-19 21:36:55 +00002842 return Result;
2843}
2844
2845CXSourceLocation clang_getRangeEnd(CXSourceRange range) {
Daniel Dunbarbb4a61a2010-02-14 01:47:36 +00002846 CXSourceLocation Result = { { range.ptr_data[0], range.ptr_data[1] },
Douglas Gregor5352ac02010-01-28 00:27:43 +00002847 range.end_int_data };
Douglas Gregor1db19de2010-01-19 21:36:55 +00002848 return Result;
2849}
2850
Douglas Gregorb9790342010-01-22 21:44:22 +00002851} // end: extern "C"
2852
Douglas Gregor1db19de2010-01-19 21:36:55 +00002853//===----------------------------------------------------------------------===//
Ted Kremenekfb480492010-01-13 21:46:36 +00002854// CXFile Operations.
2855//===----------------------------------------------------------------------===//
2856
2857extern "C" {
Ted Kremenek74844072010-02-17 00:41:20 +00002858CXString clang_getFileName(CXFile SFile) {
Douglas Gregor98258af2010-01-18 22:46:11 +00002859 if (!SFile)
Ted Kremeneka60ed472010-11-16 08:15:36 +00002860 return createCXString((const char*)NULL);
Ted Kremenekf0e23e82010-02-17 00:41:40 +00002861
Steve Naroff88145032009-10-27 14:35:18 +00002862 FileEntry *FEnt = static_cast<FileEntry *>(SFile);
Ted Kremenek74844072010-02-17 00:41:20 +00002863 return createCXString(FEnt->getName());
Steve Naroff88145032009-10-27 14:35:18 +00002864}
2865
2866time_t clang_getFileTime(CXFile SFile) {
Douglas Gregor98258af2010-01-18 22:46:11 +00002867 if (!SFile)
2868 return 0;
Ted Kremenekf0e23e82010-02-17 00:41:40 +00002869
Steve Naroff88145032009-10-27 14:35:18 +00002870 FileEntry *FEnt = static_cast<FileEntry *>(SFile);
2871 return FEnt->getModificationTime();
Steve Naroffee9405e2009-09-25 21:45:39 +00002872}
Ted Kremenekf0e23e82010-02-17 00:41:40 +00002873
Douglas Gregorb9790342010-01-22 21:44:22 +00002874CXFile clang_getFile(CXTranslationUnit tu, const char *file_name) {
2875 if (!tu)
2876 return 0;
Ted Kremenekf0e23e82010-02-17 00:41:40 +00002877
Ted Kremeneka60ed472010-11-16 08:15:36 +00002878 ASTUnit *CXXUnit = static_cast<ASTUnit *>(tu->TUData);
Ted Kremenekf0e23e82010-02-17 00:41:40 +00002879
Douglas Gregorb9790342010-01-22 21:44:22 +00002880 FileManager &FMgr = CXXUnit->getFileManager();
Chris Lattner39b49bc2010-11-23 08:35:12 +00002881 return const_cast<FileEntry *>(FMgr.getFile(file_name));
Douglas Gregorb9790342010-01-22 21:44:22 +00002882}
Ted Kremenekf0e23e82010-02-17 00:41:40 +00002883
Ted Kremenekfb480492010-01-13 21:46:36 +00002884} // end: extern "C"
Steve Naroffee9405e2009-09-25 21:45:39 +00002885
Ted Kremenekfb480492010-01-13 21:46:36 +00002886//===----------------------------------------------------------------------===//
2887// CXCursor Operations.
2888//===----------------------------------------------------------------------===//
2889
Ted Kremenekfb480492010-01-13 21:46:36 +00002890static Decl *getDeclFromExpr(Stmt *E) {
Douglas Gregordb1314e2010-10-01 21:11:22 +00002891 if (CastExpr *CE = dyn_cast<CastExpr>(E))
2892 return getDeclFromExpr(CE->getSubExpr());
2893
Ted Kremenekfb480492010-01-13 21:46:36 +00002894 if (DeclRefExpr *RefExpr = dyn_cast<DeclRefExpr>(E))
2895 return RefExpr->getDecl();
Douglas Gregor38f28c12010-10-22 22:24:08 +00002896 if (BlockDeclRefExpr *RefExpr = dyn_cast<BlockDeclRefExpr>(E))
2897 return RefExpr->getDecl();
Ted Kremenekfb480492010-01-13 21:46:36 +00002898 if (MemberExpr *ME = dyn_cast<MemberExpr>(E))
2899 return ME->getMemberDecl();
2900 if (ObjCIvarRefExpr *RE = dyn_cast<ObjCIvarRefExpr>(E))
2901 return RE->getDecl();
Douglas Gregordb1314e2010-10-01 21:11:22 +00002902 if (ObjCPropertyRefExpr *PRE = dyn_cast<ObjCPropertyRefExpr>(E))
John McCall12f78a62010-12-02 01:19:52 +00002903 return PRE->isExplicitProperty() ? PRE->getExplicitProperty() : 0;
Douglas Gregordb1314e2010-10-01 21:11:22 +00002904
Ted Kremenekfb480492010-01-13 21:46:36 +00002905 if (CallExpr *CE = dyn_cast<CallExpr>(E))
2906 return getDeclFromExpr(CE->getCallee());
Douglas Gregor93798e22010-11-05 21:11:19 +00002907 if (CXXConstructExpr *CE = llvm::dyn_cast<CXXConstructExpr>(E))
2908 if (!CE->isElidable())
2909 return CE->getConstructor();
Ted Kremenekfb480492010-01-13 21:46:36 +00002910 if (ObjCMessageExpr *OME = dyn_cast<ObjCMessageExpr>(E))
2911 return OME->getMethodDecl();
Ted Kremenekf0e23e82010-02-17 00:41:40 +00002912
Douglas Gregordb1314e2010-10-01 21:11:22 +00002913 if (ObjCProtocolExpr *PE = dyn_cast<ObjCProtocolExpr>(E))
2914 return PE->getProtocol();
Douglas Gregorc7793c72011-01-15 01:15:58 +00002915 if (SubstNonTypeTemplateParmPackExpr *NTTP
2916 = dyn_cast<SubstNonTypeTemplateParmPackExpr>(E))
2917 return NTTP->getParameterPack();
Douglas Gregor94d96292011-01-19 20:34:17 +00002918 if (SizeOfPackExpr *SizeOfPack = dyn_cast<SizeOfPackExpr>(E))
2919 if (isa<NonTypeTemplateParmDecl>(SizeOfPack->getPack()) ||
2920 isa<ParmVarDecl>(SizeOfPack->getPack()))
2921 return SizeOfPack->getPack();
Douglas Gregordb1314e2010-10-01 21:11:22 +00002922
Ted Kremenekfb480492010-01-13 21:46:36 +00002923 return 0;
2924}
2925
Daniel Dunbarc29f4c32010-02-02 05:00:22 +00002926static SourceLocation getLocationFromExpr(Expr *E) {
2927 if (ObjCMessageExpr *Msg = dyn_cast<ObjCMessageExpr>(E))
2928 return /*FIXME:*/Msg->getLeftLoc();
2929 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
2930 return DRE->getLocation();
Douglas Gregor38f28c12010-10-22 22:24:08 +00002931 if (BlockDeclRefExpr *RefExpr = dyn_cast<BlockDeclRefExpr>(E))
2932 return RefExpr->getLocation();
Daniel Dunbarc29f4c32010-02-02 05:00:22 +00002933 if (MemberExpr *Member = dyn_cast<MemberExpr>(E))
2934 return Member->getMemberLoc();
2935 if (ObjCIvarRefExpr *Ivar = dyn_cast<ObjCIvarRefExpr>(E))
2936 return Ivar->getLocation();
Douglas Gregor94d96292011-01-19 20:34:17 +00002937 if (SizeOfPackExpr *SizeOfPack = dyn_cast<SizeOfPackExpr>(E))
2938 return SizeOfPack->getPackLoc();
2939
Daniel Dunbarc29f4c32010-02-02 05:00:22 +00002940 return E->getLocStart();
2941}
2942
Ted Kremenekfb480492010-01-13 21:46:36 +00002943extern "C" {
Ted Kremenekf0e23e82010-02-17 00:41:40 +00002944
2945unsigned clang_visitChildren(CXCursor parent,
Douglas Gregorb1373d02010-01-20 20:59:29 +00002946 CXCursorVisitor visitor,
2947 CXClientData client_data) {
Ted Kremeneka60ed472010-11-16 08:15:36 +00002948 CursorVisitor CursorVis(getCursorTU(parent), visitor, client_data,
Douglas Gregor04a9eb32011-03-16 23:23:30 +00002949 getCursorASTUnit(parent)->getMaxPCHLevel(),
2950 false);
Douglas Gregorb1373d02010-01-20 20:59:29 +00002951 return CursorVis.VisitChildren(parent);
2952}
2953
David Chisnall3387c652010-11-03 14:12:26 +00002954#ifndef __has_feature
2955#define __has_feature(x) 0
2956#endif
2957#if __has_feature(blocks)
2958typedef enum CXChildVisitResult
2959 (^CXCursorVisitorBlock)(CXCursor cursor, CXCursor parent);
2960
2961static enum CXChildVisitResult visitWithBlock(CXCursor cursor, CXCursor parent,
2962 CXClientData client_data) {
2963 CXCursorVisitorBlock block = (CXCursorVisitorBlock)client_data;
2964 return block(cursor, parent);
2965}
2966#else
2967// If we are compiled with a compiler that doesn't have native blocks support,
2968// define and call the block manually, so the
2969typedef struct _CXChildVisitResult
2970{
2971 void *isa;
2972 int flags;
2973 int reserved;
Daniel Dunbar9e1ebdd2010-11-05 07:19:21 +00002974 enum CXChildVisitResult(*invoke)(struct _CXChildVisitResult*, CXCursor,
2975 CXCursor);
David Chisnall3387c652010-11-03 14:12:26 +00002976} *CXCursorVisitorBlock;
2977
2978static enum CXChildVisitResult visitWithBlock(CXCursor cursor, CXCursor parent,
2979 CXClientData client_data) {
2980 CXCursorVisitorBlock block = (CXCursorVisitorBlock)client_data;
2981 return block->invoke(block, cursor, parent);
2982}
2983#endif
2984
2985
Daniel Dunbar9e1ebdd2010-11-05 07:19:21 +00002986unsigned clang_visitChildrenWithBlock(CXCursor parent,
2987 CXCursorVisitorBlock block) {
David Chisnall3387c652010-11-03 14:12:26 +00002988 return clang_visitChildren(parent, visitWithBlock, block);
2989}
2990
Douglas Gregor78205d42010-01-20 21:45:58 +00002991static CXString getDeclSpelling(Decl *D) {
2992 NamedDecl *ND = dyn_cast_or_null<NamedDecl>(D);
Douglas Gregore3c60a72010-11-17 00:13:31 +00002993 if (!ND) {
2994 if (ObjCPropertyImplDecl *PropImpl =llvm::dyn_cast<ObjCPropertyImplDecl>(D))
2995 if (ObjCPropertyDecl *Property = PropImpl->getPropertyDecl())
2996 return createCXString(Property->getIdentifier()->getName());
2997
Ted Kremenekee4db4f2010-02-17 00:41:08 +00002998 return createCXString("");
Douglas Gregore3c60a72010-11-17 00:13:31 +00002999 }
3000
Douglas Gregor78205d42010-01-20 21:45:58 +00003001 if (ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(ND))
Ted Kremenekee4db4f2010-02-17 00:41:08 +00003002 return createCXString(OMD->getSelector().getAsString());
Ted Kremenekf0e23e82010-02-17 00:41:40 +00003003
Douglas Gregor78205d42010-01-20 21:45:58 +00003004 if (ObjCCategoryImplDecl *CIMP = dyn_cast<ObjCCategoryImplDecl>(ND))
3005 // No, this isn't the same as the code below. getIdentifier() is non-virtual
3006 // and returns different names. NamedDecl returns the class name and
3007 // ObjCCategoryImplDecl returns the category name.
Ted Kremenekee4db4f2010-02-17 00:41:08 +00003008 return createCXString(CIMP->getIdentifier()->getNameStart());
Ted Kremenekf0e23e82010-02-17 00:41:40 +00003009
Douglas Gregor0a35bce2010-09-01 03:07:18 +00003010 if (isa<UsingDirectiveDecl>(D))
3011 return createCXString("");
3012
Ted Kremenek50aa6ac2010-05-19 21:51:10 +00003013 llvm::SmallString<1024> S;
3014 llvm::raw_svector_ostream os(S);
3015 ND->printName(os);
3016
3017 return createCXString(os.str());
Douglas Gregor78205d42010-01-20 21:45:58 +00003018}
Ted Kremenekf0e23e82010-02-17 00:41:40 +00003019
Daniel Dunbar9ebfa312009-12-01 03:14:51 +00003020CXString clang_getCursorSpelling(CXCursor C) {
Douglas Gregor7eaa8ae2010-01-20 00:23:15 +00003021 if (clang_isTranslationUnit(C.kind))
Ted Kremeneka60ed472010-11-16 08:15:36 +00003022 return clang_getTranslationUnitSpelling(
3023 static_cast<CXTranslationUnit>(C.data[2]));
Douglas Gregor7eaa8ae2010-01-20 00:23:15 +00003024
Steve Narofff334b4e2009-09-02 18:26:48 +00003025 if (clang_isReference(C.kind)) {
3026 switch (C.kind) {
Daniel Dunbaracca7252009-11-30 20:42:49 +00003027 case CXCursor_ObjCSuperClassRef: {
Douglas Gregor2e331b92010-01-16 14:00:32 +00003028 ObjCInterfaceDecl *Super = getCursorObjCSuperClassRef(C).first;
Ted Kremenekee4db4f2010-02-17 00:41:08 +00003029 return createCXString(Super->getIdentifier()->getNameStart());
Daniel Dunbaracca7252009-11-30 20:42:49 +00003030 }
3031 case CXCursor_ObjCClassRef: {
Douglas Gregor1adb0822010-01-16 17:14:40 +00003032 ObjCInterfaceDecl *Class = getCursorObjCClassRef(C).first;
Ted Kremenekee4db4f2010-02-17 00:41:08 +00003033 return createCXString(Class->getIdentifier()->getNameStart());
Daniel Dunbaracca7252009-11-30 20:42:49 +00003034 }
3035 case CXCursor_ObjCProtocolRef: {
Douglas Gregor78db0cd2010-01-16 15:44:18 +00003036 ObjCProtocolDecl *OID = getCursorObjCProtocolRef(C).first;
Douglas Gregorf46034a2010-01-18 23:41:10 +00003037 assert(OID && "getCursorSpelling(): Missing protocol decl");
Ted Kremenekee4db4f2010-02-17 00:41:08 +00003038 return createCXString(OID->getIdentifier()->getNameStart());
Daniel Dunbaracca7252009-11-30 20:42:49 +00003039 }
Ted Kremenek3064ef92010-08-27 21:34:58 +00003040 case CXCursor_CXXBaseSpecifier: {
3041 CXXBaseSpecifier *B = getCursorCXXBaseSpecifier(C);
3042 return createCXString(B->getType().getAsString());
3043 }
Douglas Gregor7d0d40e2010-01-21 16:28:34 +00003044 case CXCursor_TypeRef: {
3045 TypeDecl *Type = getCursorTypeRef(C).first;
3046 assert(Type && "Missing type decl");
3047
Ted Kremenekee4db4f2010-02-17 00:41:08 +00003048 return createCXString(getCursorContext(C).getTypeDeclType(Type).
3049 getAsString());
Douglas Gregor7d0d40e2010-01-21 16:28:34 +00003050 }
Douglas Gregor0b36e612010-08-31 20:37:03 +00003051 case CXCursor_TemplateRef: {
3052 TemplateDecl *Template = getCursorTemplateRef(C).first;
Douglas Gregor69319002010-08-31 23:48:11 +00003053 assert(Template && "Missing template decl");
Douglas Gregor0b36e612010-08-31 20:37:03 +00003054
3055 return createCXString(Template->getNameAsString());
3056 }
Douglas Gregor69319002010-08-31 23:48:11 +00003057
3058 case CXCursor_NamespaceRef: {
3059 NamedDecl *NS = getCursorNamespaceRef(C).first;
3060 assert(NS && "Missing namespace decl");
3061
3062 return createCXString(NS->getNameAsString());
3063 }
Douglas Gregor7d0d40e2010-01-21 16:28:34 +00003064
Douglas Gregora67e03f2010-09-09 21:42:20 +00003065 case CXCursor_MemberRef: {
3066 FieldDecl *Field = getCursorMemberRef(C).first;
3067 assert(Field && "Missing member decl");
3068
3069 return createCXString(Field->getNameAsString());
3070 }
3071
Douglas Gregor36897b02010-09-10 00:22:18 +00003072 case CXCursor_LabelRef: {
3073 LabelStmt *Label = getCursorLabelRef(C).first;
3074 assert(Label && "Missing label");
3075
Chris Lattnerad8dcf42011-02-17 07:39:24 +00003076 return createCXString(Label->getName());
Douglas Gregor36897b02010-09-10 00:22:18 +00003077 }
3078
Douglas Gregor1f60d9e2010-09-13 22:52:57 +00003079 case CXCursor_OverloadedDeclRef: {
3080 OverloadedDeclRefStorage Storage = getCursorOverloadedDeclRef(C).first;
3081 if (Decl *D = Storage.dyn_cast<Decl *>()) {
3082 if (NamedDecl *ND = dyn_cast<NamedDecl>(D))
3083 return createCXString(ND->getNameAsString());
3084 return createCXString("");
3085 }
3086 if (OverloadExpr *E = Storage.dyn_cast<OverloadExpr *>())
3087 return createCXString(E->getName().getAsString());
3088 OverloadedTemplateStorage *Ovl
3089 = Storage.get<OverloadedTemplateStorage*>();
3090 if (Ovl->size() == 0)
3091 return createCXString("");
3092 return createCXString((*Ovl->begin())->getNameAsString());
3093 }
3094
Daniel Dunbaracca7252009-11-30 20:42:49 +00003095 default:
Ted Kremenekee4db4f2010-02-17 00:41:08 +00003096 return createCXString("<not implemented>");
Steve Narofff334b4e2009-09-02 18:26:48 +00003097 }
3098 }
Douglas Gregor97b98722010-01-19 23:20:36 +00003099
3100 if (clang_isExpression(C.kind)) {
3101 Decl *D = getDeclFromExpr(getCursorExpr(C));
3102 if (D)
Douglas Gregor78205d42010-01-20 21:45:58 +00003103 return getDeclSpelling(D);
Ted Kremenekee4db4f2010-02-17 00:41:08 +00003104 return createCXString("");
Douglas Gregor97b98722010-01-19 23:20:36 +00003105 }
3106
Douglas Gregor36897b02010-09-10 00:22:18 +00003107 if (clang_isStatement(C.kind)) {
3108 Stmt *S = getCursorStmt(C);
3109 if (LabelStmt *Label = dyn_cast_or_null<LabelStmt>(S))
Chris Lattnerad8dcf42011-02-17 07:39:24 +00003110 return createCXString(Label->getName());
Douglas Gregor36897b02010-09-10 00:22:18 +00003111
3112 return createCXString("");
3113 }
3114
Douglas Gregor4ae8f292010-03-18 17:52:52 +00003115 if (C.kind == CXCursor_MacroInstantiation)
3116 return createCXString(getCursorMacroInstantiation(C)->getName()
3117 ->getNameStart());
3118
Douglas Gregor572feb22010-03-18 18:04:21 +00003119 if (C.kind == CXCursor_MacroDefinition)
3120 return createCXString(getCursorMacroDefinition(C)->getName()
3121 ->getNameStart());
3122
Douglas Gregorecdcb882010-10-20 22:00:55 +00003123 if (C.kind == CXCursor_InclusionDirective)
3124 return createCXString(getCursorInclusionDirective(C)->getFileName());
3125
Douglas Gregor60cbfac2010-01-25 16:56:17 +00003126 if (clang_isDeclaration(C.kind))
3127 return getDeclSpelling(getCursorDecl(C));
Ted Kremeneke68fff62010-02-17 00:41:32 +00003128
Ted Kremenekee4db4f2010-02-17 00:41:08 +00003129 return createCXString("");
Steve Narofff334b4e2009-09-02 18:26:48 +00003130}
3131
Douglas Gregor358559d2010-10-02 22:49:11 +00003132CXString clang_getCursorDisplayName(CXCursor C) {
3133 if (!clang_isDeclaration(C.kind))
3134 return clang_getCursorSpelling(C);
3135
3136 Decl *D = getCursorDecl(C);
3137 if (!D)
3138 return createCXString("");
3139
3140 PrintingPolicy &Policy = getCursorContext(C).PrintingPolicy;
3141 if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(D))
3142 D = FunTmpl->getTemplatedDecl();
3143
3144 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
3145 llvm::SmallString<64> Str;
3146 llvm::raw_svector_ostream OS(Str);
3147 OS << Function->getNameAsString();
3148 if (Function->getPrimaryTemplate())
3149 OS << "<>";
3150 OS << "(";
3151 for (unsigned I = 0, N = Function->getNumParams(); I != N; ++I) {
3152 if (I)
3153 OS << ", ";
3154 OS << Function->getParamDecl(I)->getType().getAsString(Policy);
3155 }
3156
3157 if (Function->isVariadic()) {
3158 if (Function->getNumParams())
3159 OS << ", ";
3160 OS << "...";
3161 }
3162 OS << ")";
3163 return createCXString(OS.str());
3164 }
3165
3166 if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(D)) {
3167 llvm::SmallString<64> Str;
3168 llvm::raw_svector_ostream OS(Str);
3169 OS << ClassTemplate->getNameAsString();
3170 OS << "<";
3171 TemplateParameterList *Params = ClassTemplate->getTemplateParameters();
3172 for (unsigned I = 0, N = Params->size(); I != N; ++I) {
3173 if (I)
3174 OS << ", ";
3175
3176 NamedDecl *Param = Params->getParam(I);
3177 if (Param->getIdentifier()) {
3178 OS << Param->getIdentifier()->getName();
3179 continue;
3180 }
3181
3182 // There is no parameter name, which makes this tricky. Try to come up
3183 // with something useful that isn't too long.
3184 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
3185 OS << (TTP->wasDeclaredWithTypename()? "typename" : "class");
3186 else if (NonTypeTemplateParmDecl *NTTP
3187 = dyn_cast<NonTypeTemplateParmDecl>(Param))
3188 OS << NTTP->getType().getAsString(Policy);
3189 else
3190 OS << "template<...> class";
3191 }
3192
3193 OS << ">";
3194 return createCXString(OS.str());
3195 }
3196
3197 if (ClassTemplateSpecializationDecl *ClassSpec
3198 = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
3199 // If the type was explicitly written, use that.
3200 if (TypeSourceInfo *TSInfo = ClassSpec->getTypeAsWritten())
3201 return createCXString(TSInfo->getType().getAsString(Policy));
3202
3203 llvm::SmallString<64> Str;
3204 llvm::raw_svector_ostream OS(Str);
3205 OS << ClassSpec->getNameAsString();
3206 OS << TemplateSpecializationType::PrintTemplateArgumentList(
Douglas Gregor910f8002010-11-07 23:05:16 +00003207 ClassSpec->getTemplateArgs().data(),
3208 ClassSpec->getTemplateArgs().size(),
Douglas Gregor358559d2010-10-02 22:49:11 +00003209 Policy);
3210 return createCXString(OS.str());
3211 }
3212
3213 return clang_getCursorSpelling(C);
3214}
3215
Ted Kremeneke68fff62010-02-17 00:41:32 +00003216CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) {
Steve Naroff89922f82009-08-31 00:59:03 +00003217 switch (Kind) {
Ted Kremeneke68fff62010-02-17 00:41:32 +00003218 case CXCursor_FunctionDecl:
3219 return createCXString("FunctionDecl");
3220 case CXCursor_TypedefDecl:
3221 return createCXString("TypedefDecl");
3222 case CXCursor_EnumDecl:
3223 return createCXString("EnumDecl");
3224 case CXCursor_EnumConstantDecl:
3225 return createCXString("EnumConstantDecl");
3226 case CXCursor_StructDecl:
3227 return createCXString("StructDecl");
3228 case CXCursor_UnionDecl:
3229 return createCXString("UnionDecl");
3230 case CXCursor_ClassDecl:
3231 return createCXString("ClassDecl");
3232 case CXCursor_FieldDecl:
3233 return createCXString("FieldDecl");
3234 case CXCursor_VarDecl:
3235 return createCXString("VarDecl");
3236 case CXCursor_ParmDecl:
3237 return createCXString("ParmDecl");
3238 case CXCursor_ObjCInterfaceDecl:
3239 return createCXString("ObjCInterfaceDecl");
3240 case CXCursor_ObjCCategoryDecl:
3241 return createCXString("ObjCCategoryDecl");
3242 case CXCursor_ObjCProtocolDecl:
3243 return createCXString("ObjCProtocolDecl");
3244 case CXCursor_ObjCPropertyDecl:
3245 return createCXString("ObjCPropertyDecl");
3246 case CXCursor_ObjCIvarDecl:
3247 return createCXString("ObjCIvarDecl");
3248 case CXCursor_ObjCInstanceMethodDecl:
3249 return createCXString("ObjCInstanceMethodDecl");
3250 case CXCursor_ObjCClassMethodDecl:
3251 return createCXString("ObjCClassMethodDecl");
3252 case CXCursor_ObjCImplementationDecl:
3253 return createCXString("ObjCImplementationDecl");
3254 case CXCursor_ObjCCategoryImplDecl:
3255 return createCXString("ObjCCategoryImplDecl");
Ted Kremenek8bd5a692010-04-13 23:39:06 +00003256 case CXCursor_CXXMethod:
3257 return createCXString("CXXMethod");
Ted Kremeneke68fff62010-02-17 00:41:32 +00003258 case CXCursor_UnexposedDecl:
3259 return createCXString("UnexposedDecl");
3260 case CXCursor_ObjCSuperClassRef:
3261 return createCXString("ObjCSuperClassRef");
3262 case CXCursor_ObjCProtocolRef:
3263 return createCXString("ObjCProtocolRef");
3264 case CXCursor_ObjCClassRef:
3265 return createCXString("ObjCClassRef");
3266 case CXCursor_TypeRef:
3267 return createCXString("TypeRef");
Douglas Gregor0b36e612010-08-31 20:37:03 +00003268 case CXCursor_TemplateRef:
3269 return createCXString("TemplateRef");
Douglas Gregor69319002010-08-31 23:48:11 +00003270 case CXCursor_NamespaceRef:
3271 return createCXString("NamespaceRef");
Douglas Gregora67e03f2010-09-09 21:42:20 +00003272 case CXCursor_MemberRef:
3273 return createCXString("MemberRef");
Douglas Gregor36897b02010-09-10 00:22:18 +00003274 case CXCursor_LabelRef:
3275 return createCXString("LabelRef");
Douglas Gregor1f60d9e2010-09-13 22:52:57 +00003276 case CXCursor_OverloadedDeclRef:
3277 return createCXString("OverloadedDeclRef");
Ted Kremeneke68fff62010-02-17 00:41:32 +00003278 case CXCursor_UnexposedExpr:
3279 return createCXString("UnexposedExpr");
Ted Kremenek1ee6cad2010-04-11 21:47:37 +00003280 case CXCursor_BlockExpr:
3281 return createCXString("BlockExpr");
Ted Kremeneke68fff62010-02-17 00:41:32 +00003282 case CXCursor_DeclRefExpr:
3283 return createCXString("DeclRefExpr");
3284 case CXCursor_MemberRefExpr:
3285 return createCXString("MemberRefExpr");
3286 case CXCursor_CallExpr:
3287 return createCXString("CallExpr");
3288 case CXCursor_ObjCMessageExpr:
3289 return createCXString("ObjCMessageExpr");
3290 case CXCursor_UnexposedStmt:
3291 return createCXString("UnexposedStmt");
Douglas Gregor36897b02010-09-10 00:22:18 +00003292 case CXCursor_LabelStmt:
3293 return createCXString("LabelStmt");
Ted Kremeneke68fff62010-02-17 00:41:32 +00003294 case CXCursor_InvalidFile:
3295 return createCXString("InvalidFile");
Ted Kremenek292db642010-03-19 20:39:05 +00003296 case CXCursor_InvalidCode:
3297 return createCXString("InvalidCode");
Ted Kremeneke68fff62010-02-17 00:41:32 +00003298 case CXCursor_NoDeclFound:
3299 return createCXString("NoDeclFound");
3300 case CXCursor_NotImplemented:
3301 return createCXString("NotImplemented");
3302 case CXCursor_TranslationUnit:
3303 return createCXString("TranslationUnit");
Ted Kremeneke77f4432010-02-18 03:09:07 +00003304 case CXCursor_UnexposedAttr:
3305 return createCXString("UnexposedAttr");
3306 case CXCursor_IBActionAttr:
3307 return createCXString("attribute(ibaction)");
Douglas Gregor9f1e3ff2010-03-18 00:42:48 +00003308 case CXCursor_IBOutletAttr:
3309 return createCXString("attribute(iboutlet)");
Ted Kremenek857e9182010-05-19 17:38:06 +00003310 case CXCursor_IBOutletCollectionAttr:
3311 return createCXString("attribute(iboutletcollection)");
Douglas Gregor9f1e3ff2010-03-18 00:42:48 +00003312 case CXCursor_PreprocessingDirective:
3313 return createCXString("preprocessing directive");
Douglas Gregor572feb22010-03-18 18:04:21 +00003314 case CXCursor_MacroDefinition:
3315 return createCXString("macro definition");
Douglas Gregor48072312010-03-18 15:23:44 +00003316 case CXCursor_MacroInstantiation:
3317 return createCXString("macro instantiation");
Douglas Gregorecdcb882010-10-20 22:00:55 +00003318 case CXCursor_InclusionDirective:
3319 return createCXString("inclusion directive");
Ted Kremenek8f06e0e2010-05-06 23:38:21 +00003320 case CXCursor_Namespace:
3321 return createCXString("Namespace");
Ted Kremeneka0536d82010-05-07 01:04:29 +00003322 case CXCursor_LinkageSpec:
3323 return createCXString("LinkageSpec");
Ted Kremenek3064ef92010-08-27 21:34:58 +00003324 case CXCursor_CXXBaseSpecifier:
3325 return createCXString("C++ base class specifier");
Douglas Gregor01829d32010-08-31 14:41:23 +00003326 case CXCursor_Constructor:
3327 return createCXString("CXXConstructor");
3328 case CXCursor_Destructor:
3329 return createCXString("CXXDestructor");
3330 case CXCursor_ConversionFunction:
3331 return createCXString("CXXConversion");
Douglas Gregorfe72e9c2010-08-31 17:01:39 +00003332 case CXCursor_TemplateTypeParameter:
3333 return createCXString("TemplateTypeParameter");
3334 case CXCursor_NonTypeTemplateParameter:
3335 return createCXString("NonTypeTemplateParameter");
3336 case CXCursor_TemplateTemplateParameter:
3337 return createCXString("TemplateTemplateParameter");
3338 case CXCursor_FunctionTemplate:
3339 return createCXString("FunctionTemplate");
Douglas Gregor39d6f072010-08-31 19:02:00 +00003340 case CXCursor_ClassTemplate:
3341 return createCXString("ClassTemplate");
Douglas Gregor74dbe642010-08-31 19:31:58 +00003342 case CXCursor_ClassTemplatePartialSpecialization:
3343 return createCXString("ClassTemplatePartialSpecialization");
Douglas Gregor69319002010-08-31 23:48:11 +00003344 case CXCursor_NamespaceAlias:
3345 return createCXString("NamespaceAlias");
Douglas Gregor0a35bce2010-09-01 03:07:18 +00003346 case CXCursor_UsingDirective:
3347 return createCXString("UsingDirective");
Douglas Gregor7e242562010-09-01 19:52:22 +00003348 case CXCursor_UsingDeclaration:
3349 return createCXString("UsingDeclaration");
Richard Smith162e1c12011-04-15 14:24:37 +00003350 case CXCursor_TypeAliasDecl:
3351 return createCXString("TypeAliasDecl");
Steve Naroff89922f82009-08-31 00:59:03 +00003352 }
Ted Kremeneke68fff62010-02-17 00:41:32 +00003353
Ted Kremenekdeb06bd2010-01-16 02:02:09 +00003354 llvm_unreachable("Unhandled CXCursorKind");
Ted Kremeneka60ed472010-11-16 08:15:36 +00003355 return createCXString((const char*) 0);
Steve Naroff600866c2009-08-27 19:51:58 +00003356}
Steve Naroff89922f82009-08-31 00:59:03 +00003357
Ted Kremeneke68fff62010-02-17 00:41:32 +00003358enum CXChildVisitResult GetCursorVisitor(CXCursor cursor,
3359 CXCursor parent,
Douglas Gregor33e9abd2010-01-22 19:49:59 +00003360 CXClientData client_data) {
3361 CXCursor *BestCursor = static_cast<CXCursor *>(client_data);
Douglas Gregor93798e22010-11-05 21:11:19 +00003362
3363 // If our current best cursor is the construction of a temporary object,
3364 // don't replace that cursor with a type reference, because we want
3365 // clang_getCursor() to point at the constructor.
3366 if (clang_isExpression(BestCursor->kind) &&
3367 isa<CXXTemporaryObjectExpr>(getCursorExpr(*BestCursor)) &&
3368 cursor.kind == CXCursor_TypeRef)
3369 return CXChildVisit_Recurse;
3370
Douglas Gregor85fe1562010-12-10 07:23:11 +00003371 // Don't override a preprocessing cursor with another preprocessing
3372 // cursor; we want the outermost preprocessing cursor.
3373 if (clang_isPreprocessing(cursor.kind) &&
3374 clang_isPreprocessing(BestCursor->kind))
3375 return CXChildVisit_Recurse;
3376
Douglas Gregor33e9abd2010-01-22 19:49:59 +00003377 *BestCursor = cursor;
3378 return CXChildVisit_Recurse;
3379}
Ted Kremeneke68fff62010-02-17 00:41:32 +00003380
Douglas Gregorb9790342010-01-22 21:44:22 +00003381CXCursor clang_getCursor(CXTranslationUnit TU, CXSourceLocation Loc) {
3382 if (!TU)
Ted Kremenekf4629892010-01-14 01:51:23 +00003383 return clang_getNullCursor();
Ted Kremeneke68fff62010-02-17 00:41:32 +00003384
Ted Kremeneka60ed472010-11-16 08:15:36 +00003385 ASTUnit *CXXUnit = static_cast<ASTUnit *>(TU->TUData);
Douglas Gregorbdf60622010-03-05 21:16:25 +00003386 ASTUnit::ConcurrencyCheck Check(*CXXUnit);
3387
Douglas Gregora8e5c5b2010-07-22 20:22:31 +00003388 // Translate the given source location to make it point at the beginning of
3389 // the token under the cursor.
Ted Kremeneka297de22010-01-25 22:34:44 +00003390 SourceLocation SLoc = cxloc::translateSourceLocation(Loc);
Ted Kremeneka629ea42010-07-29 00:52:07 +00003391
3392 // Guard against an invalid SourceLocation, or we may assert in one
3393 // of the following calls.
3394 if (SLoc.isInvalid())
3395 return clang_getNullCursor();
3396
Douglas Gregor40749ee2010-11-03 00:35:38 +00003397 bool Logging = getenv("LIBCLANG_LOGGING");
Douglas Gregora8e5c5b2010-07-22 20:22:31 +00003398 SLoc = Lexer::GetBeginningOfToken(SLoc, CXXUnit->getSourceManager(),
3399 CXXUnit->getASTContext().getLangOptions());
3400
Douglas Gregor33e9abd2010-01-22 19:49:59 +00003401 CXCursor Result = MakeCXCursorInvalid(CXCursor_NoDeclFound);
3402 if (SLoc.isValid()) {
Douglas Gregor33e9abd2010-01-22 19:49:59 +00003403 // FIXME: Would be great to have a "hint" cursor, then walk from that
3404 // hint cursor upward until we find a cursor whose source range encloses
3405 // the region of interest, rather than starting from the translation unit.
Ted Kremeneka60ed472010-11-16 08:15:36 +00003406 CXCursor Parent = clang_getTranslationUnitCursor(TU);
3407 CursorVisitor CursorVis(TU, GetCursorVisitor, &Result,
Douglas Gregor04a9eb32011-03-16 23:23:30 +00003408 Decl::MaxPCHLevel, true, SourceLocation(SLoc));
Douglas Gregor33e9abd2010-01-22 19:49:59 +00003409 CursorVis.VisitChildren(Parent);
Steve Naroff77128dd2009-09-15 20:25:34 +00003410 }
Douglas Gregor40749ee2010-11-03 00:35:38 +00003411
3412 if (Logging) {
3413 CXFile SearchFile;
3414 unsigned SearchLine, SearchColumn;
3415 CXFile ResultFile;
3416 unsigned ResultLine, ResultColumn;
Douglas Gregor66537982010-11-17 17:14:07 +00003417 CXString SearchFileName, ResultFileName, KindSpelling, USR;
3418 const char *IsDef = clang_isCursorDefinition(Result)? " (Definition)" : "";
Douglas Gregor40749ee2010-11-03 00:35:38 +00003419 CXSourceLocation ResultLoc = clang_getCursorLocation(Result);
3420
3421 clang_getInstantiationLocation(Loc, &SearchFile, &SearchLine, &SearchColumn,
3422 0);
3423 clang_getInstantiationLocation(ResultLoc, &ResultFile, &ResultLine,
3424 &ResultColumn, 0);
3425 SearchFileName = clang_getFileName(SearchFile);
3426 ResultFileName = clang_getFileName(ResultFile);
3427 KindSpelling = clang_getCursorKindSpelling(Result.kind);
Douglas Gregor66537982010-11-17 17:14:07 +00003428 USR = clang_getCursorUSR(Result);
3429 fprintf(stderr, "clang_getCursor(%s:%d:%d) = %s(%s:%d:%d):%s%s\n",
Douglas Gregor40749ee2010-11-03 00:35:38 +00003430 clang_getCString(SearchFileName), SearchLine, SearchColumn,
3431 clang_getCString(KindSpelling),
Douglas Gregor66537982010-11-17 17:14:07 +00003432 clang_getCString(ResultFileName), ResultLine, ResultColumn,
3433 clang_getCString(USR), IsDef);
Douglas Gregor40749ee2010-11-03 00:35:38 +00003434 clang_disposeString(SearchFileName);
3435 clang_disposeString(ResultFileName);
3436 clang_disposeString(KindSpelling);
Douglas Gregor66537982010-11-17 17:14:07 +00003437 clang_disposeString(USR);
Douglas Gregor0aefbd82010-12-10 01:45:00 +00003438
3439 CXCursor Definition = clang_getCursorDefinition(Result);
3440 if (!clang_equalCursors(Definition, clang_getNullCursor())) {
3441 CXSourceLocation DefinitionLoc = clang_getCursorLocation(Definition);
3442 CXString DefinitionKindSpelling
3443 = clang_getCursorKindSpelling(Definition.kind);
3444 CXFile DefinitionFile;
3445 unsigned DefinitionLine, DefinitionColumn;
3446 clang_getInstantiationLocation(DefinitionLoc, &DefinitionFile,
3447 &DefinitionLine, &DefinitionColumn, 0);
3448 CXString DefinitionFileName = clang_getFileName(DefinitionFile);
3449 fprintf(stderr, " -> %s(%s:%d:%d)\n",
3450 clang_getCString(DefinitionKindSpelling),
3451 clang_getCString(DefinitionFileName),
3452 DefinitionLine, DefinitionColumn);
3453 clang_disposeString(DefinitionFileName);
3454 clang_disposeString(DefinitionKindSpelling);
3455 }
Douglas Gregor40749ee2010-11-03 00:35:38 +00003456 }
3457
Ted Kremeneke68fff62010-02-17 00:41:32 +00003458 return Result;
Steve Naroff600866c2009-08-27 19:51:58 +00003459}
3460
Ted Kremenek73885552009-11-17 19:28:59 +00003461CXCursor clang_getNullCursor(void) {
Douglas Gregor5bfb8c12010-01-20 23:34:41 +00003462 return MakeCXCursorInvalid(CXCursor_InvalidFile);
Ted Kremenek73885552009-11-17 19:28:59 +00003463}
3464
3465unsigned clang_equalCursors(CXCursor X, CXCursor Y) {
Douglas Gregor283cae32010-01-15 21:56:13 +00003466 return X == Y;
Ted Kremenek73885552009-11-17 19:28:59 +00003467}
Daniel Dunbar0d7dd222009-11-30 20:42:43 +00003468
Douglas Gregor9ce55842010-11-20 00:09:34 +00003469unsigned clang_hashCursor(CXCursor C) {
3470 unsigned Index = 0;
3471 if (clang_isExpression(C.kind) || clang_isStatement(C.kind))
3472 Index = 1;
3473
3474 return llvm::DenseMapInfo<std::pair<unsigned, void*> >::getHashValue(
3475 std::make_pair(C.kind, C.data[Index]));
3476}
3477
Daniel Dunbar9ebfa312009-12-01 03:14:51 +00003478unsigned clang_isInvalid(enum CXCursorKind K) {
Steve Naroff77128dd2009-09-15 20:25:34 +00003479 return K >= CXCursor_FirstInvalid && K <= CXCursor_LastInvalid;
3480}
3481
Daniel Dunbar9ebfa312009-12-01 03:14:51 +00003482unsigned clang_isDeclaration(enum CXCursorKind K) {
Steve Naroff89922f82009-08-31 00:59:03 +00003483 return K >= CXCursor_FirstDecl && K <= CXCursor_LastDecl;
3484}
Steve Naroff2d4d6292009-08-31 14:26:51 +00003485
Daniel Dunbar9ebfa312009-12-01 03:14:51 +00003486unsigned clang_isReference(enum CXCursorKind K) {
Steve Narofff334b4e2009-09-02 18:26:48 +00003487 return K >= CXCursor_FirstRef && K <= CXCursor_LastRef;
3488}
3489
Douglas Gregor97b98722010-01-19 23:20:36 +00003490unsigned clang_isExpression(enum CXCursorKind K) {
3491 return K >= CXCursor_FirstExpr && K <= CXCursor_LastExpr;
3492}
3493
3494unsigned clang_isStatement(enum CXCursorKind K) {
3495 return K >= CXCursor_FirstStmt && K <= CXCursor_LastStmt;
3496}
3497
Douglas Gregor7eaa8ae2010-01-20 00:23:15 +00003498unsigned clang_isTranslationUnit(enum CXCursorKind K) {
3499 return K == CXCursor_TranslationUnit;
3500}
3501
Douglas Gregor9f1e3ff2010-03-18 00:42:48 +00003502unsigned clang_isPreprocessing(enum CXCursorKind K) {
3503 return K >= CXCursor_FirstPreprocessing && K <= CXCursor_LastPreprocessing;
3504}
3505
Ted Kremenekad6eff62010-03-08 21:17:29 +00003506unsigned clang_isUnexposed(enum CXCursorKind K) {
3507 switch (K) {
3508 case CXCursor_UnexposedDecl:
3509 case CXCursor_UnexposedExpr:
3510 case CXCursor_UnexposedStmt:
3511 case CXCursor_UnexposedAttr:
3512 return true;
3513 default:
3514 return false;
3515 }
3516}
3517
Daniel Dunbar9ebfa312009-12-01 03:14:51 +00003518CXCursorKind clang_getCursorKind(CXCursor C) {
Steve Naroff9efa7672009-09-04 15:44:05 +00003519 return C.kind;
3520}
3521
Douglas Gregor98258af2010-01-18 22:46:11 +00003522CXSourceLocation clang_getCursorLocation(CXCursor C) {
3523 if (clang_isReference(C.kind)) {
Douglas Gregorf46034a2010-01-18 23:41:10 +00003524 switch (C.kind) {
Ted Kremenekf0e23e82010-02-17 00:41:40 +00003525 case CXCursor_ObjCSuperClassRef: {
Douglas Gregorf46034a2010-01-18 23:41:10 +00003526 std::pair<ObjCInterfaceDecl *, SourceLocation> P
3527 = getCursorObjCSuperClassRef(C);
Ted Kremeneka297de22010-01-25 22:34:44 +00003528 return cxloc::translateSourceLocation(P.first->getASTContext(), P.second);
Douglas Gregorf46034a2010-01-18 23:41:10 +00003529 }
3530
Ted Kremenekf0e23e82010-02-17 00:41:40 +00003531 case CXCursor_ObjCProtocolRef: {
Douglas Gregorf46034a2010-01-18 23:41:10 +00003532 std::pair<ObjCProtocolDecl *, SourceLocation> P
3533 = getCursorObjCProtocolRef(C);
Ted Kremeneka297de22010-01-25 22:34:44 +00003534 return cxloc::translateSourceLocation(P.first->getASTContext(), P.second);
Douglas Gregorf46034a2010-01-18 23:41:10 +00003535 }
3536
Ted Kremenekf0e23e82010-02-17 00:41:40 +00003537 case CXCursor_ObjCClassRef: {
Douglas Gregorf46034a2010-01-18 23:41:10 +00003538 std::pair<ObjCInterfaceDecl *, SourceLocation> P
3539 = getCursorObjCClassRef(C);
Ted Kremeneka297de22010-01-25 22:34:44 +00003540 return cxloc::translateSourceLocation(P.first->getASTContext(), P.second);
Douglas Gregorf46034a2010-01-18 23:41:10 +00003541 }
Douglas Gregor7d0d40e2010-01-21 16:28:34 +00003542
Ted Kremenekf0e23e82010-02-17 00:41:40 +00003543 case CXCursor_TypeRef: {
Douglas Gregor7d0d40e2010-01-21 16:28:34 +00003544 std::pair<TypeDecl *, SourceLocation> P = getCursorTypeRef(C);
Ted Kremeneka297de22010-01-25 22:34:44 +00003545 return cxloc::translateSourceLocation(P.first->getASTContext(), P.second);
Douglas Gregor7d0d40e2010-01-21 16:28:34 +00003546 }
Douglas Gregor0b36e612010-08-31 20:37:03 +00003547
3548 case CXCursor_TemplateRef: {
3549 std::pair<TemplateDecl *, SourceLocation> P = getCursorTemplateRef(C);
3550 return cxloc::translateSourceLocation(P.first->getASTContext(), P.second);
3551 }
3552
Douglas Gregor69319002010-08-31 23:48:11 +00003553 case CXCursor_NamespaceRef: {
3554 std::pair<NamedDecl *, SourceLocation> P = getCursorNamespaceRef(C);
3555 return cxloc::translateSourceLocation(P.first->getASTContext(), P.second);
3556 }
3557
Douglas Gregora67e03f2010-09-09 21:42:20 +00003558 case CXCursor_MemberRef: {
3559 std::pair<FieldDecl *, SourceLocation> P = getCursorMemberRef(C);
3560 return cxloc::translateSourceLocation(P.first->getASTContext(), P.second);
3561 }
3562
Ted Kremenek3064ef92010-08-27 21:34:58 +00003563 case CXCursor_CXXBaseSpecifier: {
Douglas Gregor1b0f7af2010-10-02 19:51:13 +00003564 CXXBaseSpecifier *BaseSpec = getCursorCXXBaseSpecifier(C);
3565 if (!BaseSpec)
3566 return clang_getNullLocation();
3567
3568 if (TypeSourceInfo *TSInfo = BaseSpec->getTypeSourceInfo())
3569 return cxloc::translateSourceLocation(getCursorContext(C),
3570 TSInfo->getTypeLoc().getBeginLoc());
3571
3572 return cxloc::translateSourceLocation(getCursorContext(C),
3573 BaseSpec->getSourceRange().getBegin());
Ted Kremenek3064ef92010-08-27 21:34:58 +00003574 }
Ted Kremenekf0e23e82010-02-17 00:41:40 +00003575
Douglas Gregor36897b02010-09-10 00:22:18 +00003576 case CXCursor_LabelRef: {
3577 std::pair<LabelStmt *, SourceLocation> P = getCursorLabelRef(C);
3578 return cxloc::translateSourceLocation(getCursorContext(C), P.second);
3579 }
3580
Douglas Gregor1f60d9e2010-09-13 22:52:57 +00003581 case CXCursor_OverloadedDeclRef:
3582 return cxloc::translateSourceLocation(getCursorContext(C),
3583 getCursorOverloadedDeclRef(C).second);
3584
Douglas Gregorf46034a2010-01-18 23:41:10 +00003585 default:
3586 // FIXME: Need a way to enumerate all non-reference cases.
3587 llvm_unreachable("Missed a reference kind");
3588 }
Douglas Gregor98258af2010-01-18 22:46:11 +00003589 }
Douglas Gregor97b98722010-01-19 23:20:36 +00003590
3591 if (clang_isExpression(C.kind))
Ted Kremenekf0e23e82010-02-17 00:41:40 +00003592 return cxloc::translateSourceLocation(getCursorContext(C),
Douglas Gregor97b98722010-01-19 23:20:36 +00003593 getLocationFromExpr(getCursorExpr(C)));
3594
Douglas Gregor36897b02010-09-10 00:22:18 +00003595 if (clang_isStatement(C.kind))
3596 return cxloc::translateSourceLocation(getCursorContext(C),
3597 getCursorStmt(C)->getLocStart());
3598
Douglas Gregor9f1e3ff2010-03-18 00:42:48 +00003599 if (C.kind == CXCursor_PreprocessingDirective) {
3600 SourceLocation L = cxcursor::getCursorPreprocessingDirective(C).getBegin();
3601 return cxloc::translateSourceLocation(getCursorContext(C), L);
3602 }
Douglas Gregor48072312010-03-18 15:23:44 +00003603
3604 if (C.kind == CXCursor_MacroInstantiation) {
Douglas Gregor4ae8f292010-03-18 17:52:52 +00003605 SourceLocation L
3606 = cxcursor::getCursorMacroInstantiation(C)->getSourceRange().getBegin();
Douglas Gregor48072312010-03-18 15:23:44 +00003607 return cxloc::translateSourceLocation(getCursorContext(C), L);
3608 }
Douglas Gregor572feb22010-03-18 18:04:21 +00003609
3610 if (C.kind == CXCursor_MacroDefinition) {
3611 SourceLocation L = cxcursor::getCursorMacroDefinition(C)->getLocation();
3612 return cxloc::translateSourceLocation(getCursorContext(C), L);
3613 }
Douglas Gregorecdcb882010-10-20 22:00:55 +00003614
3615 if (C.kind == CXCursor_InclusionDirective) {
3616 SourceLocation L
3617 = cxcursor::getCursorInclusionDirective(C)->getSourceRange().getBegin();
3618 return cxloc::translateSourceLocation(getCursorContext(C), L);
3619 }
3620
Ted Kremenek9a700d22010-05-12 06:16:13 +00003621 if (C.kind < CXCursor_FirstDecl || C.kind > CXCursor_LastDecl)
Douglas Gregor5352ac02010-01-28 00:27:43 +00003622 return clang_getNullLocation();
Douglas Gregor98258af2010-01-18 22:46:11 +00003623
Douglas Gregorf46034a2010-01-18 23:41:10 +00003624 Decl *D = getCursorDecl(C);
Douglas Gregorf46034a2010-01-18 23:41:10 +00003625 SourceLocation Loc = D->getLocation();
3626 if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(D))
3627 Loc = Class->getClassLoc();
Ted Kremenek007a7c92010-11-01 23:26:51 +00003628 // FIXME: Multiple variables declared in a single declaration
3629 // currently lack the information needed to correctly determine their
3630 // ranges when accounting for the type-specifier. We use context
3631 // stored in the CXCursor to determine if the VarDecl is in a DeclGroup,
3632 // and if so, whether it is the first decl.
3633 if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
3634 if (!cxcursor::isFirstInDeclGroup(C))
3635 Loc = VD->getLocation();
3636 }
3637
Douglas Gregor2ca54fe2010-03-22 15:53:50 +00003638 return cxloc::translateSourceLocation(getCursorContext(C), Loc);
Douglas Gregor98258af2010-01-18 22:46:11 +00003639}
Douglas Gregora7bde202010-01-19 00:34:46 +00003640
Douglas Gregora8e5c5b2010-07-22 20:22:31 +00003641} // end extern "C"
3642
3643static SourceRange getRawCursorExtent(CXCursor C) {
Douglas Gregora7bde202010-01-19 00:34:46 +00003644 if (clang_isReference(C.kind)) {
3645 switch (C.kind) {
Douglas Gregora8e5c5b2010-07-22 20:22:31 +00003646 case CXCursor_ObjCSuperClassRef:
3647 return getCursorObjCSuperClassRef(C).second;
Ted Kremenekf0e23e82010-02-17 00:41:40 +00003648
Douglas Gregora8e5c5b2010-07-22 20:22:31 +00003649 case CXCursor_ObjCProtocolRef:
3650 return getCursorObjCProtocolRef(C).second;
Ted Kremenekf0e23e82010-02-17 00:41:40 +00003651
Douglas Gregora8e5c5b2010-07-22 20:22:31 +00003652 case CXCursor_ObjCClassRef:
3653 return getCursorObjCClassRef(C).second;
Ted Kremenekf0e23e82010-02-17 00:41:40 +00003654
Douglas Gregora8e5c5b2010-07-22 20:22:31 +00003655 case CXCursor_TypeRef:
3656 return getCursorTypeRef(C).second;
Douglas Gregor0b36e612010-08-31 20:37:03 +00003657
3658 case CXCursor_TemplateRef:
3659 return getCursorTemplateRef(C).second;
3660
Douglas Gregor69319002010-08-31 23:48:11 +00003661 case CXCursor_NamespaceRef:
3662 return getCursorNamespaceRef(C).second;
Douglas Gregora67e03f2010-09-09 21:42:20 +00003663
3664 case CXCursor_MemberRef:
3665 return getCursorMemberRef(C).second;
3666
Ted Kremenek3064ef92010-08-27 21:34:58 +00003667 case CXCursor_CXXBaseSpecifier:
Douglas Gregor1b0f7af2010-10-02 19:51:13 +00003668 return getCursorCXXBaseSpecifier(C)->getSourceRange();
Douglas Gregor7d0d40e2010-01-21 16:28:34 +00003669
Douglas Gregor36897b02010-09-10 00:22:18 +00003670 case CXCursor_LabelRef:
3671 return getCursorLabelRef(C).second;
3672
Douglas Gregor1f60d9e2010-09-13 22:52:57 +00003673 case CXCursor_OverloadedDeclRef:
3674 return getCursorOverloadedDeclRef(C).second;
3675
Douglas Gregora8e5c5b2010-07-22 20:22:31 +00003676 default:
3677 // FIXME: Need a way to enumerate all non-reference cases.
3678 llvm_unreachable("Missed a reference kind");
Douglas Gregora7bde202010-01-19 00:34:46 +00003679 }
3680 }
Douglas Gregor97b98722010-01-19 23:20:36 +00003681
3682 if (clang_isExpression(C.kind))
Douglas Gregora8e5c5b2010-07-22 20:22:31 +00003683 return getCursorExpr(C)->getSourceRange();
Douglas Gregor33e9abd2010-01-22 19:49:59 +00003684
3685 if (clang_isStatement(C.kind))
Douglas Gregora8e5c5b2010-07-22 20:22:31 +00003686 return getCursorStmt(C)->getSourceRange();
Ted Kremenekf0e23e82010-02-17 00:41:40 +00003687
Douglas Gregora8e5c5b2010-07-22 20:22:31 +00003688 if (C.kind == CXCursor_PreprocessingDirective)
3689 return cxcursor::getCursorPreprocessingDirective(C);
Douglas Gregor48072312010-03-18 15:23:44 +00003690
Douglas Gregora8e5c5b2010-07-22 20:22:31 +00003691 if (C.kind == CXCursor_MacroInstantiation)
3692 return cxcursor::getCursorMacroInstantiation(C)->getSourceRange();
Douglas Gregor572feb22010-03-18 18:04:21 +00003693
Douglas Gregora8e5c5b2010-07-22 20:22:31 +00003694 if (C.kind == CXCursor_MacroDefinition)
3695 return cxcursor::getCursorMacroDefinition(C)->getSourceRange();
Douglas Gregorecdcb882010-10-20 22:00:55 +00003696
3697 if (C.kind == CXCursor_InclusionDirective)
3698 return cxcursor::getCursorInclusionDirective(C)->getSourceRange();
3699
Ted Kremenek007a7c92010-11-01 23:26:51 +00003700 if (C.kind >= CXCursor_FirstDecl && C.kind <= CXCursor_LastDecl) {
3701 Decl *D = cxcursor::getCursorDecl(C);
3702 SourceRange R = D->getSourceRange();
3703 // FIXME: Multiple variables declared in a single declaration
3704 // currently lack the information needed to correctly determine their
3705 // ranges when accounting for the type-specifier. We use context
3706 // stored in the CXCursor to determine if the VarDecl is in a DeclGroup,
3707 // and if so, whether it is the first decl.
3708 if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
3709 if (!cxcursor::isFirstInDeclGroup(C))
3710 R.setBegin(VD->getLocation());
3711 }
3712 return R;
3713 }
Douglas Gregor66537982010-11-17 17:14:07 +00003714 return SourceRange();
3715}
3716
3717/// \brief Retrieves the "raw" cursor extent, which is then extended to include
3718/// the decl-specifier-seq for declarations.
3719static SourceRange getFullCursorExtent(CXCursor C, SourceManager &SrcMgr) {
3720 if (C.kind >= CXCursor_FirstDecl && C.kind <= CXCursor_LastDecl) {
3721 Decl *D = cxcursor::getCursorDecl(C);
3722 SourceRange R = D->getSourceRange();
Douglas Gregor66537982010-11-17 17:14:07 +00003723
Douglas Gregor2494dd02011-03-01 01:34:45 +00003724 // Adjust the start of the location for declarations preceded by
3725 // declaration specifiers.
3726 SourceLocation StartLoc;
3727 if (const DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(D)) {
3728 if (TypeSourceInfo *TI = DD->getTypeSourceInfo())
3729 StartLoc = TI->getTypeLoc().getSourceRange().getBegin();
3730 } else if (TypedefDecl *Typedef = dyn_cast<TypedefDecl>(D)) {
3731 if (TypeSourceInfo *TI = Typedef->getTypeSourceInfo())
3732 StartLoc = TI->getTypeLoc().getSourceRange().getBegin();
3733 }
3734
3735 if (StartLoc.isValid() && R.getBegin().isValid() &&
3736 SrcMgr.isBeforeInTranslationUnit(StartLoc, R.getBegin()))
3737 R.setBegin(StartLoc);
3738
3739 // FIXME: Multiple variables declared in a single declaration
3740 // currently lack the information needed to correctly determine their
3741 // ranges when accounting for the type-specifier. We use context
3742 // stored in the CXCursor to determine if the VarDecl is in a DeclGroup,
3743 // and if so, whether it is the first decl.
3744 if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
3745 if (!cxcursor::isFirstInDeclGroup(C))
3746 R.setBegin(VD->getLocation());
Douglas Gregor66537982010-11-17 17:14:07 +00003747 }
3748
3749 return R;
3750 }
3751
3752 return getRawCursorExtent(C);
3753}
Douglas Gregora8e5c5b2010-07-22 20:22:31 +00003754
3755extern "C" {
3756
3757CXSourceRange clang_getCursorExtent(CXCursor C) {
3758 SourceRange R = getRawCursorExtent(C);
3759 if (R.isInvalid())
Douglas Gregor5352ac02010-01-28 00:27:43 +00003760 return clang_getNullRange();
Ted Kremenekf0e23e82010-02-17 00:41:40 +00003761
Douglas Gregora8e5c5b2010-07-22 20:22:31 +00003762 return cxloc::translateSourceRange(getCursorContext(C), R);
Douglas Gregora7bde202010-01-19 00:34:46 +00003763}
Douglas Gregorc5d1e932010-01-19 01:20:04 +00003764
3765CXCursor clang_getCursorReferenced(CXCursor C) {
Douglas Gregorb2cd4872010-01-20 23:57:43 +00003766 if (clang_isInvalid(C.kind))
3767 return clang_getNullCursor();
Ted Kremenekf0e23e82010-02-17 00:41:40 +00003768
Ted Kremeneka60ed472010-11-16 08:15:36 +00003769 CXTranslationUnit tu = getCursorTU(C);
Douglas Gregor1f60d9e2010-09-13 22:52:57 +00003770 if (clang_isDeclaration(C.kind)) {
3771 Decl *D = getCursorDecl(C);
3772 if (UsingDecl *Using = dyn_cast<UsingDecl>(D))
Ted Kremeneka60ed472010-11-16 08:15:36 +00003773 return MakeCursorOverloadedDeclRef(Using, D->getLocation(), tu);
Douglas Gregor1f60d9e2010-09-13 22:52:57 +00003774 if (ObjCClassDecl *Classes = dyn_cast<ObjCClassDecl>(D))
Ted Kremeneka60ed472010-11-16 08:15:36 +00003775 return MakeCursorOverloadedDeclRef(Classes, D->getLocation(), tu);
Douglas Gregor1f60d9e2010-09-13 22:52:57 +00003776 if (ObjCForwardProtocolDecl *Protocols
3777 = dyn_cast<ObjCForwardProtocolDecl>(D))
Ted Kremeneka60ed472010-11-16 08:15:36 +00003778 return MakeCursorOverloadedDeclRef(Protocols, D->getLocation(), tu);
Douglas Gregore3c60a72010-11-17 00:13:31 +00003779 if (ObjCPropertyImplDecl *PropImpl =llvm::dyn_cast<ObjCPropertyImplDecl>(D))
3780 if (ObjCPropertyDecl *Property = PropImpl->getPropertyDecl())
3781 return MakeCXCursor(Property, tu);
3782
Douglas Gregorc5d1e932010-01-19 01:20:04 +00003783 return C;
Douglas Gregor1f60d9e2010-09-13 22:52:57 +00003784 }
3785
Douglas Gregor97b98722010-01-19 23:20:36 +00003786 if (clang_isExpression(C.kind)) {
Douglas Gregor1f60d9e2010-09-13 22:52:57 +00003787 Expr *E = getCursorExpr(C);
3788 Decl *D = getDeclFromExpr(E);
Douglas Gregor97b98722010-01-19 23:20:36 +00003789 if (D)
Ted Kremeneka60ed472010-11-16 08:15:36 +00003790 return MakeCXCursor(D, tu);
Douglas Gregor1f60d9e2010-09-13 22:52:57 +00003791
3792 if (OverloadExpr *Ovl = dyn_cast_or_null<OverloadExpr>(E))
Ted Kremeneka60ed472010-11-16 08:15:36 +00003793 return MakeCursorOverloadedDeclRef(Ovl, tu);
Douglas Gregor1f60d9e2010-09-13 22:52:57 +00003794
Douglas Gregor97b98722010-01-19 23:20:36 +00003795 return clang_getNullCursor();
3796 }
3797
Douglas Gregor36897b02010-09-10 00:22:18 +00003798 if (clang_isStatement(C.kind)) {
3799 Stmt *S = getCursorStmt(C);
3800 if (GotoStmt *Goto = dyn_cast_or_null<GotoStmt>(S))
Ted Kremenek37c2e962011-03-15 23:47:49 +00003801 if (LabelDecl *label = Goto->getLabel())
3802 if (LabelStmt *labelS = label->getStmt())
3803 return MakeCXCursor(labelS, getCursorDecl(C), tu);
Douglas Gregor36897b02010-09-10 00:22:18 +00003804
3805 return clang_getNullCursor();
3806 }
3807
Douglas Gregorbf7efa22010-03-18 18:23:03 +00003808 if (C.kind == CXCursor_MacroInstantiation) {
3809 if (MacroDefinition *Def = getCursorMacroInstantiation(C)->getDefinition())
Ted Kremeneka60ed472010-11-16 08:15:36 +00003810 return MakeMacroDefinitionCursor(Def, tu);
Douglas Gregorbf7efa22010-03-18 18:23:03 +00003811 }
3812
Douglas Gregorc5d1e932010-01-19 01:20:04 +00003813 if (!clang_isReference(C.kind))
3814 return clang_getNullCursor();
Ted Kremenekf0e23e82010-02-17 00:41:40 +00003815
Douglas Gregorc5d1e932010-01-19 01:20:04 +00003816 switch (C.kind) {
3817 case CXCursor_ObjCSuperClassRef:
Ted Kremeneka60ed472010-11-16 08:15:36 +00003818 return MakeCXCursor(getCursorObjCSuperClassRef(C).first, tu);
Ted Kremenekf0e23e82010-02-17 00:41:40 +00003819
3820 case CXCursor_ObjCProtocolRef: {
Ted Kremeneka60ed472010-11-16 08:15:36 +00003821 return MakeCXCursor(getCursorObjCProtocolRef(C).first, tu);
Ted Kremenekf0e23e82010-02-17 00:41:40 +00003822
3823 case CXCursor_ObjCClassRef:
Ted Kremeneka60ed472010-11-16 08:15:36 +00003824 return MakeCXCursor(getCursorObjCClassRef(C).first, tu );
Douglas Gregor7d0d40e2010-01-21 16:28:34 +00003825
Ted Kremenekf0e23e82010-02-17 00:41:40 +00003826 case CXCursor_TypeRef:
Ted Kremeneka60ed472010-11-16 08:15:36 +00003827 return MakeCXCursor(getCursorTypeRef(C).first, tu );
Douglas Gregor0b36e612010-08-31 20:37:03 +00003828
3829 case CXCursor_TemplateRef:
Ted Kremeneka60ed472010-11-16 08:15:36 +00003830 return MakeCXCursor(getCursorTemplateRef(C).first, tu );
Douglas Gregor0b36e612010-08-31 20:37:03 +00003831
Douglas Gregor69319002010-08-31 23:48:11 +00003832 case CXCursor_NamespaceRef:
Ted Kremeneka60ed472010-11-16 08:15:36 +00003833 return MakeCXCursor(getCursorNamespaceRef(C).first, tu );
Douglas Gregor69319002010-08-31 23:48:11 +00003834
Douglas Gregora67e03f2010-09-09 21:42:20 +00003835 case CXCursor_MemberRef:
Ted Kremeneka60ed472010-11-16 08:15:36 +00003836 return MakeCXCursor(getCursorMemberRef(C).first, tu );
Douglas Gregora67e03f2010-09-09 21:42:20 +00003837
Ted Kremenek3064ef92010-08-27 21:34:58 +00003838 case CXCursor_CXXBaseSpecifier: {
3839 CXXBaseSpecifier *B = cxcursor::getCursorCXXBaseSpecifier(C);
3840 return clang_getTypeDeclaration(cxtype::MakeCXType(B->getType(),
Ted Kremeneka60ed472010-11-16 08:15:36 +00003841 tu ));
Ted Kremenek3064ef92010-08-27 21:34:58 +00003842 }
Ted Kremenekf0e23e82010-02-17 00:41:40 +00003843
Douglas Gregor36897b02010-09-10 00:22:18 +00003844 case CXCursor_LabelRef:
3845 // FIXME: We end up faking the "parent" declaration here because we
3846 // don't want to make CXCursor larger.
3847 return MakeCXCursor(getCursorLabelRef(C).first,
Ted Kremeneka60ed472010-11-16 08:15:36 +00003848 static_cast<ASTUnit*>(tu->TUData)->getASTContext()
3849 .getTranslationUnitDecl(),
3850 tu);
Douglas Gregor36897b02010-09-10 00:22:18 +00003851
Douglas Gregor1f60d9e2010-09-13 22:52:57 +00003852 case CXCursor_OverloadedDeclRef:
3853 return C;
3854
Douglas Gregorc5d1e932010-01-19 01:20:04 +00003855 default:
3856 // We would prefer to enumerate all non-reference cursor kinds here.
3857 llvm_unreachable("Unhandled reference cursor kind");
3858 break;
3859 }
3860 }
Ted Kremenekf0e23e82010-02-17 00:41:40 +00003861
Douglas Gregorc5d1e932010-01-19 01:20:04 +00003862 return clang_getNullCursor();
3863}
3864
Douglas Gregorb6998662010-01-19 19:34:47 +00003865CXCursor clang_getCursorDefinition(CXCursor C) {
Douglas Gregorb2cd4872010-01-20 23:57:43 +00003866 if (clang_isInvalid(C.kind))
3867 return clang_getNullCursor();
Ted Kremenekf0e23e82010-02-17 00:41:40 +00003868
Ted Kremeneka60ed472010-11-16 08:15:36 +00003869 CXTranslationUnit TU = getCursorTU(C);
Ted Kremenekf0e23e82010-02-17 00:41:40 +00003870
Douglas Gregorb6998662010-01-19 19:34:47 +00003871 bool WasReference = false;
Douglas Gregor97b98722010-01-19 23:20:36 +00003872 if (clang_isReference(C.kind) || clang_isExpression(C.kind)) {
Douglas Gregorb6998662010-01-19 19:34:47 +00003873 C = clang_getCursorReferenced(C);
3874 WasReference = true;
3875 }
3876
Douglas Gregorbf7efa22010-03-18 18:23:03 +00003877 if (C.kind == CXCursor_MacroInstantiation)
3878 return clang_getCursorReferenced(C);
3879
Douglas Gregorb6998662010-01-19 19:34:47 +00003880 if (!clang_isDeclaration(C.kind))
3881 return clang_getNullCursor();
3882
3883 Decl *D = getCursorDecl(C);
3884 if (!D)
3885 return clang_getNullCursor();
Ted Kremenekf0e23e82010-02-17 00:41:40 +00003886
Douglas Gregorb6998662010-01-19 19:34:47 +00003887 switch (D->getKind()) {
3888 // Declaration kinds that don't really separate the notions of
3889 // declaration and definition.
3890 case Decl::Namespace:
3891 case Decl::Typedef:
Richard Smith162e1c12011-04-15 14:24:37 +00003892 case Decl::TypeAlias:
Douglas Gregorb6998662010-01-19 19:34:47 +00003893 case Decl::TemplateTypeParm:
3894 case Decl::EnumConstant:
3895 case Decl::Field:
Benjamin Kramerd9811462010-11-21 14:11:41 +00003896 case Decl::IndirectField:
Douglas Gregorb6998662010-01-19 19:34:47 +00003897 case Decl::ObjCIvar:
3898 case Decl::ObjCAtDefsField:
3899 case Decl::ImplicitParam:
3900 case Decl::ParmVar:
3901 case Decl::NonTypeTemplateParm:
3902 case Decl::TemplateTemplateParm:
3903 case Decl::ObjCCategoryImpl:
3904 case Decl::ObjCImplementation:
Abramo Bagnara6206d532010-06-05 05:09:32 +00003905 case Decl::AccessSpec:
Douglas Gregorb6998662010-01-19 19:34:47 +00003906 case Decl::LinkageSpec:
3907 case Decl::ObjCPropertyImpl:
3908 case Decl::FileScopeAsm:
3909 case Decl::StaticAssert:
3910 case Decl::Block:
Chris Lattnerad8dcf42011-02-17 07:39:24 +00003911 case Decl::Label: // FIXME: Is this right??
Douglas Gregorb6998662010-01-19 19:34:47 +00003912 return C;
3913
3914 // Declaration kinds that don't make any sense here, but are
3915 // nonetheless harmless.
3916 case Decl::TranslationUnit:
Douglas Gregorb6998662010-01-19 19:34:47 +00003917 break;
3918
3919 // Declaration kinds for which the definition is not resolvable.
3920 case Decl::UnresolvedUsingTypename:
3921 case Decl::UnresolvedUsingValue:
3922 break;
3923
3924 case Decl::UsingDirective:
Douglas Gregorb2cd4872010-01-20 23:57:43 +00003925 return MakeCXCursor(cast<UsingDirectiveDecl>(D)->getNominatedNamespace(),
Ted Kremeneka60ed472010-11-16 08:15:36 +00003926 TU);
Douglas Gregorb6998662010-01-19 19:34:47 +00003927
3928 case Decl::NamespaceAlias:
Ted Kremeneka60ed472010-11-16 08:15:36 +00003929 return MakeCXCursor(cast<NamespaceAliasDecl>(D)->getNamespace(), TU);
Douglas Gregorb6998662010-01-19 19:34:47 +00003930
3931 case Decl::Enum:
3932 case Decl::Record:
3933 case Decl::CXXRecord:
3934 case Decl::ClassTemplateSpecialization:
3935 case Decl::ClassTemplatePartialSpecialization:
Douglas Gregor952b0172010-02-11 01:04:33 +00003936 if (TagDecl *Def = cast<TagDecl>(D)->getDefinition())
Ted Kremeneka60ed472010-11-16 08:15:36 +00003937 return MakeCXCursor(Def, TU);
Douglas Gregorb6998662010-01-19 19:34:47 +00003938 return clang_getNullCursor();
3939
3940 case Decl::Function:
3941 case Decl::CXXMethod:
3942 case Decl::CXXConstructor:
3943 case Decl::CXXDestructor:
3944 case Decl::CXXConversion: {
3945 const FunctionDecl *Def = 0;
3946 if (cast<FunctionDecl>(D)->getBody(Def))
Ted Kremeneka60ed472010-11-16 08:15:36 +00003947 return MakeCXCursor(const_cast<FunctionDecl *>(Def), TU);
Douglas Gregorb6998662010-01-19 19:34:47 +00003948 return clang_getNullCursor();
3949 }
3950
3951 case Decl::Var: {
Sebastian Redl31310a22010-02-01 20:16:42 +00003952 // Ask the variable if it has a definition.
3953 if (VarDecl *Def = cast<VarDecl>(D)->getDefinition())
Ted Kremeneka60ed472010-11-16 08:15:36 +00003954 return MakeCXCursor(Def, TU);
Sebastian Redl31310a22010-02-01 20:16:42 +00003955 return clang_getNullCursor();
Douglas Gregorb6998662010-01-19 19:34:47 +00003956 }
Ted Kremenekf0e23e82010-02-17 00:41:40 +00003957
Douglas Gregorb6998662010-01-19 19:34:47 +00003958 case Decl::FunctionTemplate: {
3959 const FunctionDecl *Def = 0;
3960 if (cast<FunctionTemplateDecl>(D)->getTemplatedDecl()->getBody(Def))
Ted Kremeneka60ed472010-11-16 08:15:36 +00003961 return MakeCXCursor(Def->getDescribedFunctionTemplate(), TU);
Douglas Gregorb6998662010-01-19 19:34:47 +00003962 return clang_getNullCursor();
3963 }
Ted Kremenekf0e23e82010-02-17 00:41:40 +00003964
Douglas Gregorb6998662010-01-19 19:34:47 +00003965 case Decl::ClassTemplate: {
3966 if (RecordDecl *Def = cast<ClassTemplateDecl>(D)->getTemplatedDecl()
Douglas Gregor952b0172010-02-11 01:04:33 +00003967 ->getDefinition())
Douglas Gregor0b36e612010-08-31 20:37:03 +00003968 return MakeCXCursor(cast<CXXRecordDecl>(Def)->getDescribedClassTemplate(),
Ted Kremeneka60ed472010-11-16 08:15:36 +00003969 TU);
Douglas Gregorb6998662010-01-19 19:34:47 +00003970 return clang_getNullCursor();
3971 }
3972
Douglas Gregor1f60d9e2010-09-13 22:52:57 +00003973 case Decl::Using:
3974 return MakeCursorOverloadedDeclRef(cast<UsingDecl>(D),
Ted Kremeneka60ed472010-11-16 08:15:36 +00003975 D->getLocation(), TU);
Douglas Gregorb6998662010-01-19 19:34:47 +00003976
3977 case Decl::UsingShadow:
3978 return clang_getCursorDefinition(
Ted Kremenekf0e23e82010-02-17 00:41:40 +00003979 MakeCXCursor(cast<UsingShadowDecl>(D)->getTargetDecl(),
Ted Kremeneka60ed472010-11-16 08:15:36 +00003980 TU));
Douglas Gregorb6998662010-01-19 19:34:47 +00003981
3982 case Decl::ObjCMethod: {
3983 ObjCMethodDecl *Method = cast<ObjCMethodDecl>(D);
3984 if (Method->isThisDeclarationADefinition())
3985 return C;
3986
3987 // Dig out the method definition in the associated
3988 // @implementation, if we have it.
3989 // FIXME: The ASTs should make finding the definition easier.
3990 if (ObjCInterfaceDecl *Class
3991 = dyn_cast<ObjCInterfaceDecl>(Method->getDeclContext()))
3992 if (ObjCImplementationDecl *ClassImpl = Class->getImplementation())
3993 if (ObjCMethodDecl *Def = ClassImpl->getMethod(Method->getSelector(),
3994 Method->isInstanceMethod()))
3995 if (Def->isThisDeclarationADefinition())
Ted Kremeneka60ed472010-11-16 08:15:36 +00003996 return MakeCXCursor(Def, TU);
Douglas Gregorb6998662010-01-19 19:34:47 +00003997
3998 return clang_getNullCursor();
3999 }
4000
4001 case Decl::ObjCCategory:
4002 if (ObjCCategoryImplDecl *Impl
4003 = cast<ObjCCategoryDecl>(D)->getImplementation())
Ted Kremeneka60ed472010-11-16 08:15:36 +00004004 return MakeCXCursor(Impl, TU);
Douglas Gregorb6998662010-01-19 19:34:47 +00004005 return clang_getNullCursor();
4006
4007 case Decl::ObjCProtocol:
4008 if (!cast<ObjCProtocolDecl>(D)->isForwardDecl())
4009 return C;
4010 return clang_getNullCursor();
4011
4012 case Decl::ObjCInterface:
4013 // There are two notions of a "definition" for an Objective-C
4014 // class: the interface and its implementation. When we resolved a
4015 // reference to an Objective-C class, produce the @interface as
4016 // the definition; when we were provided with the interface,
4017 // produce the @implementation as the definition.
4018 if (WasReference) {
4019 if (!cast<ObjCInterfaceDecl>(D)->isForwardDecl())
4020 return C;
4021 } else if (ObjCImplementationDecl *Impl
4022 = cast<ObjCInterfaceDecl>(D)->getImplementation())
Ted Kremeneka60ed472010-11-16 08:15:36 +00004023 return MakeCXCursor(Impl, TU);
Douglas Gregorb6998662010-01-19 19:34:47 +00004024 return clang_getNullCursor();
Ted Kremenekf0e23e82010-02-17 00:41:40 +00004025
Douglas Gregorb6998662010-01-19 19:34:47 +00004026 case Decl::ObjCProperty:
4027 // FIXME: We don't really know where to find the
4028 // ObjCPropertyImplDecls that implement this property.
4029 return clang_getNullCursor();
4030
4031 case Decl::ObjCCompatibleAlias:
4032 if (ObjCInterfaceDecl *Class
4033 = cast<ObjCCompatibleAliasDecl>(D)->getClassInterface())
4034 if (!Class->isForwardDecl())
Ted Kremeneka60ed472010-11-16 08:15:36 +00004035 return MakeCXCursor(Class, TU);
Ted Kremenekf0e23e82010-02-17 00:41:40 +00004036
Douglas Gregorb6998662010-01-19 19:34:47 +00004037 return clang_getNullCursor();
4038
Douglas Gregor1f60d9e2010-09-13 22:52:57 +00004039 case Decl::ObjCForwardProtocol:
4040 return MakeCursorOverloadedDeclRef(cast<ObjCForwardProtocolDecl>(D),
Ted Kremeneka60ed472010-11-16 08:15:36 +00004041 D->getLocation(), TU);
Douglas Gregorb6998662010-01-19 19:34:47 +00004042
Douglas Gregor1f60d9e2010-09-13 22:52:57 +00004043 case Decl::ObjCClass:
Daniel Dunbar9e1ebdd2010-11-05 07:19:21 +00004044 return MakeCursorOverloadedDeclRef(cast<ObjCClassDecl>(D), D->getLocation(),
Ted Kremeneka60ed472010-11-16 08:15:36 +00004045 TU);
Douglas Gregorb6998662010-01-19 19:34:47 +00004046
4047 case Decl::Friend:
4048 if (NamedDecl *Friend = cast<FriendDecl>(D)->getFriendDecl())
Ted Kremeneka60ed472010-11-16 08:15:36 +00004049 return clang_getCursorDefinition(MakeCXCursor(Friend, TU));
Douglas Gregorb6998662010-01-19 19:34:47 +00004050 return clang_getNullCursor();
4051
4052 case Decl::FriendTemplate:
4053 if (NamedDecl *Friend = cast<FriendTemplateDecl>(D)->getFriendDecl())
Ted Kremeneka60ed472010-11-16 08:15:36 +00004054 return clang_getCursorDefinition(MakeCXCursor(Friend, TU));
Douglas Gregorb6998662010-01-19 19:34:47 +00004055 return clang_getNullCursor();
4056 }
4057
4058 return clang_getNullCursor();
4059}
4060
4061unsigned clang_isCursorDefinition(CXCursor C) {
4062 if (!clang_isDeclaration(C.kind))
4063 return 0;
4064
4065 return clang_getCursorDefinition(C) == C;
4066}
4067
Douglas Gregor1a9d0502010-11-19 23:44:15 +00004068CXCursor clang_getCanonicalCursor(CXCursor C) {
4069 if (!clang_isDeclaration(C.kind))
4070 return C;
4071
4072 if (Decl *D = getCursorDecl(C))
4073 return MakeCXCursor(D->getCanonicalDecl(), getCursorTU(C));
4074
4075 return C;
4076}
4077
Douglas Gregor1f60d9e2010-09-13 22:52:57 +00004078unsigned clang_getNumOverloadedDecls(CXCursor C) {
Douglas Gregor7c432dd2010-09-16 13:54:00 +00004079 if (C.kind != CXCursor_OverloadedDeclRef)
Douglas Gregor1f60d9e2010-09-13 22:52:57 +00004080 return 0;
4081
4082 OverloadedDeclRefStorage Storage = getCursorOverloadedDeclRef(C).first;
4083 if (OverloadExpr *E = Storage.dyn_cast<OverloadExpr *>())
4084 return E->getNumDecls();
4085
4086 if (OverloadedTemplateStorage *S
4087 = Storage.dyn_cast<OverloadedTemplateStorage*>())
4088 return S->size();
4089
4090 Decl *D = Storage.get<Decl*>();
4091 if (UsingDecl *Using = dyn_cast<UsingDecl>(D))
Argyrios Kyrtzidis826faa22010-11-10 05:40:41 +00004092 return Using->shadow_size();
Douglas Gregor1f60d9e2010-09-13 22:52:57 +00004093 if (ObjCClassDecl *Classes = dyn_cast<ObjCClassDecl>(D))
4094 return Classes->size();
4095 if (ObjCForwardProtocolDecl *Protocols =dyn_cast<ObjCForwardProtocolDecl>(D))
4096 return Protocols->protocol_size();
4097
4098 return 0;
4099}
4100
4101CXCursor clang_getOverloadedDecl(CXCursor cursor, unsigned index) {
Douglas Gregor7c432dd2010-09-16 13:54:00 +00004102 if (cursor.kind != CXCursor_OverloadedDeclRef)
Douglas Gregor1f60d9e2010-09-13 22:52:57 +00004103 return clang_getNullCursor();
4104
4105 if (index >= clang_getNumOverloadedDecls(cursor))
4106 return clang_getNullCursor();
4107
Ted Kremeneka60ed472010-11-16 08:15:36 +00004108 CXTranslationUnit TU = getCursorTU(cursor);
Douglas Gregor1f60d9e2010-09-13 22:52:57 +00004109 OverloadedDeclRefStorage Storage = getCursorOverloadedDeclRef(cursor).first;
4110 if (OverloadExpr *E = Storage.dyn_cast<OverloadExpr *>())
Ted Kremeneka60ed472010-11-16 08:15:36 +00004111 return MakeCXCursor(E->decls_begin()[index], TU);
Douglas Gregor1f60d9e2010-09-13 22:52:57 +00004112
4113 if (OverloadedTemplateStorage *S
4114 = Storage.dyn_cast<OverloadedTemplateStorage*>())
Ted Kremeneka60ed472010-11-16 08:15:36 +00004115 return MakeCXCursor(S->begin()[index], TU);
Douglas Gregor1f60d9e2010-09-13 22:52:57 +00004116
4117 Decl *D = Storage.get<Decl*>();
4118 if (UsingDecl *Using = dyn_cast<UsingDecl>(D)) {
4119 // FIXME: This is, unfortunately, linear time.
4120 UsingDecl::shadow_iterator Pos = Using->shadow_begin();
4121 std::advance(Pos, index);
Ted Kremeneka60ed472010-11-16 08:15:36 +00004122 return MakeCXCursor(cast<UsingShadowDecl>(*Pos)->getTargetDecl(), TU);
Douglas Gregor1f60d9e2010-09-13 22:52:57 +00004123 }
4124
4125 if (ObjCClassDecl *Classes = dyn_cast<ObjCClassDecl>(D))
Ted Kremeneka60ed472010-11-16 08:15:36 +00004126 return MakeCXCursor(Classes->begin()[index].getInterface(), TU);
Douglas Gregor1f60d9e2010-09-13 22:52:57 +00004127
4128 if (ObjCForwardProtocolDecl *Protocols = dyn_cast<ObjCForwardProtocolDecl>(D))
Ted Kremeneka60ed472010-11-16 08:15:36 +00004129 return MakeCXCursor(Protocols->protocol_begin()[index], TU);
Douglas Gregor1f60d9e2010-09-13 22:52:57 +00004130
4131 return clang_getNullCursor();
4132}
4133
Daniel Dunbar0d7dd222009-11-30 20:42:43 +00004134void clang_getDefinitionSpellingAndExtent(CXCursor C,
Steve Naroff4ade6d62009-09-23 17:52:52 +00004135 const char **startBuf,
4136 const char **endBuf,
4137 unsigned *startLine,
4138 unsigned *startColumn,
4139 unsigned *endLine,
Daniel Dunbar9ebfa312009-12-01 03:14:51 +00004140 unsigned *endColumn) {
Douglas Gregor283cae32010-01-15 21:56:13 +00004141 assert(getCursorDecl(C) && "CXCursor has null decl");
4142 NamedDecl *ND = static_cast<NamedDecl *>(getCursorDecl(C));
Steve Naroff4ade6d62009-09-23 17:52:52 +00004143 FunctionDecl *FD = dyn_cast<FunctionDecl>(ND);
4144 CompoundStmt *Body = dyn_cast<CompoundStmt>(FD->getBody());
Ted Kremenekf0e23e82010-02-17 00:41:40 +00004145
Steve Naroff4ade6d62009-09-23 17:52:52 +00004146 SourceManager &SM = FD->getASTContext().getSourceManager();
4147 *startBuf = SM.getCharacterData(Body->getLBracLoc());
4148 *endBuf = SM.getCharacterData(Body->getRBracLoc());
4149 *startLine = SM.getSpellingLineNumber(Body->getLBracLoc());
4150 *startColumn = SM.getSpellingColumnNumber(Body->getLBracLoc());
4151 *endLine = SM.getSpellingLineNumber(Body->getRBracLoc());
4152 *endColumn = SM.getSpellingColumnNumber(Body->getRBracLoc());
4153}
Ted Kremenekf0e23e82010-02-17 00:41:40 +00004154
Douglas Gregor0a812cf2010-02-18 23:07:20 +00004155void clang_enableStackTraces(void) {
4156 llvm::sys::PrintStackTraceOnErrorSignal();
4157}
4158
Daniel Dunbar995aaf92010-11-04 01:26:29 +00004159void clang_executeOnThread(void (*fn)(void*), void *user_data,
4160 unsigned stack_size) {
4161 llvm::llvm_execute_on_thread(fn, user_data, stack_size);
4162}
4163
Ted Kremenekfb480492010-01-13 21:46:36 +00004164} // end: extern "C"
Steve Naroff4ade6d62009-09-23 17:52:52 +00004165
Ted Kremenekfb480492010-01-13 21:46:36 +00004166//===----------------------------------------------------------------------===//
Douglas Gregorfc8ea232010-01-26 17:06:03 +00004167// Token-based Operations.
4168//===----------------------------------------------------------------------===//
4169
4170/* CXToken layout:
4171 * int_data[0]: a CXTokenKind
4172 * int_data[1]: starting token location
4173 * int_data[2]: token length
4174 * int_data[3]: reserved
Ted Kremenekf0e23e82010-02-17 00:41:40 +00004175 * ptr_data: for identifiers and keywords, an IdentifierInfo*.
Douglas Gregorfc8ea232010-01-26 17:06:03 +00004176 * otherwise unused.
4177 */
4178extern "C" {
4179
4180CXTokenKind clang_getTokenKind(CXToken CXTok) {
4181 return static_cast<CXTokenKind>(CXTok.int_data[0]);
4182}
4183
4184CXString clang_getTokenSpelling(CXTranslationUnit TU, CXToken CXTok) {
4185 switch (clang_getTokenKind(CXTok)) {
4186 case CXToken_Identifier:
4187 case CXToken_Keyword:
4188 // We know we have an IdentifierInfo*, so use that.
Ted Kremenekee4db4f2010-02-17 00:41:08 +00004189 return createCXString(static_cast<IdentifierInfo *>(CXTok.ptr_data)
4190 ->getNameStart());
Douglas Gregorfc8ea232010-01-26 17:06:03 +00004191
4192 case CXToken_Literal: {
4193 // We have stashed the starting pointer in the ptr_data field. Use it.
4194 const char *Text = static_cast<const char *>(CXTok.ptr_data);
Ted Kremenekee4db4f2010-02-17 00:41:08 +00004195 return createCXString(llvm::StringRef(Text, CXTok.int_data[2]));
Douglas Gregorfc8ea232010-01-26 17:06:03 +00004196 }
Ted Kremenekf0e23e82010-02-17 00:41:40 +00004197
Douglas Gregorfc8ea232010-01-26 17:06:03 +00004198 case CXToken_Punctuation:
4199 case CXToken_Comment:
4200 break;
4201 }
Ted Kremenekf0e23e82010-02-17 00:41:40 +00004202
4203 // We have to find the starting buffer pointer the hard way, by
Douglas Gregorfc8ea232010-01-26 17:06:03 +00004204 // deconstructing the source location.
Ted Kremeneka60ed472010-11-16 08:15:36 +00004205 ASTUnit *CXXUnit = static_cast<ASTUnit *>(TU->TUData);
Douglas Gregorfc8ea232010-01-26 17:06:03 +00004206 if (!CXXUnit)
Ted Kremenekee4db4f2010-02-17 00:41:08 +00004207 return createCXString("");
Ted Kremenekf0e23e82010-02-17 00:41:40 +00004208
Douglas Gregorfc8ea232010-01-26 17:06:03 +00004209 SourceLocation Loc = SourceLocation::getFromRawEncoding(CXTok.int_data[1]);
4210 std::pair<FileID, unsigned> LocInfo
4211 = CXXUnit->getSourceManager().getDecomposedLoc(Loc);
Douglas Gregorf715ca12010-03-16 00:06:06 +00004212 bool Invalid = false;
Benjamin Kramerf6ac97b2010-03-16 14:14:31 +00004213 llvm::StringRef Buffer
Douglas Gregorf715ca12010-03-16 00:06:06 +00004214 = CXXUnit->getSourceManager().getBufferData(LocInfo.first, &Invalid);
4215 if (Invalid)
Douglas Gregoraea67db2010-03-15 22:54:52 +00004216 return createCXString("");
Douglas Gregorfc8ea232010-01-26 17:06:03 +00004217
Benjamin Kramerf6ac97b2010-03-16 14:14:31 +00004218 return createCXString(Buffer.substr(LocInfo.second, CXTok.int_data[2]));
Douglas Gregorfc8ea232010-01-26 17:06:03 +00004219}
Ted Kremenekf0e23e82010-02-17 00:41:40 +00004220
Douglas Gregorfc8ea232010-01-26 17:06:03 +00004221CXSourceLocation clang_getTokenLocation(CXTranslationUnit TU, CXToken CXTok) {
Ted Kremeneka60ed472010-11-16 08:15:36 +00004222 ASTUnit *CXXUnit = static_cast<ASTUnit *>(TU->TUData);
Douglas Gregorfc8ea232010-01-26 17:06:03 +00004223 if (!CXXUnit)
4224 return clang_getNullLocation();
Ted Kremenekf0e23e82010-02-17 00:41:40 +00004225
Douglas Gregorfc8ea232010-01-26 17:06:03 +00004226 return cxloc::translateSourceLocation(CXXUnit->getASTContext(),
4227 SourceLocation::getFromRawEncoding(CXTok.int_data[1]));
4228}
4229
4230CXSourceRange clang_getTokenExtent(CXTranslationUnit TU, CXToken CXTok) {
Ted Kremeneka60ed472010-11-16 08:15:36 +00004231 ASTUnit *CXXUnit = static_cast<ASTUnit *>(TU->TUData);
Douglas Gregor5352ac02010-01-28 00:27:43 +00004232 if (!CXXUnit)
4233 return clang_getNullRange();
Ted Kremenekf0e23e82010-02-17 00:41:40 +00004234
4235 return cxloc::translateSourceRange(CXXUnit->getASTContext(),
Douglas Gregorfc8ea232010-01-26 17:06:03 +00004236 SourceLocation::getFromRawEncoding(CXTok.int_data[1]));
4237}
Ted Kremenekf0e23e82010-02-17 00:41:40 +00004238
Douglas Gregorfc8ea232010-01-26 17:06:03 +00004239void clang_tokenize(CXTranslationUnit TU, CXSourceRange Range,
4240 CXToken **Tokens, unsigned *NumTokens) {
4241 if (Tokens)
4242 *Tokens = 0;
4243 if (NumTokens)
4244 *NumTokens = 0;
Ted Kremenekf0e23e82010-02-17 00:41:40 +00004245
Ted Kremeneka60ed472010-11-16 08:15:36 +00004246 ASTUnit *CXXUnit = static_cast<ASTUnit *>(TU->TUData);
Douglas Gregorfc8ea232010-01-26 17:06:03 +00004247 if (!CXXUnit || !Tokens || !NumTokens)
4248 return;
Ted Kremenekf0e23e82010-02-17 00:41:40 +00004249
Douglas Gregorbdf60622010-03-05 21:16:25 +00004250 ASTUnit::ConcurrencyCheck Check(*CXXUnit);
4251
Daniel Dunbar85b988f2010-02-14 08:31:57 +00004252 SourceRange R = cxloc::translateCXSourceRange(Range);
Douglas Gregorfc8ea232010-01-26 17:06:03 +00004253 if (R.isInvalid())
4254 return;
Ted Kremenekf0e23e82010-02-17 00:41:40 +00004255
Douglas Gregorfc8ea232010-01-26 17:06:03 +00004256 SourceManager &SourceMgr = CXXUnit->getSourceManager();
4257 std::pair<FileID, unsigned> BeginLocInfo
4258 = SourceMgr.getDecomposedLoc(R.getBegin());
4259 std::pair<FileID, unsigned> EndLocInfo
4260 = SourceMgr.getDecomposedLoc(R.getEnd());
Ted Kremenekf0e23e82010-02-17 00:41:40 +00004261
Douglas Gregorfc8ea232010-01-26 17:06:03 +00004262 // Cannot tokenize across files.
4263 if (BeginLocInfo.first != EndLocInfo.first)
4264 return;
Ted Kremenekf0e23e82010-02-17 00:41:40 +00004265
4266 // Create a lexer
Douglas Gregorf715ca12010-03-16 00:06:06 +00004267 bool Invalid = false;
Benjamin Kramerf6ac97b2010-03-16 14:14:31 +00004268 llvm::StringRef Buffer
Douglas Gregorf715ca12010-03-16 00:06:06 +00004269 = SourceMgr.getBufferData(BeginLocInfo.first, &Invalid);
Douglas Gregor47a3fcd2010-03-16 20:26:15 +00004270 if (Invalid)
4271 return;
Douglas Gregoraea67db2010-03-15 22:54:52 +00004272
Douglas Gregorfc8ea232010-01-26 17:06:03 +00004273 Lexer Lex(SourceMgr.getLocForStartOfFile(BeginLocInfo.first),
4274 CXXUnit->getASTContext().getLangOptions(),
Benjamin Kramerf6ac97b2010-03-16 14:14:31 +00004275 Buffer.begin(), Buffer.data() + BeginLocInfo.second, Buffer.end());
Douglas Gregorfc8ea232010-01-26 17:06:03 +00004276 Lex.SetCommentRetentionState(true);
Ted Kremenekf0e23e82010-02-17 00:41:40 +00004277
Douglas Gregorfc8ea232010-01-26 17:06:03 +00004278 // Lex tokens until we hit the end of the range.
Benjamin Kramerf6ac97b2010-03-16 14:14:31 +00004279 const char *EffectiveBufferEnd = Buffer.data() + EndLocInfo.second;
Douglas Gregorfc8ea232010-01-26 17:06:03 +00004280 llvm::SmallVector<CXToken, 32> CXTokens;
4281 Token Tok;
David Chisnall096428b2010-10-13 21:44:48 +00004282 bool previousWasAt = false;
Douglas Gregorfc8ea232010-01-26 17:06:03 +00004283 do {
4284 // Lex the next token
4285 Lex.LexFromRawLexer(Tok);
4286 if (Tok.is(tok::eof))
4287 break;
Ted Kremenekf0e23e82010-02-17 00:41:40 +00004288
Douglas Gregorfc8ea232010-01-26 17:06:03 +00004289 // Initialize the CXToken.
4290 CXToken CXTok;
Ted Kremenekf0e23e82010-02-17 00:41:40 +00004291
Douglas Gregorfc8ea232010-01-26 17:06:03 +00004292 // - Common fields
4293 CXTok.int_data[1] = Tok.getLocation().getRawEncoding();
4294 CXTok.int_data[2] = Tok.getLength();
4295 CXTok.int_data[3] = 0;
Ted Kremenekf0e23e82010-02-17 00:41:40 +00004296
Douglas Gregorfc8ea232010-01-26 17:06:03 +00004297 // - Kind-specific fields
4298 if (Tok.isLiteral()) {
4299 CXTok.int_data[0] = CXToken_Literal;
4300 CXTok.ptr_data = (void *)Tok.getLiteralData();
Abramo Bagnarac4bf2b92010-12-22 08:23:18 +00004301 } else if (Tok.is(tok::raw_identifier)) {
Douglas Gregoraea67db2010-03-15 22:54:52 +00004302 // Lookup the identifier to determine whether we have a keyword.
Douglas Gregorfc8ea232010-01-26 17:06:03 +00004303 IdentifierInfo *II
Abramo Bagnarac4bf2b92010-12-22 08:23:18 +00004304 = CXXUnit->getPreprocessor().LookUpIdentifierInfo(Tok);
Ted Kremenekaa8a66d2010-05-05 00:55:20 +00004305
David Chisnall096428b2010-10-13 21:44:48 +00004306 if ((II->getObjCKeywordID() != tok::objc_not_keyword) && previousWasAt) {
Ted Kremenekaa8a66d2010-05-05 00:55:20 +00004307 CXTok.int_data[0] = CXToken_Keyword;
4308 }
4309 else {
Abramo Bagnarac4bf2b92010-12-22 08:23:18 +00004310 CXTok.int_data[0] = Tok.is(tok::identifier)
4311 ? CXToken_Identifier
4312 : CXToken_Keyword;
Ted Kremenekaa8a66d2010-05-05 00:55:20 +00004313 }
Douglas Gregorfc8ea232010-01-26 17:06:03 +00004314 CXTok.ptr_data = II;
4315 } else if (Tok.is(tok::comment)) {
4316 CXTok.int_data[0] = CXToken_Comment;
4317 CXTok.ptr_data = 0;
4318 } else {
4319 CXTok.int_data[0] = CXToken_Punctuation;
4320 CXTok.ptr_data = 0;
4321 }
4322 CXTokens.push_back(CXTok);
David Chisnall096428b2010-10-13 21:44:48 +00004323 previousWasAt = Tok.is(tok::at);
Douglas Gregorfc8ea232010-01-26 17:06:03 +00004324 } while (Lex.getBufferLocation() <= EffectiveBufferEnd);
Ted Kremenekf0e23e82010-02-17 00:41:40 +00004325
Douglas Gregorfc8ea232010-01-26 17:06:03 +00004326 if (CXTokens.empty())
4327 return;
Ted Kremenekf0e23e82010-02-17 00:41:40 +00004328
Douglas Gregorfc8ea232010-01-26 17:06:03 +00004329 *Tokens = (CXToken *)malloc(sizeof(CXToken) * CXTokens.size());
4330 memmove(*Tokens, CXTokens.data(), sizeof(CXToken) * CXTokens.size());
4331 *NumTokens = CXTokens.size();
4332}
Douglas Gregor0045e9f2010-01-26 18:31:56 +00004333
Ted Kremenek6db61092010-05-05 00:55:15 +00004334void clang_disposeTokens(CXTranslationUnit TU,
4335 CXToken *Tokens, unsigned NumTokens) {
4336 free(Tokens);
4337}
4338
4339} // end: extern "C"
4340
4341//===----------------------------------------------------------------------===//
4342// Token annotation APIs.
4343//===----------------------------------------------------------------------===//
4344
Douglas Gregor0045e9f2010-01-26 18:31:56 +00004345typedef llvm::DenseMap<unsigned, CXCursor> AnnotateTokensData;
Ted Kremenekfbd84ca2010-05-05 00:55:23 +00004346static enum CXChildVisitResult AnnotateTokensVisitor(CXCursor cursor,
4347 CXCursor parent,
4348 CXClientData client_data);
Ted Kremenek6db61092010-05-05 00:55:15 +00004349namespace {
4350class AnnotateTokensWorker {
4351 AnnotateTokensData &Annotated;
Ted Kremenek11949cb2010-05-05 00:55:17 +00004352 CXToken *Tokens;
4353 CXCursor *Cursors;
4354 unsigned NumTokens;
Ted Kremenekfbd84ca2010-05-05 00:55:23 +00004355 unsigned TokIdx;
Douglas Gregor4419b672010-10-21 06:10:04 +00004356 unsigned PreprocessingTokIdx;
Ted Kremenekfbd84ca2010-05-05 00:55:23 +00004357 CursorVisitor AnnotateVis;
4358 SourceManager &SrcMgr;
Douglas Gregorf5251602011-03-08 17:10:18 +00004359 bool HasContextSensitiveKeywords;
4360
Ted Kremenekfbd84ca2010-05-05 00:55:23 +00004361 bool MoreTokens() const { return TokIdx < NumTokens; }
4362 unsigned NextToken() const { return TokIdx; }
4363 void AdvanceToken() { ++TokIdx; }
4364 SourceLocation GetTokenLoc(unsigned tokI) {
4365 return SourceLocation::getFromRawEncoding(Tokens[tokI].int_data[1]);
4366 }
4367
Ted Kremenek6db61092010-05-05 00:55:15 +00004368public:
Ted Kremenek11949cb2010-05-05 00:55:17 +00004369 AnnotateTokensWorker(AnnotateTokensData &annotated,
Ted Kremenekfbd84ca2010-05-05 00:55:23 +00004370 CXToken *tokens, CXCursor *cursors, unsigned numTokens,
Ted Kremeneka60ed472010-11-16 08:15:36 +00004371 CXTranslationUnit tu, SourceRange RegionOfInterest)
Ted Kremenek11949cb2010-05-05 00:55:17 +00004372 : Annotated(annotated), Tokens(tokens), Cursors(cursors),
Douglas Gregor4419b672010-10-21 06:10:04 +00004373 NumTokens(numTokens), TokIdx(0), PreprocessingTokIdx(0),
Ted Kremeneka60ed472010-11-16 08:15:36 +00004374 AnnotateVis(tu,
4375 AnnotateTokensVisitor, this,
Douglas Gregor04a9eb32011-03-16 23:23:30 +00004376 Decl::MaxPCHLevel, true, RegionOfInterest),
Douglas Gregorf5251602011-03-08 17:10:18 +00004377 SrcMgr(static_cast<ASTUnit*>(tu->TUData)->getSourceManager()),
4378 HasContextSensitiveKeywords(false) { }
Ted Kremenek11949cb2010-05-05 00:55:17 +00004379
Ted Kremenekfbd84ca2010-05-05 00:55:23 +00004380 void VisitChildren(CXCursor C) { AnnotateVis.VisitChildren(C); }
Ted Kremenek6db61092010-05-05 00:55:15 +00004381 enum CXChildVisitResult Visit(CXCursor cursor, CXCursor parent);
Ted Kremenekfbd84ca2010-05-05 00:55:23 +00004382 void AnnotateTokens(CXCursor parent);
Ted Kremenekab979612010-11-11 08:05:23 +00004383 void AnnotateTokens() {
Ted Kremeneka60ed472010-11-16 08:15:36 +00004384 AnnotateTokens(clang_getTranslationUnitCursor(AnnotateVis.getTU()));
Ted Kremenekab979612010-11-11 08:05:23 +00004385 }
Douglas Gregorf5251602011-03-08 17:10:18 +00004386
4387 /// \brief Determine whether the annotator saw any cursors that have
4388 /// context-sensitive keywords.
4389 bool hasContextSensitiveKeywords() const {
4390 return HasContextSensitiveKeywords;
4391 }
Ted Kremenek6db61092010-05-05 00:55:15 +00004392};
4393}
Douglas Gregor0045e9f2010-01-26 18:31:56 +00004394
Ted Kremenekfbd84ca2010-05-05 00:55:23 +00004395void AnnotateTokensWorker::AnnotateTokens(CXCursor parent) {
4396 // Walk the AST within the region of interest, annotating tokens
4397 // along the way.
4398 VisitChildren(parent);
Ted Kremenek11949cb2010-05-05 00:55:17 +00004399
Ted Kremenekfbd84ca2010-05-05 00:55:23 +00004400 for (unsigned I = 0 ; I < TokIdx ; ++I) {
4401 AnnotateTokensData::iterator Pos = Annotated.find(Tokens[I].int_data[1]);
Douglas Gregor4419b672010-10-21 06:10:04 +00004402 if (Pos != Annotated.end() &&
4403 (clang_isInvalid(Cursors[I].kind) ||
4404 Pos->second.kind != CXCursor_PreprocessingDirective))
Ted Kremenekfbd84ca2010-05-05 00:55:23 +00004405 Cursors[I] = Pos->second;
4406 }
4407
4408 // Finish up annotating any tokens left.
4409 if (!MoreTokens())
4410 return;
4411
4412 const CXCursor &C = clang_getNullCursor();
4413 for (unsigned I = TokIdx ; I < NumTokens ; ++I) {
4414 AnnotateTokensData::iterator Pos = Annotated.find(Tokens[I].int_data[1]);
4415 Cursors[I] = (Pos == Annotated.end()) ? C : Pos->second;
Ted Kremenek11949cb2010-05-05 00:55:17 +00004416 }
4417}
4418
Ted Kremenek6db61092010-05-05 00:55:15 +00004419enum CXChildVisitResult
Douglas Gregor4419b672010-10-21 06:10:04 +00004420AnnotateTokensWorker::Visit(CXCursor cursor, CXCursor parent) {
Ted Kremenekfbd84ca2010-05-05 00:55:23 +00004421 CXSourceLocation Loc = clang_getCursorLocation(cursor);
Douglas Gregor4419b672010-10-21 06:10:04 +00004422 SourceRange cursorRange = getRawCursorExtent(cursor);
Douglas Gregor81d3c042010-11-01 20:13:04 +00004423 if (cursorRange.isInvalid())
4424 return CXChildVisit_Recurse;
Douglas Gregorf5251602011-03-08 17:10:18 +00004425
4426 if (!HasContextSensitiveKeywords) {
4427 // Objective-C properties can have context-sensitive keywords.
4428 if (cursor.kind == CXCursor_ObjCPropertyDecl) {
4429 if (ObjCPropertyDecl *Property
4430 = dyn_cast_or_null<ObjCPropertyDecl>(getCursorDecl(cursor)))
4431 HasContextSensitiveKeywords = Property->getPropertyAttributesAsWritten() != 0;
4432 }
4433 // Objective-C methods can have context-sensitive keywords.
4434 else if (cursor.kind == CXCursor_ObjCInstanceMethodDecl ||
4435 cursor.kind == CXCursor_ObjCClassMethodDecl) {
4436 if (ObjCMethodDecl *Method
4437 = dyn_cast_or_null<ObjCMethodDecl>(getCursorDecl(cursor))) {
4438 if (Method->getObjCDeclQualifier())
4439 HasContextSensitiveKeywords = true;
4440 else {
4441 for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
4442 PEnd = Method->param_end();
4443 P != PEnd; ++P) {
4444 if ((*P)->getObjCDeclQualifier()) {
4445 HasContextSensitiveKeywords = true;
4446 break;
4447 }
4448 }
4449 }
4450 }
4451 }
4452 // C++ methods can have context-sensitive keywords.
4453 else if (cursor.kind == CXCursor_CXXMethod) {
4454 if (CXXMethodDecl *Method
4455 = dyn_cast_or_null<CXXMethodDecl>(getCursorDecl(cursor))) {
4456 if (Method->hasAttr<FinalAttr>() || Method->hasAttr<OverrideAttr>())
4457 HasContextSensitiveKeywords = true;
4458 }
4459 }
4460 // C++ classes can have context-sensitive keywords.
4461 else if (cursor.kind == CXCursor_StructDecl ||
4462 cursor.kind == CXCursor_ClassDecl ||
4463 cursor.kind == CXCursor_ClassTemplate ||
4464 cursor.kind == CXCursor_ClassTemplatePartialSpecialization) {
4465 if (Decl *D = getCursorDecl(cursor))
4466 if (D->hasAttr<FinalAttr>())
4467 HasContextSensitiveKeywords = true;
4468 }
4469 }
4470
Douglas Gregor4419b672010-10-21 06:10:04 +00004471 if (clang_isPreprocessing(cursor.kind)) {
4472 // For macro instantiations, just note where the beginning of the macro
4473 // instantiation occurs.
4474 if (cursor.kind == CXCursor_MacroInstantiation) {
4475 Annotated[Loc.int_data] = cursor;
4476 return CXChildVisit_Recurse;
4477 }
4478
Douglas Gregor4419b672010-10-21 06:10:04 +00004479 // Items in the preprocessing record are kept separate from items in
4480 // declarations, so we keep a separate token index.
4481 unsigned SavedTokIdx = TokIdx;
4482 TokIdx = PreprocessingTokIdx;
4483
4484 // Skip tokens up until we catch up to the beginning of the preprocessing
4485 // entry.
4486 while (MoreTokens()) {
4487 const unsigned I = NextToken();
4488 SourceLocation TokLoc = GetTokenLoc(I);
4489 switch (LocationCompare(SrcMgr, TokLoc, cursorRange)) {
4490 case RangeBefore:
4491 AdvanceToken();
4492 continue;
4493 case RangeAfter:
4494 case RangeOverlap:
4495 break;
4496 }
4497 break;
4498 }
4499
4500 // Look at all of the tokens within this range.
4501 while (MoreTokens()) {
4502 const unsigned I = NextToken();
4503 SourceLocation TokLoc = GetTokenLoc(I);
4504 switch (LocationCompare(SrcMgr, TokLoc, cursorRange)) {
4505 case RangeBefore:
4506 assert(0 && "Infeasible");
4507 case RangeAfter:
4508 break;
4509 case RangeOverlap:
4510 Cursors[I] = cursor;
4511 AdvanceToken();
4512 continue;
4513 }
4514 break;
4515 }
4516
4517 // Save the preprocessing token index; restore the non-preprocessing
4518 // token index.
4519 PreprocessingTokIdx = TokIdx;
4520 TokIdx = SavedTokIdx;
Douglas Gregor0045e9f2010-01-26 18:31:56 +00004521 return CXChildVisit_Recurse;
4522 }
Ted Kremenekfbd84ca2010-05-05 00:55:23 +00004523
Ted Kremenekfbd84ca2010-05-05 00:55:23 +00004524 if (cursorRange.isInvalid())
4525 return CXChildVisit_Continue;
Ted Kremeneka333c662010-05-12 05:29:33 +00004526
Ted Kremenekfbd84ca2010-05-05 00:55:23 +00004527 SourceLocation L = SourceLocation::getFromRawEncoding(Loc.int_data);
4528
Ted Kremeneka333c662010-05-12 05:29:33 +00004529 // Adjust the annotated range based specific declarations.
4530 const enum CXCursorKind cursorK = clang_getCursorKind(cursor);
4531 if (cursorK >= CXCursor_FirstDecl && cursorK <= CXCursor_LastDecl) {
Ted Kremenek23173d72010-05-18 21:09:07 +00004532 Decl *D = cxcursor::getCursorDecl(cursor);
4533 // Don't visit synthesized ObjC methods, since they have no syntatic
4534 // representation in the source.
4535 if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
4536 if (MD->isSynthesized())
4537 return CXChildVisit_Continue;
4538 }
Douglas Gregor2494dd02011-03-01 01:34:45 +00004539
4540 SourceLocation StartLoc;
Ted Kremenek23173d72010-05-18 21:09:07 +00004541 if (const DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(D)) {
Douglas Gregor2494dd02011-03-01 01:34:45 +00004542 if (TypeSourceInfo *TI = DD->getTypeSourceInfo())
4543 StartLoc = TI->getTypeLoc().getSourceRange().getBegin();
4544 } else if (TypedefDecl *Typedef = dyn_cast<TypedefDecl>(D)) {
4545 if (TypeSourceInfo *TI = Typedef->getTypeSourceInfo())
4546 StartLoc = TI->getTypeLoc().getSourceRange().getBegin();
Ted Kremeneka333c662010-05-12 05:29:33 +00004547 }
Douglas Gregor2494dd02011-03-01 01:34:45 +00004548
4549 if (StartLoc.isValid() && L.isValid() &&
4550 SrcMgr.isBeforeInTranslationUnit(StartLoc, L))
4551 cursorRange.setBegin(StartLoc);
Ted Kremeneka333c662010-05-12 05:29:33 +00004552 }
Douglas Gregor81d3c042010-11-01 20:13:04 +00004553
Ted Kremenek3f404602010-08-14 01:14:06 +00004554 // If the location of the cursor occurs within a macro instantiation, record
4555 // the spelling location of the cursor in our annotation map. We can then
4556 // paper over the token labelings during a post-processing step to try and
4557 // get cursor mappings for tokens that are the *arguments* of a macro
4558 // instantiation.
4559 if (L.isMacroID()) {
4560 unsigned rawEncoding = SrcMgr.getSpellingLoc(L).getRawEncoding();
4561 // Only invalidate the old annotation if it isn't part of a preprocessing
4562 // directive. Here we assume that the default construction of CXCursor
4563 // results in CXCursor.kind being an initialized value (i.e., 0). If
4564 // this isn't the case, we can fix by doing lookup + insertion.
Douglas Gregor4419b672010-10-21 06:10:04 +00004565
Ted Kremenek3f404602010-08-14 01:14:06 +00004566 CXCursor &oldC = Annotated[rawEncoding];
4567 if (!clang_isPreprocessing(oldC.kind))
4568 oldC = cursor;
4569 }
4570
Ted Kremenekfbd84ca2010-05-05 00:55:23 +00004571 const enum CXCursorKind K = clang_getCursorKind(parent);
4572 const CXCursor updateC =
Ted Kremenekd8b0a842010-08-25 22:16:02 +00004573 (clang_isInvalid(K) || K == CXCursor_TranslationUnit)
4574 ? clang_getNullCursor() : parent;
Ted Kremenekfbd84ca2010-05-05 00:55:23 +00004575
4576 while (MoreTokens()) {
4577 const unsigned I = NextToken();
4578 SourceLocation TokLoc = GetTokenLoc(I);
4579 switch (LocationCompare(SrcMgr, TokLoc, cursorRange)) {
4580 case RangeBefore:
4581 Cursors[I] = updateC;
4582 AdvanceToken();
4583 continue;
4584 case RangeAfter:
Ted Kremenekfbd84ca2010-05-05 00:55:23 +00004585 case RangeOverlap:
4586 break;
4587 }
4588 break;
4589 }
4590
4591 // Visit children to get their cursor information.
4592 const unsigned BeforeChildren = NextToken();
4593 VisitChildren(cursor);
4594 const unsigned AfterChildren = NextToken();
4595
4596 // Adjust 'Last' to the last token within the extent of the cursor.
4597 while (MoreTokens()) {
4598 const unsigned I = NextToken();
4599 SourceLocation TokLoc = GetTokenLoc(I);
4600 switch (LocationCompare(SrcMgr, TokLoc, cursorRange)) {
4601 case RangeBefore:
4602 assert(0 && "Infeasible");
4603 case RangeAfter:
4604 break;
4605 case RangeOverlap:
4606 Cursors[I] = updateC;
4607 AdvanceToken();
4608 continue;
4609 }
4610 break;
4611 }
4612 const unsigned Last = NextToken();
Ted Kremenek6db61092010-05-05 00:55:15 +00004613
Ted Kremenekfbd84ca2010-05-05 00:55:23 +00004614 // Scan the tokens that are at the beginning of the cursor, but are not
4615 // capture by the child cursors.
4616
4617 // For AST elements within macros, rely on a post-annotate pass to
4618 // to correctly annotate the tokens with cursors. Otherwise we can
4619 // get confusing results of having tokens that map to cursors that really
4620 // are expanded by an instantiation.
4621 if (L.isMacroID())
4622 cursor = clang_getNullCursor();
4623
4624 for (unsigned I = BeforeChildren; I != AfterChildren; ++I) {
4625 if (!clang_isInvalid(clang_getCursorKind(Cursors[I])))
4626 break;
Douglas Gregor4419b672010-10-21 06:10:04 +00004627
Ted Kremenekfbd84ca2010-05-05 00:55:23 +00004628 Cursors[I] = cursor;
4629 }
4630 // Scan the tokens that are at the end of the cursor, but are not captured
4631 // but the child cursors.
4632 for (unsigned I = AfterChildren; I != Last; ++I)
4633 Cursors[I] = cursor;
4634
4635 TokIdx = Last;
4636 return CXChildVisit_Continue;
Douglas Gregor0045e9f2010-01-26 18:31:56 +00004637}
4638
Ted Kremenek6db61092010-05-05 00:55:15 +00004639static enum CXChildVisitResult AnnotateTokensVisitor(CXCursor cursor,
4640 CXCursor parent,
4641 CXClientData client_data) {
4642 return static_cast<AnnotateTokensWorker*>(client_data)->Visit(cursor, parent);
4643}
4644
Ted Kremenek6628a612011-03-18 22:51:30 +00004645namespace {
4646 struct clang_annotateTokens_Data {
4647 CXTranslationUnit TU;
4648 ASTUnit *CXXUnit;
4649 CXToken *Tokens;
4650 unsigned NumTokens;
4651 CXCursor *Cursors;
4652 };
4653}
4654
Ted Kremenekab979612010-11-11 08:05:23 +00004655// This gets run a separate thread to avoid stack blowout.
Ted Kremenek6628a612011-03-18 22:51:30 +00004656static void clang_annotateTokensImpl(void *UserData) {
4657 CXTranslationUnit TU = ((clang_annotateTokens_Data*)UserData)->TU;
4658 ASTUnit *CXXUnit = ((clang_annotateTokens_Data*)UserData)->CXXUnit;
4659 CXToken *Tokens = ((clang_annotateTokens_Data*)UserData)->Tokens;
4660 const unsigned NumTokens = ((clang_annotateTokens_Data*)UserData)->NumTokens;
4661 CXCursor *Cursors = ((clang_annotateTokens_Data*)UserData)->Cursors;
4662
4663 // Determine the region of interest, which contains all of the tokens.
4664 SourceRange RegionOfInterest;
4665 RegionOfInterest.setBegin(
4666 cxloc::translateSourceLocation(clang_getTokenLocation(TU, Tokens[0])));
4667 RegionOfInterest.setEnd(
4668 cxloc::translateSourceLocation(clang_getTokenLocation(TU,
4669 Tokens[NumTokens-1])));
4670
4671 // A mapping from the source locations found when re-lexing or traversing the
4672 // region of interest to the corresponding cursors.
4673 AnnotateTokensData Annotated;
4674
4675 // Relex the tokens within the source range to look for preprocessing
4676 // directives.
4677 SourceManager &SourceMgr = CXXUnit->getSourceManager();
4678 std::pair<FileID, unsigned> BeginLocInfo
4679 = SourceMgr.getDecomposedLoc(RegionOfInterest.getBegin());
4680 std::pair<FileID, unsigned> EndLocInfo
4681 = SourceMgr.getDecomposedLoc(RegionOfInterest.getEnd());
4682
4683 llvm::StringRef Buffer;
4684 bool Invalid = false;
4685 if (BeginLocInfo.first == EndLocInfo.first &&
4686 ((Buffer = SourceMgr.getBufferData(BeginLocInfo.first, &Invalid)),true) &&
4687 !Invalid) {
4688 Lexer Lex(SourceMgr.getLocForStartOfFile(BeginLocInfo.first),
4689 CXXUnit->getASTContext().getLangOptions(),
4690 Buffer.begin(), Buffer.data() + BeginLocInfo.second,
4691 Buffer.end());
4692 Lex.SetCommentRetentionState(true);
4693
4694 // Lex tokens in raw mode until we hit the end of the range, to avoid
4695 // entering #includes or expanding macros.
4696 while (true) {
4697 Token Tok;
4698 Lex.LexFromRawLexer(Tok);
4699
4700 reprocess:
4701 if (Tok.is(tok::hash) && Tok.isAtStartOfLine()) {
4702 // We have found a preprocessing directive. Gobble it up so that we
4703 // don't see it while preprocessing these tokens later, but keep track
4704 // of all of the token locations inside this preprocessing directive so
4705 // that we can annotate them appropriately.
4706 //
4707 // FIXME: Some simple tests here could identify macro definitions and
4708 // #undefs, to provide specific cursor kinds for those.
4709 llvm::SmallVector<SourceLocation, 32> Locations;
4710 do {
4711 Locations.push_back(Tok.getLocation());
4712 Lex.LexFromRawLexer(Tok);
4713 } while (!Tok.isAtStartOfLine() && !Tok.is(tok::eof));
4714
4715 using namespace cxcursor;
4716 CXCursor Cursor
4717 = MakePreprocessingDirectiveCursor(SourceRange(Locations.front(),
4718 Locations.back()),
4719 TU);
4720 for (unsigned I = 0, N = Locations.size(); I != N; ++I) {
4721 Annotated[Locations[I].getRawEncoding()] = Cursor;
4722 }
4723
4724 if (Tok.isAtStartOfLine())
4725 goto reprocess;
4726
4727 continue;
4728 }
4729
4730 if (Tok.is(tok::eof))
4731 break;
4732 }
4733 }
4734
4735 // Annotate all of the source locations in the region of interest that map to
4736 // a specific cursor.
4737 AnnotateTokensWorker W(Annotated, Tokens, Cursors, NumTokens,
4738 TU, RegionOfInterest);
4739
4740 // FIXME: We use a ridiculous stack size here because the data-recursion
4741 // algorithm uses a large stack frame than the non-data recursive version,
4742 // and AnnotationTokensWorker currently transforms the data-recursion
4743 // algorithm back into a traditional recursion by explicitly calling
4744 // VisitChildren(). We will need to remove this explicit recursive call.
4745 W.AnnotateTokens();
4746
4747 // If we ran into any entities that involve context-sensitive keywords,
4748 // take another pass through the tokens to mark them as such.
4749 if (W.hasContextSensitiveKeywords()) {
4750 for (unsigned I = 0; I != NumTokens; ++I) {
4751 if (clang_getTokenKind(Tokens[I]) != CXToken_Identifier)
4752 continue;
4753
4754 if (Cursors[I].kind == CXCursor_ObjCPropertyDecl) {
4755 IdentifierInfo *II = static_cast<IdentifierInfo *>(Tokens[I].ptr_data);
4756 if (ObjCPropertyDecl *Property
4757 = dyn_cast_or_null<ObjCPropertyDecl>(getCursorDecl(Cursors[I]))) {
4758 if (Property->getPropertyAttributesAsWritten() != 0 &&
4759 llvm::StringSwitch<bool>(II->getName())
4760 .Case("readonly", true)
4761 .Case("assign", true)
4762 .Case("readwrite", true)
4763 .Case("retain", true)
4764 .Case("copy", true)
4765 .Case("nonatomic", true)
4766 .Case("atomic", true)
4767 .Case("getter", true)
4768 .Case("setter", true)
4769 .Default(false))
4770 Tokens[I].int_data[0] = CXToken_Keyword;
4771 }
4772 continue;
4773 }
4774
4775 if (Cursors[I].kind == CXCursor_ObjCInstanceMethodDecl ||
4776 Cursors[I].kind == CXCursor_ObjCClassMethodDecl) {
4777 IdentifierInfo *II = static_cast<IdentifierInfo *>(Tokens[I].ptr_data);
4778 if (llvm::StringSwitch<bool>(II->getName())
4779 .Case("in", true)
4780 .Case("out", true)
4781 .Case("inout", true)
4782 .Case("oneway", true)
4783 .Case("bycopy", true)
4784 .Case("byref", true)
4785 .Default(false))
4786 Tokens[I].int_data[0] = CXToken_Keyword;
4787 continue;
4788 }
4789
4790 if (Cursors[I].kind == CXCursor_CXXMethod) {
4791 IdentifierInfo *II = static_cast<IdentifierInfo *>(Tokens[I].ptr_data);
4792 if (CXXMethodDecl *Method
4793 = dyn_cast_or_null<CXXMethodDecl>(getCursorDecl(Cursors[I]))) {
4794 if ((Method->hasAttr<FinalAttr>() ||
4795 Method->hasAttr<OverrideAttr>()) &&
4796 Method->getLocation().getRawEncoding() != Tokens[I].int_data[1] &&
4797 llvm::StringSwitch<bool>(II->getName())
4798 .Case("final", true)
4799 .Case("override", true)
4800 .Default(false))
4801 Tokens[I].int_data[0] = CXToken_Keyword;
4802 }
4803 continue;
4804 }
4805
4806 if (Cursors[I].kind == CXCursor_ClassDecl ||
4807 Cursors[I].kind == CXCursor_StructDecl ||
4808 Cursors[I].kind == CXCursor_ClassTemplate) {
4809 IdentifierInfo *II = static_cast<IdentifierInfo *>(Tokens[I].ptr_data);
4810 if (II->getName() == "final") {
4811 // We have to be careful with 'final', since it could be the name
4812 // of a member class rather than the context-sensitive keyword.
4813 // So, check whether the cursor associated with this
4814 Decl *D = getCursorDecl(Cursors[I]);
4815 if (CXXRecordDecl *Record = dyn_cast_or_null<CXXRecordDecl>(D)) {
4816 if ((Record->hasAttr<FinalAttr>()) &&
4817 Record->getIdentifier() != II)
4818 Tokens[I].int_data[0] = CXToken_Keyword;
4819 } else if (ClassTemplateDecl *ClassTemplate
4820 = dyn_cast_or_null<ClassTemplateDecl>(D)) {
4821 CXXRecordDecl *Record = ClassTemplate->getTemplatedDecl();
4822 if ((Record->hasAttr<FinalAttr>()) &&
4823 Record->getIdentifier() != II)
4824 Tokens[I].int_data[0] = CXToken_Keyword;
4825 }
4826 }
4827 continue;
4828 }
4829 }
4830 }
Ted Kremenekab979612010-11-11 08:05:23 +00004831}
4832
Ted Kremenek6db61092010-05-05 00:55:15 +00004833extern "C" {
4834
Douglas Gregorfc8ea232010-01-26 17:06:03 +00004835void clang_annotateTokens(CXTranslationUnit TU,
4836 CXToken *Tokens, unsigned NumTokens,
4837 CXCursor *Cursors) {
Ted Kremenekfbd84ca2010-05-05 00:55:23 +00004838
4839 if (NumTokens == 0 || !Tokens || !Cursors)
Douglas Gregor0045e9f2010-01-26 18:31:56 +00004840 return;
Ted Kremenekfbd84ca2010-05-05 00:55:23 +00004841
Douglas Gregor4419b672010-10-21 06:10:04 +00004842 // Any token we don't specifically annotate will have a NULL cursor.
4843 CXCursor C = clang_getNullCursor();
4844 for (unsigned I = 0; I != NumTokens; ++I)
4845 Cursors[I] = C;
4846
Ted Kremeneka60ed472010-11-16 08:15:36 +00004847 ASTUnit *CXXUnit = static_cast<ASTUnit *>(TU->TUData);
Douglas Gregor4419b672010-10-21 06:10:04 +00004848 if (!CXXUnit)
Douglas Gregor0045e9f2010-01-26 18:31:56 +00004849 return;
Ted Kremenekfbd84ca2010-05-05 00:55:23 +00004850
Douglas Gregorbdf60622010-03-05 21:16:25 +00004851 ASTUnit::ConcurrencyCheck Check(*CXXUnit);
Ted Kremenek6628a612011-03-18 22:51:30 +00004852
4853 clang_annotateTokens_Data data = { TU, CXXUnit, Tokens, NumTokens, Cursors };
Ted Kremenekab979612010-11-11 08:05:23 +00004854 llvm::CrashRecoveryContext CRC;
Ted Kremenek6628a612011-03-18 22:51:30 +00004855 if (!RunSafely(CRC, clang_annotateTokensImpl, &data,
Ted Kremenek6c53fdd2010-11-14 17:47:35 +00004856 GetSafetyThreadStackSize() * 2)) {
Ted Kremenekab979612010-11-11 08:05:23 +00004857 fprintf(stderr, "libclang: crash detected while annotating tokens\n");
4858 }
Douglas Gregorfc8ea232010-01-26 17:06:03 +00004859}
Ted Kremenek6628a612011-03-18 22:51:30 +00004860
Douglas Gregorfc8ea232010-01-26 17:06:03 +00004861} // end: extern "C"
4862
4863//===----------------------------------------------------------------------===//
Ted Kremenek16b42592010-03-03 06:36:57 +00004864// Operations for querying linkage of a cursor.
4865//===----------------------------------------------------------------------===//
4866
4867extern "C" {
4868CXLinkageKind clang_getCursorLinkage(CXCursor cursor) {
Douglas Gregor0396f462010-03-19 05:22:59 +00004869 if (!clang_isDeclaration(cursor.kind))
4870 return CXLinkage_Invalid;
4871
Ted Kremenek16b42592010-03-03 06:36:57 +00004872 Decl *D = cxcursor::getCursorDecl(cursor);
4873 if (NamedDecl *ND = dyn_cast_or_null<NamedDecl>(D))
4874 switch (ND->getLinkage()) {
4875 case NoLinkage: return CXLinkage_NoLinkage;
4876 case InternalLinkage: return CXLinkage_Internal;
4877 case UniqueExternalLinkage: return CXLinkage_UniqueExternal;
4878 case ExternalLinkage: return CXLinkage_External;
4879 };
4880
4881 return CXLinkage_Invalid;
4882}
4883} // end: extern "C"
4884
4885//===----------------------------------------------------------------------===//
Ted Kremenek45e1dae2010-04-12 21:22:16 +00004886// Operations for querying language of a cursor.
4887//===----------------------------------------------------------------------===//
4888
4889static CXLanguageKind getDeclLanguage(const Decl *D) {
4890 switch (D->getKind()) {
4891 default:
4892 break;
4893 case Decl::ImplicitParam:
4894 case Decl::ObjCAtDefsField:
4895 case Decl::ObjCCategory:
4896 case Decl::ObjCCategoryImpl:
4897 case Decl::ObjCClass:
4898 case Decl::ObjCCompatibleAlias:
Ted Kremenek45e1dae2010-04-12 21:22:16 +00004899 case Decl::ObjCForwardProtocol:
4900 case Decl::ObjCImplementation:
4901 case Decl::ObjCInterface:
4902 case Decl::ObjCIvar:
4903 case Decl::ObjCMethod:
4904 case Decl::ObjCProperty:
4905 case Decl::ObjCPropertyImpl:
4906 case Decl::ObjCProtocol:
4907 return CXLanguage_ObjC;
4908 case Decl::CXXConstructor:
4909 case Decl::CXXConversion:
4910 case Decl::CXXDestructor:
4911 case Decl::CXXMethod:
4912 case Decl::CXXRecord:
4913 case Decl::ClassTemplate:
4914 case Decl::ClassTemplatePartialSpecialization:
4915 case Decl::ClassTemplateSpecialization:
4916 case Decl::Friend:
4917 case Decl::FriendTemplate:
4918 case Decl::FunctionTemplate:
4919 case Decl::LinkageSpec:
4920 case Decl::Namespace:
4921 case Decl::NamespaceAlias:
4922 case Decl::NonTypeTemplateParm:
4923 case Decl::StaticAssert:
Ted Kremenek45e1dae2010-04-12 21:22:16 +00004924 case Decl::TemplateTemplateParm:
4925 case Decl::TemplateTypeParm:
4926 case Decl::UnresolvedUsingTypename:
4927 case Decl::UnresolvedUsingValue:
4928 case Decl::Using:
4929 case Decl::UsingDirective:
4930 case Decl::UsingShadow:
4931 return CXLanguage_CPlusPlus;
4932 }
4933
4934 return CXLanguage_C;
4935}
4936
4937extern "C" {
Douglas Gregor58ddb602010-08-23 23:00:57 +00004938
4939enum CXAvailabilityKind clang_getCursorAvailability(CXCursor cursor) {
4940 if (clang_isDeclaration(cursor.kind))
4941 if (Decl *D = cxcursor::getCursorDecl(cursor)) {
Douglas Gregor0a0d2b12011-03-23 00:50:03 +00004942 if (isa<FunctionDecl>(D) && cast<FunctionDecl>(D)->isDeleted())
Douglas Gregor58ddb602010-08-23 23:00:57 +00004943 return CXAvailability_Available;
4944
Douglas Gregor0a0d2b12011-03-23 00:50:03 +00004945 switch (D->getAvailability()) {
4946 case AR_Available:
4947 case AR_NotYetIntroduced:
4948 return CXAvailability_Available;
4949
4950 case AR_Deprecated:
Douglas Gregor58ddb602010-08-23 23:00:57 +00004951 return CXAvailability_Deprecated;
Douglas Gregor0a0d2b12011-03-23 00:50:03 +00004952
4953 case AR_Unavailable:
4954 return CXAvailability_NotAvailable;
4955 }
Douglas Gregor58ddb602010-08-23 23:00:57 +00004956 }
Douglas Gregor0a0d2b12011-03-23 00:50:03 +00004957
Douglas Gregor58ddb602010-08-23 23:00:57 +00004958 return CXAvailability_Available;
4959}
4960
Ted Kremenek45e1dae2010-04-12 21:22:16 +00004961CXLanguageKind clang_getCursorLanguage(CXCursor cursor) {
4962 if (clang_isDeclaration(cursor.kind))
4963 return getDeclLanguage(cxcursor::getCursorDecl(cursor));
4964
4965 return CXLanguage_Invalid;
4966}
Douglas Gregor3910cfd2010-12-21 07:55:45 +00004967
4968 /// \brief If the given cursor is the "templated" declaration
4969 /// descibing a class or function template, return the class or
4970 /// function template.
4971static Decl *maybeGetTemplateCursor(Decl *D) {
4972 if (!D)
4973 return 0;
4974
4975 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
4976 if (FunctionTemplateDecl *FunTmpl = FD->getDescribedFunctionTemplate())
4977 return FunTmpl;
4978
4979 if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D))
4980 if (ClassTemplateDecl *ClassTmpl = RD->getDescribedClassTemplate())
4981 return ClassTmpl;
4982
4983 return D;
4984}
4985
Douglas Gregor2be5bc92010-09-22 21:22:29 +00004986CXCursor clang_getCursorSemanticParent(CXCursor cursor) {
4987 if (clang_isDeclaration(cursor.kind)) {
4988 if (Decl *D = getCursorDecl(cursor)) {
4989 DeclContext *DC = D->getDeclContext();
Douglas Gregor3910cfd2010-12-21 07:55:45 +00004990 if (!DC)
4991 return clang_getNullCursor();
4992
4993 return MakeCXCursor(maybeGetTemplateCursor(cast<Decl>(DC)),
4994 getCursorTU(cursor));
Douglas Gregor2be5bc92010-09-22 21:22:29 +00004995 }
4996 }
4997
4998 if (clang_isStatement(cursor.kind) || clang_isExpression(cursor.kind)) {
4999 if (Decl *D = getCursorDecl(cursor))
Ted Kremeneka60ed472010-11-16 08:15:36 +00005000 return MakeCXCursor(D, getCursorTU(cursor));
Douglas Gregor2be5bc92010-09-22 21:22:29 +00005001 }
5002
5003 return clang_getNullCursor();
5004}
5005
5006CXCursor clang_getCursorLexicalParent(CXCursor cursor) {
5007 if (clang_isDeclaration(cursor.kind)) {
5008 if (Decl *D = getCursorDecl(cursor)) {
5009 DeclContext *DC = D->getLexicalDeclContext();
Douglas Gregor3910cfd2010-12-21 07:55:45 +00005010 if (!DC)
5011 return clang_getNullCursor();
5012
5013 return MakeCXCursor(maybeGetTemplateCursor(cast<Decl>(DC)),
5014 getCursorTU(cursor));
Douglas Gregor2be5bc92010-09-22 21:22:29 +00005015 }
5016 }
5017
5018 // FIXME: Note that we can't easily compute the lexical context of a
5019 // statement or expression, so we return nothing.
5020 return clang_getNullCursor();
5021}
5022
Douglas Gregor9f592342010-10-01 20:25:15 +00005023static void CollectOverriddenMethods(DeclContext *Ctx,
5024 ObjCMethodDecl *Method,
5025 llvm::SmallVectorImpl<ObjCMethodDecl *> &Methods) {
5026 if (!Ctx)
5027 return;
5028
5029 // If we have a class or category implementation, jump straight to the
5030 // interface.
5031 if (ObjCImplDecl *Impl = dyn_cast<ObjCImplDecl>(Ctx))
5032 return CollectOverriddenMethods(Impl->getClassInterface(), Method, Methods);
5033
5034 ObjCContainerDecl *Container = dyn_cast<ObjCContainerDecl>(Ctx);
5035 if (!Container)
5036 return;
5037
5038 // Check whether we have a matching method at this level.
5039 if (ObjCMethodDecl *Overridden = Container->getMethod(Method->getSelector(),
5040 Method->isInstanceMethod()))
5041 if (Method != Overridden) {
5042 // We found an override at this level; there is no need to look
5043 // into other protocols or categories.
5044 Methods.push_back(Overridden);
5045 return;
5046 }
5047
5048 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
5049 for (ObjCProtocolDecl::protocol_iterator P = Protocol->protocol_begin(),
5050 PEnd = Protocol->protocol_end();
5051 P != PEnd; ++P)
5052 CollectOverriddenMethods(*P, Method, Methods);
5053 }
5054
5055 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Container)) {
5056 for (ObjCCategoryDecl::protocol_iterator P = Category->protocol_begin(),
5057 PEnd = Category->protocol_end();
5058 P != PEnd; ++P)
5059 CollectOverriddenMethods(*P, Method, Methods);
5060 }
5061
5062 if (ObjCInterfaceDecl *Interface = dyn_cast<ObjCInterfaceDecl>(Container)) {
5063 for (ObjCInterfaceDecl::protocol_iterator P = Interface->protocol_begin(),
5064 PEnd = Interface->protocol_end();
5065 P != PEnd; ++P)
5066 CollectOverriddenMethods(*P, Method, Methods);
5067
5068 for (ObjCCategoryDecl *Category = Interface->getCategoryList();
5069 Category; Category = Category->getNextClassCategory())
5070 CollectOverriddenMethods(Category, Method, Methods);
5071
5072 // We only look into the superclass if we haven't found anything yet.
5073 if (Methods.empty())
5074 if (ObjCInterfaceDecl *Super = Interface->getSuperClass())
5075 return CollectOverriddenMethods(Super, Method, Methods);
5076 }
5077}
5078
5079void clang_getOverriddenCursors(CXCursor cursor,
5080 CXCursor **overridden,
5081 unsigned *num_overridden) {
5082 if (overridden)
5083 *overridden = 0;
5084 if (num_overridden)
5085 *num_overridden = 0;
5086 if (!overridden || !num_overridden)
5087 return;
5088
5089 if (!clang_isDeclaration(cursor.kind))
5090 return;
5091
5092 Decl *D = getCursorDecl(cursor);
5093 if (!D)
5094 return;
5095
5096 // Handle C++ member functions.
Ted Kremeneka60ed472010-11-16 08:15:36 +00005097 CXTranslationUnit TU = getCursorTU(cursor);
Douglas Gregor9f592342010-10-01 20:25:15 +00005098 if (CXXMethodDecl *CXXMethod = dyn_cast<CXXMethodDecl>(D)) {
5099 *num_overridden = CXXMethod->size_overridden_methods();
5100 if (!*num_overridden)
5101 return;
5102
5103 *overridden = new CXCursor [*num_overridden];
5104 unsigned I = 0;
5105 for (CXXMethodDecl::method_iterator
5106 M = CXXMethod->begin_overridden_methods(),
5107 MEnd = CXXMethod->end_overridden_methods();
5108 M != MEnd; (void)++M, ++I)
Ted Kremeneka60ed472010-11-16 08:15:36 +00005109 (*overridden)[I] = MakeCXCursor(const_cast<CXXMethodDecl*>(*M), TU);
Douglas Gregor9f592342010-10-01 20:25:15 +00005110 return;
5111 }
5112
5113 ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(D);
5114 if (!Method)
5115 return;
5116
5117 // Handle Objective-C methods.
5118 llvm::SmallVector<ObjCMethodDecl *, 4> Methods;
5119 CollectOverriddenMethods(Method->getDeclContext(), Method, Methods);
5120
5121 if (Methods.empty())
5122 return;
5123
5124 *num_overridden = Methods.size();
5125 *overridden = new CXCursor [Methods.size()];
5126 for (unsigned I = 0, N = Methods.size(); I != N; ++I)
Ted Kremeneka60ed472010-11-16 08:15:36 +00005127 (*overridden)[I] = MakeCXCursor(Methods[I], TU);
Douglas Gregor9f592342010-10-01 20:25:15 +00005128}
5129
5130void clang_disposeOverriddenCursors(CXCursor *overridden) {
5131 delete [] overridden;
5132}
5133
Douglas Gregorecdcb882010-10-20 22:00:55 +00005134CXFile clang_getIncludedFile(CXCursor cursor) {
5135 if (cursor.kind != CXCursor_InclusionDirective)
5136 return 0;
5137
5138 InclusionDirective *ID = getCursorInclusionDirective(cursor);
5139 return (void *)ID->getFile();
5140}
5141
Ted Kremenek45e1dae2010-04-12 21:22:16 +00005142} // end: extern "C"
5143
Ted Kremenek9ada39a2010-05-17 20:06:56 +00005144
5145//===----------------------------------------------------------------------===//
5146// C++ AST instrospection.
5147//===----------------------------------------------------------------------===//
5148
5149extern "C" {
5150unsigned clang_CXXMethod_isStatic(CXCursor C) {
5151 if (!clang_isDeclaration(C.kind))
5152 return 0;
Douglas Gregor49f6f542010-08-31 22:12:17 +00005153
5154 CXXMethodDecl *Method = 0;
5155 Decl *D = cxcursor::getCursorDecl(C);
5156 if (FunctionTemplateDecl *FunTmpl = dyn_cast_or_null<FunctionTemplateDecl>(D))
5157 Method = dyn_cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl());
5158 else
5159 Method = dyn_cast_or_null<CXXMethodDecl>(D);
5160 return (Method && Method->isStatic()) ? 1 : 0;
Ted Kremenek40b492a2010-05-17 20:12:45 +00005161}
Ted Kremenekb12903e2010-05-18 22:32:15 +00005162
Ted Kremenek9ada39a2010-05-17 20:06:56 +00005163} // end: extern "C"
5164
Ted Kremenek45e1dae2010-04-12 21:22:16 +00005165//===----------------------------------------------------------------------===//
Ted Kremenek95f33552010-08-26 01:42:22 +00005166// Attribute introspection.
5167//===----------------------------------------------------------------------===//
5168
5169extern "C" {
5170CXType clang_getIBOutletCollectionType(CXCursor C) {
5171 if (C.kind != CXCursor_IBOutletCollectionAttr)
Ted Kremeneka60ed472010-11-16 08:15:36 +00005172 return cxtype::MakeCXType(QualType(), cxcursor::getCursorTU(C));
Ted Kremenek95f33552010-08-26 01:42:22 +00005173
5174 IBOutletCollectionAttr *A =
5175 cast<IBOutletCollectionAttr>(cxcursor::getCursorAttr(C));
5176
Douglas Gregor841b2382011-03-06 18:55:32 +00005177 return cxtype::MakeCXType(A->getInterFace(), cxcursor::getCursorTU(C));
Ted Kremenek95f33552010-08-26 01:42:22 +00005178}
5179} // end: extern "C"
5180
5181//===----------------------------------------------------------------------===//
Ted Kremenek59fc1e52011-04-18 22:47:10 +00005182// Inspecting memory usage.
5183//===----------------------------------------------------------------------===//
5184
Ted Kremenekf7870022011-04-20 16:41:07 +00005185typedef std::vector<CXTUResourceUsageEntry> MemUsageEntries;
Ted Kremenek59fc1e52011-04-18 22:47:10 +00005186
Ted Kremenekf7870022011-04-20 16:41:07 +00005187static inline void createCXTUResourceUsageEntry(MemUsageEntries &entries,
5188 enum CXTUResourceUsageKind k,
Ted Kremenek59fc1e52011-04-18 22:47:10 +00005189 double amount) {
Ted Kremenekf7870022011-04-20 16:41:07 +00005190 CXTUResourceUsageEntry entry = { k, amount };
Ted Kremenek59fc1e52011-04-18 22:47:10 +00005191 entries.push_back(entry);
5192}
5193
5194extern "C" {
5195
Ted Kremenekf7870022011-04-20 16:41:07 +00005196const char *clang_getTUResourceUsageName(CXTUResourceUsageKind kind) {
Ted Kremenek59fc1e52011-04-18 22:47:10 +00005197 const char *str = "";
5198 switch (kind) {
Ted Kremenekf7870022011-04-20 16:41:07 +00005199 case CXTUResourceUsage_AST:
Ted Kremenek59fc1e52011-04-18 22:47:10 +00005200 str = "ASTContext: expressions, declarations, and types";
5201 break;
Ted Kremenekf7870022011-04-20 16:41:07 +00005202 case CXTUResourceUsage_Identifiers:
Ted Kremenek59fc1e52011-04-18 22:47:10 +00005203 str = "ASTContext: identifiers";
5204 break;
Ted Kremenekf7870022011-04-20 16:41:07 +00005205 case CXTUResourceUsage_Selectors:
Ted Kremenek59fc1e52011-04-18 22:47:10 +00005206 str = "ASTContext: selectors";
Ted Kremeneke294ab72011-04-19 04:36:17 +00005207 break;
Ted Kremenekf7870022011-04-20 16:41:07 +00005208 case CXTUResourceUsage_GlobalCompletionResults:
Ted Kremenek4e6a3f72011-04-18 23:42:53 +00005209 str = "Code completion: cached global results";
Ted Kremeneke294ab72011-04-19 04:36:17 +00005210 break;
Ted Kremenek59fc1e52011-04-18 22:47:10 +00005211 }
5212 return str;
5213}
5214
Ted Kremenekf7870022011-04-20 16:41:07 +00005215CXTUResourceUsage clang_getCXTUResourceUsage(CXTranslationUnit TU) {
Ted Kremenek59fc1e52011-04-18 22:47:10 +00005216 if (!TU) {
Ted Kremenekf7870022011-04-20 16:41:07 +00005217 CXTUResourceUsage usage = { (void*) 0, 0, 0 };
Ted Kremenek59fc1e52011-04-18 22:47:10 +00005218 return usage;
5219 }
5220
5221 ASTUnit *astUnit = static_cast<ASTUnit*>(TU->TUData);
5222 llvm::OwningPtr<MemUsageEntries> entries(new MemUsageEntries());
5223 ASTContext &astContext = astUnit->getASTContext();
5224
5225 // How much memory is used by AST nodes and types?
Ted Kremenekf7870022011-04-20 16:41:07 +00005226 createCXTUResourceUsageEntry(*entries, CXTUResourceUsage_AST,
Ted Kremenek59fc1e52011-04-18 22:47:10 +00005227 (unsigned long) astContext.getTotalAllocatedMemory());
5228
5229 // How much memory is used by identifiers?
Ted Kremenekf7870022011-04-20 16:41:07 +00005230 createCXTUResourceUsageEntry(*entries, CXTUResourceUsage_Identifiers,
Ted Kremenek59fc1e52011-04-18 22:47:10 +00005231 (unsigned long) astContext.Idents.getAllocator().getTotalMemory());
5232
5233 // How much memory is used for selectors?
Ted Kremenekf7870022011-04-20 16:41:07 +00005234 createCXTUResourceUsageEntry(*entries, CXTUResourceUsage_Selectors,
Ted Kremenek59fc1e52011-04-18 22:47:10 +00005235 (unsigned long) astContext.Selectors.getTotalMemory());
5236
Ted Kremenek4e6a3f72011-04-18 23:42:53 +00005237 // How much memory is used for caching global code completion results?
5238 unsigned long completionBytes = 0;
5239 if (GlobalCodeCompletionAllocator *completionAllocator =
5240 astUnit->getCachedCompletionAllocator().getPtr()) {
5241 completionBytes = completionAllocator-> getTotalMemory();
5242 }
Ted Kremenekf7870022011-04-20 16:41:07 +00005243 createCXTUResourceUsageEntry(*entries, CXTUResourceUsage_GlobalCompletionResults,
Ted Kremenek4e6a3f72011-04-18 23:42:53 +00005244 completionBytes);
5245
5246
Ted Kremenekf7870022011-04-20 16:41:07 +00005247 CXTUResourceUsage usage = { (void*) entries.get(),
Ted Kremenek59fc1e52011-04-18 22:47:10 +00005248 (unsigned) entries->size(),
5249 entries->size() ? &(*entries)[0] : 0 };
5250 entries.take();
5251 return usage;
5252}
5253
Ted Kremenekf7870022011-04-20 16:41:07 +00005254void clang_disposeCXTUResourceUsage(CXTUResourceUsage usage) {
Ted Kremenek59fc1e52011-04-18 22:47:10 +00005255 if (usage.data)
5256 delete (MemUsageEntries*) usage.data;
5257}
5258
5259} // end extern "C"
5260
5261//===----------------------------------------------------------------------===//
Ted Kremenek04bb7162010-01-22 22:44:15 +00005262// Misc. utility functions.
5263//===----------------------------------------------------------------------===//
Ted Kremenekf0e23e82010-02-17 00:41:40 +00005264
Daniel Dunbarabdce7a2010-11-05 17:21:46 +00005265/// Default to using an 8 MB stack size on "safety" threads.
5266static unsigned SafetyStackThreadSize = 8 << 20;
Daniel Dunbarbf44c3b2010-11-05 07:19:31 +00005267
5268namespace clang {
5269
5270bool RunSafely(llvm::CrashRecoveryContext &CRC,
Ted Kremenek6c53fdd2010-11-14 17:47:35 +00005271 void (*Fn)(void*), void *UserData,
5272 unsigned Size) {
5273 if (!Size)
5274 Size = GetSafetyThreadStackSize();
5275 if (Size)
Daniel Dunbarbf44c3b2010-11-05 07:19:31 +00005276 return CRC.RunSafelyOnThread(Fn, UserData, Size);
5277 return CRC.RunSafely(Fn, UserData);
5278}
5279
5280unsigned GetSafetyThreadStackSize() {
5281 return SafetyStackThreadSize;
5282}
5283
5284void SetSafetyThreadStackSize(unsigned Value) {
5285 SafetyStackThreadSize = Value;
5286}
5287
5288}
5289
Ted Kremenek04bb7162010-01-22 22:44:15 +00005290extern "C" {
5291
Ted Kremeneka2a9d6e2010-02-12 22:54:40 +00005292CXString clang_getClangVersion() {
Ted Kremenekee4db4f2010-02-17 00:41:08 +00005293 return createCXString(getClangFullVersion());
Ted Kremenek04bb7162010-01-22 22:44:15 +00005294}
5295
5296} // end: extern "C"
Ted Kremenek59fc1e52011-04-18 22:47:10 +00005297