blob: 00141184c70a1fd0a1835b2d11b03b8c6a6255aa [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"
Douglas Gregordd3e5542011-05-04 00:14:37 +000033#include "clang/Lex/HeaderSearch.h"
Benjamin Kramerb846deb2010-04-12 19:45:50 +000034#include "clang/Lex/PreprocessingRecord.h"
Douglas Gregor33e9abd2010-01-22 19:49:59 +000035#include "clang/Lex/Preprocessor.h"
Douglas Gregora67e03f2010-09-09 21:42:20 +000036#include "llvm/ADT/STLExtras.h"
Ted Kremenekd8c370c2010-11-02 23:10:24 +000037#include "llvm/ADT/Optional.h"
Douglas Gregorf5251602011-03-08 17:10:18 +000038#include "llvm/ADT/StringSwitch.h"
Ted Kremenekd8c370c2010-11-02 23:10:24 +000039#include "clang/Analysis/Support/SaveAndRestore.h"
Daniel Dunbarc7df4f32010-08-18 18:43:14 +000040#include "llvm/Support/CrashRecoveryContext.h"
Daniel Dunbar48615ff2010-10-08 19:30:33 +000041#include "llvm/Support/PrettyStackTrace.h"
Douglas Gregor02465752009-10-16 21:24:31 +000042#include "llvm/Support/MemoryBuffer.h"
Douglas Gregor358559d2010-10-02 22:49:11 +000043#include "llvm/Support/raw_ostream.h"
Douglas Gregor7a07fcb2010-08-09 21:00:09 +000044#include "llvm/Support/Timer.h"
Michael J. Spencer03013fa2010-11-29 18:12:39 +000045#include "llvm/Support/Mutex.h"
46#include "llvm/Support/Program.h"
47#include "llvm/Support/Signals.h"
48#include "llvm/Support/Threading.h"
Ted Kremenek37f1ea02010-11-15 23:11:54 +000049#include "llvm/Support/Compiler.h"
Ted Kremenekfc062212009-10-19 21:44:57 +000050
Steve Naroff50398192009-08-28 15:28:48 +000051using namespace clang;
Ted Kremenek16c440a2010-01-15 20:35:54 +000052using namespace clang::cxcursor;
Ted Kremenekee4db4f2010-02-17 00:41:08 +000053using namespace clang::cxstring;
Steve Naroff50398192009-08-28 15:28:48 +000054
Ted Kremeneka60ed472010-11-16 08:15:36 +000055static CXTranslationUnit MakeCXTranslationUnit(ASTUnit *TU) {
56 if (!TU)
57 return 0;
58 CXTranslationUnit D = new CXTranslationUnitImpl();
59 D->TUData = TU;
60 D->StringPool = createCXStringPool();
61 return D;
62}
63
Douglas Gregor33e9abd2010-01-22 19:49:59 +000064/// \brief The result of comparing two source ranges.
65enum RangeComparisonResult {
66 /// \brief Either the ranges overlap or one of the ranges is invalid.
67 RangeOverlap,
Ted Kremenekf0e23e82010-02-17 00:41:40 +000068
Douglas Gregor33e9abd2010-01-22 19:49:59 +000069 /// \brief The first range ends before the second range starts.
70 RangeBefore,
Ted Kremenekf0e23e82010-02-17 00:41:40 +000071
Douglas Gregor33e9abd2010-01-22 19:49:59 +000072 /// \brief The first range starts after the second range ends.
73 RangeAfter
74};
75
Ted Kremenekf0e23e82010-02-17 00:41:40 +000076/// \brief Compare two source ranges to determine their relative position in
Douglas Gregor33e9abd2010-01-22 19:49:59 +000077/// the translation unit.
Ted Kremenekf0e23e82010-02-17 00:41:40 +000078static RangeComparisonResult RangeCompare(SourceManager &SM,
79 SourceRange R1,
Douglas Gregor33e9abd2010-01-22 19:49:59 +000080 SourceRange R2) {
81 assert(R1.isValid() && "First range is invalid?");
82 assert(R2.isValid() && "Second range is invalid?");
Douglas Gregora8e5c5b2010-07-22 20:22:31 +000083 if (R1.getEnd() != R2.getBegin() &&
Daniel Dunbard52864b2010-02-14 10:02:57 +000084 SM.isBeforeInTranslationUnit(R1.getEnd(), R2.getBegin()))
Douglas Gregor33e9abd2010-01-22 19:49:59 +000085 return RangeBefore;
Douglas Gregora8e5c5b2010-07-22 20:22:31 +000086 if (R2.getEnd() != R1.getBegin() &&
Daniel Dunbard52864b2010-02-14 10:02:57 +000087 SM.isBeforeInTranslationUnit(R2.getEnd(), R1.getBegin()))
Douglas Gregor33e9abd2010-01-22 19:49:59 +000088 return RangeAfter;
89 return RangeOverlap;
90}
91
Ted Kremenekfbd84ca2010-05-05 00:55:23 +000092/// \brief Determine if a source location falls within, before, or after a
93/// a given source range.
94static RangeComparisonResult LocationCompare(SourceManager &SM,
95 SourceLocation L, SourceRange R) {
96 assert(R.isValid() && "First range is invalid?");
97 assert(L.isValid() && "Second range is invalid?");
Douglas Gregora8e5c5b2010-07-22 20:22:31 +000098 if (L == R.getBegin() || L == R.getEnd())
Ted Kremenekfbd84ca2010-05-05 00:55:23 +000099 return RangeOverlap;
Ted Kremenekfbd84ca2010-05-05 00:55:23 +0000100 if (SM.isBeforeInTranslationUnit(L, R.getBegin()))
101 return RangeBefore;
102 if (SM.isBeforeInTranslationUnit(R.getEnd(), L))
103 return RangeAfter;
104 return RangeOverlap;
105}
106
Daniel Dunbar76dd3c22010-02-14 01:47:29 +0000107/// \brief Translate a Clang source range into a CIndex source range.
108///
109/// Clang internally represents ranges where the end location points to the
110/// start of the token at the end. However, for external clients it is more
111/// useful to have a CXSourceRange be a proper half-open interval. This routine
112/// does the appropriate translation.
Ted Kremenekf0e23e82010-02-17 00:41:40 +0000113CXSourceRange cxloc::translateSourceRange(const SourceManager &SM,
Daniel Dunbar76dd3c22010-02-14 01:47:29 +0000114 const LangOptions &LangOpts,
Chris Lattner0a76aae2010-06-18 22:45:06 +0000115 const CharSourceRange &R) {
Daniel Dunbar76dd3c22010-02-14 01:47:29 +0000116 // We want the last character in this location, so we will adjust the
Douglas Gregor6a5a23f2010-03-19 21:51:54 +0000117 // location accordingly.
Daniel Dunbar76dd3c22010-02-14 01:47:29 +0000118 SourceLocation EndLoc = R.getEnd();
Douglas Gregora9b06d42010-11-09 06:24:54 +0000119 if (EndLoc.isValid() && EndLoc.isMacroID())
Douglas Gregorffcd9852011-04-20 21:16:21 +0000120 EndLoc = SM.getInstantiationRange(EndLoc).second;
Chris Lattner0a76aae2010-06-18 22:45:06 +0000121 if (R.isTokenRange() && !EndLoc.isInvalid() && EndLoc.isFileID()) {
Douglas Gregor6a5a23f2010-03-19 21:51:54 +0000122 unsigned Length = Lexer::MeasureTokenLength(EndLoc, SM, LangOpts);
Daniel Dunbar76dd3c22010-02-14 01:47:29 +0000123 EndLoc = EndLoc.getFileLocWithOffset(Length);
124 }
125
126 CXSourceRange Result = { { (void *)&SM, (void *)&LangOpts },
127 R.getBegin().getRawEncoding(),
128 EndLoc.getRawEncoding() };
129 return Result;
130}
Douglas Gregor1db19de2010-01-19 21:36:55 +0000131
Ted Kremenek8a8da7d2010-01-06 03:42:32 +0000132//===----------------------------------------------------------------------===//
Douglas Gregor33e9abd2010-01-22 19:49:59 +0000133// Cursor visitor.
Ted Kremenek8a8da7d2010-01-06 03:42:32 +0000134//===----------------------------------------------------------------------===//
135
Steve Naroff89922f82009-08-31 00:59:03 +0000136namespace {
Ted Kremenekc0e1d922010-11-11 08:05:18 +0000137
138class VisitorJob {
139public:
Ted Kremenekcdb4caf2010-11-12 21:34:12 +0000140 enum Kind { DeclVisitKind, StmtVisitKind, MemberExprPartsKind,
Ted Kremeneke4979cc2010-11-13 00:58:18 +0000141 TypeLocVisitKind, OverloadExprPartsKind,
Ted Kremenek60608ec2010-11-17 00:50:47 +0000142 DeclRefExprPartsKind, LabelRefVisitKind,
Ted Kremenekf64d8032010-11-18 00:02:32 +0000143 ExplicitTemplateArgsVisitKind,
144 NestedNameSpecifierVisitKind,
Douglas Gregorf3db29f2011-02-25 18:19:59 +0000145 NestedNameSpecifierLocVisitKind,
Ted Kremenekcdba6592010-11-18 00:42:18 +0000146 DeclarationNameInfoVisitKind,
Douglas Gregor94d96292011-01-19 20:34:17 +0000147 MemberRefVisitKind, SizeOfPackExprPartsKind };
Ted Kremenekc0e1d922010-11-11 08:05:18 +0000148protected:
Ted Kremenekf64d8032010-11-18 00:02:32 +0000149 void *data[3];
Ted Kremenekc0e1d922010-11-11 08:05:18 +0000150 CXCursor parent;
151 Kind K;
Ted Kremenekf64d8032010-11-18 00:02:32 +0000152 VisitorJob(CXCursor C, Kind k, void *d1, void *d2 = 0, void *d3 = 0)
153 : parent(C), K(k) {
154 data[0] = d1;
155 data[1] = d2;
156 data[2] = d3;
157 }
Ted Kremenekc0e1d922010-11-11 08:05:18 +0000158public:
159 Kind getKind() const { return K; }
160 const CXCursor &getParent() const { return parent; }
161 static bool classof(VisitorJob *VJ) { return true; }
162};
163
164typedef llvm::SmallVector<VisitorJob, 10> VisitorWorkList;
165
Douglas Gregorb1373d02010-01-20 20:59:29 +0000166// Cursor visitor.
Douglas Gregor7d0d40e2010-01-21 16:28:34 +0000167class CursorVisitor : public DeclVisitor<CursorVisitor, bool>,
Ted Kremenekcdba6592010-11-18 00:42:18 +0000168 public TypeLocVisitor<CursorVisitor, bool>
Douglas Gregor7d0d40e2010-01-21 16:28:34 +0000169{
Douglas Gregor33e9abd2010-01-22 19:49:59 +0000170 /// \brief The translation unit we are traversing.
Ted Kremeneka60ed472010-11-16 08:15:36 +0000171 CXTranslationUnit TU;
172 ASTUnit *AU;
Ted Kremenekf0e23e82010-02-17 00:41:40 +0000173
Douglas Gregor33e9abd2010-01-22 19:49:59 +0000174 /// \brief The parent cursor whose children we are traversing.
Douglas Gregorb1373d02010-01-20 20:59:29 +0000175 CXCursor Parent;
Ted Kremenekf0e23e82010-02-17 00:41:40 +0000176
Douglas Gregor33e9abd2010-01-22 19:49:59 +0000177 /// \brief The declaration that serves at the parent of any statement or
178 /// expression nodes.
Douglas Gregorf20dfbc2010-01-21 17:29:07 +0000179 Decl *StmtParent;
Ted Kremenekf0e23e82010-02-17 00:41:40 +0000180
Douglas Gregor33e9abd2010-01-22 19:49:59 +0000181 /// \brief The visitor function.
Douglas Gregorb1373d02010-01-20 20:59:29 +0000182 CXCursorVisitor Visitor;
Ted Kremenekf0e23e82010-02-17 00:41:40 +0000183
Douglas Gregor33e9abd2010-01-22 19:49:59 +0000184 /// \brief The opaque client data, to be passed along to the visitor.
Douglas Gregorb1373d02010-01-20 20:59:29 +0000185 CXClientData ClientData;
Ted Kremenekf0e23e82010-02-17 00:41:40 +0000186
Douglas Gregor7d1d49d2009-10-16 20:01:17 +0000187 // MaxPCHLevel - the maximum PCH level of declarations that we will pass on
188 // to the visitor. Declarations with a PCH level greater than this value will
189 // be suppressed.
190 unsigned MaxPCHLevel;
Douglas Gregor33e9abd2010-01-22 19:49:59 +0000191
Douglas Gregor04a9eb32011-03-16 23:23:30 +0000192 /// \brief Whether we should visit the preprocessing record entries last,
193 /// after visiting other declarations.
194 bool VisitPreprocessorLast;
195
Douglas Gregor33e9abd2010-01-22 19:49:59 +0000196 /// \brief When valid, a source range to which the cursor should restrict
197 /// its search.
198 SourceRange RegionOfInterest;
Ted Kremenekf0e23e82010-02-17 00:41:40 +0000199
Ted Kremenekd8c370c2010-11-02 23:10:24 +0000200 // FIXME: Eventually remove. This part of a hack to support proper
201 // iteration over all Decls contained lexically within an ObjC container.
202 DeclContext::decl_iterator *DI_current;
203 DeclContext::decl_iterator DE_current;
204
Ted Kremenekd1ded662010-11-15 23:31:32 +0000205 // Cache of pre-allocated worklists for data-recursion walk of Stmts.
206 llvm::SmallVector<VisitorWorkList*, 5> WorkListFreeList;
207 llvm::SmallVector<VisitorWorkList*, 5> WorkListCache;
208
Douglas Gregorb1373d02010-01-20 20:59:29 +0000209 using DeclVisitor<CursorVisitor, bool>::Visit;
Douglas Gregor7d0d40e2010-01-21 16:28:34 +0000210 using TypeLocVisitor<CursorVisitor, bool>::Visit;
Ted Kremenekf0e23e82010-02-17 00:41:40 +0000211
212 /// \brief Determine whether this particular source range comes before, comes
213 /// after, or overlaps the region of interest.
Douglas Gregor33e9abd2010-01-22 19:49:59 +0000214 ///
Daniel Dunbard52864b2010-02-14 10:02:57 +0000215 /// \param R a half-open source range retrieved from the abstract syntax tree.
Ted Kremenekf0e23e82010-02-17 00:41:40 +0000216 RangeComparisonResult CompareRegionOfInterest(SourceRange R);
217
Ted Kremenek0f91f6a2010-05-13 00:25:00 +0000218 class SetParentRAII {
219 CXCursor &Parent;
220 Decl *&StmtParent;
221 CXCursor OldParent;
222
223 public:
224 SetParentRAII(CXCursor &Parent, Decl *&StmtParent, CXCursor NewParent)
225 : Parent(Parent), StmtParent(StmtParent), OldParent(Parent)
226 {
227 Parent = NewParent;
228 if (clang_isDeclaration(Parent.kind))
229 StmtParent = getCursorDecl(Parent);
230 }
231
232 ~SetParentRAII() {
233 Parent = OldParent;
234 if (clang_isDeclaration(Parent.kind))
235 StmtParent = getCursorDecl(Parent);
236 }
237 };
238
Steve Naroff89922f82009-08-31 00:59:03 +0000239public:
Ted Kremeneka60ed472010-11-16 08:15:36 +0000240 CursorVisitor(CXTranslationUnit TU, CXCursorVisitor Visitor,
241 CXClientData ClientData,
Ted Kremenekf0e23e82010-02-17 00:41:40 +0000242 unsigned MaxPCHLevel,
Douglas Gregor04a9eb32011-03-16 23:23:30 +0000243 bool VisitPreprocessorLast,
Douglas Gregor33e9abd2010-01-22 19:49:59 +0000244 SourceRange RegionOfInterest = SourceRange())
Ted Kremeneka60ed472010-11-16 08:15:36 +0000245 : TU(TU), AU(static_cast<ASTUnit*>(TU->TUData)),
246 Visitor(Visitor), ClientData(ClientData),
Douglas Gregor04a9eb32011-03-16 23:23:30 +0000247 MaxPCHLevel(MaxPCHLevel), VisitPreprocessorLast(VisitPreprocessorLast),
248 RegionOfInterest(RegionOfInterest), DI_current(0)
Douglas Gregorb1373d02010-01-20 20:59:29 +0000249 {
250 Parent.kind = CXCursor_NoDeclFound;
251 Parent.data[0] = 0;
252 Parent.data[1] = 0;
253 Parent.data[2] = 0;
Douglas Gregorf20dfbc2010-01-21 17:29:07 +0000254 StmtParent = 0;
Douglas Gregorb1373d02010-01-20 20:59:29 +0000255 }
Ted Kremenekf0e23e82010-02-17 00:41:40 +0000256
Ted Kremenekd1ded662010-11-15 23:31:32 +0000257 ~CursorVisitor() {
258 // Free the pre-allocated worklists for data-recursion.
259 for (llvm::SmallVectorImpl<VisitorWorkList*>::iterator
260 I = WorkListCache.begin(), E = WorkListCache.end(); I != E; ++I) {
261 delete *I;
262 }
263 }
264
Ted Kremeneka60ed472010-11-16 08:15:36 +0000265 ASTUnit *getASTUnit() const { return static_cast<ASTUnit*>(TU->TUData); }
266 CXTranslationUnit getTU() const { return TU; }
Ted Kremenekab979612010-11-11 08:05:23 +0000267
Douglas Gregor33e9abd2010-01-22 19:49:59 +0000268 bool Visit(CXCursor Cursor, bool CheckedRegionOfInterest = false);
Douglas Gregor788f5a12010-03-20 00:41:21 +0000269
270 std::pair<PreprocessingRecord::iterator, PreprocessingRecord::iterator>
271 getPreprocessedEntities();
272
Douglas Gregorb1373d02010-01-20 20:59:29 +0000273 bool VisitChildren(CXCursor Parent);
Ted Kremenekf0e23e82010-02-17 00:41:40 +0000274
Douglas Gregor7d0d40e2010-01-21 16:28:34 +0000275 // Declaration visitors
Richard Smith162e1c12011-04-15 14:24:37 +0000276 bool VisitTypeAliasDecl(TypeAliasDecl *D);
Ted Kremenek09dfa372010-02-18 05:46:33 +0000277 bool VisitAttributes(Decl *D);
Ted Kremenek1ee6cad2010-04-11 21:47:37 +0000278 bool VisitBlockDecl(BlockDecl *B);
Ted Kremenek3064ef92010-08-27 21:34:58 +0000279 bool VisitCXXRecordDecl(CXXRecordDecl *D);
Ted Kremenekd8c370c2010-11-02 23:10:24 +0000280 llvm::Optional<bool> shouldVisitCursor(CXCursor C);
Douglas Gregorb1373d02010-01-20 20:59:29 +0000281 bool VisitDeclContext(DeclContext *DC);
Ted Kremenek4540c9c2010-02-18 18:47:08 +0000282 bool VisitTranslationUnitDecl(TranslationUnitDecl *D);
283 bool VisitTypedefDecl(TypedefDecl *D);
Ted Kremenek79758f62010-02-18 22:36:18 +0000284 bool VisitTagDecl(TagDecl *D);
Douglas Gregor0ab1e9f2010-09-01 17:32:36 +0000285 bool VisitClassTemplateSpecializationDecl(ClassTemplateSpecializationDecl *D);
Douglas Gregor74dbe642010-08-31 19:31:58 +0000286 bool VisitClassTemplatePartialSpecializationDecl(
287 ClassTemplatePartialSpecializationDecl *D);
Douglas Gregorfe72e9c2010-08-31 17:01:39 +0000288 bool VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D);
Ted Kremenek79758f62010-02-18 22:36:18 +0000289 bool VisitEnumConstantDecl(EnumConstantDecl *D);
290 bool VisitDeclaratorDecl(DeclaratorDecl *DD);
291 bool VisitFunctionDecl(FunctionDecl *ND);
292 bool VisitFieldDecl(FieldDecl *D);
Ted Kremenek4540c9c2010-02-18 18:47:08 +0000293 bool VisitVarDecl(VarDecl *);
Douglas Gregor84b51d72010-09-01 20:16:53 +0000294 bool VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D);
Douglas Gregorfe72e9c2010-08-31 17:01:39 +0000295 bool VisitFunctionTemplateDecl(FunctionTemplateDecl *D);
Douglas Gregor39d6f072010-08-31 19:02:00 +0000296 bool VisitClassTemplateDecl(ClassTemplateDecl *D);
Douglas Gregor84b51d72010-09-01 20:16:53 +0000297 bool VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D);
Ted Kremenek79758f62010-02-18 22:36:18 +0000298 bool VisitObjCMethodDecl(ObjCMethodDecl *ND);
299 bool VisitObjCContainerDecl(ObjCContainerDecl *D);
300 bool VisitObjCCategoryDecl(ObjCCategoryDecl *ND);
301 bool VisitObjCProtocolDecl(ObjCProtocolDecl *PID);
Ted Kremenek23173d72010-05-18 21:09:07 +0000302 bool VisitObjCPropertyDecl(ObjCPropertyDecl *PD);
Ted Kremenek79758f62010-02-18 22:36:18 +0000303 bool VisitObjCInterfaceDecl(ObjCInterfaceDecl *D);
304 bool VisitObjCImplDecl(ObjCImplDecl *D);
305 bool VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D);
306 bool VisitObjCImplementationDecl(ObjCImplementationDecl *D);
Ted Kremenek79758f62010-02-18 22:36:18 +0000307 // FIXME: ObjCCompatibleAliasDecl requires aliased-class locations.
308 bool VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D);
309 bool VisitObjCClassDecl(ObjCClassDecl *D);
Douglas Gregora4ffd852010-11-17 01:03:52 +0000310 bool VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *PD);
Ted Kremeneka0536d82010-05-07 01:04:29 +0000311 bool VisitLinkageSpecDecl(LinkageSpecDecl *D);
Ted Kremenek8f06e0e2010-05-06 23:38:21 +0000312 bool VisitNamespaceDecl(NamespaceDecl *D);
Douglas Gregor69319002010-08-31 23:48:11 +0000313 bool VisitNamespaceAliasDecl(NamespaceAliasDecl *D);
Douglas Gregor0a35bce2010-09-01 03:07:18 +0000314 bool VisitUsingDirectiveDecl(UsingDirectiveDecl *D);
Douglas Gregor7e242562010-09-01 19:52:22 +0000315 bool VisitUsingDecl(UsingDecl *D);
316 bool VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D);
317 bool VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
Douglas Gregor0a35bce2010-09-01 03:07:18 +0000318
Douglas Gregor01829d32010-08-31 14:41:23 +0000319 // Name visitor
320 bool VisitDeclarationNameInfo(DeclarationNameInfo Name);
Douglas Gregorc5ade2e2010-09-02 17:35:32 +0000321 bool VisitNestedNameSpecifier(NestedNameSpecifier *NNS, SourceRange Range);
Douglas Gregordc355712011-02-25 00:36:19 +0000322 bool VisitNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS);
Douglas Gregor01829d32010-08-31 14:41:23 +0000323
Douglas Gregorfe72e9c2010-08-31 17:01:39 +0000324 // Template visitors
325 bool VisitTemplateParameters(const TemplateParameterList *Params);
Douglas Gregor0b36e612010-08-31 20:37:03 +0000326 bool VisitTemplateName(TemplateName Name, SourceLocation Loc);
Douglas Gregorfe72e9c2010-08-31 17:01:39 +0000327 bool VisitTemplateArgumentLoc(const TemplateArgumentLoc &TAL);
328
Douglas Gregor7d0d40e2010-01-21 16:28:34 +0000329 // Type visitors
Douglas Gregor01829d32010-08-31 14:41:23 +0000330 bool VisitQualifiedTypeLoc(QualifiedTypeLoc TL);
Douglas Gregorf20dfbc2010-01-21 17:29:07 +0000331 bool VisitBuiltinTypeLoc(BuiltinTypeLoc TL);
Douglas Gregor7d0d40e2010-01-21 16:28:34 +0000332 bool VisitTypedefTypeLoc(TypedefTypeLoc TL);
Douglas Gregorf20dfbc2010-01-21 17:29:07 +0000333 bool VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc TL);
334 bool VisitTagTypeLoc(TagTypeLoc TL);
Douglas Gregorfe72e9c2010-08-31 17:01:39 +0000335 bool VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL);
Douglas Gregorf20dfbc2010-01-21 17:29:07 +0000336 bool VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL);
John McCallc12c5bb2010-05-15 11:32:37 +0000337 bool VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL);
Douglas Gregorf20dfbc2010-01-21 17:29:07 +0000338 bool VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL);
Abramo Bagnara075f8f12010-12-10 16:29:40 +0000339 bool VisitParenTypeLoc(ParenTypeLoc TL);
Douglas Gregorf20dfbc2010-01-21 17:29:07 +0000340 bool VisitPointerTypeLoc(PointerTypeLoc TL);
341 bool VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL);
342 bool VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL);
343 bool VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL);
344 bool VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL);
Douglas Gregor01829d32010-08-31 14:41:23 +0000345 bool VisitFunctionTypeLoc(FunctionTypeLoc TL, bool SkipResultType = false);
Douglas Gregorf20dfbc2010-01-21 17:29:07 +0000346 bool VisitArrayTypeLoc(ArrayTypeLoc TL);
Douglas Gregorfe72e9c2010-08-31 17:01:39 +0000347 bool VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL);
Douglas Gregor2332c112010-01-21 20:48:56 +0000348 // FIXME: Implement visitors here when the unimplemented TypeLocs get
349 // implemented
350 bool VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL);
Douglas Gregor7536dd52010-12-20 02:24:11 +0000351 bool VisitPackExpansionTypeLoc(PackExpansionTypeLoc TL);
Douglas Gregor2332c112010-01-21 20:48:56 +0000352 bool VisitTypeOfTypeLoc(TypeOfTypeLoc TL);
Douglas Gregor2494dd02011-03-01 01:34:45 +0000353 bool VisitDependentNameTypeLoc(DependentNameTypeLoc TL);
Douglas Gregor94fdffa2011-03-01 20:11:18 +0000354 bool VisitDependentTemplateSpecializationTypeLoc(
355 DependentTemplateSpecializationTypeLoc TL);
Douglas Gregor9e876872011-03-01 18:12:44 +0000356 bool VisitElaboratedTypeLoc(ElaboratedTypeLoc TL);
Douglas Gregor2494dd02011-03-01 01:34:45 +0000357
Ted Kremenekc0e1d922010-11-11 08:05:18 +0000358 // Data-recursive visitor functions.
359 bool IsInRegionOfInterest(CXCursor C);
360 bool RunVisitorWorkList(VisitorWorkList &WL);
361 void EnqueueWorkList(VisitorWorkList &WL, Stmt *S);
Ted Kremenekcdba6592010-11-18 00:42:18 +0000362 LLVM_ATTRIBUTE_NOINLINE bool Visit(Stmt *S);
Steve Naroff89922f82009-08-31 00:59:03 +0000363};
Ted Kremenekf0e23e82010-02-17 00:41:40 +0000364
Ted Kremenekab188932010-01-05 19:32:54 +0000365} // end anonymous namespace
Benjamin Kramer5e4bc592009-10-18 16:11:04 +0000366
Douglas Gregora8e5c5b2010-07-22 20:22:31 +0000367static SourceRange getRawCursorExtent(CXCursor C);
Douglas Gregor66537982010-11-17 17:14:07 +0000368static SourceRange getFullCursorExtent(CXCursor C, SourceManager &SrcMgr);
369
Douglas Gregora8e5c5b2010-07-22 20:22:31 +0000370
Douglas Gregor33e9abd2010-01-22 19:49:59 +0000371RangeComparisonResult CursorVisitor::CompareRegionOfInterest(SourceRange R) {
Ted Kremeneka60ed472010-11-16 08:15:36 +0000372 return RangeCompare(AU->getSourceManager(), R, RegionOfInterest);
Douglas Gregor33e9abd2010-01-22 19:49:59 +0000373}
374
Douglas Gregorb1373d02010-01-20 20:59:29 +0000375/// \brief Visit the given cursor and, if requested by the visitor,
376/// its children.
377///
Douglas Gregor33e9abd2010-01-22 19:49:59 +0000378/// \param Cursor the cursor to visit.
379///
380/// \param CheckRegionOfInterest if true, then the caller already checked that
381/// this cursor is within the region of interest.
382///
Douglas Gregorb1373d02010-01-20 20:59:29 +0000383/// \returns true if the visitation should be aborted, false if it
384/// should continue.
Douglas Gregor33e9abd2010-01-22 19:49:59 +0000385bool CursorVisitor::Visit(CXCursor Cursor, bool CheckedRegionOfInterest) {
Douglas Gregorb1373d02010-01-20 20:59:29 +0000386 if (clang_isInvalid(Cursor.kind))
387 return false;
Ted Kremenekf0e23e82010-02-17 00:41:40 +0000388
Douglas Gregorb1373d02010-01-20 20:59:29 +0000389 if (clang_isDeclaration(Cursor.kind)) {
390 Decl *D = getCursorDecl(Cursor);
391 assert(D && "Invalid declaration cursor");
392 if (D->getPCHLevel() > MaxPCHLevel)
393 return false;
394
395 if (D->isImplicit())
396 return false;
397 }
398
Douglas Gregor33e9abd2010-01-22 19:49:59 +0000399 // If we have a range of interest, and this cursor doesn't intersect with it,
400 // we're done.
401 if (RegionOfInterest.isValid() && !CheckedRegionOfInterest) {
Douglas Gregora8e5c5b2010-07-22 20:22:31 +0000402 SourceRange Range = getRawCursorExtent(Cursor);
Daniel Dunbarf408f322010-02-14 08:32:05 +0000403 if (Range.isInvalid() || CompareRegionOfInterest(Range))
Douglas Gregor33e9abd2010-01-22 19:49:59 +0000404 return false;
405 }
Ted Kremenekf0e23e82010-02-17 00:41:40 +0000406
Douglas Gregorb1373d02010-01-20 20:59:29 +0000407 switch (Visitor(Cursor, Parent, ClientData)) {
408 case CXChildVisit_Break:
409 return true;
410
411 case CXChildVisit_Continue:
412 return false;
413
414 case CXChildVisit_Recurse:
415 return VisitChildren(Cursor);
416 }
417
Douglas Gregorfd643772010-01-25 16:45:46 +0000418 return false;
Douglas Gregorb1373d02010-01-20 20:59:29 +0000419}
420
Douglas Gregor788f5a12010-03-20 00:41:21 +0000421std::pair<PreprocessingRecord::iterator, PreprocessingRecord::iterator>
422CursorVisitor::getPreprocessedEntities() {
423 PreprocessingRecord &PPRec
Ted Kremeneka60ed472010-11-16 08:15:36 +0000424 = *AU->getPreprocessor().getPreprocessingRecord();
Douglas Gregor788f5a12010-03-20 00:41:21 +0000425
426 bool OnlyLocalDecls
Douglas Gregor32038bb2010-12-21 19:07:48 +0000427 = !AU->isMainFileAST() && AU->getOnlyLocalDecls();
428
429 if (OnlyLocalDecls && RegionOfInterest.isValid()) {
430 // If we would only look at local declarations but we have a region of
431 // interest, check whether that region of interest is in the main file.
432 // If not, we should traverse all declarations.
433 // FIXME: My kingdom for a proper binary search approach to finding
434 // cursors!
435 std::pair<FileID, unsigned> Location
436 = AU->getSourceManager().getDecomposedInstantiationLoc(
437 RegionOfInterest.getBegin());
438 if (Location.first != AU->getSourceManager().getMainFileID())
439 OnlyLocalDecls = false;
440 }
Douglas Gregor788f5a12010-03-20 00:41:21 +0000441
Douglas Gregor89d99802010-11-30 06:16:57 +0000442 PreprocessingRecord::iterator StartEntity, EndEntity;
443 if (OnlyLocalDecls) {
444 StartEntity = AU->pp_entity_begin();
445 EndEntity = AU->pp_entity_end();
446 } else {
447 StartEntity = PPRec.begin();
448 EndEntity = PPRec.end();
449 }
450
Douglas Gregor788f5a12010-03-20 00:41:21 +0000451 // There is no region of interest; we have to walk everything.
452 if (RegionOfInterest.isInvalid())
Douglas Gregor89d99802010-11-30 06:16:57 +0000453 return std::make_pair(StartEntity, EndEntity);
Douglas Gregor788f5a12010-03-20 00:41:21 +0000454
455 // Find the file in which the region of interest lands.
Ted Kremeneka60ed472010-11-16 08:15:36 +0000456 SourceManager &SM = AU->getSourceManager();
Douglas Gregor788f5a12010-03-20 00:41:21 +0000457 std::pair<FileID, unsigned> Begin
458 = SM.getDecomposedInstantiationLoc(RegionOfInterest.getBegin());
459 std::pair<FileID, unsigned> End
460 = SM.getDecomposedInstantiationLoc(RegionOfInterest.getEnd());
461
462 // The region of interest spans files; we have to walk everything.
463 if (Begin.first != End.first)
Douglas Gregor89d99802010-11-30 06:16:57 +0000464 return std::make_pair(StartEntity, EndEntity);
Douglas Gregor788f5a12010-03-20 00:41:21 +0000465
466 ASTUnit::PreprocessedEntitiesByFileMap &ByFileMap
Ted Kremeneka60ed472010-11-16 08:15:36 +0000467 = AU->getPreprocessedEntitiesByFile();
Douglas Gregor788f5a12010-03-20 00:41:21 +0000468 if (ByFileMap.empty()) {
469 // Build the mapping from files to sets of preprocessed entities.
Douglas Gregor89d99802010-11-30 06:16:57 +0000470 for (PreprocessingRecord::iterator E = StartEntity; E != EndEntity; ++E) {
Douglas Gregor788f5a12010-03-20 00:41:21 +0000471 std::pair<FileID, unsigned> P
472 = SM.getDecomposedInstantiationLoc((*E)->getSourceRange().getBegin());
Douglas Gregor89d99802010-11-30 06:16:57 +0000473
Douglas Gregor788f5a12010-03-20 00:41:21 +0000474 ByFileMap[P.first].push_back(*E);
475 }
476 }
477
478 return std::make_pair(ByFileMap[Begin.first].begin(),
479 ByFileMap[Begin.first].end());
480}
481
Douglas Gregorb1373d02010-01-20 20:59:29 +0000482/// \brief Visit the children of the given cursor.
Ted Kremeneka60ed472010-11-16 08:15:36 +0000483///
Douglas Gregorb1373d02010-01-20 20:59:29 +0000484/// \returns true if the visitation should be aborted, false if it
485/// should continue.
Ted Kremenekf0e23e82010-02-17 00:41:40 +0000486bool CursorVisitor::VisitChildren(CXCursor Cursor) {
Douglas Gregorc314aa42011-03-02 19:17:03 +0000487 if (clang_isReference(Cursor.kind) &&
488 Cursor.kind != CXCursor_CXXBaseSpecifier) {
Douglas Gregora59e3902010-01-21 23:27:09 +0000489 // By definition, references have no children.
490 return false;
491 }
Ted Kremenekf0e23e82010-02-17 00:41:40 +0000492
493 // Set the Parent field to Cursor, then back to its old value once we're
Douglas Gregorb1373d02010-01-20 20:59:29 +0000494 // done.
Ted Kremenek0f91f6a2010-05-13 00:25:00 +0000495 SetParentRAII SetParent(Parent, StmtParent, Cursor);
Ted Kremenekf0e23e82010-02-17 00:41:40 +0000496
Douglas Gregorb1373d02010-01-20 20:59:29 +0000497 if (clang_isDeclaration(Cursor.kind)) {
498 Decl *D = getCursorDecl(Cursor);
Douglas Gregor06d9b1a2011-04-14 21:41:34 +0000499 if (!D)
500 return false;
501
Ted Kremenek539311e2010-02-18 18:47:01 +0000502 return VisitAttributes(D) || Visit(D);
Douglas Gregorb1373d02010-01-20 20:59:29 +0000503 }
Ted Kremenekf0e23e82010-02-17 00:41:40 +0000504
Douglas Gregor06d9b1a2011-04-14 21:41:34 +0000505 if (clang_isStatement(Cursor.kind)) {
506 if (Stmt *S = getCursorStmt(Cursor))
507 return Visit(S);
508
509 return false;
510 }
511
512 if (clang_isExpression(Cursor.kind)) {
513 if (Expr *E = getCursorExpr(Cursor))
514 return Visit(E);
515
516 return false;
517 }
Ted Kremenekf0e23e82010-02-17 00:41:40 +0000518
Douglas Gregorb1373d02010-01-20 20:59:29 +0000519 if (clang_isTranslationUnit(Cursor.kind)) {
Ted Kremeneka60ed472010-11-16 08:15:36 +0000520 CXTranslationUnit tu = getCursorTU(Cursor);
521 ASTUnit *CXXUnit = static_cast<ASTUnit*>(tu->TUData);
Douglas Gregor04a9eb32011-03-16 23:23:30 +0000522
523 int VisitOrder[2] = { VisitPreprocessorLast, !VisitPreprocessorLast };
524 for (unsigned I = 0; I != 2; ++I) {
525 if (VisitOrder[I]) {
526 if (!CXXUnit->isMainFileAST() && CXXUnit->getOnlyLocalDecls() &&
527 RegionOfInterest.isInvalid()) {
528 for (ASTUnit::top_level_iterator TL = CXXUnit->top_level_begin(),
529 TLEnd = CXXUnit->top_level_end();
530 TL != TLEnd; ++TL) {
531 if (Visit(MakeCXCursor(*TL, tu), true))
532 return true;
533 }
534 } else if (VisitDeclContext(
535 CXXUnit->getASTContext().getTranslationUnitDecl()))
Douglas Gregor7b691f332010-01-20 21:13:59 +0000536 return true;
Douglas Gregor04a9eb32011-03-16 23:23:30 +0000537 continue;
Douglas Gregor7b691f332010-01-20 21:13:59 +0000538 }
Bob Wilson3178cb62010-03-19 03:57:57 +0000539
Douglas Gregor04a9eb32011-03-16 23:23:30 +0000540 // Walk the preprocessing record.
541 if (CXXUnit->getPreprocessor().getPreprocessingRecord()) {
542 // FIXME: Once we have the ability to deserialize a preprocessing record,
543 // do so.
544 PreprocessingRecord::iterator E, EEnd;
545 for (llvm::tie(E, EEnd) = getPreprocessedEntities(); E != EEnd; ++E) {
546 if (MacroInstantiation *MI = dyn_cast<MacroInstantiation>(*E)) {
547 if (Visit(MakeMacroInstantiationCursor(MI, tu)))
548 return true;
549
550 continue;
551 }
Douglas Gregor788f5a12010-03-20 00:41:21 +0000552
Douglas Gregor04a9eb32011-03-16 23:23:30 +0000553 if (MacroDefinition *MD = dyn_cast<MacroDefinition>(*E)) {
554 if (Visit(MakeMacroDefinitionCursor(MD, tu)))
555 return true;
556
557 continue;
558 }
Douglas Gregor0396f462010-03-19 05:22:59 +0000559
Douglas Gregor04a9eb32011-03-16 23:23:30 +0000560 if (InclusionDirective *ID = dyn_cast<InclusionDirective>(*E)) {
561 if (Visit(MakeInclusionDirectiveCursor(ID, tu)))
562 return true;
563
564 continue;
565 }
Douglas Gregorecdcb882010-10-20 22:00:55 +0000566 }
Douglas Gregor0396f462010-03-19 05:22:59 +0000567 }
568 }
Douglas Gregor04a9eb32011-03-16 23:23:30 +0000569
Douglas Gregor7b691f332010-01-20 21:13:59 +0000570 return false;
Douglas Gregorb1373d02010-01-20 20:59:29 +0000571 }
Ted Kremenekf0e23e82010-02-17 00:41:40 +0000572
Douglas Gregorc314aa42011-03-02 19:17:03 +0000573 if (Cursor.kind == CXCursor_CXXBaseSpecifier) {
574 if (CXXBaseSpecifier *Base = getCursorCXXBaseSpecifier(Cursor)) {
575 if (TypeSourceInfo *BaseTSInfo = Base->getTypeSourceInfo()) {
576 return Visit(BaseTSInfo->getTypeLoc());
577 }
578 }
579 }
580
Douglas Gregorb1373d02010-01-20 20:59:29 +0000581 // Nothing to visit at the moment.
Douglas Gregorb1373d02010-01-20 20:59:29 +0000582 return false;
583}
584
Ted Kremenek1ee6cad2010-04-11 21:47:37 +0000585bool CursorVisitor::VisitBlockDecl(BlockDecl *B) {
Douglas Gregor13c8ccb2011-04-22 23:49:24 +0000586 if (TypeSourceInfo *TSInfo = B->getSignatureAsWritten())
587 if (Visit(TSInfo->getTypeLoc()))
588 return true;
Ted Kremenek1ee6cad2010-04-11 21:47:37 +0000589
Ted Kremenek664cffd2010-07-22 11:30:19 +0000590 if (Stmt *Body = B->getBody())
591 return Visit(MakeCXCursor(Body, StmtParent, TU));
592
593 return false;
Ted Kremenek1ee6cad2010-04-11 21:47:37 +0000594}
595
Ted Kremenekd8c370c2010-11-02 23:10:24 +0000596llvm::Optional<bool> CursorVisitor::shouldVisitCursor(CXCursor Cursor) {
597 if (RegionOfInterest.isValid()) {
Douglas Gregor66537982010-11-17 17:14:07 +0000598 SourceRange Range = getFullCursorExtent(Cursor, AU->getSourceManager());
Ted Kremenekd8c370c2010-11-02 23:10:24 +0000599 if (Range.isInvalid())
600 return llvm::Optional<bool>();
Douglas Gregor66537982010-11-17 17:14:07 +0000601
Ted Kremenekd8c370c2010-11-02 23:10:24 +0000602 switch (CompareRegionOfInterest(Range)) {
603 case RangeBefore:
604 // This declaration comes before the region of interest; skip it.
605 return llvm::Optional<bool>();
606
607 case RangeAfter:
608 // This declaration comes after the region of interest; we're done.
609 return false;
610
611 case RangeOverlap:
612 // This declaration overlaps the region of interest; visit it.
613 break;
614 }
615 }
616 return true;
617}
618
619bool CursorVisitor::VisitDeclContext(DeclContext *DC) {
620 DeclContext::decl_iterator I = DC->decls_begin(), E = DC->decls_end();
621
622 // FIXME: Eventually remove. This part of a hack to support proper
623 // iteration over all Decls contained lexically within an ObjC container.
624 SaveAndRestore<DeclContext::decl_iterator*> DI_saved(DI_current, &I);
625 SaveAndRestore<DeclContext::decl_iterator> DE_saved(DE_current, E);
626
627 for ( ; I != E; ++I) {
Ted Kremenek23173d72010-05-18 21:09:07 +0000628 Decl *D = *I;
629 if (D->getLexicalDeclContext() != DC)
630 continue;
Ted Kremenek23173d72010-05-18 21:09:07 +0000631 CXCursor Cursor = MakeCXCursor(D, TU);
Ted Kremenekd8c370c2010-11-02 23:10:24 +0000632 const llvm::Optional<bool> &V = shouldVisitCursor(Cursor);
633 if (!V.hasValue())
634 continue;
635 if (!V.getValue())
636 return false;
Daniel Dunbard52864b2010-02-14 10:02:57 +0000637 if (Visit(Cursor, true))
Douglas Gregorb1373d02010-01-20 20:59:29 +0000638 return true;
639 }
Douglas Gregorb1373d02010-01-20 20:59:29 +0000640 return false;
Ted Kremenekdd6bcc52010-01-13 00:22:49 +0000641}
642
Douglas Gregor1ef2fc12010-01-22 00:50:27 +0000643bool CursorVisitor::VisitTranslationUnitDecl(TranslationUnitDecl *D) {
644 llvm_unreachable("Translation units are visited directly by Visit()");
645 return false;
646}
647
Richard Smith162e1c12011-04-15 14:24:37 +0000648bool CursorVisitor::VisitTypeAliasDecl(TypeAliasDecl *D) {
649 if (TypeSourceInfo *TSInfo = D->getTypeSourceInfo())
650 return Visit(TSInfo->getTypeLoc());
651
652 return false;
653}
654
Douglas Gregor1ef2fc12010-01-22 00:50:27 +0000655bool CursorVisitor::VisitTypedefDecl(TypedefDecl *D) {
656 if (TypeSourceInfo *TSInfo = D->getTypeSourceInfo())
657 return Visit(TSInfo->getTypeLoc());
Ted Kremenekf0e23e82010-02-17 00:41:40 +0000658
Douglas Gregor1ef2fc12010-01-22 00:50:27 +0000659 return false;
660}
661
662bool CursorVisitor::VisitTagDecl(TagDecl *D) {
663 return VisitDeclContext(D);
664}
665
Douglas Gregor0ab1e9f2010-09-01 17:32:36 +0000666bool CursorVisitor::VisitClassTemplateSpecializationDecl(
667 ClassTemplateSpecializationDecl *D) {
668 bool ShouldVisitBody = false;
669 switch (D->getSpecializationKind()) {
670 case TSK_Undeclared:
671 case TSK_ImplicitInstantiation:
672 // Nothing to visit
673 return false;
674
675 case TSK_ExplicitInstantiationDeclaration:
676 case TSK_ExplicitInstantiationDefinition:
677 break;
678
679 case TSK_ExplicitSpecialization:
680 ShouldVisitBody = true;
681 break;
682 }
683
684 // Visit the template arguments used in the specialization.
685 if (TypeSourceInfo *SpecType = D->getTypeAsWritten()) {
686 TypeLoc TL = SpecType->getTypeLoc();
687 if (TemplateSpecializationTypeLoc *TSTLoc
688 = dyn_cast<TemplateSpecializationTypeLoc>(&TL)) {
689 for (unsigned I = 0, N = TSTLoc->getNumArgs(); I != N; ++I)
690 if (VisitTemplateArgumentLoc(TSTLoc->getArgLoc(I)))
691 return true;
692 }
693 }
694
695 if (ShouldVisitBody && VisitCXXRecordDecl(D))
696 return true;
697
698 return false;
699}
700
Douglas Gregor74dbe642010-08-31 19:31:58 +0000701bool CursorVisitor::VisitClassTemplatePartialSpecializationDecl(
702 ClassTemplatePartialSpecializationDecl *D) {
703 // FIXME: Visit the "outer" template parameter lists on the TagDecl
704 // before visiting these template parameters.
705 if (VisitTemplateParameters(D->getTemplateParameters()))
706 return true;
707
708 // Visit the partial specialization arguments.
709 const TemplateArgumentLoc *TemplateArgs = D->getTemplateArgsAsWritten();
710 for (unsigned I = 0, N = D->getNumTemplateArgsAsWritten(); I != N; ++I)
711 if (VisitTemplateArgumentLoc(TemplateArgs[I]))
712 return true;
713
714 return VisitCXXRecordDecl(D);
715}
716
Douglas Gregorfe72e9c2010-08-31 17:01:39 +0000717bool CursorVisitor::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
Douglas Gregor84b51d72010-09-01 20:16:53 +0000718 // Visit the default argument.
719 if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited())
720 if (TypeSourceInfo *DefArg = D->getDefaultArgumentInfo())
721 if (Visit(DefArg->getTypeLoc()))
722 return true;
723
Douglas Gregorfe72e9c2010-08-31 17:01:39 +0000724 return false;
725}
726
Douglas Gregor1ef2fc12010-01-22 00:50:27 +0000727bool CursorVisitor::VisitEnumConstantDecl(EnumConstantDecl *D) {
728 if (Expr *Init = D->getInitExpr())
729 return Visit(MakeCXCursor(Init, StmtParent, TU));
730 return false;
731}
732
Douglas Gregor7d0d40e2010-01-21 16:28:34 +0000733bool CursorVisitor::VisitDeclaratorDecl(DeclaratorDecl *DD) {
734 if (TypeSourceInfo *TSInfo = DD->getTypeSourceInfo())
735 if (Visit(TSInfo->getTypeLoc()))
736 return true;
737
Douglas Gregorc22b5ff2011-02-25 02:25:35 +0000738 // Visit the nested-name-specifier, if present.
739 if (NestedNameSpecifierLoc QualifierLoc = DD->getQualifierLoc())
740 if (VisitNestedNameSpecifierLoc(QualifierLoc))
741 return true;
742
Douglas Gregor7d0d40e2010-01-21 16:28:34 +0000743 return false;
744}
745
Douglas Gregora67e03f2010-09-09 21:42:20 +0000746/// \brief Compare two base or member initializers based on their source order.
Sean Huntcbb67482011-01-08 20:30:50 +0000747static int CompareCXXCtorInitializers(const void* Xp, const void *Yp) {
748 CXXCtorInitializer const * const *X
749 = static_cast<CXXCtorInitializer const * const *>(Xp);
750 CXXCtorInitializer const * const *Y
751 = static_cast<CXXCtorInitializer const * const *>(Yp);
Douglas Gregora67e03f2010-09-09 21:42:20 +0000752
753 if ((*X)->getSourceOrder() < (*Y)->getSourceOrder())
754 return -1;
755 else if ((*X)->getSourceOrder() > (*Y)->getSourceOrder())
756 return 1;
757 else
758 return 0;
759}
760
Douglas Gregorb1373d02010-01-20 20:59:29 +0000761bool CursorVisitor::VisitFunctionDecl(FunctionDecl *ND) {
Douglas Gregor01829d32010-08-31 14:41:23 +0000762 if (TypeSourceInfo *TSInfo = ND->getTypeSourceInfo()) {
763 // Visit the function declaration's syntactic components in the order
764 // written. This requires a bit of work.
Abramo Bagnara723df242010-12-14 22:11:44 +0000765 TypeLoc TL = TSInfo->getTypeLoc().IgnoreParens();
Douglas Gregor01829d32010-08-31 14:41:23 +0000766 FunctionTypeLoc *FTL = dyn_cast<FunctionTypeLoc>(&TL);
767
768 // If we have a function declared directly (without the use of a typedef),
769 // visit just the return type. Otherwise, just visit the function's type
770 // now.
771 if ((FTL && !isa<CXXConversionDecl>(ND) && Visit(FTL->getResultLoc())) ||
772 (!FTL && Visit(TL)))
773 return true;
774
Douglas Gregorc5ade2e2010-09-02 17:35:32 +0000775 // Visit the nested-name-specifier, if present.
Douglas Gregorc22b5ff2011-02-25 02:25:35 +0000776 if (NestedNameSpecifierLoc QualifierLoc = ND->getQualifierLoc())
777 if (VisitNestedNameSpecifierLoc(QualifierLoc))
Douglas Gregorc5ade2e2010-09-02 17:35:32 +0000778 return true;
Douglas Gregor01829d32010-08-31 14:41:23 +0000779
780 // Visit the declaration name.
781 if (VisitDeclarationNameInfo(ND->getNameInfo()))
782 return true;
783
784 // FIXME: Visit explicitly-specified template arguments!
785
786 // Visit the function parameters, if we have a function type.
787 if (FTL && VisitFunctionTypeLoc(*FTL, true))
788 return true;
789
790 // FIXME: Attributes?
791 }
792
Sean Hunt10620eb2011-05-06 20:44:56 +0000793 if (ND->doesThisDeclarationHaveABody() && !ND->isLateTemplateParsed()) {
Douglas Gregora67e03f2010-09-09 21:42:20 +0000794 if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(ND)) {
795 // Find the initializers that were written in the source.
Sean Huntcbb67482011-01-08 20:30:50 +0000796 llvm::SmallVector<CXXCtorInitializer *, 4> WrittenInits;
Douglas Gregora67e03f2010-09-09 21:42:20 +0000797 for (CXXConstructorDecl::init_iterator I = Constructor->init_begin(),
798 IEnd = Constructor->init_end();
799 I != IEnd; ++I) {
800 if (!(*I)->isWritten())
801 continue;
802
803 WrittenInits.push_back(*I);
804 }
805
806 // Sort the initializers in source order
807 llvm::array_pod_sort(WrittenInits.begin(), WrittenInits.end(),
Sean Huntcbb67482011-01-08 20:30:50 +0000808 &CompareCXXCtorInitializers);
Douglas Gregora67e03f2010-09-09 21:42:20 +0000809
810 // Visit the initializers in source order
811 for (unsigned I = 0, N = WrittenInits.size(); I != N; ++I) {
Sean Huntcbb67482011-01-08 20:30:50 +0000812 CXXCtorInitializer *Init = WrittenInits[I];
Francois Pichet00eb3f92010-12-04 09:14:42 +0000813 if (Init->isAnyMemberInitializer()) {
814 if (Visit(MakeCursorMemberRef(Init->getAnyMember(),
Douglas Gregora67e03f2010-09-09 21:42:20 +0000815 Init->getMemberLocation(), TU)))
816 return true;
817 } else if (TypeSourceInfo *BaseInfo = Init->getBaseClassInfo()) {
818 if (Visit(BaseInfo->getTypeLoc()))
819 return true;
820 }
821
822 // Visit the initializer value.
823 if (Expr *Initializer = Init->getInit())
824 if (Visit(MakeCXCursor(Initializer, ND, TU)))
825 return true;
826 }
827 }
828
829 if (Visit(MakeCXCursor(ND->getBody(), StmtParent, TU)))
830 return true;
831 }
Ted Kremenekf0e23e82010-02-17 00:41:40 +0000832
Douglas Gregorb1373d02010-01-20 20:59:29 +0000833 return false;
834}
Ted Kremenekdd6bcc52010-01-13 00:22:49 +0000835
Douglas Gregor1ef2fc12010-01-22 00:50:27 +0000836bool CursorVisitor::VisitFieldDecl(FieldDecl *D) {
837 if (VisitDeclaratorDecl(D))
838 return true;
Ted Kremenekf0e23e82010-02-17 00:41:40 +0000839
Douglas Gregor1ef2fc12010-01-22 00:50:27 +0000840 if (Expr *BitWidth = D->getBitWidth())
841 return Visit(MakeCXCursor(BitWidth, StmtParent, TU));
Ted Kremenekf0e23e82010-02-17 00:41:40 +0000842
Douglas Gregor1ef2fc12010-01-22 00:50:27 +0000843 return false;
844}
845
846bool CursorVisitor::VisitVarDecl(VarDecl *D) {
847 if (VisitDeclaratorDecl(D))
848 return true;
Ted Kremenekf0e23e82010-02-17 00:41:40 +0000849
Douglas Gregor1ef2fc12010-01-22 00:50:27 +0000850 if (Expr *Init = D->getInit())
851 return Visit(MakeCXCursor(Init, StmtParent, TU));
Ted Kremenekf0e23e82010-02-17 00:41:40 +0000852
Douglas Gregor1ef2fc12010-01-22 00:50:27 +0000853 return false;
854}
855
Douglas Gregor84b51d72010-09-01 20:16:53 +0000856bool CursorVisitor::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) {
857 if (VisitDeclaratorDecl(D))
858 return true;
859
860 if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited())
861 if (Expr *DefArg = D->getDefaultArgument())
862 return Visit(MakeCXCursor(DefArg, StmtParent, TU));
863
864 return false;
865}
866
Douglas Gregorfe72e9c2010-08-31 17:01:39 +0000867bool CursorVisitor::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
868 // FIXME: Visit the "outer" template parameter lists on the FunctionDecl
869 // before visiting these template parameters.
870 if (VisitTemplateParameters(D->getTemplateParameters()))
871 return true;
872
873 return VisitFunctionDecl(D->getTemplatedDecl());
874}
875
Douglas Gregor39d6f072010-08-31 19:02:00 +0000876bool CursorVisitor::VisitClassTemplateDecl(ClassTemplateDecl *D) {
877 // FIXME: Visit the "outer" template parameter lists on the TagDecl
878 // before visiting these template parameters.
879 if (VisitTemplateParameters(D->getTemplateParameters()))
880 return true;
881
882 return VisitCXXRecordDecl(D->getTemplatedDecl());
883}
884
Douglas Gregor84b51d72010-09-01 20:16:53 +0000885bool CursorVisitor::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) {
886 if (VisitTemplateParameters(D->getTemplateParameters()))
887 return true;
888
889 if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited() &&
890 VisitTemplateArgumentLoc(D->getDefaultArgument()))
891 return true;
892
893 return false;
894}
895
Douglas Gregor1ef2fc12010-01-22 00:50:27 +0000896bool CursorVisitor::VisitObjCMethodDecl(ObjCMethodDecl *ND) {
Douglas Gregor4bc1cb62010-03-08 14:59:44 +0000897 if (TypeSourceInfo *TSInfo = ND->getResultTypeSourceInfo())
898 if (Visit(TSInfo->getTypeLoc()))
899 return true;
900
Ted Kremenekf0e23e82010-02-17 00:41:40 +0000901 for (ObjCMethodDecl::param_iterator P = ND->param_begin(),
Douglas Gregor1ef2fc12010-01-22 00:50:27 +0000902 PEnd = ND->param_end();
903 P != PEnd; ++P) {
904 if (Visit(MakeCXCursor(*P, TU)))
905 return true;
906 }
Ted Kremenekf0e23e82010-02-17 00:41:40 +0000907
Douglas Gregor1ef2fc12010-01-22 00:50:27 +0000908 if (ND->isThisDeclarationADefinition() &&
909 Visit(MakeCXCursor(ND->getBody(), StmtParent, TU)))
910 return true;
Ted Kremenekf0e23e82010-02-17 00:41:40 +0000911
Douglas Gregor1ef2fc12010-01-22 00:50:27 +0000912 return false;
913}
914
Ted Kremenekd8c370c2010-11-02 23:10:24 +0000915namespace {
916 struct ContainerDeclsSort {
917 SourceManager &SM;
918 ContainerDeclsSort(SourceManager &sm) : SM(sm) {}
919 bool operator()(Decl *A, Decl *B) {
920 SourceLocation L_A = A->getLocStart();
921 SourceLocation L_B = B->getLocStart();
922 assert(L_A.isValid() && L_B.isValid());
923 return SM.isBeforeInTranslationUnit(L_A, L_B);
924 }
925 };
926}
927
Douglas Gregora59e3902010-01-21 23:27:09 +0000928bool CursorVisitor::VisitObjCContainerDecl(ObjCContainerDecl *D) {
Ted Kremenekd8c370c2010-11-02 23:10:24 +0000929 // FIXME: Eventually convert back to just 'VisitDeclContext()'. Essentially
930 // an @implementation can lexically contain Decls that are not properly
931 // nested in the AST. When we identify such cases, we need to retrofit
932 // this nesting here.
933 if (!DI_current)
934 return VisitDeclContext(D);
935
936 // Scan the Decls that immediately come after the container
937 // in the current DeclContext. If any fall within the
938 // container's lexical region, stash them into a vector
939 // for later processing.
940 llvm::SmallVector<Decl *, 24> DeclsInContainer;
941 SourceLocation EndLoc = D->getSourceRange().getEnd();
Ted Kremeneka60ed472010-11-16 08:15:36 +0000942 SourceManager &SM = AU->getSourceManager();
Ted Kremenekd8c370c2010-11-02 23:10:24 +0000943 if (EndLoc.isValid()) {
944 DeclContext::decl_iterator next = *DI_current;
945 while (++next != DE_current) {
946 Decl *D_next = *next;
947 if (!D_next)
948 break;
949 SourceLocation L = D_next->getLocStart();
950 if (!L.isValid())
951 break;
952 if (SM.isBeforeInTranslationUnit(L, EndLoc)) {
953 *DI_current = next;
954 DeclsInContainer.push_back(D_next);
955 continue;
956 }
957 break;
958 }
959 }
960
961 // The common case.
962 if (DeclsInContainer.empty())
963 return VisitDeclContext(D);
964
965 // Get all the Decls in the DeclContext, and sort them with the
966 // additional ones we've collected. Then visit them.
967 for (DeclContext::decl_iterator I = D->decls_begin(), E = D->decls_end();
968 I!=E; ++I) {
969 Decl *subDecl = *I;
Ted Kremenek0582c892010-11-02 23:17:51 +0000970 if (!subDecl || subDecl->getLexicalDeclContext() != D ||
971 subDecl->getLocStart().isInvalid())
Ted Kremenekd8c370c2010-11-02 23:10:24 +0000972 continue;
973 DeclsInContainer.push_back(subDecl);
974 }
975
976 // Now sort the Decls so that they appear in lexical order.
977 std::sort(DeclsInContainer.begin(), DeclsInContainer.end(),
978 ContainerDeclsSort(SM));
979
980 // Now visit the decls.
981 for (llvm::SmallVectorImpl<Decl*>::iterator I = DeclsInContainer.begin(),
982 E = DeclsInContainer.end(); I != E; ++I) {
983 CXCursor Cursor = MakeCXCursor(*I, TU);
984 const llvm::Optional<bool> &V = shouldVisitCursor(Cursor);
985 if (!V.hasValue())
986 continue;
987 if (!V.getValue())
988 return false;
989 if (Visit(Cursor, true))
990 return true;
991 }
992 return false;
Douglas Gregora59e3902010-01-21 23:27:09 +0000993}
994
Douglas Gregorb1373d02010-01-20 20:59:29 +0000995bool CursorVisitor::VisitObjCCategoryDecl(ObjCCategoryDecl *ND) {
Douglas Gregorb2cd4872010-01-20 23:57:43 +0000996 if (Visit(MakeCursorObjCClassRef(ND->getClassInterface(), ND->getLocation(),
997 TU)))
Douglas Gregorb1373d02010-01-20 20:59:29 +0000998 return true;
Ted Kremenekf0e23e82010-02-17 00:41:40 +0000999
Douglas Gregor78db0cd2010-01-16 15:44:18 +00001000 ObjCCategoryDecl::protocol_loc_iterator PL = ND->protocol_loc_begin();
1001 for (ObjCCategoryDecl::protocol_iterator I = ND->protocol_begin(),
1002 E = ND->protocol_end(); I != E; ++I, ++PL)
Douglas Gregorb2cd4872010-01-20 23:57:43 +00001003 if (Visit(MakeCursorObjCProtocolRef(*I, *PL, TU)))
Douglas Gregorb1373d02010-01-20 20:59:29 +00001004 return true;
Ted Kremenekf0e23e82010-02-17 00:41:40 +00001005
Douglas Gregora59e3902010-01-21 23:27:09 +00001006 return VisitObjCContainerDecl(ND);
Ted Kremenekdd6bcc52010-01-13 00:22:49 +00001007}
1008
Douglas Gregor1ef2fc12010-01-22 00:50:27 +00001009bool CursorVisitor::VisitObjCProtocolDecl(ObjCProtocolDecl *PID) {
1010 ObjCProtocolDecl::protocol_loc_iterator PL = PID->protocol_loc_begin();
1011 for (ObjCProtocolDecl::protocol_iterator I = PID->protocol_begin(),
1012 E = PID->protocol_end(); I != E; ++I, ++PL)
1013 if (Visit(MakeCursorObjCProtocolRef(*I, *PL, TU)))
1014 return true;
Ted Kremenekf0e23e82010-02-17 00:41:40 +00001015
Douglas Gregor1ef2fc12010-01-22 00:50:27 +00001016 return VisitObjCContainerDecl(PID);
1017}
1018
Ted Kremenek23173d72010-05-18 21:09:07 +00001019bool CursorVisitor::VisitObjCPropertyDecl(ObjCPropertyDecl *PD) {
Douglas Gregor83cb9422010-09-09 17:09:21 +00001020 if (PD->getTypeSourceInfo() && Visit(PD->getTypeSourceInfo()->getTypeLoc()))
John McCallfc929202010-06-04 22:33:30 +00001021 return true;
1022
Ted Kremenek23173d72010-05-18 21:09:07 +00001023 // FIXME: This implements a workaround with @property declarations also being
1024 // installed in the DeclContext for the @interface. Eventually this code
1025 // should be removed.
1026 ObjCCategoryDecl *CDecl = dyn_cast<ObjCCategoryDecl>(PD->getDeclContext());
1027 if (!CDecl || !CDecl->IsClassExtension())
1028 return false;
1029
1030 ObjCInterfaceDecl *ID = CDecl->getClassInterface();
1031 if (!ID)
1032 return false;
1033
1034 IdentifierInfo *PropertyId = PD->getIdentifier();
1035 ObjCPropertyDecl *prevDecl =
1036 ObjCPropertyDecl::findPropertyDecl(cast<DeclContext>(ID), PropertyId);
1037
1038 if (!prevDecl)
1039 return false;
1040
1041 // Visit synthesized methods since they will be skipped when visiting
1042 // the @interface.
1043 if (ObjCMethodDecl *MD = prevDecl->getGetterMethodDecl())
Ted Kremeneka054fb42010-09-21 20:52:59 +00001044 if (MD->isSynthesized() && MD->getLexicalDeclContext() == CDecl)
Ted Kremenek23173d72010-05-18 21:09:07 +00001045 if (Visit(MakeCXCursor(MD, TU)))
1046 return true;
1047
1048 if (ObjCMethodDecl *MD = prevDecl->getSetterMethodDecl())
Ted Kremeneka054fb42010-09-21 20:52:59 +00001049 if (MD->isSynthesized() && MD->getLexicalDeclContext() == CDecl)
Ted Kremenek23173d72010-05-18 21:09:07 +00001050 if (Visit(MakeCXCursor(MD, TU)))
1051 return true;
1052
1053 return false;
1054}
1055
Douglas Gregorb1373d02010-01-20 20:59:29 +00001056bool CursorVisitor::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
Ted Kremenekdd6bcc52010-01-13 00:22:49 +00001057 // Issue callbacks for super class.
Douglas Gregorb1373d02010-01-20 20:59:29 +00001058 if (D->getSuperClass() &&
1059 Visit(MakeCursorObjCSuperClassRef(D->getSuperClass(),
Ted Kremenekf0e23e82010-02-17 00:41:40 +00001060 D->getSuperClassLoc(),
Douglas Gregorb2cd4872010-01-20 23:57:43 +00001061 TU)))
Douglas Gregorb1373d02010-01-20 20:59:29 +00001062 return true;
Ted Kremenekf0e23e82010-02-17 00:41:40 +00001063
Douglas Gregor78db0cd2010-01-16 15:44:18 +00001064 ObjCInterfaceDecl::protocol_loc_iterator PL = D->protocol_loc_begin();
1065 for (ObjCInterfaceDecl::protocol_iterator I = D->protocol_begin(),
1066 E = D->protocol_end(); I != E; ++I, ++PL)
Douglas Gregorb2cd4872010-01-20 23:57:43 +00001067 if (Visit(MakeCursorObjCProtocolRef(*I, *PL, TU)))
Douglas Gregorb1373d02010-01-20 20:59:29 +00001068 return true;
Ted Kremenekf0e23e82010-02-17 00:41:40 +00001069
Douglas Gregora59e3902010-01-21 23:27:09 +00001070 return VisitObjCContainerDecl(D);
Ted Kremenekdd6bcc52010-01-13 00:22:49 +00001071}
1072
Douglas Gregor1ef2fc12010-01-22 00:50:27 +00001073bool CursorVisitor::VisitObjCImplDecl(ObjCImplDecl *D) {
1074 return VisitObjCContainerDecl(D);
Ted Kremenekdd6bcc52010-01-13 00:22:49 +00001075}
1076
Douglas Gregor1ef2fc12010-01-22 00:50:27 +00001077bool CursorVisitor::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) {
Ted Kremenekebfa3392010-03-19 20:39:03 +00001078 // 'ID' could be null when dealing with invalid code.
1079 if (ObjCInterfaceDecl *ID = D->getClassInterface())
1080 if (Visit(MakeCursorObjCClassRef(ID, D->getLocation(), TU)))
1081 return true;
Ted Kremenekf0e23e82010-02-17 00:41:40 +00001082
Douglas Gregor1ef2fc12010-01-22 00:50:27 +00001083 return VisitObjCImplDecl(D);
1084}
1085
1086bool CursorVisitor::VisitObjCImplementationDecl(ObjCImplementationDecl *D) {
1087#if 0
1088 // Issue callbacks for super class.
1089 // FIXME: No source location information!
1090 if (D->getSuperClass() &&
1091 Visit(MakeCursorObjCSuperClassRef(D->getSuperClass(),
Ted Kremenekf0e23e82010-02-17 00:41:40 +00001092 D->getSuperClassLoc(),
Douglas Gregor1ef2fc12010-01-22 00:50:27 +00001093 TU)))
1094 return true;
1095#endif
Ted Kremenekf0e23e82010-02-17 00:41:40 +00001096
Douglas Gregor1ef2fc12010-01-22 00:50:27 +00001097 return VisitObjCImplDecl(D);
1098}
1099
1100bool CursorVisitor::VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D) {
1101 ObjCForwardProtocolDecl::protocol_loc_iterator PL = D->protocol_loc_begin();
1102 for (ObjCForwardProtocolDecl::protocol_iterator I = D->protocol_begin(),
1103 E = D->protocol_end();
1104 I != E; ++I, ++PL)
Douglas Gregorb2cd4872010-01-20 23:57:43 +00001105 if (Visit(MakeCursorObjCProtocolRef(*I, *PL, TU)))
Douglas Gregorb1373d02010-01-20 20:59:29 +00001106 return true;
Ted Kremenekf0e23e82010-02-17 00:41:40 +00001107
1108 return false;
Ted Kremenekdd6bcc52010-01-13 00:22:49 +00001109}
1110
Douglas Gregor1ef2fc12010-01-22 00:50:27 +00001111bool CursorVisitor::VisitObjCClassDecl(ObjCClassDecl *D) {
1112 for (ObjCClassDecl::iterator C = D->begin(), CEnd = D->end(); C != CEnd; ++C)
1113 if (Visit(MakeCursorObjCClassRef(C->getInterface(), C->getLocation(), TU)))
1114 return true;
Ted Kremenekf0e23e82010-02-17 00:41:40 +00001115
Douglas Gregor1ef2fc12010-01-22 00:50:27 +00001116 return false;
Ted Kremenekdd6bcc52010-01-13 00:22:49 +00001117}
1118
Douglas Gregora4ffd852010-11-17 01:03:52 +00001119bool CursorVisitor::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *PD) {
1120 if (ObjCIvarDecl *Ivar = PD->getPropertyIvarDecl())
1121 return Visit(MakeCursorMemberRef(Ivar, PD->getPropertyIvarDeclLoc(), TU));
1122
1123 return false;
1124}
1125
Ted Kremenek8f06e0e2010-05-06 23:38:21 +00001126bool CursorVisitor::VisitNamespaceDecl(NamespaceDecl *D) {
1127 return VisitDeclContext(D);
1128}
1129
Douglas Gregor69319002010-08-31 23:48:11 +00001130bool CursorVisitor::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
Douglas Gregorc5ade2e2010-09-02 17:35:32 +00001131 // Visit nested-name-specifier.
Douglas Gregor0cfaf6a2011-02-25 17:08:07 +00001132 if (NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc())
1133 if (VisitNestedNameSpecifierLoc(QualifierLoc))
Douglas Gregorc5ade2e2010-09-02 17:35:32 +00001134 return true;
Douglas Gregor69319002010-08-31 23:48:11 +00001135
1136 return Visit(MakeCursorNamespaceRef(D->getAliasedNamespace(),
1137 D->getTargetNameLoc(), TU));
1138}
1139
Douglas Gregor7e242562010-09-01 19:52:22 +00001140bool CursorVisitor::VisitUsingDecl(UsingDecl *D) {
Douglas Gregorc5ade2e2010-09-02 17:35:32 +00001141 // Visit nested-name-specifier.
Douglas Gregordc355712011-02-25 00:36:19 +00001142 if (NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc()) {
1143 if (VisitNestedNameSpecifierLoc(QualifierLoc))
Douglas Gregorc5ade2e2010-09-02 17:35:32 +00001144 return true;
Douglas Gregordc355712011-02-25 00:36:19 +00001145 }
Douglas Gregor7e242562010-09-01 19:52:22 +00001146
Douglas Gregor1f60d9e2010-09-13 22:52:57 +00001147 if (Visit(MakeCursorOverloadedDeclRef(D, D->getLocation(), TU)))
1148 return true;
1149
Douglas Gregor7e242562010-09-01 19:52:22 +00001150 return VisitDeclarationNameInfo(D->getNameInfo());
1151}
1152
Douglas Gregor0a35bce2010-09-01 03:07:18 +00001153bool CursorVisitor::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
Douglas Gregorc5ade2e2010-09-02 17:35:32 +00001154 // Visit nested-name-specifier.
Douglas Gregordb992412011-02-25 16:33:46 +00001155 if (NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc())
1156 if (VisitNestedNameSpecifierLoc(QualifierLoc))
Douglas Gregorc5ade2e2010-09-02 17:35:32 +00001157 return true;
Douglas Gregor0a35bce2010-09-01 03:07:18 +00001158
1159 return Visit(MakeCursorNamespaceRef(D->getNominatedNamespaceAsWritten(),
1160 D->getIdentLocation(), TU));
1161}
1162
Douglas Gregor7e242562010-09-01 19:52:22 +00001163bool CursorVisitor::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) {
Douglas Gregorc5ade2e2010-09-02 17:35:32 +00001164 // Visit nested-name-specifier.
Douglas Gregordc355712011-02-25 00:36:19 +00001165 if (NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc()) {
1166 if (VisitNestedNameSpecifierLoc(QualifierLoc))
Douglas Gregorc5ade2e2010-09-02 17:35:32 +00001167 return true;
Douglas Gregordc355712011-02-25 00:36:19 +00001168 }
Douglas Gregorc5ade2e2010-09-02 17:35:32 +00001169
Douglas Gregor7e242562010-09-01 19:52:22 +00001170 return VisitDeclarationNameInfo(D->getNameInfo());
1171}
1172
1173bool CursorVisitor::VisitUnresolvedUsingTypenameDecl(
1174 UnresolvedUsingTypenameDecl *D) {
Douglas Gregorc5ade2e2010-09-02 17:35:32 +00001175 // Visit nested-name-specifier.
Douglas Gregordc355712011-02-25 00:36:19 +00001176 if (NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc())
1177 if (VisitNestedNameSpecifierLoc(QualifierLoc))
Douglas Gregorc5ade2e2010-09-02 17:35:32 +00001178 return true;
1179
Douglas Gregor7e242562010-09-01 19:52:22 +00001180 return false;
1181}
1182
Douglas Gregor01829d32010-08-31 14:41:23 +00001183bool CursorVisitor::VisitDeclarationNameInfo(DeclarationNameInfo Name) {
1184 switch (Name.getName().getNameKind()) {
1185 case clang::DeclarationName::Identifier:
1186 case clang::DeclarationName::CXXLiteralOperatorName:
1187 case clang::DeclarationName::CXXOperatorName:
1188 case clang::DeclarationName::CXXUsingDirective:
1189 return false;
1190
1191 case clang::DeclarationName::CXXConstructorName:
1192 case clang::DeclarationName::CXXDestructorName:
1193 case clang::DeclarationName::CXXConversionFunctionName:
1194 if (TypeSourceInfo *TSInfo = Name.getNamedTypeInfo())
1195 return Visit(TSInfo->getTypeLoc());
1196 return false;
1197
1198 case clang::DeclarationName::ObjCZeroArgSelector:
1199 case clang::DeclarationName::ObjCOneArgSelector:
1200 case clang::DeclarationName::ObjCMultiArgSelector:
1201 // FIXME: Per-identifier location info?
1202 return false;
1203 }
1204
1205 return false;
1206}
1207
Douglas Gregorc5ade2e2010-09-02 17:35:32 +00001208bool CursorVisitor::VisitNestedNameSpecifier(NestedNameSpecifier *NNS,
1209 SourceRange Range) {
1210 // FIXME: This whole routine is a hack to work around the lack of proper
1211 // source information in nested-name-specifiers (PR5791). Since we do have
1212 // a beginning source location, we can visit the first component of the
1213 // nested-name-specifier, if it's a single-token component.
1214 if (!NNS)
1215 return false;
1216
1217 // Get the first component in the nested-name-specifier.
1218 while (NestedNameSpecifier *Prefix = NNS->getPrefix())
1219 NNS = Prefix;
1220
1221 switch (NNS->getKind()) {
1222 case NestedNameSpecifier::Namespace:
Douglas Gregorc5ade2e2010-09-02 17:35:32 +00001223 return Visit(MakeCursorNamespaceRef(NNS->getAsNamespace(), Range.getBegin(),
1224 TU));
1225
Douglas Gregor14aba762011-02-24 02:36:08 +00001226 case NestedNameSpecifier::NamespaceAlias:
1227 return Visit(MakeCursorNamespaceRef(NNS->getAsNamespaceAlias(),
1228 Range.getBegin(), TU));
1229
Douglas Gregorc5ade2e2010-09-02 17:35:32 +00001230 case NestedNameSpecifier::TypeSpec: {
1231 // If the type has a form where we know that the beginning of the source
1232 // range matches up with a reference cursor. Visit the appropriate reference
1233 // cursor.
John McCallf4c73712011-01-19 06:33:43 +00001234 const Type *T = NNS->getAsType();
Douglas Gregorc5ade2e2010-09-02 17:35:32 +00001235 if (const TypedefType *Typedef = dyn_cast<TypedefType>(T))
1236 return Visit(MakeCursorTypeRef(Typedef->getDecl(), Range.getBegin(), TU));
1237 if (const TagType *Tag = dyn_cast<TagType>(T))
1238 return Visit(MakeCursorTypeRef(Tag->getDecl(), Range.getBegin(), TU));
1239 if (const TemplateSpecializationType *TST
1240 = dyn_cast<TemplateSpecializationType>(T))
1241 return VisitTemplateName(TST->getTemplateName(), Range.getBegin());
1242 break;
1243 }
1244
1245 case NestedNameSpecifier::TypeSpecWithTemplate:
1246 case NestedNameSpecifier::Global:
1247 case NestedNameSpecifier::Identifier:
1248 break;
1249 }
1250
1251 return false;
1252}
1253
Douglas Gregordc355712011-02-25 00:36:19 +00001254bool
1255CursorVisitor::VisitNestedNameSpecifierLoc(NestedNameSpecifierLoc Qualifier) {
1256 llvm::SmallVector<NestedNameSpecifierLoc, 4> Qualifiers;
1257 for (; Qualifier; Qualifier = Qualifier.getPrefix())
1258 Qualifiers.push_back(Qualifier);
1259
1260 while (!Qualifiers.empty()) {
1261 NestedNameSpecifierLoc Q = Qualifiers.pop_back_val();
1262 NestedNameSpecifier *NNS = Q.getNestedNameSpecifier();
1263 switch (NNS->getKind()) {
1264 case NestedNameSpecifier::Namespace:
1265 if (Visit(MakeCursorNamespaceRef(NNS->getAsNamespace(),
Douglas Gregorc22b5ff2011-02-25 02:25:35 +00001266 Q.getLocalBeginLoc(),
Douglas Gregordc355712011-02-25 00:36:19 +00001267 TU)))
1268 return true;
1269
1270 break;
1271
1272 case NestedNameSpecifier::NamespaceAlias:
1273 if (Visit(MakeCursorNamespaceRef(NNS->getAsNamespaceAlias(),
Douglas Gregorc22b5ff2011-02-25 02:25:35 +00001274 Q.getLocalBeginLoc(),
Douglas Gregordc355712011-02-25 00:36:19 +00001275 TU)))
1276 return true;
1277
1278 break;
1279
1280 case NestedNameSpecifier::TypeSpec:
1281 case NestedNameSpecifier::TypeSpecWithTemplate:
1282 if (Visit(Q.getTypeLoc()))
1283 return true;
1284
1285 break;
1286
1287 case NestedNameSpecifier::Global:
1288 case NestedNameSpecifier::Identifier:
1289 break;
1290 }
1291 }
1292
1293 return false;
1294}
1295
Douglas Gregorfe72e9c2010-08-31 17:01:39 +00001296bool CursorVisitor::VisitTemplateParameters(
1297 const TemplateParameterList *Params) {
1298 if (!Params)
1299 return false;
1300
1301 for (TemplateParameterList::const_iterator P = Params->begin(),
1302 PEnd = Params->end();
1303 P != PEnd; ++P) {
1304 if (Visit(MakeCXCursor(*P, TU)))
1305 return true;
1306 }
1307
1308 return false;
1309}
1310
Douglas Gregor0b36e612010-08-31 20:37:03 +00001311bool CursorVisitor::VisitTemplateName(TemplateName Name, SourceLocation Loc) {
1312 switch (Name.getKind()) {
1313 case TemplateName::Template:
1314 return Visit(MakeCursorTemplateRef(Name.getAsTemplateDecl(), Loc, TU));
1315
1316 case TemplateName::OverloadedTemplate:
Douglas Gregor1f60d9e2010-09-13 22:52:57 +00001317 // Visit the overloaded template set.
1318 if (Visit(MakeCursorOverloadedDeclRef(Name, Loc, TU)))
1319 return true;
1320
Douglas Gregor0b36e612010-08-31 20:37:03 +00001321 return false;
1322
1323 case TemplateName::DependentTemplate:
1324 // FIXME: Visit nested-name-specifier.
1325 return false;
1326
1327 case TemplateName::QualifiedTemplate:
1328 // FIXME: Visit nested-name-specifier.
1329 return Visit(MakeCursorTemplateRef(
1330 Name.getAsQualifiedTemplateName()->getDecl(),
1331 Loc, TU));
Douglas Gregor1aee05d2011-01-15 06:45:20 +00001332
1333 case TemplateName::SubstTemplateTemplateParmPack:
1334 return Visit(MakeCursorTemplateRef(
1335 Name.getAsSubstTemplateTemplateParmPack()->getParameterPack(),
1336 Loc, TU));
Douglas Gregor0b36e612010-08-31 20:37:03 +00001337 }
1338
1339 return false;
1340}
1341
Douglas Gregorfe72e9c2010-08-31 17:01:39 +00001342bool CursorVisitor::VisitTemplateArgumentLoc(const TemplateArgumentLoc &TAL) {
1343 switch (TAL.getArgument().getKind()) {
1344 case TemplateArgument::Null:
1345 case TemplateArgument::Integral:
Douglas Gregor87dd6972010-12-20 16:52:59 +00001346 case TemplateArgument::Pack:
Douglas Gregorfe72e9c2010-08-31 17:01:39 +00001347 return false;
1348
Douglas Gregorfe72e9c2010-08-31 17:01:39 +00001349 case TemplateArgument::Type:
1350 if (TypeSourceInfo *TSInfo = TAL.getTypeSourceInfo())
1351 return Visit(TSInfo->getTypeLoc());
1352 return false;
1353
1354 case TemplateArgument::Declaration:
1355 if (Expr *E = TAL.getSourceDeclExpression())
1356 return Visit(MakeCXCursor(E, StmtParent, TU));
1357 return false;
1358
1359 case TemplateArgument::Expression:
1360 if (Expr *E = TAL.getSourceExpression())
1361 return Visit(MakeCXCursor(E, StmtParent, TU));
1362 return false;
1363
1364 case TemplateArgument::Template:
Douglas Gregora7fc9012011-01-05 18:58:31 +00001365 case TemplateArgument::TemplateExpansion:
Douglas Gregorb6744ef2011-03-02 17:09:35 +00001366 if (VisitNestedNameSpecifierLoc(TAL.getTemplateQualifierLoc()))
1367 return true;
1368
Douglas Gregora7fc9012011-01-05 18:58:31 +00001369 return VisitTemplateName(TAL.getArgument().getAsTemplateOrTemplatePattern(),
Douglas Gregor0b36e612010-08-31 20:37:03 +00001370 TAL.getTemplateNameLoc());
Douglas Gregorfe72e9c2010-08-31 17:01:39 +00001371 }
1372
1373 return false;
1374}
1375
Ted Kremeneka0536d82010-05-07 01:04:29 +00001376bool CursorVisitor::VisitLinkageSpecDecl(LinkageSpecDecl *D) {
1377 return VisitDeclContext(D);
1378}
1379
Douglas Gregor01829d32010-08-31 14:41:23 +00001380bool CursorVisitor::VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {
1381 return Visit(TL.getUnqualifiedLoc());
1382}
1383
Douglas Gregorf20dfbc2010-01-21 17:29:07 +00001384bool CursorVisitor::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) {
Ted Kremeneka60ed472010-11-16 08:15:36 +00001385 ASTContext &Context = AU->getASTContext();
Douglas Gregorf20dfbc2010-01-21 17:29:07 +00001386
1387 // Some builtin types (such as Objective-C's "id", "sel", and
1388 // "Class") have associated declarations. Create cursors for those.
1389 QualType VisitType;
1390 switch (TL.getType()->getAs<BuiltinType>()->getKind()) {
Ted Kremenek6b3b5142010-02-18 22:32:43 +00001391 case BuiltinType::Void:
Douglas Gregorf20dfbc2010-01-21 17:29:07 +00001392 case BuiltinType::Bool:
Ted Kremenek6b3b5142010-02-18 22:32:43 +00001393 case BuiltinType::Char_U:
1394 case BuiltinType::UChar:
Douglas Gregorf20dfbc2010-01-21 17:29:07 +00001395 case BuiltinType::Char16:
1396 case BuiltinType::Char32:
Ted Kremenek6b3b5142010-02-18 22:32:43 +00001397 case BuiltinType::UShort:
Douglas Gregorf20dfbc2010-01-21 17:29:07 +00001398 case BuiltinType::UInt:
1399 case BuiltinType::ULong:
1400 case BuiltinType::ULongLong:
Ted Kremenek6b3b5142010-02-18 22:32:43 +00001401 case BuiltinType::UInt128:
1402 case BuiltinType::Char_S:
1403 case BuiltinType::SChar:
Chris Lattner3f59c972010-12-25 23:25:43 +00001404 case BuiltinType::WChar_U:
1405 case BuiltinType::WChar_S:
Ted Kremenek6b3b5142010-02-18 22:32:43 +00001406 case BuiltinType::Short:
1407 case BuiltinType::Int:
1408 case BuiltinType::Long:
1409 case BuiltinType::LongLong:
1410 case BuiltinType::Int128:
1411 case BuiltinType::Float:
1412 case BuiltinType::Double:
1413 case BuiltinType::LongDouble:
1414 case BuiltinType::NullPtr:
1415 case BuiltinType::Overload:
John McCall864c0412011-04-26 20:42:42 +00001416 case BuiltinType::BoundMember:
Ted Kremenek6b3b5142010-02-18 22:32:43 +00001417 case BuiltinType::Dependent:
John McCall1de4d4e2011-04-07 08:22:57 +00001418 case BuiltinType::UnknownAny:
Douglas Gregorf20dfbc2010-01-21 17:29:07 +00001419 break;
Ted Kremenek6b3b5142010-02-18 22:32:43 +00001420
Ted Kremenekc4174cc2010-02-18 18:52:18 +00001421 case BuiltinType::ObjCId:
1422 VisitType = Context.getObjCIdType();
1423 break;
Ted Kremenek6b3b5142010-02-18 22:32:43 +00001424
1425 case BuiltinType::ObjCClass:
1426 VisitType = Context.getObjCClassType();
1427 break;
1428
Douglas Gregorf20dfbc2010-01-21 17:29:07 +00001429 case BuiltinType::ObjCSel:
1430 VisitType = Context.getObjCSelType();
1431 break;
1432 }
1433
1434 if (!VisitType.isNull()) {
1435 if (const TypedefType *Typedef = VisitType->getAs<TypedefType>())
Ted Kremenekf0e23e82010-02-17 00:41:40 +00001436 return Visit(MakeCursorTypeRef(Typedef->getDecl(), TL.getBuiltinLoc(),
Douglas Gregorf20dfbc2010-01-21 17:29:07 +00001437 TU));
1438 }
1439
1440 return false;
1441}
1442
Douglas Gregor7d0d40e2010-01-21 16:28:34 +00001443bool CursorVisitor::VisitTypedefTypeLoc(TypedefTypeLoc TL) {
Richard Smith162e1c12011-04-15 14:24:37 +00001444 return Visit(MakeCursorTypeRef(TL.getTypedefNameDecl(), TL.getNameLoc(), TU));
Douglas Gregor7d0d40e2010-01-21 16:28:34 +00001445}
1446
Douglas Gregorf20dfbc2010-01-21 17:29:07 +00001447bool CursorVisitor::VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc TL) {
1448 return Visit(MakeCursorTypeRef(TL.getDecl(), TL.getNameLoc(), TU));
1449}
1450
1451bool CursorVisitor::VisitTagTypeLoc(TagTypeLoc TL) {
1452 return Visit(MakeCursorTypeRef(TL.getDecl(), TL.getNameLoc(), TU));
1453}
1454
Douglas Gregorfe72e9c2010-08-31 17:01:39 +00001455bool CursorVisitor::VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) {
Chandler Carruth960d13d2011-05-01 09:53:37 +00001456 return Visit(MakeCursorTypeRef(TL.getDecl(), TL.getNameLoc(), TU));
Douglas Gregorfe72e9c2010-08-31 17:01:39 +00001457}
1458
Douglas Gregorf20dfbc2010-01-21 17:29:07 +00001459bool CursorVisitor::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
1460 if (Visit(MakeCursorObjCClassRef(TL.getIFaceDecl(), TL.getNameLoc(), TU)))
1461 return true;
1462
John McCallc12c5bb2010-05-15 11:32:37 +00001463 return false;
1464}
1465
1466bool CursorVisitor::VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) {
1467 if (TL.hasBaseTypeAsWritten() && Visit(TL.getBaseLoc()))
1468 return true;
1469
Douglas Gregorf20dfbc2010-01-21 17:29:07 +00001470 for (unsigned I = 0, N = TL.getNumProtocols(); I != N; ++I) {
1471 if (Visit(MakeCursorObjCProtocolRef(TL.getProtocol(I), TL.getProtocolLoc(I),
1472 TU)))
1473 return true;
1474 }
1475
1476 return false;
1477}
1478
1479bool CursorVisitor::VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) {
John McCallc12c5bb2010-05-15 11:32:37 +00001480 return Visit(TL.getPointeeLoc());
Douglas Gregorf20dfbc2010-01-21 17:29:07 +00001481}
1482
Abramo Bagnara075f8f12010-12-10 16:29:40 +00001483bool CursorVisitor::VisitParenTypeLoc(ParenTypeLoc TL) {
1484 return Visit(TL.getInnerLoc());
1485}
1486
Douglas Gregorf20dfbc2010-01-21 17:29:07 +00001487bool CursorVisitor::VisitPointerTypeLoc(PointerTypeLoc TL) {
1488 return Visit(TL.getPointeeLoc());
1489}
1490
1491bool CursorVisitor::VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL) {
1492 return Visit(TL.getPointeeLoc());
1493}
1494
1495bool CursorVisitor::VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) {
1496 return Visit(TL.getPointeeLoc());
1497}
1498
1499bool CursorVisitor::VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL) {
Ted Kremenekf0e23e82010-02-17 00:41:40 +00001500 return Visit(TL.getPointeeLoc());
Douglas Gregorf20dfbc2010-01-21 17:29:07 +00001501}
1502
1503bool CursorVisitor::VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL) {
Ted Kremenekf0e23e82010-02-17 00:41:40 +00001504 return Visit(TL.getPointeeLoc());
Douglas Gregorf20dfbc2010-01-21 17:29:07 +00001505}
1506
Douglas Gregor01829d32010-08-31 14:41:23 +00001507bool CursorVisitor::VisitFunctionTypeLoc(FunctionTypeLoc TL,
1508 bool SkipResultType) {
1509 if (!SkipResultType && Visit(TL.getResultLoc()))
Douglas Gregorf20dfbc2010-01-21 17:29:07 +00001510 return true;
1511
Douglas Gregorf20dfbc2010-01-21 17:29:07 +00001512 for (unsigned I = 0, N = TL.getNumArgs(); I != N; ++I)
Ted Kremenek5dbacb42010-04-07 00:27:13 +00001513 if (Decl *D = TL.getArg(I))
1514 if (Visit(MakeCXCursor(D, TU)))
1515 return true;
Douglas Gregorf20dfbc2010-01-21 17:29:07 +00001516
1517 return false;
1518}
1519
1520bool CursorVisitor::VisitArrayTypeLoc(ArrayTypeLoc TL) {
1521 if (Visit(TL.getElementLoc()))
1522 return true;
1523
1524 if (Expr *Size = TL.getSizeExpr())
1525 return Visit(MakeCXCursor(Size, StmtParent, TU));
1526
1527 return false;
1528}
1529
Douglas Gregorfe72e9c2010-08-31 17:01:39 +00001530bool CursorVisitor::VisitTemplateSpecializationTypeLoc(
1531 TemplateSpecializationTypeLoc TL) {
Douglas Gregor0b36e612010-08-31 20:37:03 +00001532 // Visit the template name.
1533 if (VisitTemplateName(TL.getTypePtr()->getTemplateName(),
1534 TL.getTemplateNameLoc()))
1535 return true;
Douglas Gregorfe72e9c2010-08-31 17:01:39 +00001536
1537 // Visit the template arguments.
1538 for (unsigned I = 0, N = TL.getNumArgs(); I != N; ++I)
1539 if (VisitTemplateArgumentLoc(TL.getArgLoc(I)))
1540 return true;
1541
1542 return false;
1543}
1544
Douglas Gregor2332c112010-01-21 20:48:56 +00001545bool CursorVisitor::VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) {
1546 return Visit(MakeCXCursor(TL.getUnderlyingExpr(), StmtParent, TU));
1547}
1548
1549bool CursorVisitor::VisitTypeOfTypeLoc(TypeOfTypeLoc TL) {
1550 if (TypeSourceInfo *TSInfo = TL.getUnderlyingTInfo())
1551 return Visit(TSInfo->getTypeLoc());
1552
1553 return false;
1554}
1555
Douglas Gregor2494dd02011-03-01 01:34:45 +00001556bool CursorVisitor::VisitDependentNameTypeLoc(DependentNameTypeLoc TL) {
1557 if (VisitNestedNameSpecifierLoc(TL.getQualifierLoc()))
1558 return true;
1559
1560 return false;
1561}
1562
Douglas Gregor94fdffa2011-03-01 20:11:18 +00001563bool CursorVisitor::VisitDependentTemplateSpecializationTypeLoc(
1564 DependentTemplateSpecializationTypeLoc TL) {
1565 // Visit the nested-name-specifier, if there is one.
1566 if (TL.getQualifierLoc() &&
1567 VisitNestedNameSpecifierLoc(TL.getQualifierLoc()))
1568 return true;
1569
1570 // Visit the template arguments.
1571 for (unsigned I = 0, N = TL.getNumArgs(); I != N; ++I)
1572 if (VisitTemplateArgumentLoc(TL.getArgLoc(I)))
1573 return true;
1574
1575 return false;
1576}
1577
Douglas Gregor9e876872011-03-01 18:12:44 +00001578bool CursorVisitor::VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) {
1579 if (VisitNestedNameSpecifierLoc(TL.getQualifierLoc()))
1580 return true;
1581
1582 return Visit(TL.getNamedTypeLoc());
1583}
1584
Douglas Gregor7536dd52010-12-20 02:24:11 +00001585bool CursorVisitor::VisitPackExpansionTypeLoc(PackExpansionTypeLoc TL) {
1586 return Visit(TL.getPatternLoc());
1587}
1588
Ted Kremenek3064ef92010-08-27 21:34:58 +00001589bool CursorVisitor::VisitCXXRecordDecl(CXXRecordDecl *D) {
Douglas Gregorc22b5ff2011-02-25 02:25:35 +00001590 // Visit the nested-name-specifier, if present.
1591 if (NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc())
1592 if (VisitNestedNameSpecifierLoc(QualifierLoc))
1593 return true;
1594
Ted Kremenek3064ef92010-08-27 21:34:58 +00001595 if (D->isDefinition()) {
1596 for (CXXRecordDecl::base_class_iterator I = D->bases_begin(),
1597 E = D->bases_end(); I != E; ++I) {
1598 if (Visit(cxcursor::MakeCursorCXXBaseSpecifier(I, TU)))
1599 return true;
1600 }
1601 }
1602
1603 return VisitTagDecl(D);
1604}
1605
Ted Kremenek09dfa372010-02-18 05:46:33 +00001606bool CursorVisitor::VisitAttributes(Decl *D) {
Sean Huntcf807c42010-08-18 23:23:40 +00001607 for (AttrVec::const_iterator i = D->attr_begin(), e = D->attr_end();
1608 i != e; ++i)
1609 if (Visit(MakeCXCursor(*i, D, TU)))
Ted Kremenek09dfa372010-02-18 05:46:33 +00001610 return true;
1611
1612 return false;
1613}
1614
Ted Kremenekc0e1d922010-11-11 08:05:18 +00001615//===----------------------------------------------------------------------===//
1616// Data-recursive visitor methods.
1617//===----------------------------------------------------------------------===//
1618
Ted Kremenek28a71942010-11-13 00:36:47 +00001619namespace {
Ted Kremenek035dc412010-11-13 00:36:50 +00001620#define DEF_JOB(NAME, DATA, KIND)\
1621class NAME : public VisitorJob {\
1622public:\
1623 NAME(DATA *d, CXCursor parent) : VisitorJob(parent, VisitorJob::KIND, d) {} \
1624 static bool classof(const VisitorJob *VJ) { return VJ->getKind() == KIND; }\
Ted Kremenekf64d8032010-11-18 00:02:32 +00001625 DATA *get() const { return static_cast<DATA*>(data[0]); }\
Ted Kremenek035dc412010-11-13 00:36:50 +00001626};
1627
1628DEF_JOB(StmtVisit, Stmt, StmtVisitKind)
1629DEF_JOB(MemberExprParts, MemberExpr, MemberExprPartsKind)
Ted Kremeneke4979cc2010-11-13 00:58:18 +00001630DEF_JOB(DeclRefExprParts, DeclRefExpr, DeclRefExprPartsKind)
Ted Kremenek035dc412010-11-13 00:36:50 +00001631DEF_JOB(OverloadExprParts, OverloadExpr, OverloadExprPartsKind)
Ted Kremenek60608ec2010-11-17 00:50:47 +00001632DEF_JOB(ExplicitTemplateArgsVisit, ExplicitTemplateArgumentList,
1633 ExplicitTemplateArgsVisitKind)
Douglas Gregor94d96292011-01-19 20:34:17 +00001634DEF_JOB(SizeOfPackExprParts, SizeOfPackExpr, SizeOfPackExprPartsKind)
Ted Kremenek035dc412010-11-13 00:36:50 +00001635#undef DEF_JOB
1636
1637class DeclVisit : public VisitorJob {
1638public:
1639 DeclVisit(Decl *d, CXCursor parent, bool isFirst) :
1640 VisitorJob(parent, VisitorJob::DeclVisitKind,
1641 d, isFirst ? (void*) 1 : (void*) 0) {}
1642 static bool classof(const VisitorJob *VJ) {
Ted Kremenek82f3c502010-11-15 22:23:26 +00001643 return VJ->getKind() == DeclVisitKind;
Ted Kremenek035dc412010-11-13 00:36:50 +00001644 }
Ted Kremenekf64d8032010-11-18 00:02:32 +00001645 Decl *get() const { return static_cast<Decl*>(data[0]); }
1646 bool isFirst() const { return data[1] ? true : false; }
Ted Kremenek035dc412010-11-13 00:36:50 +00001647};
Ted Kremenek035dc412010-11-13 00:36:50 +00001648class TypeLocVisit : public VisitorJob {
1649public:
1650 TypeLocVisit(TypeLoc tl, CXCursor parent) :
1651 VisitorJob(parent, VisitorJob::TypeLocVisitKind,
1652 tl.getType().getAsOpaquePtr(), tl.getOpaqueData()) {}
1653
1654 static bool classof(const VisitorJob *VJ) {
1655 return VJ->getKind() == TypeLocVisitKind;
1656 }
1657
Ted Kremenek82f3c502010-11-15 22:23:26 +00001658 TypeLoc get() const {
Ted Kremenekf64d8032010-11-18 00:02:32 +00001659 QualType T = QualType::getFromOpaquePtr(data[0]);
1660 return TypeLoc(T, data[1]);
Ted Kremenek035dc412010-11-13 00:36:50 +00001661 }
1662};
1663
Ted Kremenekae1fd6f2010-11-17 00:50:45 +00001664class LabelRefVisit : public VisitorJob {
1665public:
Chris Lattnerad8dcf42011-02-17 07:39:24 +00001666 LabelRefVisit(LabelDecl *LD, SourceLocation labelLoc, CXCursor parent)
1667 : VisitorJob(parent, VisitorJob::LabelRefVisitKind, LD,
Jeffrey Yasskindec09842011-01-18 02:00:16 +00001668 labelLoc.getPtrEncoding()) {}
Ted Kremenekae1fd6f2010-11-17 00:50:45 +00001669
1670 static bool classof(const VisitorJob *VJ) {
1671 return VJ->getKind() == VisitorJob::LabelRefVisitKind;
1672 }
Chris Lattnerad8dcf42011-02-17 07:39:24 +00001673 LabelDecl *get() const { return static_cast<LabelDecl*>(data[0]); }
Ted Kremenekae1fd6f2010-11-17 00:50:45 +00001674 SourceLocation getLoc() const {
Jeffrey Yasskindec09842011-01-18 02:00:16 +00001675 return SourceLocation::getFromPtrEncoding(data[1]); }
Ted Kremenekf64d8032010-11-18 00:02:32 +00001676};
1677class NestedNameSpecifierVisit : public VisitorJob {
1678public:
1679 NestedNameSpecifierVisit(NestedNameSpecifier *NS, SourceRange R,
1680 CXCursor parent)
1681 : VisitorJob(parent, VisitorJob::NestedNameSpecifierVisitKind,
Jeffrey Yasskindec09842011-01-18 02:00:16 +00001682 NS, R.getBegin().getPtrEncoding(),
1683 R.getEnd().getPtrEncoding()) {}
Ted Kremenekf64d8032010-11-18 00:02:32 +00001684 static bool classof(const VisitorJob *VJ) {
1685 return VJ->getKind() == VisitorJob::NestedNameSpecifierVisitKind;
1686 }
1687 NestedNameSpecifier *get() const {
1688 return static_cast<NestedNameSpecifier*>(data[0]);
1689 }
1690 SourceRange getSourceRange() const {
1691 SourceLocation A =
1692 SourceLocation::getFromRawEncoding((unsigned)(uintptr_t) data[1]);
1693 SourceLocation B =
1694 SourceLocation::getFromRawEncoding((unsigned)(uintptr_t) data[2]);
1695 return SourceRange(A, B);
1696 }
1697};
Douglas Gregorf3db29f2011-02-25 18:19:59 +00001698
1699class NestedNameSpecifierLocVisit : public VisitorJob {
1700public:
1701 NestedNameSpecifierLocVisit(NestedNameSpecifierLoc Qualifier, CXCursor parent)
1702 : VisitorJob(parent, VisitorJob::NestedNameSpecifierLocVisitKind,
1703 Qualifier.getNestedNameSpecifier(),
1704 Qualifier.getOpaqueData()) { }
1705
1706 static bool classof(const VisitorJob *VJ) {
1707 return VJ->getKind() == VisitorJob::NestedNameSpecifierLocVisitKind;
1708 }
1709
1710 NestedNameSpecifierLoc get() const {
1711 return NestedNameSpecifierLoc(static_cast<NestedNameSpecifier*>(data[0]),
1712 data[1]);
1713 }
1714};
1715
Ted Kremenekf64d8032010-11-18 00:02:32 +00001716class DeclarationNameInfoVisit : public VisitorJob {
1717public:
1718 DeclarationNameInfoVisit(Stmt *S, CXCursor parent)
1719 : VisitorJob(parent, VisitorJob::DeclarationNameInfoVisitKind, S) {}
1720 static bool classof(const VisitorJob *VJ) {
1721 return VJ->getKind() == VisitorJob::DeclarationNameInfoVisitKind;
1722 }
1723 DeclarationNameInfo get() const {
1724 Stmt *S = static_cast<Stmt*>(data[0]);
1725 switch (S->getStmtClass()) {
1726 default:
1727 llvm_unreachable("Unhandled Stmt");
1728 case Stmt::CXXDependentScopeMemberExprClass:
1729 return cast<CXXDependentScopeMemberExpr>(S)->getMemberNameInfo();
1730 case Stmt::DependentScopeDeclRefExprClass:
1731 return cast<DependentScopeDeclRefExpr>(S)->getNameInfo();
1732 }
1733 }
Ted Kremenekae1fd6f2010-11-17 00:50:45 +00001734};
Ted Kremenekcdba6592010-11-18 00:42:18 +00001735class MemberRefVisit : public VisitorJob {
1736public:
1737 MemberRefVisit(FieldDecl *D, SourceLocation L, CXCursor parent)
1738 : VisitorJob(parent, VisitorJob::MemberRefVisitKind, D,
Jeffrey Yasskindec09842011-01-18 02:00:16 +00001739 L.getPtrEncoding()) {}
Ted Kremenekcdba6592010-11-18 00:42:18 +00001740 static bool classof(const VisitorJob *VJ) {
1741 return VJ->getKind() == VisitorJob::MemberRefVisitKind;
1742 }
1743 FieldDecl *get() const {
1744 return static_cast<FieldDecl*>(data[0]);
1745 }
1746 SourceLocation getLoc() const {
1747 return SourceLocation::getFromRawEncoding((unsigned)(uintptr_t) data[1]);
1748 }
1749};
Ted Kremenek28a71942010-11-13 00:36:47 +00001750class EnqueueVisitor : public StmtVisitor<EnqueueVisitor, void> {
1751 VisitorWorkList &WL;
1752 CXCursor Parent;
1753public:
1754 EnqueueVisitor(VisitorWorkList &wl, CXCursor parent)
1755 : WL(wl), Parent(parent) {}
1756
Ted Kremenekae1fd6f2010-11-17 00:50:45 +00001757 void VisitAddrLabelExpr(AddrLabelExpr *E);
Ted Kremenek73d15c42010-11-13 01:09:29 +00001758 void VisitBlockExpr(BlockExpr *B);
Ted Kremenek28a71942010-11-13 00:36:47 +00001759 void VisitCompoundLiteralExpr(CompoundLiteralExpr *E);
Ted Kremenek083c7e22010-11-13 05:38:03 +00001760 void VisitCompoundStmt(CompoundStmt *S);
Ted Kremenek11b8e3e2010-11-13 05:55:53 +00001761 void VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) { /* Do nothing. */ }
Ted Kremenekf64d8032010-11-18 00:02:32 +00001762 void VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E);
Ted Kremenek11b8e3e2010-11-13 05:55:53 +00001763 void VisitCXXNewExpr(CXXNewExpr *E);
Ted Kremenek6d0a00d2010-11-17 02:18:35 +00001764 void VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E);
Ted Kremenek28a71942010-11-13 00:36:47 +00001765 void VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E);
Ted Kremenekcdba6592010-11-18 00:42:18 +00001766 void VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E);
Ted Kremenek73d15c42010-11-13 01:09:29 +00001767 void VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E);
Ted Kremenekb8dd1ca2010-11-17 00:50:41 +00001768 void VisitCXXTypeidExpr(CXXTypeidExpr *E);
Ted Kremenek55b933a2010-11-17 00:50:36 +00001769 void VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr *E);
Ted Kremenek1e7e8772010-11-17 00:50:52 +00001770 void VisitCXXUuidofExpr(CXXUuidofExpr *E);
Ted Kremeneke4979cc2010-11-13 00:58:18 +00001771 void VisitDeclRefExpr(DeclRefExpr *D);
Ted Kremenek035dc412010-11-13 00:36:50 +00001772 void VisitDeclStmt(DeclStmt *S);
Ted Kremenekf64d8032010-11-18 00:02:32 +00001773 void VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E);
Ted Kremenekcdba6592010-11-18 00:42:18 +00001774 void VisitDesignatedInitExpr(DesignatedInitExpr *E);
Ted Kremenek28a71942010-11-13 00:36:47 +00001775 void VisitExplicitCastExpr(ExplicitCastExpr *E);
1776 void VisitForStmt(ForStmt *FS);
Ted Kremenekae1fd6f2010-11-17 00:50:45 +00001777 void VisitGotoStmt(GotoStmt *GS);
Ted Kremenek28a71942010-11-13 00:36:47 +00001778 void VisitIfStmt(IfStmt *If);
1779 void VisitInitListExpr(InitListExpr *IE);
1780 void VisitMemberExpr(MemberExpr *M);
Ted Kremenekcdba6592010-11-18 00:42:18 +00001781 void VisitOffsetOfExpr(OffsetOfExpr *E);
Ted Kremenek73d15c42010-11-13 01:09:29 +00001782 void VisitObjCEncodeExpr(ObjCEncodeExpr *E);
Ted Kremenek28a71942010-11-13 00:36:47 +00001783 void VisitObjCMessageExpr(ObjCMessageExpr *M);
1784 void VisitOverloadExpr(OverloadExpr *E);
Peter Collingbournef4e3cfb2011-03-11 19:24:49 +00001785 void VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E);
Ted Kremenek28a71942010-11-13 00:36:47 +00001786 void VisitStmt(Stmt *S);
1787 void VisitSwitchStmt(SwitchStmt *S);
1788 void VisitWhileStmt(WhileStmt *W);
Ted Kremenek2939b6f2010-11-17 00:50:50 +00001789 void VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E);
Francois Pichet6ad6f282010-12-07 00:08:36 +00001790 void VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *E);
John Wiegley21ff2e52011-04-28 00:16:57 +00001791 void VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E);
John Wiegley55262202011-04-25 06:54:41 +00001792 void VisitExpressionTraitExpr(ExpressionTraitExpr *E);
Ted Kremenek28a71942010-11-13 00:36:47 +00001793 void VisitUnresolvedMemberExpr(UnresolvedMemberExpr *U);
Ted Kremenek9d3bf792010-11-17 00:50:43 +00001794 void VisitVAArgExpr(VAArgExpr *E);
Douglas Gregor94d96292011-01-19 20:34:17 +00001795 void VisitSizeOfPackExpr(SizeOfPackExpr *E);
Douglas Gregoree8aff02011-01-04 17:33:58 +00001796
Ted Kremenek28a71942010-11-13 00:36:47 +00001797private:
Ted Kremenekf64d8032010-11-18 00:02:32 +00001798 void AddDeclarationNameInfo(Stmt *S);
1799 void AddNestedNameSpecifier(NestedNameSpecifier *NS, SourceRange R);
Douglas Gregorf3db29f2011-02-25 18:19:59 +00001800 void AddNestedNameSpecifierLoc(NestedNameSpecifierLoc Qualifier);
Ted Kremenek60608ec2010-11-17 00:50:47 +00001801 void AddExplicitTemplateArgs(const ExplicitTemplateArgumentList *A);
Ted Kremenekcdba6592010-11-18 00:42:18 +00001802 void AddMemberRef(FieldDecl *D, SourceLocation L);
Ted Kremenek28a71942010-11-13 00:36:47 +00001803 void AddStmt(Stmt *S);
Ted Kremenek035dc412010-11-13 00:36:50 +00001804 void AddDecl(Decl *D, bool isFirst = true);
Ted Kremenek28a71942010-11-13 00:36:47 +00001805 void AddTypeLoc(TypeSourceInfo *TI);
1806 void EnqueueChildren(Stmt *S);
1807};
1808} // end anonyous namespace
1809
Ted Kremenekf64d8032010-11-18 00:02:32 +00001810void EnqueueVisitor::AddDeclarationNameInfo(Stmt *S) {
1811 // 'S' should always be non-null, since it comes from the
1812 // statement we are visiting.
1813 WL.push_back(DeclarationNameInfoVisit(S, Parent));
1814}
1815void EnqueueVisitor::AddNestedNameSpecifier(NestedNameSpecifier *N,
1816 SourceRange R) {
1817 if (N)
1818 WL.push_back(NestedNameSpecifierVisit(N, R, Parent));
1819}
Douglas Gregorf3db29f2011-02-25 18:19:59 +00001820
1821void
1822EnqueueVisitor::AddNestedNameSpecifierLoc(NestedNameSpecifierLoc Qualifier) {
1823 if (Qualifier)
1824 WL.push_back(NestedNameSpecifierLocVisit(Qualifier, Parent));
1825}
1826
Ted Kremenek28a71942010-11-13 00:36:47 +00001827void EnqueueVisitor::AddStmt(Stmt *S) {
1828 if (S)
1829 WL.push_back(StmtVisit(S, Parent));
1830}
Ted Kremenek035dc412010-11-13 00:36:50 +00001831void EnqueueVisitor::AddDecl(Decl *D, bool isFirst) {
Ted Kremenek28a71942010-11-13 00:36:47 +00001832 if (D)
Ted Kremenek035dc412010-11-13 00:36:50 +00001833 WL.push_back(DeclVisit(D, Parent, isFirst));
Ted Kremenek28a71942010-11-13 00:36:47 +00001834}
Ted Kremenek60608ec2010-11-17 00:50:47 +00001835void EnqueueVisitor::
1836 AddExplicitTemplateArgs(const ExplicitTemplateArgumentList *A) {
1837 if (A)
1838 WL.push_back(ExplicitTemplateArgsVisit(
1839 const_cast<ExplicitTemplateArgumentList*>(A), Parent));
1840}
Ted Kremenekcdba6592010-11-18 00:42:18 +00001841void EnqueueVisitor::AddMemberRef(FieldDecl *D, SourceLocation L) {
1842 if (D)
1843 WL.push_back(MemberRefVisit(D, L, Parent));
1844}
Ted Kremenek28a71942010-11-13 00:36:47 +00001845void EnqueueVisitor::AddTypeLoc(TypeSourceInfo *TI) {
1846 if (TI)
1847 WL.push_back(TypeLocVisit(TI->getTypeLoc(), Parent));
1848 }
1849void EnqueueVisitor::EnqueueChildren(Stmt *S) {
Ted Kremeneka6b70432010-11-12 21:34:09 +00001850 unsigned size = WL.size();
John McCall7502c1d2011-02-13 04:07:26 +00001851 for (Stmt::child_range Child = S->children(); Child; ++Child) {
Ted Kremenek28a71942010-11-13 00:36:47 +00001852 AddStmt(*Child);
Ted Kremeneka6b70432010-11-12 21:34:09 +00001853 }
1854 if (size == WL.size())
1855 return;
1856 // Now reverse the entries we just added. This will match the DFS
1857 // ordering performed by the worklist.
1858 VisitorWorkList::iterator I = WL.begin() + size, E = WL.end();
1859 std::reverse(I, E);
1860}
Ted Kremenekae1fd6f2010-11-17 00:50:45 +00001861void EnqueueVisitor::VisitAddrLabelExpr(AddrLabelExpr *E) {
1862 WL.push_back(LabelRefVisit(E->getLabel(), E->getLabelLoc(), Parent));
1863}
Ted Kremenek73d15c42010-11-13 01:09:29 +00001864void EnqueueVisitor::VisitBlockExpr(BlockExpr *B) {
1865 AddDecl(B->getBlockDecl());
1866}
Ted Kremenek28a71942010-11-13 00:36:47 +00001867void EnqueueVisitor::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
1868 EnqueueChildren(E);
1869 AddTypeLoc(E->getTypeSourceInfo());
1870}
Ted Kremenek083c7e22010-11-13 05:38:03 +00001871void EnqueueVisitor::VisitCompoundStmt(CompoundStmt *S) {
1872 for (CompoundStmt::reverse_body_iterator I = S->body_rbegin(),
1873 E = S->body_rend(); I != E; ++I) {
1874 AddStmt(*I);
1875 }
Ted Kremenek11b8e3e2010-11-13 05:55:53 +00001876}
Ted Kremenekf64d8032010-11-18 00:02:32 +00001877void EnqueueVisitor::
1878VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E) {
1879 AddExplicitTemplateArgs(E->getOptionalExplicitTemplateArgs());
1880 AddDeclarationNameInfo(E);
Douglas Gregor7c3179c2011-02-28 18:50:33 +00001881 if (NestedNameSpecifierLoc QualifierLoc = E->getQualifierLoc())
1882 AddNestedNameSpecifierLoc(QualifierLoc);
Ted Kremenekf64d8032010-11-18 00:02:32 +00001883 if (!E->isImplicitAccess())
1884 AddStmt(E->getBase());
1885}
Ted Kremenek11b8e3e2010-11-13 05:55:53 +00001886void EnqueueVisitor::VisitCXXNewExpr(CXXNewExpr *E) {
1887 // Enqueue the initializer or constructor arguments.
1888 for (unsigned I = E->getNumConstructorArgs(); I > 0; --I)
1889 AddStmt(E->getConstructorArg(I-1));
1890 // Enqueue the array size, if any.
1891 AddStmt(E->getArraySize());
1892 // Enqueue the allocated type.
1893 AddTypeLoc(E->getAllocatedTypeSourceInfo());
1894 // Enqueue the placement arguments.
1895 for (unsigned I = E->getNumPlacementArgs(); I > 0; --I)
1896 AddStmt(E->getPlacementArg(I-1));
1897}
Ted Kremenek28a71942010-11-13 00:36:47 +00001898void EnqueueVisitor::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *CE) {
Ted Kremenek8b8d8c92010-11-13 05:55:56 +00001899 for (unsigned I = CE->getNumArgs(); I > 1 /* Yes, this is 1 */; --I)
1900 AddStmt(CE->getArg(I-1));
Ted Kremenek28a71942010-11-13 00:36:47 +00001901 AddStmt(CE->getCallee());
1902 AddStmt(CE->getArg(0));
1903}
Ted Kremenekcdba6592010-11-18 00:42:18 +00001904void EnqueueVisitor::VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E) {
1905 // Visit the name of the type being destroyed.
1906 AddTypeLoc(E->getDestroyedTypeInfo());
1907 // Visit the scope type that looks disturbingly like the nested-name-specifier
1908 // but isn't.
1909 AddTypeLoc(E->getScopeTypeInfo());
1910 // Visit the nested-name-specifier.
Douglas Gregorf3db29f2011-02-25 18:19:59 +00001911 if (NestedNameSpecifierLoc QualifierLoc = E->getQualifierLoc())
1912 AddNestedNameSpecifierLoc(QualifierLoc);
Ted Kremenekcdba6592010-11-18 00:42:18 +00001913 // Visit base expression.
1914 AddStmt(E->getBase());
1915}
Ted Kremenek6d0a00d2010-11-17 02:18:35 +00001916void EnqueueVisitor::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E) {
1917 AddTypeLoc(E->getTypeSourceInfo());
1918}
Ted Kremenek73d15c42010-11-13 01:09:29 +00001919void EnqueueVisitor::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E) {
1920 EnqueueChildren(E);
1921 AddTypeLoc(E->getTypeSourceInfo());
1922}
Ted Kremenekb8dd1ca2010-11-17 00:50:41 +00001923void EnqueueVisitor::VisitCXXTypeidExpr(CXXTypeidExpr *E) {
1924 EnqueueChildren(E);
1925 if (E->isTypeOperand())
1926 AddTypeLoc(E->getTypeOperandSourceInfo());
1927}
Ted Kremenek55b933a2010-11-17 00:50:36 +00001928
1929void EnqueueVisitor::VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr
1930 *E) {
1931 EnqueueChildren(E);
1932 AddTypeLoc(E->getTypeSourceInfo());
1933}
Ted Kremenek1e7e8772010-11-17 00:50:52 +00001934void EnqueueVisitor::VisitCXXUuidofExpr(CXXUuidofExpr *E) {
1935 EnqueueChildren(E);
1936 if (E->isTypeOperand())
1937 AddTypeLoc(E->getTypeOperandSourceInfo());
1938}
Ted Kremeneke4979cc2010-11-13 00:58:18 +00001939void EnqueueVisitor::VisitDeclRefExpr(DeclRefExpr *DR) {
Ted Kremenek60608ec2010-11-17 00:50:47 +00001940 if (DR->hasExplicitTemplateArgs()) {
1941 AddExplicitTemplateArgs(&DR->getExplicitTemplateArgs());
1942 }
Ted Kremeneke4979cc2010-11-13 00:58:18 +00001943 WL.push_back(DeclRefExprParts(DR, Parent));
1944}
Ted Kremenekf64d8032010-11-18 00:02:32 +00001945void EnqueueVisitor::VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) {
1946 AddExplicitTemplateArgs(E->getOptionalExplicitTemplateArgs());
1947 AddDeclarationNameInfo(E);
Douglas Gregor00cf3cc2011-02-25 20:49:16 +00001948 AddNestedNameSpecifierLoc(E->getQualifierLoc());
Ted Kremenekf64d8032010-11-18 00:02:32 +00001949}
Ted Kremenek035dc412010-11-13 00:36:50 +00001950void EnqueueVisitor::VisitDeclStmt(DeclStmt *S) {
1951 unsigned size = WL.size();
1952 bool isFirst = true;
1953 for (DeclStmt::decl_iterator D = S->decl_begin(), DEnd = S->decl_end();
1954 D != DEnd; ++D) {
1955 AddDecl(*D, isFirst);
1956 isFirst = false;
1957 }
1958 if (size == WL.size())
1959 return;
1960 // Now reverse the entries we just added. This will match the DFS
1961 // ordering performed by the worklist.
1962 VisitorWorkList::iterator I = WL.begin() + size, E = WL.end();
1963 std::reverse(I, E);
1964}
Ted Kremenekcdba6592010-11-18 00:42:18 +00001965void EnqueueVisitor::VisitDesignatedInitExpr(DesignatedInitExpr *E) {
1966 AddStmt(E->getInit());
1967 typedef DesignatedInitExpr::Designator Designator;
1968 for (DesignatedInitExpr::reverse_designators_iterator
1969 D = E->designators_rbegin(), DEnd = E->designators_rend();
1970 D != DEnd; ++D) {
1971 if (D->isFieldDesignator()) {
1972 if (FieldDecl *Field = D->getField())
1973 AddMemberRef(Field, D->getFieldLoc());
1974 continue;
1975 }
1976 if (D->isArrayDesignator()) {
1977 AddStmt(E->getArrayIndex(*D));
1978 continue;
1979 }
1980 assert(D->isArrayRangeDesignator() && "Unknown designator kind");
1981 AddStmt(E->getArrayRangeEnd(*D));
1982 AddStmt(E->getArrayRangeStart(*D));
1983 }
1984}
Ted Kremenek28a71942010-11-13 00:36:47 +00001985void EnqueueVisitor::VisitExplicitCastExpr(ExplicitCastExpr *E) {
1986 EnqueueChildren(E);
1987 AddTypeLoc(E->getTypeInfoAsWritten());
1988}
1989void EnqueueVisitor::VisitForStmt(ForStmt *FS) {
1990 AddStmt(FS->getBody());
1991 AddStmt(FS->getInc());
1992 AddStmt(FS->getCond());
1993 AddDecl(FS->getConditionVariable());
1994 AddStmt(FS->getInit());
1995}
Ted Kremenekae1fd6f2010-11-17 00:50:45 +00001996void EnqueueVisitor::VisitGotoStmt(GotoStmt *GS) {
1997 WL.push_back(LabelRefVisit(GS->getLabel(), GS->getLabelLoc(), Parent));
1998}
Ted Kremenek28a71942010-11-13 00:36:47 +00001999void EnqueueVisitor::VisitIfStmt(IfStmt *If) {
2000 AddStmt(If->getElse());
2001 AddStmt(If->getThen());
2002 AddStmt(If->getCond());
2003 AddDecl(If->getConditionVariable());
2004}
2005void EnqueueVisitor::VisitInitListExpr(InitListExpr *IE) {
2006 // We care about the syntactic form of the initializer list, only.
2007 if (InitListExpr *Syntactic = IE->getSyntacticForm())
2008 IE = Syntactic;
2009 EnqueueChildren(IE);
2010}
2011void EnqueueVisitor::VisitMemberExpr(MemberExpr *M) {
Douglas Gregor89629a72010-11-17 17:15:08 +00002012 WL.push_back(MemberExprParts(M, Parent));
2013
2014 // If the base of the member access expression is an implicit 'this', don't
2015 // visit it.
2016 // FIXME: If we ever want to show these implicit accesses, this will be
2017 // unfortunate. However, clang_getCursor() relies on this behavior.
Douglas Gregor75e85042011-03-02 21:06:53 +00002018 if (!M->isImplicitAccess())
2019 AddStmt(M->getBase());
Ted Kremenek28a71942010-11-13 00:36:47 +00002020}
Ted Kremenek73d15c42010-11-13 01:09:29 +00002021void EnqueueVisitor::VisitObjCEncodeExpr(ObjCEncodeExpr *E) {
2022 AddTypeLoc(E->getEncodedTypeSourceInfo());
2023}
Ted Kremenek28a71942010-11-13 00:36:47 +00002024void EnqueueVisitor::VisitObjCMessageExpr(ObjCMessageExpr *M) {
2025 EnqueueChildren(M);
2026 AddTypeLoc(M->getClassReceiverTypeInfo());
2027}
Ted Kremenekcdba6592010-11-18 00:42:18 +00002028void EnqueueVisitor::VisitOffsetOfExpr(OffsetOfExpr *E) {
2029 // Visit the components of the offsetof expression.
2030 for (unsigned N = E->getNumComponents(), I = N; I > 0; --I) {
2031 typedef OffsetOfExpr::OffsetOfNode OffsetOfNode;
2032 const OffsetOfNode &Node = E->getComponent(I-1);
2033 switch (Node.getKind()) {
2034 case OffsetOfNode::Array:
2035 AddStmt(E->getIndexExpr(Node.getArrayExprIndex()));
2036 break;
2037 case OffsetOfNode::Field:
Abramo Bagnara06dec892011-03-12 09:45:03 +00002038 AddMemberRef(Node.getField(), Node.getSourceRange().getEnd());
Ted Kremenekcdba6592010-11-18 00:42:18 +00002039 break;
2040 case OffsetOfNode::Identifier:
2041 case OffsetOfNode::Base:
2042 continue;
2043 }
2044 }
2045 // Visit the type into which we're computing the offset.
2046 AddTypeLoc(E->getTypeSourceInfo());
2047}
Ted Kremenek28a71942010-11-13 00:36:47 +00002048void EnqueueVisitor::VisitOverloadExpr(OverloadExpr *E) {
Ted Kremenek60608ec2010-11-17 00:50:47 +00002049 AddExplicitTemplateArgs(E->getOptionalExplicitTemplateArgs());
Ted Kremenek60458782010-11-12 21:34:16 +00002050 WL.push_back(OverloadExprParts(E, Parent));
2051}
Peter Collingbournef4e3cfb2011-03-11 19:24:49 +00002052void EnqueueVisitor::VisitUnaryExprOrTypeTraitExpr(
2053 UnaryExprOrTypeTraitExpr *E) {
Ted Kremenek6d0a00d2010-11-17 02:18:35 +00002054 EnqueueChildren(E);
2055 if (E->isArgumentType())
2056 AddTypeLoc(E->getArgumentTypeInfo());
2057}
Ted Kremenek28a71942010-11-13 00:36:47 +00002058void EnqueueVisitor::VisitStmt(Stmt *S) {
2059 EnqueueChildren(S);
2060}
2061void EnqueueVisitor::VisitSwitchStmt(SwitchStmt *S) {
2062 AddStmt(S->getBody());
2063 AddStmt(S->getCond());
2064 AddDecl(S->getConditionVariable());
2065}
Ted Kremenekfafa75a2010-11-17 00:50:39 +00002066
Ted Kremenek28a71942010-11-13 00:36:47 +00002067void EnqueueVisitor::VisitWhileStmt(WhileStmt *W) {
2068 AddStmt(W->getBody());
2069 AddStmt(W->getCond());
2070 AddDecl(W->getConditionVariable());
2071}
John Wiegley21ff2e52011-04-28 00:16:57 +00002072
Ted Kremenek2939b6f2010-11-17 00:50:50 +00002073void EnqueueVisitor::VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E) {
2074 AddTypeLoc(E->getQueriedTypeSourceInfo());
2075}
Francois Pichet6ad6f282010-12-07 00:08:36 +00002076
2077void EnqueueVisitor::VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *E) {
Francois Pichet6ad6f282010-12-07 00:08:36 +00002078 AddTypeLoc(E->getRhsTypeSourceInfo());
Francois Pichet0a03a3f2010-12-08 09:11:05 +00002079 AddTypeLoc(E->getLhsTypeSourceInfo());
Francois Pichet6ad6f282010-12-07 00:08:36 +00002080}
2081
John Wiegley21ff2e52011-04-28 00:16:57 +00002082void EnqueueVisitor::VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E) {
2083 AddTypeLoc(E->getQueriedTypeSourceInfo());
2084}
2085
John Wiegley55262202011-04-25 06:54:41 +00002086void EnqueueVisitor::VisitExpressionTraitExpr(ExpressionTraitExpr *E) {
2087 EnqueueChildren(E);
2088}
2089
Ted Kremenek28a71942010-11-13 00:36:47 +00002090void EnqueueVisitor::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *U) {
2091 VisitOverloadExpr(U);
2092 if (!U->isImplicitAccess())
2093 AddStmt(U->getBase());
2094}
Ted Kremenek9d3bf792010-11-17 00:50:43 +00002095void EnqueueVisitor::VisitVAArgExpr(VAArgExpr *E) {
2096 AddStmt(E->getSubExpr());
2097 AddTypeLoc(E->getWrittenTypeInfo());
2098}
Douglas Gregor94d96292011-01-19 20:34:17 +00002099void EnqueueVisitor::VisitSizeOfPackExpr(SizeOfPackExpr *E) {
2100 WL.push_back(SizeOfPackExprParts(E, Parent));
2101}
Ted Kremenek60458782010-11-12 21:34:16 +00002102
Ted Kremenekc0e1d922010-11-11 08:05:18 +00002103void CursorVisitor::EnqueueWorkList(VisitorWorkList &WL, Stmt *S) {
Ted Kremenek28a71942010-11-13 00:36:47 +00002104 EnqueueVisitor(WL, MakeCXCursor(S, StmtParent, TU)).Visit(S);
Ted Kremenekc0e1d922010-11-11 08:05:18 +00002105}
2106
2107bool CursorVisitor::IsInRegionOfInterest(CXCursor C) {
2108 if (RegionOfInterest.isValid()) {
2109 SourceRange Range = getRawCursorExtent(C);
2110 if (Range.isInvalid() || CompareRegionOfInterest(Range))
2111 return false;
2112 }
2113 return true;
2114}
2115
2116bool CursorVisitor::RunVisitorWorkList(VisitorWorkList &WL) {
2117 while (!WL.empty()) {
2118 // Dequeue the worklist item.
Ted Kremenek82f3c502010-11-15 22:23:26 +00002119 VisitorJob LI = WL.back();
2120 WL.pop_back();
2121
Ted Kremenekc0e1d922010-11-11 08:05:18 +00002122 // Set the Parent field, then back to its old value once we're done.
2123 SetParentRAII SetParent(Parent, StmtParent, LI.getParent());
2124
2125 switch (LI.getKind()) {
Ted Kremenekf1107452010-11-12 18:26:56 +00002126 case VisitorJob::DeclVisitKind: {
Ted Kremenek82f3c502010-11-15 22:23:26 +00002127 Decl *D = cast<DeclVisit>(&LI)->get();
Ted Kremenekf1107452010-11-12 18:26:56 +00002128 if (!D)
2129 continue;
2130
2131 // For now, perform default visitation for Decls.
Ted Kremenek82f3c502010-11-15 22:23:26 +00002132 if (Visit(MakeCXCursor(D, TU, cast<DeclVisit>(&LI)->isFirst())))
Ted Kremenekf1107452010-11-12 18:26:56 +00002133 return true;
2134
2135 continue;
2136 }
Ted Kremenek60608ec2010-11-17 00:50:47 +00002137 case VisitorJob::ExplicitTemplateArgsVisitKind: {
2138 const ExplicitTemplateArgumentList *ArgList =
2139 cast<ExplicitTemplateArgsVisit>(&LI)->get();
2140 for (const TemplateArgumentLoc *Arg = ArgList->getTemplateArgs(),
2141 *ArgEnd = Arg + ArgList->NumTemplateArgs;
2142 Arg != ArgEnd; ++Arg) {
2143 if (VisitTemplateArgumentLoc(*Arg))
2144 return true;
2145 }
2146 continue;
2147 }
Ted Kremenekcdb4caf2010-11-12 21:34:12 +00002148 case VisitorJob::TypeLocVisitKind: {
2149 // Perform default visitation for TypeLocs.
Ted Kremenek82f3c502010-11-15 22:23:26 +00002150 if (Visit(cast<TypeLocVisit>(&LI)->get()))
Ted Kremenekcdb4caf2010-11-12 21:34:12 +00002151 return true;
2152 continue;
2153 }
Ted Kremenekae1fd6f2010-11-17 00:50:45 +00002154 case VisitorJob::LabelRefVisitKind: {
Chris Lattnerad8dcf42011-02-17 07:39:24 +00002155 LabelDecl *LS = cast<LabelRefVisit>(&LI)->get();
Ted Kremeneke7455012011-02-23 04:54:51 +00002156 if (LabelStmt *stmt = LS->getStmt()) {
2157 if (Visit(MakeCursorLabelRef(stmt, cast<LabelRefVisit>(&LI)->getLoc(),
2158 TU))) {
2159 return true;
2160 }
2161 }
Ted Kremenekae1fd6f2010-11-17 00:50:45 +00002162 continue;
2163 }
Douglas Gregorf3db29f2011-02-25 18:19:59 +00002164
Ted Kremenekf64d8032010-11-18 00:02:32 +00002165 case VisitorJob::NestedNameSpecifierVisitKind: {
2166 NestedNameSpecifierVisit *V = cast<NestedNameSpecifierVisit>(&LI);
2167 if (VisitNestedNameSpecifier(V->get(), V->getSourceRange()))
2168 return true;
2169 continue;
2170 }
Douglas Gregorf3db29f2011-02-25 18:19:59 +00002171
2172 case VisitorJob::NestedNameSpecifierLocVisitKind: {
2173 NestedNameSpecifierLocVisit *V = cast<NestedNameSpecifierLocVisit>(&LI);
2174 if (VisitNestedNameSpecifierLoc(V->get()))
2175 return true;
2176 continue;
2177 }
2178
Ted Kremenekf64d8032010-11-18 00:02:32 +00002179 case VisitorJob::DeclarationNameInfoVisitKind: {
2180 if (VisitDeclarationNameInfo(cast<DeclarationNameInfoVisit>(&LI)
2181 ->get()))
2182 return true;
2183 continue;
2184 }
Ted Kremenekcdba6592010-11-18 00:42:18 +00002185 case VisitorJob::MemberRefVisitKind: {
2186 MemberRefVisit *V = cast<MemberRefVisit>(&LI);
2187 if (Visit(MakeCursorMemberRef(V->get(), V->getLoc(), TU)))
2188 return true;
2189 continue;
2190 }
Ted Kremenekc0e1d922010-11-11 08:05:18 +00002191 case VisitorJob::StmtVisitKind: {
Ted Kremenek82f3c502010-11-15 22:23:26 +00002192 Stmt *S = cast<StmtVisit>(&LI)->get();
Ted Kremenek8c269ac2010-11-11 23:11:43 +00002193 if (!S)
2194 continue;
2195
Ted Kremenekf1107452010-11-12 18:26:56 +00002196 // Update the current cursor.
Ted Kremenekc0e1d922010-11-11 08:05:18 +00002197 CXCursor Cursor = MakeCXCursor(S, StmtParent, TU);
Ted Kremenekcdba6592010-11-18 00:42:18 +00002198 if (!IsInRegionOfInterest(Cursor))
2199 continue;
2200 switch (Visitor(Cursor, Parent, ClientData)) {
2201 case CXChildVisit_Break: return true;
2202 case CXChildVisit_Continue: break;
2203 case CXChildVisit_Recurse:
2204 EnqueueWorkList(WL, S);
Ted Kremenek82f3c502010-11-15 22:23:26 +00002205 break;
Ted Kremenekc0e1d922010-11-11 08:05:18 +00002206 }
Ted Kremenek82f3c502010-11-15 22:23:26 +00002207 continue;
Ted Kremenekc0e1d922010-11-11 08:05:18 +00002208 }
2209 case VisitorJob::MemberExprPartsKind: {
2210 // Handle the other pieces in the MemberExpr besides the base.
Ted Kremenek82f3c502010-11-15 22:23:26 +00002211 MemberExpr *M = cast<MemberExprParts>(&LI)->get();
Ted Kremenekc0e1d922010-11-11 08:05:18 +00002212
2213 // Visit the nested-name-specifier
Douglas Gregor40d96a62011-02-28 21:54:11 +00002214 if (NestedNameSpecifierLoc QualifierLoc = M->getQualifierLoc())
2215 if (VisitNestedNameSpecifierLoc(QualifierLoc))
Ted Kremenekc0e1d922010-11-11 08:05:18 +00002216 return true;
2217
2218 // Visit the declaration name.
2219 if (VisitDeclarationNameInfo(M->getMemberNameInfo()))
2220 return true;
2221
2222 // Visit the explicitly-specified template arguments, if any.
2223 if (M->hasExplicitTemplateArgs()) {
2224 for (const TemplateArgumentLoc *Arg = M->getTemplateArgs(),
2225 *ArgEnd = Arg + M->getNumTemplateArgs();
2226 Arg != ArgEnd; ++Arg) {
2227 if (VisitTemplateArgumentLoc(*Arg))
2228 return true;
2229 }
2230 }
2231 continue;
2232 }
Ted Kremeneke4979cc2010-11-13 00:58:18 +00002233 case VisitorJob::DeclRefExprPartsKind: {
Ted Kremenek82f3c502010-11-15 22:23:26 +00002234 DeclRefExpr *DR = cast<DeclRefExprParts>(&LI)->get();
Ted Kremeneke4979cc2010-11-13 00:58:18 +00002235 // Visit nested-name-specifier, if present.
Douglas Gregor40d96a62011-02-28 21:54:11 +00002236 if (NestedNameSpecifierLoc QualifierLoc = DR->getQualifierLoc())
2237 if (VisitNestedNameSpecifierLoc(QualifierLoc))
Ted Kremeneke4979cc2010-11-13 00:58:18 +00002238 return true;
2239 // Visit declaration name.
2240 if (VisitDeclarationNameInfo(DR->getNameInfo()))
2241 return true;
Ted Kremeneke4979cc2010-11-13 00:58:18 +00002242 continue;
2243 }
Ted Kremenek60458782010-11-12 21:34:16 +00002244 case VisitorJob::OverloadExprPartsKind: {
Ted Kremenek82f3c502010-11-15 22:23:26 +00002245 OverloadExpr *O = cast<OverloadExprParts>(&LI)->get();
Ted Kremenek60458782010-11-12 21:34:16 +00002246 // Visit the nested-name-specifier.
Douglas Gregor4c9be892011-02-28 20:01:57 +00002247 if (NestedNameSpecifierLoc QualifierLoc = O->getQualifierLoc())
2248 if (VisitNestedNameSpecifierLoc(QualifierLoc))
Ted Kremenek60458782010-11-12 21:34:16 +00002249 return true;
2250 // Visit the declaration name.
2251 if (VisitDeclarationNameInfo(O->getNameInfo()))
2252 return true;
2253 // Visit the overloaded declaration reference.
2254 if (Visit(MakeCursorOverloadedDeclRef(O, TU)))
2255 return true;
Ted Kremenek60458782010-11-12 21:34:16 +00002256 continue;
2257 }
Douglas Gregor94d96292011-01-19 20:34:17 +00002258 case VisitorJob::SizeOfPackExprPartsKind: {
2259 SizeOfPackExpr *E = cast<SizeOfPackExprParts>(&LI)->get();
2260 NamedDecl *Pack = E->getPack();
2261 if (isa<TemplateTypeParmDecl>(Pack)) {
2262 if (Visit(MakeCursorTypeRef(cast<TemplateTypeParmDecl>(Pack),
2263 E->getPackLoc(), TU)))
2264 return true;
2265
2266 continue;
2267 }
2268
2269 if (isa<TemplateTemplateParmDecl>(Pack)) {
2270 if (Visit(MakeCursorTemplateRef(cast<TemplateTemplateParmDecl>(Pack),
2271 E->getPackLoc(), TU)))
2272 return true;
2273
2274 continue;
2275 }
2276
2277 // Non-type template parameter packs and function parameter packs are
2278 // treated like DeclRefExpr cursors.
2279 continue;
2280 }
Ted Kremenekc0e1d922010-11-11 08:05:18 +00002281 }
2282 }
2283 return false;
2284}
2285
Ted Kremenekcdba6592010-11-18 00:42:18 +00002286bool CursorVisitor::Visit(Stmt *S) {
Ted Kremenekd1ded662010-11-15 23:31:32 +00002287 VisitorWorkList *WL = 0;
2288 if (!WorkListFreeList.empty()) {
2289 WL = WorkListFreeList.back();
2290 WL->clear();
2291 WorkListFreeList.pop_back();
2292 }
2293 else {
2294 WL = new VisitorWorkList();
2295 WorkListCache.push_back(WL);
2296 }
2297 EnqueueWorkList(*WL, S);
2298 bool result = RunVisitorWorkList(*WL);
2299 WorkListFreeList.push_back(WL);
2300 return result;
Ted Kremenekc0e1d922010-11-11 08:05:18 +00002301}
2302
2303//===----------------------------------------------------------------------===//
2304// Misc. API hooks.
2305//===----------------------------------------------------------------------===//
2306
Douglas Gregor8c8d5412010-09-24 21:18:36 +00002307static llvm::sys::Mutex EnableMultithreadingMutex;
2308static bool EnabledMultithreading;
2309
Benjamin Kramer5e4bc592009-10-18 16:11:04 +00002310extern "C" {
Douglas Gregor0a812cf2010-02-18 23:07:20 +00002311CXIndex clang_createIndex(int excludeDeclarationsFromPCH,
2312 int displayDiagnostics) {
Daniel Dunbar48615ff2010-10-08 19:30:33 +00002313 // Disable pretty stack trace functionality, which will otherwise be a very
2314 // poor citizen of the world and set up all sorts of signal handlers.
2315 llvm::DisablePrettyStackTrace = true;
2316
Daniel Dunbarc7df4f32010-08-18 18:43:14 +00002317 // We use crash recovery to make some of our APIs more reliable, implicitly
2318 // enable it.
2319 llvm::CrashRecoveryContext::Enable();
2320
Douglas Gregor8c8d5412010-09-24 21:18:36 +00002321 // Enable support for multithreading in LLVM.
2322 {
2323 llvm::sys::ScopedLock L(EnableMultithreadingMutex);
2324 if (!EnabledMultithreading) {
2325 llvm::llvm_start_multithreaded();
2326 EnabledMultithreading = true;
2327 }
2328 }
2329
Douglas Gregora030b7c2010-01-22 20:35:53 +00002330 CIndexer *CIdxr = new CIndexer();
Steve Naroffe56b4ba2009-10-20 14:46:24 +00002331 if (excludeDeclarationsFromPCH)
2332 CIdxr->setOnlyLocalDecls();
Douglas Gregor0a812cf2010-02-18 23:07:20 +00002333 if (displayDiagnostics)
2334 CIdxr->setDisplayDiagnostics();
Steve Naroffe56b4ba2009-10-20 14:46:24 +00002335 return CIdxr;
Steve Naroff600866c2009-08-27 19:51:58 +00002336}
2337
Daniel Dunbar9ebfa312009-12-01 03:14:51 +00002338void clang_disposeIndex(CXIndex CIdx) {
Douglas Gregor2b37c9e2010-01-29 00:47:48 +00002339 if (CIdx)
2340 delete static_cast<CIndexer *>(CIdx);
Steve Naroff2bd6b9f2009-09-17 18:33:27 +00002341}
2342
Ted Kremenekd2427dd2011-03-18 23:05:39 +00002343void clang_toggleCrashRecovery(unsigned isEnabled) {
2344 if (isEnabled)
2345 llvm::CrashRecoveryContext::Enable();
2346 else
2347 llvm::CrashRecoveryContext::Disable();
2348}
2349
Daniel Dunbar9ebfa312009-12-01 03:14:51 +00002350CXTranslationUnit clang_createTranslationUnit(CXIndex CIdx,
Douglas Gregora88084b2010-02-18 18:08:43 +00002351 const char *ast_filename) {
Douglas Gregor2b37c9e2010-01-29 00:47:48 +00002352 if (!CIdx)
2353 return 0;
Ted Kremenekf0e23e82010-02-17 00:41:40 +00002354
Douglas Gregor7d1d49d2009-10-16 20:01:17 +00002355 CIndexer *CXXIdx = static_cast<CIndexer *>(CIdx);
Argyrios Kyrtzidis389db162010-11-03 22:45:23 +00002356 FileSystemOptions FileSystemOpts;
2357 FileSystemOpts.WorkingDir = CXXIdx->getWorkingDirectory();
Daniel Dunbar0d7dd222009-11-30 20:42:43 +00002358
Douglas Gregor28019772010-04-05 23:52:57 +00002359 llvm::IntrusiveRefCntPtr<Diagnostic> Diags;
Ted Kremeneka60ed472010-11-16 08:15:36 +00002360 ASTUnit *TU = ASTUnit::LoadFromASTFile(ast_filename, Diags, FileSystemOpts,
Douglas Gregora88084b2010-02-18 18:08:43 +00002361 CXXIdx->getOnlyLocalDecls(),
2362 0, 0, true);
Ted Kremeneka60ed472010-11-16 08:15:36 +00002363 return MakeCXTranslationUnit(TU);
Steve Naroff600866c2009-08-27 19:51:58 +00002364}
2365
Douglas Gregorb1c031b2010-08-09 22:28:58 +00002366unsigned clang_defaultEditingTranslationUnitOptions() {
Douglas Gregor2a2c50b2010-09-27 05:49:58 +00002367 return CXTranslationUnit_PrecompiledPreamble |
Douglas Gregor99ba2022010-10-27 17:24:53 +00002368 CXTranslationUnit_CacheCompletionResults |
2369 CXTranslationUnit_CXXPrecompiledPreamble;
Douglas Gregorb1c031b2010-08-09 22:28:58 +00002370}
2371
Daniel Dunbar9ebfa312009-12-01 03:14:51 +00002372CXTranslationUnit
2373clang_createTranslationUnitFromSourceFile(CXIndex CIdx,
2374 const char *source_filename,
2375 int num_command_line_args,
Douglas Gregor2ef69442010-09-01 16:43:19 +00002376 const char * const *command_line_args,
Douglas Gregor4db64a42010-01-23 00:14:00 +00002377 unsigned num_unsaved_files,
Douglas Gregora88084b2010-02-18 18:08:43 +00002378 struct CXUnsavedFile *unsaved_files) {
Douglas Gregordca8ee82011-05-06 16:33:08 +00002379 unsigned Options = CXTranslationUnit_DetailedPreprocessingRecord |
2380 CXTranslationUnit_NestedMacroInstantiations;
Douglas Gregor5a430212010-07-21 18:52:53 +00002381 return clang_parseTranslationUnit(CIdx, source_filename,
2382 command_line_args, num_command_line_args,
2383 unsaved_files, num_unsaved_files,
Douglas Gregordca8ee82011-05-06 16:33:08 +00002384 Options);
Douglas Gregor5a430212010-07-21 18:52:53 +00002385}
Daniel Dunbar19ffd492010-08-18 18:43:17 +00002386
2387struct ParseTranslationUnitInfo {
2388 CXIndex CIdx;
2389 const char *source_filename;
Douglas Gregor2ef69442010-09-01 16:43:19 +00002390 const char *const *command_line_args;
Daniel Dunbar19ffd492010-08-18 18:43:17 +00002391 int num_command_line_args;
2392 struct CXUnsavedFile *unsaved_files;
2393 unsigned num_unsaved_files;
2394 unsigned options;
2395 CXTranslationUnit result;
2396};
Daniel Dunbarb1fd3452010-08-19 23:44:10 +00002397static void clang_parseTranslationUnit_Impl(void *UserData) {
Daniel Dunbar19ffd492010-08-18 18:43:17 +00002398 ParseTranslationUnitInfo *PTUI =
2399 static_cast<ParseTranslationUnitInfo*>(UserData);
2400 CXIndex CIdx = PTUI->CIdx;
2401 const char *source_filename = PTUI->source_filename;
Douglas Gregor2ef69442010-09-01 16:43:19 +00002402 const char * const *command_line_args = PTUI->command_line_args;
Daniel Dunbar19ffd492010-08-18 18:43:17 +00002403 int num_command_line_args = PTUI->num_command_line_args;
2404 struct CXUnsavedFile *unsaved_files = PTUI->unsaved_files;
2405 unsigned num_unsaved_files = PTUI->num_unsaved_files;
2406 unsigned options = PTUI->options;
2407 PTUI->result = 0;
Douglas Gregor5a430212010-07-21 18:52:53 +00002408
Douglas Gregor2b37c9e2010-01-29 00:47:48 +00002409 if (!CIdx)
Daniel Dunbar19ffd492010-08-18 18:43:17 +00002410 return;
Ted Kremenekf0e23e82010-02-17 00:41:40 +00002411
Steve Naroffe56b4ba2009-10-20 14:46:24 +00002412 CIndexer *CXXIdx = static_cast<CIndexer *>(CIdx);
2413
Douglas Gregor44c181a2010-07-23 00:33:23 +00002414 bool PrecompilePreamble = options & CXTranslationUnit_PrecompiledPreamble;
Douglas Gregordf95a132010-08-09 20:45:32 +00002415 bool CompleteTranslationUnit
2416 = ((options & CXTranslationUnit_Incomplete) == 0);
Douglas Gregor87c08a52010-08-13 22:48:40 +00002417 bool CacheCodeCompetionResults
2418 = options & CXTranslationUnit_CacheCompletionResults;
Douglas Gregor99ba2022010-10-27 17:24:53 +00002419 bool CXXPrecompilePreamble
2420 = options & CXTranslationUnit_CXXPrecompiledPreamble;
2421 bool CXXChainedPCH
2422 = options & CXTranslationUnit_CXXChainedPCH;
Douglas Gregor87c08a52010-08-13 22:48:40 +00002423
Douglas Gregor5352ac02010-01-28 00:27:43 +00002424 // Configure the diagnostics.
2425 DiagnosticOptions DiagOpts;
Ted Kremenek25a11e12011-03-22 01:15:24 +00002426 llvm::IntrusiveRefCntPtr<Diagnostic>
2427 Diags(CompilerInstance::createDiagnostics(DiagOpts, num_command_line_args,
2428 command_line_args));
Ted Kremenekf0e23e82010-02-17 00:41:40 +00002429
Ted Kremenek25a11e12011-03-22 01:15:24 +00002430 // Recover resources if we crash before exiting this function.
2431 llvm::CrashRecoveryContextCleanupRegistrar<Diagnostic,
2432 llvm::CrashRecoveryContextReleaseRefCleanup<Diagnostic> >
2433 DiagCleanup(Diags.getPtr());
2434
2435 llvm::OwningPtr<std::vector<ASTUnit::RemappedFile> >
2436 RemappedFiles(new std::vector<ASTUnit::RemappedFile>());
2437
2438 // Recover resources if we crash before exiting this function.
2439 llvm::CrashRecoveryContextCleanupRegistrar<
2440 std::vector<ASTUnit::RemappedFile> > RemappedCleanup(RemappedFiles.get());
2441
Douglas Gregor4db64a42010-01-23 00:14:00 +00002442 for (unsigned I = 0; I != num_unsaved_files; ++I) {
Chris Lattnera0a270c2010-04-05 22:42:27 +00002443 llvm::StringRef Data(unsaved_files[I].Contents, unsaved_files[I].Length);
Ted Kremenekf0e23e82010-02-17 00:41:40 +00002444 const llvm::MemoryBuffer *Buffer
Chris Lattnera0a270c2010-04-05 22:42:27 +00002445 = llvm::MemoryBuffer::getMemBufferCopy(Data, unsaved_files[I].Filename);
Ted Kremenek25a11e12011-03-22 01:15:24 +00002446 RemappedFiles->push_back(std::make_pair(unsaved_files[I].Filename,
2447 Buffer));
Douglas Gregor4db64a42010-01-23 00:14:00 +00002448 }
Ted Kremenekf0e23e82010-02-17 00:41:40 +00002449
Ted Kremenek25a11e12011-03-22 01:15:24 +00002450 llvm::OwningPtr<std::vector<const char *> >
2451 Args(new std::vector<const char*>());
2452
2453 // Recover resources if we crash before exiting this method.
2454 llvm::CrashRecoveryContextCleanupRegistrar<std::vector<const char*> >
2455 ArgsCleanup(Args.get());
2456
Douglas Gregor52ddc5d2010-07-09 18:39:07 +00002457 // Since the Clang C library is primarily used by batch tools dealing with
2458 // (often very broken) source code, where spell-checking can have a
2459 // significant negative impact on performance (particularly when
2460 // precompiled headers are involved), we disable it by default.
Douglas Gregorb10daed2010-10-11 16:52:23 +00002461 // Only do this if we haven't found a spell-checking-related argument.
2462 bool FoundSpellCheckingArgument = false;
2463 for (int I = 0; I != num_command_line_args; ++I) {
2464 if (strcmp(command_line_args[I], "-fno-spell-checking") == 0 ||
2465 strcmp(command_line_args[I], "-fspell-checking") == 0) {
2466 FoundSpellCheckingArgument = true;
2467 break;
Steve Naroffe56b4ba2009-10-20 14:46:24 +00002468 }
Douglas Gregorb10daed2010-10-11 16:52:23 +00002469 }
2470 if (!FoundSpellCheckingArgument)
Ted Kremenek25a11e12011-03-22 01:15:24 +00002471 Args->push_back("-fno-spell-checking");
Douglas Gregorb10daed2010-10-11 16:52:23 +00002472
Ted Kremenek25a11e12011-03-22 01:15:24 +00002473 Args->insert(Args->end(), command_line_args,
2474 command_line_args + num_command_line_args);
Douglas Gregord93256e2010-01-28 06:00:51 +00002475
Argyrios Kyrtzidisc8429552011-03-20 18:17:52 +00002476 // The 'source_filename' argument is optional. If the caller does not
2477 // specify it then it is assumed that the source file is specified
2478 // in the actual argument list.
2479 // Put the source file after command_line_args otherwise if '-x' flag is
2480 // present it will be unused.
2481 if (source_filename)
Ted Kremenek25a11e12011-03-22 01:15:24 +00002482 Args->push_back(source_filename);
Argyrios Kyrtzidisc8429552011-03-20 18:17:52 +00002483
Douglas Gregor44c181a2010-07-23 00:33:23 +00002484 // Do we need the detailed preprocessing record?
Douglas Gregordca8ee82011-05-06 16:33:08 +00002485 bool NestedMacroInstantiations = false;
Douglas Gregor44c181a2010-07-23 00:33:23 +00002486 if (options & CXTranslationUnit_DetailedPreprocessingRecord) {
Ted Kremenek25a11e12011-03-22 01:15:24 +00002487 Args->push_back("-Xclang");
2488 Args->push_back("-detailed-preprocessing-record");
Douglas Gregordca8ee82011-05-06 16:33:08 +00002489 NestedMacroInstantiations
2490 = (options & CXTranslationUnit_NestedMacroInstantiations);
Douglas Gregor44c181a2010-07-23 00:33:23 +00002491 }
2492
Argyrios Kyrtzidis026f6912010-11-18 21:47:04 +00002493 unsigned NumErrors = Diags->getClient()->getNumErrors();
Douglas Gregorb10daed2010-10-11 16:52:23 +00002494 llvm::OwningPtr<ASTUnit> Unit(
Ted Kremenek4ee99262011-03-22 20:16:19 +00002495 ASTUnit::LoadFromCommandLine(Args->size() ? &(*Args)[0] : 0
2496 /* vector::data() not portable */,
2497 Args->size() ? (&(*Args)[0] + Args->size()) :0,
Douglas Gregorb10daed2010-10-11 16:52:23 +00002498 Diags,
2499 CXXIdx->getClangResourcesPath(),
2500 CXXIdx->getOnlyLocalDecls(),
Douglas Gregore47be3e2010-11-11 00:39:14 +00002501 /*CaptureDiagnostics=*/true,
Ted Kremenek4ee99262011-03-22 20:16:19 +00002502 RemappedFiles->size() ? &(*RemappedFiles)[0]:0,
Ted Kremenek25a11e12011-03-22 01:15:24 +00002503 RemappedFiles->size(),
Argyrios Kyrtzidis299a4a92011-03-08 23:35:24 +00002504 /*RemappedFilesKeepOriginalName=*/true,
Douglas Gregorb10daed2010-10-11 16:52:23 +00002505 PrecompilePreamble,
2506 CompleteTranslationUnit,
Douglas Gregor99ba2022010-10-27 17:24:53 +00002507 CacheCodeCompetionResults,
2508 CXXPrecompilePreamble,
Douglas Gregordca8ee82011-05-06 16:33:08 +00002509 CXXChainedPCH,
2510 NestedMacroInstantiations));
Ted Kremenekf0e23e82010-02-17 00:41:40 +00002511
Argyrios Kyrtzidis026f6912010-11-18 21:47:04 +00002512 if (NumErrors != Diags->getClient()->getNumErrors()) {
Douglas Gregorb10daed2010-10-11 16:52:23 +00002513 // Make sure to check that 'Unit' is non-NULL.
2514 if (CXXIdx->getDisplayDiagnostics() && Unit.get()) {
2515 for (ASTUnit::stored_diag_iterator D = Unit->stored_diag_begin(),
2516 DEnd = Unit->stored_diag_end();
2517 D != DEnd; ++D) {
2518 CXStoredDiagnostic Diag(*D, Unit->getASTContext().getLangOptions());
2519 CXString Msg = clang_formatDiagnostic(&Diag,
2520 clang_defaultDiagnosticDisplayOptions());
2521 fprintf(stderr, "%s\n", clang_getCString(Msg));
2522 clang_disposeString(Msg);
2523 }
Douglas Gregor274f1902010-02-22 23:17:23 +00002524#ifdef LLVM_ON_WIN32
Douglas Gregorb10daed2010-10-11 16:52:23 +00002525 // On Windows, force a flush, since there may be multiple copies of
2526 // stderr and stdout in the file system, all with different buffers
2527 // but writing to the same device.
2528 fflush(stderr);
2529#endif
2530 }
Douglas Gregora88084b2010-02-18 18:08:43 +00002531 }
Douglas Gregord93256e2010-01-28 06:00:51 +00002532
Ted Kremeneka60ed472010-11-16 08:15:36 +00002533 PTUI->result = MakeCXTranslationUnit(Unit.take());
Daniel Dunbar19ffd492010-08-18 18:43:17 +00002534}
2535CXTranslationUnit clang_parseTranslationUnit(CXIndex CIdx,
2536 const char *source_filename,
Douglas Gregor2ef69442010-09-01 16:43:19 +00002537 const char * const *command_line_args,
Daniel Dunbar19ffd492010-08-18 18:43:17 +00002538 int num_command_line_args,
Daniel Dunbar9e1ebdd2010-11-05 07:19:21 +00002539 struct CXUnsavedFile *unsaved_files,
Daniel Dunbar19ffd492010-08-18 18:43:17 +00002540 unsigned num_unsaved_files,
2541 unsigned options) {
2542 ParseTranslationUnitInfo PTUI = { CIdx, source_filename, command_line_args,
Daniel Dunbar9e1ebdd2010-11-05 07:19:21 +00002543 num_command_line_args, unsaved_files,
2544 num_unsaved_files, options, 0 };
Daniel Dunbar19ffd492010-08-18 18:43:17 +00002545 llvm::CrashRecoveryContext CRC;
2546
Daniel Dunbarbf44c3b2010-11-05 07:19:31 +00002547 if (!RunSafely(CRC, clang_parseTranslationUnit_Impl, &PTUI)) {
Daniel Dunbar60a45432010-08-23 22:35:34 +00002548 fprintf(stderr, "libclang: crash detected during parsing: {\n");
2549 fprintf(stderr, " 'source_filename' : '%s'\n", source_filename);
2550 fprintf(stderr, " 'command_line_args' : [");
2551 for (int i = 0; i != num_command_line_args; ++i) {
2552 if (i)
2553 fprintf(stderr, ", ");
2554 fprintf(stderr, "'%s'", command_line_args[i]);
2555 }
2556 fprintf(stderr, "],\n");
2557 fprintf(stderr, " 'unsaved_files' : [");
2558 for (unsigned i = 0; i != num_unsaved_files; ++i) {
2559 if (i)
2560 fprintf(stderr, ", ");
2561 fprintf(stderr, "('%s', '...', %ld)", unsaved_files[i].Filename,
2562 unsaved_files[i].Length);
2563 }
2564 fprintf(stderr, "],\n");
2565 fprintf(stderr, " 'options' : %d,\n", options);
2566 fprintf(stderr, "}\n");
2567
Daniel Dunbar19ffd492010-08-18 18:43:17 +00002568 return 0;
Douglas Gregor6df78732011-05-05 20:27:22 +00002569 } else if (getenv("LIBCLANG_RESOURCE_USAGE")) {
2570 PrintLibclangResourceUsage(PTUI.result);
Daniel Dunbar19ffd492010-08-18 18:43:17 +00002571 }
Douglas Gregor6df78732011-05-05 20:27:22 +00002572
Daniel Dunbar19ffd492010-08-18 18:43:17 +00002573 return PTUI.result;
Steve Naroff5b7d8e22009-10-15 20:04:39 +00002574}
2575
Douglas Gregor19998442010-08-13 15:35:05 +00002576unsigned clang_defaultSaveOptions(CXTranslationUnit TU) {
2577 return CXSaveTranslationUnit_None;
2578}
2579
2580int clang_saveTranslationUnit(CXTranslationUnit TU, const char *FileName,
2581 unsigned options) {
Douglas Gregor7ae2faa2010-08-13 05:36:37 +00002582 if (!TU)
2583 return 1;
2584
Douglas Gregor6df78732011-05-05 20:27:22 +00002585 int result = static_cast<ASTUnit *>(TU->TUData)->Save(FileName);
2586 if (getenv("LIBCLANG_RESOURCE_USAGE"))
2587 PrintLibclangResourceUsage(TU);
2588 return result;
Douglas Gregor7ae2faa2010-08-13 05:36:37 +00002589}
Daniel Dunbar19ffd492010-08-18 18:43:17 +00002590
Daniel Dunbar9ebfa312009-12-01 03:14:51 +00002591void clang_disposeTranslationUnit(CXTranslationUnit CTUnit) {
Daniel Dunbarea94bbc2010-08-18 23:09:31 +00002592 if (CTUnit) {
2593 // If the translation unit has been marked as unsafe to free, just discard
2594 // it.
Ted Kremeneka60ed472010-11-16 08:15:36 +00002595 if (static_cast<ASTUnit *>(CTUnit->TUData)->isUnsafeToFree())
Daniel Dunbarea94bbc2010-08-18 23:09:31 +00002596 return;
2597
Ted Kremeneka60ed472010-11-16 08:15:36 +00002598 delete static_cast<ASTUnit *>(CTUnit->TUData);
2599 disposeCXStringPool(CTUnit->StringPool);
2600 delete CTUnit;
Daniel Dunbarea94bbc2010-08-18 23:09:31 +00002601 }
Steve Naroff2bd6b9f2009-09-17 18:33:27 +00002602}
Daniel Dunbar0d7dd222009-11-30 20:42:43 +00002603
Douglas Gregore1e13bf2010-08-11 15:58:42 +00002604unsigned clang_defaultReparseOptions(CXTranslationUnit TU) {
2605 return CXReparse_None;
2606}
2607
Daniel Dunbarea94bbc2010-08-18 23:09:31 +00002608struct ReparseTranslationUnitInfo {
2609 CXTranslationUnit TU;
2610 unsigned num_unsaved_files;
2611 struct CXUnsavedFile *unsaved_files;
2612 unsigned options;
2613 int result;
2614};
Douglas Gregor593b0c12010-09-23 18:47:53 +00002615
Daniel Dunbarb1fd3452010-08-19 23:44:10 +00002616static void clang_reparseTranslationUnit_Impl(void *UserData) {
Daniel Dunbarea94bbc2010-08-18 23:09:31 +00002617 ReparseTranslationUnitInfo *RTUI =
2618 static_cast<ReparseTranslationUnitInfo*>(UserData);
2619 CXTranslationUnit TU = RTUI->TU;
2620 unsigned num_unsaved_files = RTUI->num_unsaved_files;
2621 struct CXUnsavedFile *unsaved_files = RTUI->unsaved_files;
2622 unsigned options = RTUI->options;
2623 (void) options;
2624 RTUI->result = 1;
2625
Douglas Gregorabc563f2010-07-19 21:46:24 +00002626 if (!TU)
Daniel Dunbarea94bbc2010-08-18 23:09:31 +00002627 return;
Douglas Gregor593b0c12010-09-23 18:47:53 +00002628
Ted Kremeneka60ed472010-11-16 08:15:36 +00002629 ASTUnit *CXXUnit = static_cast<ASTUnit *>(TU->TUData);
Douglas Gregor593b0c12010-09-23 18:47:53 +00002630 ASTUnit::ConcurrencyCheck Check(*CXXUnit);
Douglas Gregorabc563f2010-07-19 21:46:24 +00002631
Ted Kremenek25a11e12011-03-22 01:15:24 +00002632 llvm::OwningPtr<std::vector<ASTUnit::RemappedFile> >
2633 RemappedFiles(new std::vector<ASTUnit::RemappedFile>());
2634
2635 // Recover resources if we crash before exiting this function.
2636 llvm::CrashRecoveryContextCleanupRegistrar<
2637 std::vector<ASTUnit::RemappedFile> > RemappedCleanup(RemappedFiles.get());
2638
Douglas Gregorabc563f2010-07-19 21:46:24 +00002639 for (unsigned I = 0; I != num_unsaved_files; ++I) {
2640 llvm::StringRef Data(unsaved_files[I].Contents, unsaved_files[I].Length);
2641 const llvm::MemoryBuffer *Buffer
Douglas Gregor1abc6bc2010-08-04 16:47:14 +00002642 = llvm::MemoryBuffer::getMemBufferCopy(Data, unsaved_files[I].Filename);
Ted Kremenek25a11e12011-03-22 01:15:24 +00002643 RemappedFiles->push_back(std::make_pair(unsaved_files[I].Filename,
2644 Buffer));
Douglas Gregorabc563f2010-07-19 21:46:24 +00002645 }
2646
Ted Kremenek4ee99262011-03-22 20:16:19 +00002647 if (!CXXUnit->Reparse(RemappedFiles->size() ? &(*RemappedFiles)[0] : 0,
2648 RemappedFiles->size()))
Douglas Gregor593b0c12010-09-23 18:47:53 +00002649 RTUI->result = 0;
Douglas Gregorabc563f2010-07-19 21:46:24 +00002650}
Douglas Gregor593b0c12010-09-23 18:47:53 +00002651
Daniel Dunbarea94bbc2010-08-18 23:09:31 +00002652int clang_reparseTranslationUnit(CXTranslationUnit TU,
2653 unsigned num_unsaved_files,
2654 struct CXUnsavedFile *unsaved_files,
2655 unsigned options) {
2656 ReparseTranslationUnitInfo RTUI = { TU, num_unsaved_files, unsaved_files,
2657 options, 0 };
2658 llvm::CrashRecoveryContext CRC;
2659
Daniel Dunbarbf44c3b2010-11-05 07:19:31 +00002660 if (!RunSafely(CRC, clang_reparseTranslationUnit_Impl, &RTUI)) {
Daniel Dunbarb1fd3452010-08-19 23:44:10 +00002661 fprintf(stderr, "libclang: crash detected during reparsing\n");
Ted Kremeneka60ed472010-11-16 08:15:36 +00002662 static_cast<ASTUnit *>(TU->TUData)->setUnsafeToFree(true);
Daniel Dunbarea94bbc2010-08-18 23:09:31 +00002663 return 1;
Douglas Gregor6df78732011-05-05 20:27:22 +00002664 } else if (getenv("LIBCLANG_RESOURCE_USAGE"))
2665 PrintLibclangResourceUsage(TU);
Ted Kremenek1dfb26a2010-10-29 01:06:50 +00002666
Daniel Dunbarea94bbc2010-08-18 23:09:31 +00002667 return RTUI.result;
2668}
2669
Douglas Gregordf95a132010-08-09 20:45:32 +00002670
Daniel Dunbar9ebfa312009-12-01 03:14:51 +00002671CXString clang_getTranslationUnitSpelling(CXTranslationUnit CTUnit) {
Douglas Gregor2b37c9e2010-01-29 00:47:48 +00002672 if (!CTUnit)
Ted Kremenekee4db4f2010-02-17 00:41:08 +00002673 return createCXString("");
Ted Kremenekf0e23e82010-02-17 00:41:40 +00002674
Ted Kremeneka60ed472010-11-16 08:15:36 +00002675 ASTUnit *CXXUnit = static_cast<ASTUnit *>(CTUnit->TUData);
Ted Kremenekee4db4f2010-02-17 00:41:08 +00002676 return createCXString(CXXUnit->getOriginalSourceFileName(), true);
Steve Naroffaf08ddc2009-09-03 15:49:00 +00002677}
Daniel Dunbar1eb79b52009-08-28 16:30:07 +00002678
Douglas Gregor7eaa8ae2010-01-20 00:23:15 +00002679CXCursor clang_getTranslationUnitCursor(CXTranslationUnit TU) {
Douglas Gregorb2cd4872010-01-20 23:57:43 +00002680 CXCursor Result = { CXCursor_TranslationUnit, { 0, 0, TU } };
Douglas Gregor7eaa8ae2010-01-20 00:23:15 +00002681 return Result;
2682}
2683
Ted Kremenekfb480492010-01-13 21:46:36 +00002684} // end: extern "C"
Steve Naroff600866c2009-08-27 19:51:58 +00002685
Ted Kremenekfb480492010-01-13 21:46:36 +00002686//===----------------------------------------------------------------------===//
Douglas Gregor1db19de2010-01-19 21:36:55 +00002687// CXSourceLocation and CXSourceRange Operations.
2688//===----------------------------------------------------------------------===//
2689
Douglas Gregorb9790342010-01-22 21:44:22 +00002690extern "C" {
2691CXSourceLocation clang_getNullLocation() {
Douglas Gregor5352ac02010-01-28 00:27:43 +00002692 CXSourceLocation Result = { { 0, 0 }, 0 };
Douglas Gregorb9790342010-01-22 21:44:22 +00002693 return Result;
2694}
2695
2696unsigned clang_equalLocations(CXSourceLocation loc1, CXSourceLocation loc2) {
Daniel Dunbar90a6b9e2010-01-30 23:58:27 +00002697 return (loc1.ptr_data[0] == loc2.ptr_data[0] &&
2698 loc1.ptr_data[1] == loc2.ptr_data[1] &&
2699 loc1.int_data == loc2.int_data);
Douglas Gregorb9790342010-01-22 21:44:22 +00002700}
2701
2702CXSourceLocation clang_getLocation(CXTranslationUnit tu,
2703 CXFile file,
2704 unsigned line,
2705 unsigned column) {
Douglas Gregor42748ec2010-04-30 19:45:53 +00002706 if (!tu || !file)
Douglas Gregorb9790342010-01-22 21:44:22 +00002707 return clang_getNullLocation();
Douglas Gregor42748ec2010-04-30 19:45:53 +00002708
Douglas Gregor86a4d0d2011-02-03 17:17:35 +00002709 bool Logging = ::getenv("LIBCLANG_LOGGING");
Ted Kremeneka60ed472010-11-16 08:15:36 +00002710 ASTUnit *CXXUnit = static_cast<ASTUnit *>(tu->TUData);
Douglas Gregor86a4d0d2011-02-03 17:17:35 +00002711 const FileEntry *File = static_cast<const FileEntry *>(file);
Douglas Gregorb9790342010-01-22 21:44:22 +00002712 SourceLocation SLoc
Douglas Gregor86a4d0d2011-02-03 17:17:35 +00002713 = CXXUnit->getSourceManager().getLocation(File, line, column);
2714 if (SLoc.isInvalid()) {
2715 if (Logging)
2716 llvm::errs() << "clang_getLocation(\"" << File->getName()
2717 << "\", " << line << ", " << column << ") = invalid\n";
2718 return clang_getNullLocation();
2719 }
2720
2721 if (Logging)
2722 llvm::errs() << "clang_getLocation(\"" << File->getName()
2723 << "\", " << line << ", " << column << ") = "
2724 << SLoc.getRawEncoding() << "\n";
David Chisnall83889a72010-10-15 17:07:39 +00002725
2726 return cxloc::translateSourceLocation(CXXUnit->getASTContext(), SLoc);
2727}
2728
2729CXSourceLocation clang_getLocationForOffset(CXTranslationUnit tu,
2730 CXFile file,
2731 unsigned offset) {
2732 if (!tu || !file)
2733 return clang_getNullLocation();
2734
Ted Kremeneka60ed472010-11-16 08:15:36 +00002735 ASTUnit *CXXUnit = static_cast<ASTUnit *>(tu->TUData);
David Chisnall83889a72010-10-15 17:07:39 +00002736 SourceLocation Start
2737 = CXXUnit->getSourceManager().getLocation(
2738 static_cast<const FileEntry *>(file),
2739 1, 1);
2740 if (Start.isInvalid()) return clang_getNullLocation();
2741
2742 SourceLocation SLoc = Start.getFileLocWithOffset(offset);
2743
2744 if (SLoc.isInvalid()) return clang_getNullLocation();
Ted Kremenekf0e23e82010-02-17 00:41:40 +00002745
Ted Kremenek1a9a0bc2010-06-28 23:54:17 +00002746 return cxloc::translateSourceLocation(CXXUnit->getASTContext(), SLoc);
Douglas Gregorb9790342010-01-22 21:44:22 +00002747}
2748
Douglas Gregor5352ac02010-01-28 00:27:43 +00002749CXSourceRange clang_getNullRange() {
2750 CXSourceRange Result = { { 0, 0 }, 0, 0 };
2751 return Result;
2752}
Daniel Dunbard52864b2010-02-14 10:02:57 +00002753
Douglas Gregor5352ac02010-01-28 00:27:43 +00002754CXSourceRange clang_getRange(CXSourceLocation begin, CXSourceLocation end) {
2755 if (begin.ptr_data[0] != end.ptr_data[0] ||
2756 begin.ptr_data[1] != end.ptr_data[1])
2757 return clang_getNullRange();
Ted Kremenekf0e23e82010-02-17 00:41:40 +00002758
2759 CXSourceRange Result = { { begin.ptr_data[0], begin.ptr_data[1] },
Douglas Gregor5352ac02010-01-28 00:27:43 +00002760 begin.int_data, end.int_data };
Douglas Gregorb9790342010-01-22 21:44:22 +00002761 return Result;
2762}
Ted Kremenek9d5a1652011-03-23 02:16:44 +00002763} // end: extern "C"
Douglas Gregorb9790342010-01-22 21:44:22 +00002764
Ted Kremenek9d5a1652011-03-23 02:16:44 +00002765static void createNullLocation(CXFile *file, unsigned *line,
2766 unsigned *column, unsigned *offset) {
2767 if (file)
2768 *file = 0;
2769 if (line)
2770 *line = 0;
2771 if (column)
2772 *column = 0;
2773 if (offset)
2774 *offset = 0;
2775 return;
2776}
2777
2778extern "C" {
Douglas Gregor46766dc2010-01-26 19:19:08 +00002779void clang_getInstantiationLocation(CXSourceLocation location,
2780 CXFile *file,
2781 unsigned *line,
2782 unsigned *column,
2783 unsigned *offset) {
Douglas Gregor1db19de2010-01-19 21:36:55 +00002784 SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data);
2785
Daniel Dunbarbb4a61a2010-02-14 01:47:36 +00002786 if (!location.ptr_data[0] || Loc.isInvalid()) {
Ted Kremenek9d5a1652011-03-23 02:16:44 +00002787 createNullLocation(file, line, column, offset);
Douglas Gregor46766dc2010-01-26 19:19:08 +00002788 return;
2789 }
2790
Daniel Dunbarbb4a61a2010-02-14 01:47:36 +00002791 const SourceManager &SM =
2792 *static_cast<const SourceManager*>(location.ptr_data[0]);
Douglas Gregor1db19de2010-01-19 21:36:55 +00002793 SourceLocation InstLoc = SM.getInstantiationLoc(Loc);
Douglas Gregor1db19de2010-01-19 21:36:55 +00002794
Ted Kremenek9d5a1652011-03-23 02:16:44 +00002795 // Check that the FileID is invalid on the instantiation location.
2796 // This can manifest in invalid code.
2797 FileID fileID = SM.getFileID(InstLoc);
Douglas Gregore23ac652011-04-20 00:21:03 +00002798 bool Invalid = false;
2799 const SrcMgr::SLocEntry &sloc = SM.getSLocEntry(fileID, &Invalid);
2800 if (!sloc.isFile() || Invalid) {
Ted Kremenek9d5a1652011-03-23 02:16:44 +00002801 createNullLocation(file, line, column, offset);
2802 return;
2803 }
2804
Douglas Gregor1db19de2010-01-19 21:36:55 +00002805 if (file)
Ted Kremenek9d5a1652011-03-23 02:16:44 +00002806 *file = (void *)SM.getFileEntryForSLocEntry(sloc);
Douglas Gregor1db19de2010-01-19 21:36:55 +00002807 if (line)
2808 *line = SM.getInstantiationLineNumber(InstLoc);
2809 if (column)
2810 *column = SM.getInstantiationColumnNumber(InstLoc);
Douglas Gregore69517c2010-01-26 03:07:15 +00002811 if (offset)
Douglas Gregor46766dc2010-01-26 19:19:08 +00002812 *offset = SM.getDecomposedLoc(InstLoc).second;
Douglas Gregore69517c2010-01-26 03:07:15 +00002813}
2814
Douglas Gregora9b06d42010-11-09 06:24:54 +00002815void clang_getSpellingLocation(CXSourceLocation location,
2816 CXFile *file,
2817 unsigned *line,
2818 unsigned *column,
2819 unsigned *offset) {
2820 SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data);
2821
Argyrios Kyrtzidis5adc0512011-05-17 22:09:53 +00002822 if (!location.ptr_data[0] || Loc.isInvalid())
2823 return createNullLocation(file, line, column, offset);
Douglas Gregora9b06d42010-11-09 06:24:54 +00002824
2825 const SourceManager &SM =
2826 *static_cast<const SourceManager*>(location.ptr_data[0]);
2827 SourceLocation SpellLoc = Loc;
2828 if (SpellLoc.isMacroID()) {
2829 SourceLocation SimpleSpellingLoc = SM.getImmediateSpellingLoc(SpellLoc);
2830 if (SimpleSpellingLoc.isFileID() &&
2831 SM.getFileEntryForID(SM.getDecomposedLoc(SimpleSpellingLoc).first))
2832 SpellLoc = SimpleSpellingLoc;
2833 else
2834 SpellLoc = SM.getInstantiationLoc(SpellLoc);
2835 }
2836
2837 std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(SpellLoc);
2838 FileID FID = LocInfo.first;
2839 unsigned FileOffset = LocInfo.second;
2840
Argyrios Kyrtzidis5adc0512011-05-17 22:09:53 +00002841 if (FID.isInvalid())
2842 return createNullLocation(file, line, column, offset);
2843
Douglas Gregora9b06d42010-11-09 06:24:54 +00002844 if (file)
2845 *file = (void *)SM.getFileEntryForID(FID);
2846 if (line)
2847 *line = SM.getLineNumber(FID, FileOffset);
2848 if (column)
2849 *column = SM.getColumnNumber(FID, FileOffset);
2850 if (offset)
2851 *offset = FileOffset;
2852}
2853
Douglas Gregor1db19de2010-01-19 21:36:55 +00002854CXSourceLocation clang_getRangeStart(CXSourceRange range) {
Ted Kremenekf0e23e82010-02-17 00:41:40 +00002855 CXSourceLocation Result = { { range.ptr_data[0], range.ptr_data[1] },
Douglas Gregor5352ac02010-01-28 00:27:43 +00002856 range.begin_int_data };
Douglas Gregor1db19de2010-01-19 21:36:55 +00002857 return Result;
2858}
2859
2860CXSourceLocation clang_getRangeEnd(CXSourceRange range) {
Daniel Dunbarbb4a61a2010-02-14 01:47:36 +00002861 CXSourceLocation Result = { { range.ptr_data[0], range.ptr_data[1] },
Douglas Gregor5352ac02010-01-28 00:27:43 +00002862 range.end_int_data };
Douglas Gregor1db19de2010-01-19 21:36:55 +00002863 return Result;
2864}
2865
Douglas Gregorb9790342010-01-22 21:44:22 +00002866} // end: extern "C"
2867
Douglas Gregor1db19de2010-01-19 21:36:55 +00002868//===----------------------------------------------------------------------===//
Ted Kremenekfb480492010-01-13 21:46:36 +00002869// CXFile Operations.
2870//===----------------------------------------------------------------------===//
2871
2872extern "C" {
Ted Kremenek74844072010-02-17 00:41:20 +00002873CXString clang_getFileName(CXFile SFile) {
Douglas Gregor98258af2010-01-18 22:46:11 +00002874 if (!SFile)
Ted Kremeneka60ed472010-11-16 08:15:36 +00002875 return createCXString((const char*)NULL);
Ted Kremenekf0e23e82010-02-17 00:41:40 +00002876
Steve Naroff88145032009-10-27 14:35:18 +00002877 FileEntry *FEnt = static_cast<FileEntry *>(SFile);
Ted Kremenek74844072010-02-17 00:41:20 +00002878 return createCXString(FEnt->getName());
Steve Naroff88145032009-10-27 14:35:18 +00002879}
2880
2881time_t clang_getFileTime(CXFile SFile) {
Douglas Gregor98258af2010-01-18 22:46:11 +00002882 if (!SFile)
2883 return 0;
Ted Kremenekf0e23e82010-02-17 00:41:40 +00002884
Steve Naroff88145032009-10-27 14:35:18 +00002885 FileEntry *FEnt = static_cast<FileEntry *>(SFile);
2886 return FEnt->getModificationTime();
Steve Naroffee9405e2009-09-25 21:45:39 +00002887}
Ted Kremenekf0e23e82010-02-17 00:41:40 +00002888
Douglas Gregorb9790342010-01-22 21:44:22 +00002889CXFile clang_getFile(CXTranslationUnit tu, const char *file_name) {
2890 if (!tu)
2891 return 0;
Ted Kremenekf0e23e82010-02-17 00:41:40 +00002892
Ted Kremeneka60ed472010-11-16 08:15:36 +00002893 ASTUnit *CXXUnit = static_cast<ASTUnit *>(tu->TUData);
Ted Kremenekf0e23e82010-02-17 00:41:40 +00002894
Douglas Gregorb9790342010-01-22 21:44:22 +00002895 FileManager &FMgr = CXXUnit->getFileManager();
Chris Lattner39b49bc2010-11-23 08:35:12 +00002896 return const_cast<FileEntry *>(FMgr.getFile(file_name));
Douglas Gregorb9790342010-01-22 21:44:22 +00002897}
Ted Kremenekf0e23e82010-02-17 00:41:40 +00002898
Douglas Gregordd3e5542011-05-04 00:14:37 +00002899unsigned clang_isFileMultipleIncludeGuarded(CXTranslationUnit tu, CXFile file) {
2900 if (!tu || !file)
2901 return 0;
2902
2903 ASTUnit *CXXUnit = static_cast<ASTUnit *>(tu->TUData);
2904 FileEntry *FEnt = static_cast<FileEntry *>(file);
2905 return CXXUnit->getPreprocessor().getHeaderSearchInfo()
2906 .isFileMultipleIncludeGuarded(FEnt);
2907}
2908
Ted Kremenekfb480492010-01-13 21:46:36 +00002909} // end: extern "C"
Steve Naroffee9405e2009-09-25 21:45:39 +00002910
Ted Kremenekfb480492010-01-13 21:46:36 +00002911//===----------------------------------------------------------------------===//
2912// CXCursor Operations.
2913//===----------------------------------------------------------------------===//
2914
Ted Kremenekfb480492010-01-13 21:46:36 +00002915static Decl *getDeclFromExpr(Stmt *E) {
Douglas Gregordb1314e2010-10-01 21:11:22 +00002916 if (CastExpr *CE = dyn_cast<CastExpr>(E))
2917 return getDeclFromExpr(CE->getSubExpr());
2918
Ted Kremenekfb480492010-01-13 21:46:36 +00002919 if (DeclRefExpr *RefExpr = dyn_cast<DeclRefExpr>(E))
2920 return RefExpr->getDecl();
Douglas Gregor38f28c12010-10-22 22:24:08 +00002921 if (BlockDeclRefExpr *RefExpr = dyn_cast<BlockDeclRefExpr>(E))
2922 return RefExpr->getDecl();
Ted Kremenekfb480492010-01-13 21:46:36 +00002923 if (MemberExpr *ME = dyn_cast<MemberExpr>(E))
2924 return ME->getMemberDecl();
2925 if (ObjCIvarRefExpr *RE = dyn_cast<ObjCIvarRefExpr>(E))
2926 return RE->getDecl();
Douglas Gregordb1314e2010-10-01 21:11:22 +00002927 if (ObjCPropertyRefExpr *PRE = dyn_cast<ObjCPropertyRefExpr>(E))
John McCall12f78a62010-12-02 01:19:52 +00002928 return PRE->isExplicitProperty() ? PRE->getExplicitProperty() : 0;
Douglas Gregordb1314e2010-10-01 21:11:22 +00002929
Ted Kremenekfb480492010-01-13 21:46:36 +00002930 if (CallExpr *CE = dyn_cast<CallExpr>(E))
2931 return getDeclFromExpr(CE->getCallee());
Douglas Gregor93798e22010-11-05 21:11:19 +00002932 if (CXXConstructExpr *CE = llvm::dyn_cast<CXXConstructExpr>(E))
2933 if (!CE->isElidable())
2934 return CE->getConstructor();
Ted Kremenekfb480492010-01-13 21:46:36 +00002935 if (ObjCMessageExpr *OME = dyn_cast<ObjCMessageExpr>(E))
2936 return OME->getMethodDecl();
Ted Kremenekf0e23e82010-02-17 00:41:40 +00002937
Douglas Gregordb1314e2010-10-01 21:11:22 +00002938 if (ObjCProtocolExpr *PE = dyn_cast<ObjCProtocolExpr>(E))
2939 return PE->getProtocol();
Douglas Gregorc7793c72011-01-15 01:15:58 +00002940 if (SubstNonTypeTemplateParmPackExpr *NTTP
2941 = dyn_cast<SubstNonTypeTemplateParmPackExpr>(E))
2942 return NTTP->getParameterPack();
Douglas Gregor94d96292011-01-19 20:34:17 +00002943 if (SizeOfPackExpr *SizeOfPack = dyn_cast<SizeOfPackExpr>(E))
2944 if (isa<NonTypeTemplateParmDecl>(SizeOfPack->getPack()) ||
2945 isa<ParmVarDecl>(SizeOfPack->getPack()))
2946 return SizeOfPack->getPack();
Douglas Gregordb1314e2010-10-01 21:11:22 +00002947
Ted Kremenekfb480492010-01-13 21:46:36 +00002948 return 0;
2949}
2950
Daniel Dunbarc29f4c32010-02-02 05:00:22 +00002951static SourceLocation getLocationFromExpr(Expr *E) {
2952 if (ObjCMessageExpr *Msg = dyn_cast<ObjCMessageExpr>(E))
2953 return /*FIXME:*/Msg->getLeftLoc();
2954 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
2955 return DRE->getLocation();
Douglas Gregor38f28c12010-10-22 22:24:08 +00002956 if (BlockDeclRefExpr *RefExpr = dyn_cast<BlockDeclRefExpr>(E))
2957 return RefExpr->getLocation();
Daniel Dunbarc29f4c32010-02-02 05:00:22 +00002958 if (MemberExpr *Member = dyn_cast<MemberExpr>(E))
2959 return Member->getMemberLoc();
2960 if (ObjCIvarRefExpr *Ivar = dyn_cast<ObjCIvarRefExpr>(E))
2961 return Ivar->getLocation();
Douglas Gregor94d96292011-01-19 20:34:17 +00002962 if (SizeOfPackExpr *SizeOfPack = dyn_cast<SizeOfPackExpr>(E))
2963 return SizeOfPack->getPackLoc();
2964
Daniel Dunbarc29f4c32010-02-02 05:00:22 +00002965 return E->getLocStart();
2966}
2967
Ted Kremenekfb480492010-01-13 21:46:36 +00002968extern "C" {
Ted Kremenekf0e23e82010-02-17 00:41:40 +00002969
2970unsigned clang_visitChildren(CXCursor parent,
Douglas Gregorb1373d02010-01-20 20:59:29 +00002971 CXCursorVisitor visitor,
2972 CXClientData client_data) {
Ted Kremeneka60ed472010-11-16 08:15:36 +00002973 CursorVisitor CursorVis(getCursorTU(parent), visitor, client_data,
Douglas Gregor04a9eb32011-03-16 23:23:30 +00002974 getCursorASTUnit(parent)->getMaxPCHLevel(),
2975 false);
Douglas Gregorb1373d02010-01-20 20:59:29 +00002976 return CursorVis.VisitChildren(parent);
2977}
2978
David Chisnall3387c652010-11-03 14:12:26 +00002979#ifndef __has_feature
2980#define __has_feature(x) 0
2981#endif
2982#if __has_feature(blocks)
2983typedef enum CXChildVisitResult
2984 (^CXCursorVisitorBlock)(CXCursor cursor, CXCursor parent);
2985
2986static enum CXChildVisitResult visitWithBlock(CXCursor cursor, CXCursor parent,
2987 CXClientData client_data) {
2988 CXCursorVisitorBlock block = (CXCursorVisitorBlock)client_data;
2989 return block(cursor, parent);
2990}
2991#else
2992// If we are compiled with a compiler that doesn't have native blocks support,
2993// define and call the block manually, so the
2994typedef struct _CXChildVisitResult
2995{
2996 void *isa;
2997 int flags;
2998 int reserved;
Daniel Dunbar9e1ebdd2010-11-05 07:19:21 +00002999 enum CXChildVisitResult(*invoke)(struct _CXChildVisitResult*, CXCursor,
3000 CXCursor);
David Chisnall3387c652010-11-03 14:12:26 +00003001} *CXCursorVisitorBlock;
3002
3003static enum CXChildVisitResult visitWithBlock(CXCursor cursor, CXCursor parent,
3004 CXClientData client_data) {
3005 CXCursorVisitorBlock block = (CXCursorVisitorBlock)client_data;
3006 return block->invoke(block, cursor, parent);
3007}
3008#endif
3009
3010
Daniel Dunbar9e1ebdd2010-11-05 07:19:21 +00003011unsigned clang_visitChildrenWithBlock(CXCursor parent,
3012 CXCursorVisitorBlock block) {
David Chisnall3387c652010-11-03 14:12:26 +00003013 return clang_visitChildren(parent, visitWithBlock, block);
3014}
3015
Douglas Gregor78205d42010-01-20 21:45:58 +00003016static CXString getDeclSpelling(Decl *D) {
3017 NamedDecl *ND = dyn_cast_or_null<NamedDecl>(D);
Douglas Gregore3c60a72010-11-17 00:13:31 +00003018 if (!ND) {
3019 if (ObjCPropertyImplDecl *PropImpl =llvm::dyn_cast<ObjCPropertyImplDecl>(D))
3020 if (ObjCPropertyDecl *Property = PropImpl->getPropertyDecl())
3021 return createCXString(Property->getIdentifier()->getName());
3022
Ted Kremenekee4db4f2010-02-17 00:41:08 +00003023 return createCXString("");
Douglas Gregore3c60a72010-11-17 00:13:31 +00003024 }
3025
Douglas Gregor78205d42010-01-20 21:45:58 +00003026 if (ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(ND))
Ted Kremenekee4db4f2010-02-17 00:41:08 +00003027 return createCXString(OMD->getSelector().getAsString());
Ted Kremenekf0e23e82010-02-17 00:41:40 +00003028
Douglas Gregor78205d42010-01-20 21:45:58 +00003029 if (ObjCCategoryImplDecl *CIMP = dyn_cast<ObjCCategoryImplDecl>(ND))
3030 // No, this isn't the same as the code below. getIdentifier() is non-virtual
3031 // and returns different names. NamedDecl returns the class name and
3032 // ObjCCategoryImplDecl returns the category name.
Ted Kremenekee4db4f2010-02-17 00:41:08 +00003033 return createCXString(CIMP->getIdentifier()->getNameStart());
Ted Kremenekf0e23e82010-02-17 00:41:40 +00003034
Douglas Gregor0a35bce2010-09-01 03:07:18 +00003035 if (isa<UsingDirectiveDecl>(D))
3036 return createCXString("");
3037
Ted Kremenek50aa6ac2010-05-19 21:51:10 +00003038 llvm::SmallString<1024> S;
3039 llvm::raw_svector_ostream os(S);
3040 ND->printName(os);
3041
3042 return createCXString(os.str());
Douglas Gregor78205d42010-01-20 21:45:58 +00003043}
Ted Kremenekf0e23e82010-02-17 00:41:40 +00003044
Daniel Dunbar9ebfa312009-12-01 03:14:51 +00003045CXString clang_getCursorSpelling(CXCursor C) {
Douglas Gregor7eaa8ae2010-01-20 00:23:15 +00003046 if (clang_isTranslationUnit(C.kind))
Ted Kremeneka60ed472010-11-16 08:15:36 +00003047 return clang_getTranslationUnitSpelling(
3048 static_cast<CXTranslationUnit>(C.data[2]));
Douglas Gregor7eaa8ae2010-01-20 00:23:15 +00003049
Steve Narofff334b4e2009-09-02 18:26:48 +00003050 if (clang_isReference(C.kind)) {
3051 switch (C.kind) {
Daniel Dunbaracca7252009-11-30 20:42:49 +00003052 case CXCursor_ObjCSuperClassRef: {
Douglas Gregor2e331b92010-01-16 14:00:32 +00003053 ObjCInterfaceDecl *Super = getCursorObjCSuperClassRef(C).first;
Ted Kremenekee4db4f2010-02-17 00:41:08 +00003054 return createCXString(Super->getIdentifier()->getNameStart());
Daniel Dunbaracca7252009-11-30 20:42:49 +00003055 }
3056 case CXCursor_ObjCClassRef: {
Douglas Gregor1adb0822010-01-16 17:14:40 +00003057 ObjCInterfaceDecl *Class = getCursorObjCClassRef(C).first;
Ted Kremenekee4db4f2010-02-17 00:41:08 +00003058 return createCXString(Class->getIdentifier()->getNameStart());
Daniel Dunbaracca7252009-11-30 20:42:49 +00003059 }
3060 case CXCursor_ObjCProtocolRef: {
Douglas Gregor78db0cd2010-01-16 15:44:18 +00003061 ObjCProtocolDecl *OID = getCursorObjCProtocolRef(C).first;
Douglas Gregorf46034a2010-01-18 23:41:10 +00003062 assert(OID && "getCursorSpelling(): Missing protocol decl");
Ted Kremenekee4db4f2010-02-17 00:41:08 +00003063 return createCXString(OID->getIdentifier()->getNameStart());
Daniel Dunbaracca7252009-11-30 20:42:49 +00003064 }
Ted Kremenek3064ef92010-08-27 21:34:58 +00003065 case CXCursor_CXXBaseSpecifier: {
3066 CXXBaseSpecifier *B = getCursorCXXBaseSpecifier(C);
3067 return createCXString(B->getType().getAsString());
3068 }
Douglas Gregor7d0d40e2010-01-21 16:28:34 +00003069 case CXCursor_TypeRef: {
3070 TypeDecl *Type = getCursorTypeRef(C).first;
3071 assert(Type && "Missing type decl");
3072
Ted Kremenekee4db4f2010-02-17 00:41:08 +00003073 return createCXString(getCursorContext(C).getTypeDeclType(Type).
3074 getAsString());
Douglas Gregor7d0d40e2010-01-21 16:28:34 +00003075 }
Douglas Gregor0b36e612010-08-31 20:37:03 +00003076 case CXCursor_TemplateRef: {
3077 TemplateDecl *Template = getCursorTemplateRef(C).first;
Douglas Gregor69319002010-08-31 23:48:11 +00003078 assert(Template && "Missing template decl");
Douglas Gregor0b36e612010-08-31 20:37:03 +00003079
3080 return createCXString(Template->getNameAsString());
3081 }
Douglas Gregor69319002010-08-31 23:48:11 +00003082
3083 case CXCursor_NamespaceRef: {
3084 NamedDecl *NS = getCursorNamespaceRef(C).first;
3085 assert(NS && "Missing namespace decl");
3086
3087 return createCXString(NS->getNameAsString());
3088 }
Douglas Gregor7d0d40e2010-01-21 16:28:34 +00003089
Douglas Gregora67e03f2010-09-09 21:42:20 +00003090 case CXCursor_MemberRef: {
3091 FieldDecl *Field = getCursorMemberRef(C).first;
3092 assert(Field && "Missing member decl");
3093
3094 return createCXString(Field->getNameAsString());
3095 }
3096
Douglas Gregor36897b02010-09-10 00:22:18 +00003097 case CXCursor_LabelRef: {
3098 LabelStmt *Label = getCursorLabelRef(C).first;
3099 assert(Label && "Missing label");
3100
Chris Lattnerad8dcf42011-02-17 07:39:24 +00003101 return createCXString(Label->getName());
Douglas Gregor36897b02010-09-10 00:22:18 +00003102 }
3103
Douglas Gregor1f60d9e2010-09-13 22:52:57 +00003104 case CXCursor_OverloadedDeclRef: {
3105 OverloadedDeclRefStorage Storage = getCursorOverloadedDeclRef(C).first;
3106 if (Decl *D = Storage.dyn_cast<Decl *>()) {
3107 if (NamedDecl *ND = dyn_cast<NamedDecl>(D))
3108 return createCXString(ND->getNameAsString());
3109 return createCXString("");
3110 }
3111 if (OverloadExpr *E = Storage.dyn_cast<OverloadExpr *>())
3112 return createCXString(E->getName().getAsString());
3113 OverloadedTemplateStorage *Ovl
3114 = Storage.get<OverloadedTemplateStorage*>();
3115 if (Ovl->size() == 0)
3116 return createCXString("");
3117 return createCXString((*Ovl->begin())->getNameAsString());
3118 }
3119
Daniel Dunbaracca7252009-11-30 20:42:49 +00003120 default:
Ted Kremenekee4db4f2010-02-17 00:41:08 +00003121 return createCXString("<not implemented>");
Steve Narofff334b4e2009-09-02 18:26:48 +00003122 }
3123 }
Douglas Gregor97b98722010-01-19 23:20:36 +00003124
3125 if (clang_isExpression(C.kind)) {
3126 Decl *D = getDeclFromExpr(getCursorExpr(C));
3127 if (D)
Douglas Gregor78205d42010-01-20 21:45:58 +00003128 return getDeclSpelling(D);
Ted Kremenekee4db4f2010-02-17 00:41:08 +00003129 return createCXString("");
Douglas Gregor97b98722010-01-19 23:20:36 +00003130 }
3131
Douglas Gregor36897b02010-09-10 00:22:18 +00003132 if (clang_isStatement(C.kind)) {
3133 Stmt *S = getCursorStmt(C);
3134 if (LabelStmt *Label = dyn_cast_or_null<LabelStmt>(S))
Chris Lattnerad8dcf42011-02-17 07:39:24 +00003135 return createCXString(Label->getName());
Douglas Gregor36897b02010-09-10 00:22:18 +00003136
3137 return createCXString("");
3138 }
3139
Douglas Gregor4ae8f292010-03-18 17:52:52 +00003140 if (C.kind == CXCursor_MacroInstantiation)
3141 return createCXString(getCursorMacroInstantiation(C)->getName()
3142 ->getNameStart());
3143
Douglas Gregor572feb22010-03-18 18:04:21 +00003144 if (C.kind == CXCursor_MacroDefinition)
3145 return createCXString(getCursorMacroDefinition(C)->getName()
3146 ->getNameStart());
3147
Douglas Gregorecdcb882010-10-20 22:00:55 +00003148 if (C.kind == CXCursor_InclusionDirective)
3149 return createCXString(getCursorInclusionDirective(C)->getFileName());
3150
Douglas Gregor60cbfac2010-01-25 16:56:17 +00003151 if (clang_isDeclaration(C.kind))
3152 return getDeclSpelling(getCursorDecl(C));
Ted Kremeneke68fff62010-02-17 00:41:32 +00003153
Ted Kremenekee4db4f2010-02-17 00:41:08 +00003154 return createCXString("");
Steve Narofff334b4e2009-09-02 18:26:48 +00003155}
3156
Douglas Gregor358559d2010-10-02 22:49:11 +00003157CXString clang_getCursorDisplayName(CXCursor C) {
3158 if (!clang_isDeclaration(C.kind))
3159 return clang_getCursorSpelling(C);
3160
3161 Decl *D = getCursorDecl(C);
3162 if (!D)
3163 return createCXString("");
3164
3165 PrintingPolicy &Policy = getCursorContext(C).PrintingPolicy;
3166 if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(D))
3167 D = FunTmpl->getTemplatedDecl();
3168
3169 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
3170 llvm::SmallString<64> Str;
3171 llvm::raw_svector_ostream OS(Str);
3172 OS << Function->getNameAsString();
3173 if (Function->getPrimaryTemplate())
3174 OS << "<>";
3175 OS << "(";
3176 for (unsigned I = 0, N = Function->getNumParams(); I != N; ++I) {
3177 if (I)
3178 OS << ", ";
3179 OS << Function->getParamDecl(I)->getType().getAsString(Policy);
3180 }
3181
3182 if (Function->isVariadic()) {
3183 if (Function->getNumParams())
3184 OS << ", ";
3185 OS << "...";
3186 }
3187 OS << ")";
3188 return createCXString(OS.str());
3189 }
3190
3191 if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(D)) {
3192 llvm::SmallString<64> Str;
3193 llvm::raw_svector_ostream OS(Str);
3194 OS << ClassTemplate->getNameAsString();
3195 OS << "<";
3196 TemplateParameterList *Params = ClassTemplate->getTemplateParameters();
3197 for (unsigned I = 0, N = Params->size(); I != N; ++I) {
3198 if (I)
3199 OS << ", ";
3200
3201 NamedDecl *Param = Params->getParam(I);
3202 if (Param->getIdentifier()) {
3203 OS << Param->getIdentifier()->getName();
3204 continue;
3205 }
3206
3207 // There is no parameter name, which makes this tricky. Try to come up
3208 // with something useful that isn't too long.
3209 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
3210 OS << (TTP->wasDeclaredWithTypename()? "typename" : "class");
3211 else if (NonTypeTemplateParmDecl *NTTP
3212 = dyn_cast<NonTypeTemplateParmDecl>(Param))
3213 OS << NTTP->getType().getAsString(Policy);
3214 else
3215 OS << "template<...> class";
3216 }
3217
3218 OS << ">";
3219 return createCXString(OS.str());
3220 }
3221
3222 if (ClassTemplateSpecializationDecl *ClassSpec
3223 = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
3224 // If the type was explicitly written, use that.
3225 if (TypeSourceInfo *TSInfo = ClassSpec->getTypeAsWritten())
3226 return createCXString(TSInfo->getType().getAsString(Policy));
3227
3228 llvm::SmallString<64> Str;
3229 llvm::raw_svector_ostream OS(Str);
3230 OS << ClassSpec->getNameAsString();
3231 OS << TemplateSpecializationType::PrintTemplateArgumentList(
Douglas Gregor910f8002010-11-07 23:05:16 +00003232 ClassSpec->getTemplateArgs().data(),
3233 ClassSpec->getTemplateArgs().size(),
Douglas Gregor358559d2010-10-02 22:49:11 +00003234 Policy);
3235 return createCXString(OS.str());
3236 }
3237
3238 return clang_getCursorSpelling(C);
3239}
3240
Ted Kremeneke68fff62010-02-17 00:41:32 +00003241CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) {
Steve Naroff89922f82009-08-31 00:59:03 +00003242 switch (Kind) {
Ted Kremeneke68fff62010-02-17 00:41:32 +00003243 case CXCursor_FunctionDecl:
3244 return createCXString("FunctionDecl");
3245 case CXCursor_TypedefDecl:
3246 return createCXString("TypedefDecl");
3247 case CXCursor_EnumDecl:
3248 return createCXString("EnumDecl");
3249 case CXCursor_EnumConstantDecl:
3250 return createCXString("EnumConstantDecl");
3251 case CXCursor_StructDecl:
3252 return createCXString("StructDecl");
3253 case CXCursor_UnionDecl:
3254 return createCXString("UnionDecl");
3255 case CXCursor_ClassDecl:
3256 return createCXString("ClassDecl");
3257 case CXCursor_FieldDecl:
3258 return createCXString("FieldDecl");
3259 case CXCursor_VarDecl:
3260 return createCXString("VarDecl");
3261 case CXCursor_ParmDecl:
3262 return createCXString("ParmDecl");
3263 case CXCursor_ObjCInterfaceDecl:
3264 return createCXString("ObjCInterfaceDecl");
3265 case CXCursor_ObjCCategoryDecl:
3266 return createCXString("ObjCCategoryDecl");
3267 case CXCursor_ObjCProtocolDecl:
3268 return createCXString("ObjCProtocolDecl");
3269 case CXCursor_ObjCPropertyDecl:
3270 return createCXString("ObjCPropertyDecl");
3271 case CXCursor_ObjCIvarDecl:
3272 return createCXString("ObjCIvarDecl");
3273 case CXCursor_ObjCInstanceMethodDecl:
3274 return createCXString("ObjCInstanceMethodDecl");
3275 case CXCursor_ObjCClassMethodDecl:
3276 return createCXString("ObjCClassMethodDecl");
3277 case CXCursor_ObjCImplementationDecl:
3278 return createCXString("ObjCImplementationDecl");
3279 case CXCursor_ObjCCategoryImplDecl:
3280 return createCXString("ObjCCategoryImplDecl");
Ted Kremenek8bd5a692010-04-13 23:39:06 +00003281 case CXCursor_CXXMethod:
3282 return createCXString("CXXMethod");
Ted Kremeneke68fff62010-02-17 00:41:32 +00003283 case CXCursor_UnexposedDecl:
3284 return createCXString("UnexposedDecl");
3285 case CXCursor_ObjCSuperClassRef:
3286 return createCXString("ObjCSuperClassRef");
3287 case CXCursor_ObjCProtocolRef:
3288 return createCXString("ObjCProtocolRef");
3289 case CXCursor_ObjCClassRef:
3290 return createCXString("ObjCClassRef");
3291 case CXCursor_TypeRef:
3292 return createCXString("TypeRef");
Douglas Gregor0b36e612010-08-31 20:37:03 +00003293 case CXCursor_TemplateRef:
3294 return createCXString("TemplateRef");
Douglas Gregor69319002010-08-31 23:48:11 +00003295 case CXCursor_NamespaceRef:
3296 return createCXString("NamespaceRef");
Douglas Gregora67e03f2010-09-09 21:42:20 +00003297 case CXCursor_MemberRef:
3298 return createCXString("MemberRef");
Douglas Gregor36897b02010-09-10 00:22:18 +00003299 case CXCursor_LabelRef:
3300 return createCXString("LabelRef");
Douglas Gregor1f60d9e2010-09-13 22:52:57 +00003301 case CXCursor_OverloadedDeclRef:
3302 return createCXString("OverloadedDeclRef");
Ted Kremeneke68fff62010-02-17 00:41:32 +00003303 case CXCursor_UnexposedExpr:
3304 return createCXString("UnexposedExpr");
Ted Kremenek1ee6cad2010-04-11 21:47:37 +00003305 case CXCursor_BlockExpr:
3306 return createCXString("BlockExpr");
Ted Kremeneke68fff62010-02-17 00:41:32 +00003307 case CXCursor_DeclRefExpr:
3308 return createCXString("DeclRefExpr");
3309 case CXCursor_MemberRefExpr:
3310 return createCXString("MemberRefExpr");
3311 case CXCursor_CallExpr:
3312 return createCXString("CallExpr");
3313 case CXCursor_ObjCMessageExpr:
3314 return createCXString("ObjCMessageExpr");
3315 case CXCursor_UnexposedStmt:
3316 return createCXString("UnexposedStmt");
Douglas Gregor36897b02010-09-10 00:22:18 +00003317 case CXCursor_LabelStmt:
3318 return createCXString("LabelStmt");
Ted Kremeneke68fff62010-02-17 00:41:32 +00003319 case CXCursor_InvalidFile:
3320 return createCXString("InvalidFile");
Ted Kremenek292db642010-03-19 20:39:05 +00003321 case CXCursor_InvalidCode:
3322 return createCXString("InvalidCode");
Ted Kremeneke68fff62010-02-17 00:41:32 +00003323 case CXCursor_NoDeclFound:
3324 return createCXString("NoDeclFound");
3325 case CXCursor_NotImplemented:
3326 return createCXString("NotImplemented");
3327 case CXCursor_TranslationUnit:
3328 return createCXString("TranslationUnit");
Ted Kremeneke77f4432010-02-18 03:09:07 +00003329 case CXCursor_UnexposedAttr:
3330 return createCXString("UnexposedAttr");
3331 case CXCursor_IBActionAttr:
3332 return createCXString("attribute(ibaction)");
Douglas Gregor9f1e3ff2010-03-18 00:42:48 +00003333 case CXCursor_IBOutletAttr:
3334 return createCXString("attribute(iboutlet)");
Ted Kremenek857e9182010-05-19 17:38:06 +00003335 case CXCursor_IBOutletCollectionAttr:
3336 return createCXString("attribute(iboutletcollection)");
Douglas Gregor9f1e3ff2010-03-18 00:42:48 +00003337 case CXCursor_PreprocessingDirective:
3338 return createCXString("preprocessing directive");
Douglas Gregor572feb22010-03-18 18:04:21 +00003339 case CXCursor_MacroDefinition:
3340 return createCXString("macro definition");
Douglas Gregor48072312010-03-18 15:23:44 +00003341 case CXCursor_MacroInstantiation:
3342 return createCXString("macro instantiation");
Douglas Gregorecdcb882010-10-20 22:00:55 +00003343 case CXCursor_InclusionDirective:
3344 return createCXString("inclusion directive");
Ted Kremenek8f06e0e2010-05-06 23:38:21 +00003345 case CXCursor_Namespace:
3346 return createCXString("Namespace");
Ted Kremeneka0536d82010-05-07 01:04:29 +00003347 case CXCursor_LinkageSpec:
3348 return createCXString("LinkageSpec");
Ted Kremenek3064ef92010-08-27 21:34:58 +00003349 case CXCursor_CXXBaseSpecifier:
3350 return createCXString("C++ base class specifier");
Douglas Gregor01829d32010-08-31 14:41:23 +00003351 case CXCursor_Constructor:
3352 return createCXString("CXXConstructor");
3353 case CXCursor_Destructor:
3354 return createCXString("CXXDestructor");
3355 case CXCursor_ConversionFunction:
3356 return createCXString("CXXConversion");
Douglas Gregorfe72e9c2010-08-31 17:01:39 +00003357 case CXCursor_TemplateTypeParameter:
3358 return createCXString("TemplateTypeParameter");
3359 case CXCursor_NonTypeTemplateParameter:
3360 return createCXString("NonTypeTemplateParameter");
3361 case CXCursor_TemplateTemplateParameter:
3362 return createCXString("TemplateTemplateParameter");
3363 case CXCursor_FunctionTemplate:
3364 return createCXString("FunctionTemplate");
Douglas Gregor39d6f072010-08-31 19:02:00 +00003365 case CXCursor_ClassTemplate:
3366 return createCXString("ClassTemplate");
Douglas Gregor74dbe642010-08-31 19:31:58 +00003367 case CXCursor_ClassTemplatePartialSpecialization:
3368 return createCXString("ClassTemplatePartialSpecialization");
Douglas Gregor69319002010-08-31 23:48:11 +00003369 case CXCursor_NamespaceAlias:
3370 return createCXString("NamespaceAlias");
Douglas Gregor0a35bce2010-09-01 03:07:18 +00003371 case CXCursor_UsingDirective:
3372 return createCXString("UsingDirective");
Douglas Gregor7e242562010-09-01 19:52:22 +00003373 case CXCursor_UsingDeclaration:
3374 return createCXString("UsingDeclaration");
Richard Smith162e1c12011-04-15 14:24:37 +00003375 case CXCursor_TypeAliasDecl:
3376 return createCXString("TypeAliasDecl");
Steve Naroff89922f82009-08-31 00:59:03 +00003377 }
Ted Kremeneke68fff62010-02-17 00:41:32 +00003378
Ted Kremenekdeb06bd2010-01-16 02:02:09 +00003379 llvm_unreachable("Unhandled CXCursorKind");
Ted Kremeneka60ed472010-11-16 08:15:36 +00003380 return createCXString((const char*) 0);
Steve Naroff600866c2009-08-27 19:51:58 +00003381}
Steve Naroff89922f82009-08-31 00:59:03 +00003382
Ted Kremeneke68fff62010-02-17 00:41:32 +00003383enum CXChildVisitResult GetCursorVisitor(CXCursor cursor,
3384 CXCursor parent,
Douglas Gregor33e9abd2010-01-22 19:49:59 +00003385 CXClientData client_data) {
3386 CXCursor *BestCursor = static_cast<CXCursor *>(client_data);
Douglas Gregor93798e22010-11-05 21:11:19 +00003387
3388 // If our current best cursor is the construction of a temporary object,
3389 // don't replace that cursor with a type reference, because we want
3390 // clang_getCursor() to point at the constructor.
3391 if (clang_isExpression(BestCursor->kind) &&
3392 isa<CXXTemporaryObjectExpr>(getCursorExpr(*BestCursor)) &&
3393 cursor.kind == CXCursor_TypeRef)
3394 return CXChildVisit_Recurse;
3395
Douglas Gregor85fe1562010-12-10 07:23:11 +00003396 // Don't override a preprocessing cursor with another preprocessing
3397 // cursor; we want the outermost preprocessing cursor.
3398 if (clang_isPreprocessing(cursor.kind) &&
3399 clang_isPreprocessing(BestCursor->kind))
3400 return CXChildVisit_Recurse;
3401
Douglas Gregor33e9abd2010-01-22 19:49:59 +00003402 *BestCursor = cursor;
3403 return CXChildVisit_Recurse;
3404}
Ted Kremeneke68fff62010-02-17 00:41:32 +00003405
Douglas Gregorb9790342010-01-22 21:44:22 +00003406CXCursor clang_getCursor(CXTranslationUnit TU, CXSourceLocation Loc) {
3407 if (!TU)
Ted Kremenekf4629892010-01-14 01:51:23 +00003408 return clang_getNullCursor();
Ted Kremeneke68fff62010-02-17 00:41:32 +00003409
Ted Kremeneka60ed472010-11-16 08:15:36 +00003410 ASTUnit *CXXUnit = static_cast<ASTUnit *>(TU->TUData);
Douglas Gregorbdf60622010-03-05 21:16:25 +00003411 ASTUnit::ConcurrencyCheck Check(*CXXUnit);
3412
Douglas Gregora8e5c5b2010-07-22 20:22:31 +00003413 // Translate the given source location to make it point at the beginning of
3414 // the token under the cursor.
Ted Kremeneka297de22010-01-25 22:34:44 +00003415 SourceLocation SLoc = cxloc::translateSourceLocation(Loc);
Ted Kremeneka629ea42010-07-29 00:52:07 +00003416
3417 // Guard against an invalid SourceLocation, or we may assert in one
3418 // of the following calls.
3419 if (SLoc.isInvalid())
3420 return clang_getNullCursor();
3421
Douglas Gregor40749ee2010-11-03 00:35:38 +00003422 bool Logging = getenv("LIBCLANG_LOGGING");
Douglas Gregora8e5c5b2010-07-22 20:22:31 +00003423 SLoc = Lexer::GetBeginningOfToken(SLoc, CXXUnit->getSourceManager(),
3424 CXXUnit->getASTContext().getLangOptions());
3425
Douglas Gregor33e9abd2010-01-22 19:49:59 +00003426 CXCursor Result = MakeCXCursorInvalid(CXCursor_NoDeclFound);
3427 if (SLoc.isValid()) {
Douglas Gregor33e9abd2010-01-22 19:49:59 +00003428 // FIXME: Would be great to have a "hint" cursor, then walk from that
3429 // hint cursor upward until we find a cursor whose source range encloses
3430 // the region of interest, rather than starting from the translation unit.
Ted Kremeneka60ed472010-11-16 08:15:36 +00003431 CXCursor Parent = clang_getTranslationUnitCursor(TU);
3432 CursorVisitor CursorVis(TU, GetCursorVisitor, &Result,
Douglas Gregor04a9eb32011-03-16 23:23:30 +00003433 Decl::MaxPCHLevel, true, SourceLocation(SLoc));
Douglas Gregor33e9abd2010-01-22 19:49:59 +00003434 CursorVis.VisitChildren(Parent);
Steve Naroff77128dd2009-09-15 20:25:34 +00003435 }
Douglas Gregor40749ee2010-11-03 00:35:38 +00003436
3437 if (Logging) {
3438 CXFile SearchFile;
3439 unsigned SearchLine, SearchColumn;
3440 CXFile ResultFile;
3441 unsigned ResultLine, ResultColumn;
Douglas Gregor66537982010-11-17 17:14:07 +00003442 CXString SearchFileName, ResultFileName, KindSpelling, USR;
3443 const char *IsDef = clang_isCursorDefinition(Result)? " (Definition)" : "";
Douglas Gregor40749ee2010-11-03 00:35:38 +00003444 CXSourceLocation ResultLoc = clang_getCursorLocation(Result);
3445
3446 clang_getInstantiationLocation(Loc, &SearchFile, &SearchLine, &SearchColumn,
3447 0);
3448 clang_getInstantiationLocation(ResultLoc, &ResultFile, &ResultLine,
3449 &ResultColumn, 0);
3450 SearchFileName = clang_getFileName(SearchFile);
3451 ResultFileName = clang_getFileName(ResultFile);
3452 KindSpelling = clang_getCursorKindSpelling(Result.kind);
Douglas Gregor66537982010-11-17 17:14:07 +00003453 USR = clang_getCursorUSR(Result);
3454 fprintf(stderr, "clang_getCursor(%s:%d:%d) = %s(%s:%d:%d):%s%s\n",
Douglas Gregor40749ee2010-11-03 00:35:38 +00003455 clang_getCString(SearchFileName), SearchLine, SearchColumn,
3456 clang_getCString(KindSpelling),
Douglas Gregor66537982010-11-17 17:14:07 +00003457 clang_getCString(ResultFileName), ResultLine, ResultColumn,
3458 clang_getCString(USR), IsDef);
Douglas Gregor40749ee2010-11-03 00:35:38 +00003459 clang_disposeString(SearchFileName);
3460 clang_disposeString(ResultFileName);
3461 clang_disposeString(KindSpelling);
Douglas Gregor66537982010-11-17 17:14:07 +00003462 clang_disposeString(USR);
Douglas Gregor0aefbd82010-12-10 01:45:00 +00003463
3464 CXCursor Definition = clang_getCursorDefinition(Result);
3465 if (!clang_equalCursors(Definition, clang_getNullCursor())) {
3466 CXSourceLocation DefinitionLoc = clang_getCursorLocation(Definition);
3467 CXString DefinitionKindSpelling
3468 = clang_getCursorKindSpelling(Definition.kind);
3469 CXFile DefinitionFile;
3470 unsigned DefinitionLine, DefinitionColumn;
3471 clang_getInstantiationLocation(DefinitionLoc, &DefinitionFile,
3472 &DefinitionLine, &DefinitionColumn, 0);
3473 CXString DefinitionFileName = clang_getFileName(DefinitionFile);
3474 fprintf(stderr, " -> %s(%s:%d:%d)\n",
3475 clang_getCString(DefinitionKindSpelling),
3476 clang_getCString(DefinitionFileName),
3477 DefinitionLine, DefinitionColumn);
3478 clang_disposeString(DefinitionFileName);
3479 clang_disposeString(DefinitionKindSpelling);
3480 }
Douglas Gregor40749ee2010-11-03 00:35:38 +00003481 }
3482
Ted Kremeneke68fff62010-02-17 00:41:32 +00003483 return Result;
Steve Naroff600866c2009-08-27 19:51:58 +00003484}
3485
Ted Kremenek73885552009-11-17 19:28:59 +00003486CXCursor clang_getNullCursor(void) {
Douglas Gregor5bfb8c12010-01-20 23:34:41 +00003487 return MakeCXCursorInvalid(CXCursor_InvalidFile);
Ted Kremenek73885552009-11-17 19:28:59 +00003488}
3489
3490unsigned clang_equalCursors(CXCursor X, CXCursor Y) {
Douglas Gregor283cae32010-01-15 21:56:13 +00003491 return X == Y;
Ted Kremenek73885552009-11-17 19:28:59 +00003492}
Daniel Dunbar0d7dd222009-11-30 20:42:43 +00003493
Douglas Gregor9ce55842010-11-20 00:09:34 +00003494unsigned clang_hashCursor(CXCursor C) {
3495 unsigned Index = 0;
3496 if (clang_isExpression(C.kind) || clang_isStatement(C.kind))
3497 Index = 1;
3498
3499 return llvm::DenseMapInfo<std::pair<unsigned, void*> >::getHashValue(
3500 std::make_pair(C.kind, C.data[Index]));
3501}
3502
Daniel Dunbar9ebfa312009-12-01 03:14:51 +00003503unsigned clang_isInvalid(enum CXCursorKind K) {
Steve Naroff77128dd2009-09-15 20:25:34 +00003504 return K >= CXCursor_FirstInvalid && K <= CXCursor_LastInvalid;
3505}
3506
Daniel Dunbar9ebfa312009-12-01 03:14:51 +00003507unsigned clang_isDeclaration(enum CXCursorKind K) {
Steve Naroff89922f82009-08-31 00:59:03 +00003508 return K >= CXCursor_FirstDecl && K <= CXCursor_LastDecl;
3509}
Steve Naroff2d4d6292009-08-31 14:26:51 +00003510
Daniel Dunbar9ebfa312009-12-01 03:14:51 +00003511unsigned clang_isReference(enum CXCursorKind K) {
Steve Narofff334b4e2009-09-02 18:26:48 +00003512 return K >= CXCursor_FirstRef && K <= CXCursor_LastRef;
3513}
3514
Douglas Gregor97b98722010-01-19 23:20:36 +00003515unsigned clang_isExpression(enum CXCursorKind K) {
3516 return K >= CXCursor_FirstExpr && K <= CXCursor_LastExpr;
3517}
3518
3519unsigned clang_isStatement(enum CXCursorKind K) {
3520 return K >= CXCursor_FirstStmt && K <= CXCursor_LastStmt;
3521}
3522
Douglas Gregor7eaa8ae2010-01-20 00:23:15 +00003523unsigned clang_isTranslationUnit(enum CXCursorKind K) {
3524 return K == CXCursor_TranslationUnit;
3525}
3526
Douglas Gregor9f1e3ff2010-03-18 00:42:48 +00003527unsigned clang_isPreprocessing(enum CXCursorKind K) {
3528 return K >= CXCursor_FirstPreprocessing && K <= CXCursor_LastPreprocessing;
3529}
3530
Ted Kremenekad6eff62010-03-08 21:17:29 +00003531unsigned clang_isUnexposed(enum CXCursorKind K) {
3532 switch (K) {
3533 case CXCursor_UnexposedDecl:
3534 case CXCursor_UnexposedExpr:
3535 case CXCursor_UnexposedStmt:
3536 case CXCursor_UnexposedAttr:
3537 return true;
3538 default:
3539 return false;
3540 }
3541}
3542
Daniel Dunbar9ebfa312009-12-01 03:14:51 +00003543CXCursorKind clang_getCursorKind(CXCursor C) {
Steve Naroff9efa7672009-09-04 15:44:05 +00003544 return C.kind;
3545}
3546
Douglas Gregor98258af2010-01-18 22:46:11 +00003547CXSourceLocation clang_getCursorLocation(CXCursor C) {
3548 if (clang_isReference(C.kind)) {
Douglas Gregorf46034a2010-01-18 23:41:10 +00003549 switch (C.kind) {
Ted Kremenekf0e23e82010-02-17 00:41:40 +00003550 case CXCursor_ObjCSuperClassRef: {
Douglas Gregorf46034a2010-01-18 23:41:10 +00003551 std::pair<ObjCInterfaceDecl *, SourceLocation> P
3552 = getCursorObjCSuperClassRef(C);
Ted Kremeneka297de22010-01-25 22:34:44 +00003553 return cxloc::translateSourceLocation(P.first->getASTContext(), P.second);
Douglas Gregorf46034a2010-01-18 23:41:10 +00003554 }
3555
Ted Kremenekf0e23e82010-02-17 00:41:40 +00003556 case CXCursor_ObjCProtocolRef: {
Douglas Gregorf46034a2010-01-18 23:41:10 +00003557 std::pair<ObjCProtocolDecl *, SourceLocation> P
3558 = getCursorObjCProtocolRef(C);
Ted Kremeneka297de22010-01-25 22:34:44 +00003559 return cxloc::translateSourceLocation(P.first->getASTContext(), P.second);
Douglas Gregorf46034a2010-01-18 23:41:10 +00003560 }
3561
Ted Kremenekf0e23e82010-02-17 00:41:40 +00003562 case CXCursor_ObjCClassRef: {
Douglas Gregorf46034a2010-01-18 23:41:10 +00003563 std::pair<ObjCInterfaceDecl *, SourceLocation> P
3564 = getCursorObjCClassRef(C);
Ted Kremeneka297de22010-01-25 22:34:44 +00003565 return cxloc::translateSourceLocation(P.first->getASTContext(), P.second);
Douglas Gregorf46034a2010-01-18 23:41:10 +00003566 }
Douglas Gregor7d0d40e2010-01-21 16:28:34 +00003567
Ted Kremenekf0e23e82010-02-17 00:41:40 +00003568 case CXCursor_TypeRef: {
Douglas Gregor7d0d40e2010-01-21 16:28:34 +00003569 std::pair<TypeDecl *, SourceLocation> P = getCursorTypeRef(C);
Ted Kremeneka297de22010-01-25 22:34:44 +00003570 return cxloc::translateSourceLocation(P.first->getASTContext(), P.second);
Douglas Gregor7d0d40e2010-01-21 16:28:34 +00003571 }
Douglas Gregor0b36e612010-08-31 20:37:03 +00003572
3573 case CXCursor_TemplateRef: {
3574 std::pair<TemplateDecl *, SourceLocation> P = getCursorTemplateRef(C);
3575 return cxloc::translateSourceLocation(P.first->getASTContext(), P.second);
3576 }
3577
Douglas Gregor69319002010-08-31 23:48:11 +00003578 case CXCursor_NamespaceRef: {
3579 std::pair<NamedDecl *, SourceLocation> P = getCursorNamespaceRef(C);
3580 return cxloc::translateSourceLocation(P.first->getASTContext(), P.second);
3581 }
3582
Douglas Gregora67e03f2010-09-09 21:42:20 +00003583 case CXCursor_MemberRef: {
3584 std::pair<FieldDecl *, SourceLocation> P = getCursorMemberRef(C);
3585 return cxloc::translateSourceLocation(P.first->getASTContext(), P.second);
3586 }
3587
Ted Kremenek3064ef92010-08-27 21:34:58 +00003588 case CXCursor_CXXBaseSpecifier: {
Douglas Gregor1b0f7af2010-10-02 19:51:13 +00003589 CXXBaseSpecifier *BaseSpec = getCursorCXXBaseSpecifier(C);
3590 if (!BaseSpec)
3591 return clang_getNullLocation();
3592
3593 if (TypeSourceInfo *TSInfo = BaseSpec->getTypeSourceInfo())
3594 return cxloc::translateSourceLocation(getCursorContext(C),
3595 TSInfo->getTypeLoc().getBeginLoc());
3596
3597 return cxloc::translateSourceLocation(getCursorContext(C),
3598 BaseSpec->getSourceRange().getBegin());
Ted Kremenek3064ef92010-08-27 21:34:58 +00003599 }
Ted Kremenekf0e23e82010-02-17 00:41:40 +00003600
Douglas Gregor36897b02010-09-10 00:22:18 +00003601 case CXCursor_LabelRef: {
3602 std::pair<LabelStmt *, SourceLocation> P = getCursorLabelRef(C);
3603 return cxloc::translateSourceLocation(getCursorContext(C), P.second);
3604 }
3605
Douglas Gregor1f60d9e2010-09-13 22:52:57 +00003606 case CXCursor_OverloadedDeclRef:
3607 return cxloc::translateSourceLocation(getCursorContext(C),
3608 getCursorOverloadedDeclRef(C).second);
3609
Douglas Gregorf46034a2010-01-18 23:41:10 +00003610 default:
3611 // FIXME: Need a way to enumerate all non-reference cases.
3612 llvm_unreachable("Missed a reference kind");
3613 }
Douglas Gregor98258af2010-01-18 22:46:11 +00003614 }
Douglas Gregor97b98722010-01-19 23:20:36 +00003615
3616 if (clang_isExpression(C.kind))
Ted Kremenekf0e23e82010-02-17 00:41:40 +00003617 return cxloc::translateSourceLocation(getCursorContext(C),
Douglas Gregor97b98722010-01-19 23:20:36 +00003618 getLocationFromExpr(getCursorExpr(C)));
3619
Douglas Gregor36897b02010-09-10 00:22:18 +00003620 if (clang_isStatement(C.kind))
3621 return cxloc::translateSourceLocation(getCursorContext(C),
3622 getCursorStmt(C)->getLocStart());
3623
Douglas Gregor9f1e3ff2010-03-18 00:42:48 +00003624 if (C.kind == CXCursor_PreprocessingDirective) {
3625 SourceLocation L = cxcursor::getCursorPreprocessingDirective(C).getBegin();
3626 return cxloc::translateSourceLocation(getCursorContext(C), L);
3627 }
Douglas Gregor48072312010-03-18 15:23:44 +00003628
3629 if (C.kind == CXCursor_MacroInstantiation) {
Douglas Gregor4ae8f292010-03-18 17:52:52 +00003630 SourceLocation L
3631 = cxcursor::getCursorMacroInstantiation(C)->getSourceRange().getBegin();
Douglas Gregor48072312010-03-18 15:23:44 +00003632 return cxloc::translateSourceLocation(getCursorContext(C), L);
3633 }
Douglas Gregor572feb22010-03-18 18:04:21 +00003634
3635 if (C.kind == CXCursor_MacroDefinition) {
3636 SourceLocation L = cxcursor::getCursorMacroDefinition(C)->getLocation();
3637 return cxloc::translateSourceLocation(getCursorContext(C), L);
3638 }
Douglas Gregorecdcb882010-10-20 22:00:55 +00003639
3640 if (C.kind == CXCursor_InclusionDirective) {
3641 SourceLocation L
3642 = cxcursor::getCursorInclusionDirective(C)->getSourceRange().getBegin();
3643 return cxloc::translateSourceLocation(getCursorContext(C), L);
3644 }
3645
Ted Kremenek9a700d22010-05-12 06:16:13 +00003646 if (C.kind < CXCursor_FirstDecl || C.kind > CXCursor_LastDecl)
Douglas Gregor5352ac02010-01-28 00:27:43 +00003647 return clang_getNullLocation();
Douglas Gregor98258af2010-01-18 22:46:11 +00003648
Douglas Gregorf46034a2010-01-18 23:41:10 +00003649 Decl *D = getCursorDecl(C);
Douglas Gregorf46034a2010-01-18 23:41:10 +00003650 SourceLocation Loc = D->getLocation();
3651 if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(D))
3652 Loc = Class->getClassLoc();
Ted Kremenek007a7c92010-11-01 23:26:51 +00003653 // FIXME: Multiple variables declared in a single declaration
3654 // currently lack the information needed to correctly determine their
3655 // ranges when accounting for the type-specifier. We use context
3656 // stored in the CXCursor to determine if the VarDecl is in a DeclGroup,
3657 // and if so, whether it is the first decl.
3658 if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
3659 if (!cxcursor::isFirstInDeclGroup(C))
3660 Loc = VD->getLocation();
3661 }
3662
Douglas Gregor2ca54fe2010-03-22 15:53:50 +00003663 return cxloc::translateSourceLocation(getCursorContext(C), Loc);
Douglas Gregor98258af2010-01-18 22:46:11 +00003664}
Douglas Gregora7bde202010-01-19 00:34:46 +00003665
Douglas Gregora8e5c5b2010-07-22 20:22:31 +00003666} // end extern "C"
3667
3668static SourceRange getRawCursorExtent(CXCursor C) {
Douglas Gregora7bde202010-01-19 00:34:46 +00003669 if (clang_isReference(C.kind)) {
3670 switch (C.kind) {
Douglas Gregora8e5c5b2010-07-22 20:22:31 +00003671 case CXCursor_ObjCSuperClassRef:
3672 return getCursorObjCSuperClassRef(C).second;
Ted Kremenekf0e23e82010-02-17 00:41:40 +00003673
Douglas Gregora8e5c5b2010-07-22 20:22:31 +00003674 case CXCursor_ObjCProtocolRef:
3675 return getCursorObjCProtocolRef(C).second;
Ted Kremenekf0e23e82010-02-17 00:41:40 +00003676
Douglas Gregora8e5c5b2010-07-22 20:22:31 +00003677 case CXCursor_ObjCClassRef:
3678 return getCursorObjCClassRef(C).second;
Ted Kremenekf0e23e82010-02-17 00:41:40 +00003679
Douglas Gregora8e5c5b2010-07-22 20:22:31 +00003680 case CXCursor_TypeRef:
3681 return getCursorTypeRef(C).second;
Douglas Gregor0b36e612010-08-31 20:37:03 +00003682
3683 case CXCursor_TemplateRef:
3684 return getCursorTemplateRef(C).second;
3685
Douglas Gregor69319002010-08-31 23:48:11 +00003686 case CXCursor_NamespaceRef:
3687 return getCursorNamespaceRef(C).second;
Douglas Gregora67e03f2010-09-09 21:42:20 +00003688
3689 case CXCursor_MemberRef:
3690 return getCursorMemberRef(C).second;
3691
Ted Kremenek3064ef92010-08-27 21:34:58 +00003692 case CXCursor_CXXBaseSpecifier:
Douglas Gregor1b0f7af2010-10-02 19:51:13 +00003693 return getCursorCXXBaseSpecifier(C)->getSourceRange();
Douglas Gregor7d0d40e2010-01-21 16:28:34 +00003694
Douglas Gregor36897b02010-09-10 00:22:18 +00003695 case CXCursor_LabelRef:
3696 return getCursorLabelRef(C).second;
3697
Douglas Gregor1f60d9e2010-09-13 22:52:57 +00003698 case CXCursor_OverloadedDeclRef:
3699 return getCursorOverloadedDeclRef(C).second;
3700
Douglas Gregora8e5c5b2010-07-22 20:22:31 +00003701 default:
3702 // FIXME: Need a way to enumerate all non-reference cases.
3703 llvm_unreachable("Missed a reference kind");
Douglas Gregora7bde202010-01-19 00:34:46 +00003704 }
3705 }
Douglas Gregor97b98722010-01-19 23:20:36 +00003706
3707 if (clang_isExpression(C.kind))
Douglas Gregora8e5c5b2010-07-22 20:22:31 +00003708 return getCursorExpr(C)->getSourceRange();
Douglas Gregor33e9abd2010-01-22 19:49:59 +00003709
3710 if (clang_isStatement(C.kind))
Douglas Gregora8e5c5b2010-07-22 20:22:31 +00003711 return getCursorStmt(C)->getSourceRange();
Ted Kremenekf0e23e82010-02-17 00:41:40 +00003712
Douglas Gregora8e5c5b2010-07-22 20:22:31 +00003713 if (C.kind == CXCursor_PreprocessingDirective)
3714 return cxcursor::getCursorPreprocessingDirective(C);
Douglas Gregor48072312010-03-18 15:23:44 +00003715
Douglas Gregora8e5c5b2010-07-22 20:22:31 +00003716 if (C.kind == CXCursor_MacroInstantiation)
3717 return cxcursor::getCursorMacroInstantiation(C)->getSourceRange();
Douglas Gregor572feb22010-03-18 18:04:21 +00003718
Douglas Gregora8e5c5b2010-07-22 20:22:31 +00003719 if (C.kind == CXCursor_MacroDefinition)
3720 return cxcursor::getCursorMacroDefinition(C)->getSourceRange();
Douglas Gregorecdcb882010-10-20 22:00:55 +00003721
3722 if (C.kind == CXCursor_InclusionDirective)
3723 return cxcursor::getCursorInclusionDirective(C)->getSourceRange();
3724
Ted Kremenek007a7c92010-11-01 23:26:51 +00003725 if (C.kind >= CXCursor_FirstDecl && C.kind <= CXCursor_LastDecl) {
3726 Decl *D = cxcursor::getCursorDecl(C);
3727 SourceRange R = D->getSourceRange();
3728 // FIXME: Multiple variables declared in a single declaration
3729 // currently lack the information needed to correctly determine their
3730 // ranges when accounting for the type-specifier. We use context
3731 // stored in the CXCursor to determine if the VarDecl is in a DeclGroup,
3732 // and if so, whether it is the first decl.
3733 if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
3734 if (!cxcursor::isFirstInDeclGroup(C))
3735 R.setBegin(VD->getLocation());
3736 }
3737 return R;
3738 }
Douglas Gregor66537982010-11-17 17:14:07 +00003739 return SourceRange();
3740}
3741
3742/// \brief Retrieves the "raw" cursor extent, which is then extended to include
3743/// the decl-specifier-seq for declarations.
3744static SourceRange getFullCursorExtent(CXCursor C, SourceManager &SrcMgr) {
3745 if (C.kind >= CXCursor_FirstDecl && C.kind <= CXCursor_LastDecl) {
3746 Decl *D = cxcursor::getCursorDecl(C);
3747 SourceRange R = D->getSourceRange();
Douglas Gregor66537982010-11-17 17:14:07 +00003748
Douglas Gregor2494dd02011-03-01 01:34:45 +00003749 // Adjust the start of the location for declarations preceded by
3750 // declaration specifiers.
3751 SourceLocation StartLoc;
3752 if (const DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(D)) {
3753 if (TypeSourceInfo *TI = DD->getTypeSourceInfo())
3754 StartLoc = TI->getTypeLoc().getSourceRange().getBegin();
3755 } else if (TypedefDecl *Typedef = dyn_cast<TypedefDecl>(D)) {
3756 if (TypeSourceInfo *TI = Typedef->getTypeSourceInfo())
3757 StartLoc = TI->getTypeLoc().getSourceRange().getBegin();
3758 }
3759
3760 if (StartLoc.isValid() && R.getBegin().isValid() &&
3761 SrcMgr.isBeforeInTranslationUnit(StartLoc, R.getBegin()))
3762 R.setBegin(StartLoc);
3763
3764 // FIXME: Multiple variables declared in a single declaration
3765 // currently lack the information needed to correctly determine their
3766 // ranges when accounting for the type-specifier. We use context
3767 // stored in the CXCursor to determine if the VarDecl is in a DeclGroup,
3768 // and if so, whether it is the first decl.
3769 if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
3770 if (!cxcursor::isFirstInDeclGroup(C))
3771 R.setBegin(VD->getLocation());
Douglas Gregor66537982010-11-17 17:14:07 +00003772 }
3773
3774 return R;
3775 }
3776
3777 return getRawCursorExtent(C);
3778}
Douglas Gregora8e5c5b2010-07-22 20:22:31 +00003779
3780extern "C" {
3781
3782CXSourceRange clang_getCursorExtent(CXCursor C) {
3783 SourceRange R = getRawCursorExtent(C);
3784 if (R.isInvalid())
Douglas Gregor5352ac02010-01-28 00:27:43 +00003785 return clang_getNullRange();
Ted Kremenekf0e23e82010-02-17 00:41:40 +00003786
Douglas Gregora8e5c5b2010-07-22 20:22:31 +00003787 return cxloc::translateSourceRange(getCursorContext(C), R);
Douglas Gregora7bde202010-01-19 00:34:46 +00003788}
Douglas Gregorc5d1e932010-01-19 01:20:04 +00003789
3790CXCursor clang_getCursorReferenced(CXCursor C) {
Douglas Gregorb2cd4872010-01-20 23:57:43 +00003791 if (clang_isInvalid(C.kind))
3792 return clang_getNullCursor();
Ted Kremenekf0e23e82010-02-17 00:41:40 +00003793
Ted Kremeneka60ed472010-11-16 08:15:36 +00003794 CXTranslationUnit tu = getCursorTU(C);
Douglas Gregor1f60d9e2010-09-13 22:52:57 +00003795 if (clang_isDeclaration(C.kind)) {
3796 Decl *D = getCursorDecl(C);
3797 if (UsingDecl *Using = dyn_cast<UsingDecl>(D))
Ted Kremeneka60ed472010-11-16 08:15:36 +00003798 return MakeCursorOverloadedDeclRef(Using, D->getLocation(), tu);
Douglas Gregor1f60d9e2010-09-13 22:52:57 +00003799 if (ObjCClassDecl *Classes = dyn_cast<ObjCClassDecl>(D))
Ted Kremeneka60ed472010-11-16 08:15:36 +00003800 return MakeCursorOverloadedDeclRef(Classes, D->getLocation(), tu);
Douglas Gregor1f60d9e2010-09-13 22:52:57 +00003801 if (ObjCForwardProtocolDecl *Protocols
3802 = dyn_cast<ObjCForwardProtocolDecl>(D))
Ted Kremeneka60ed472010-11-16 08:15:36 +00003803 return MakeCursorOverloadedDeclRef(Protocols, D->getLocation(), tu);
Douglas Gregore3c60a72010-11-17 00:13:31 +00003804 if (ObjCPropertyImplDecl *PropImpl =llvm::dyn_cast<ObjCPropertyImplDecl>(D))
3805 if (ObjCPropertyDecl *Property = PropImpl->getPropertyDecl())
3806 return MakeCXCursor(Property, tu);
3807
Douglas Gregorc5d1e932010-01-19 01:20:04 +00003808 return C;
Douglas Gregor1f60d9e2010-09-13 22:52:57 +00003809 }
3810
Douglas Gregor97b98722010-01-19 23:20:36 +00003811 if (clang_isExpression(C.kind)) {
Douglas Gregor1f60d9e2010-09-13 22:52:57 +00003812 Expr *E = getCursorExpr(C);
3813 Decl *D = getDeclFromExpr(E);
Douglas Gregor97b98722010-01-19 23:20:36 +00003814 if (D)
Ted Kremeneka60ed472010-11-16 08:15:36 +00003815 return MakeCXCursor(D, tu);
Douglas Gregor1f60d9e2010-09-13 22:52:57 +00003816
3817 if (OverloadExpr *Ovl = dyn_cast_or_null<OverloadExpr>(E))
Ted Kremeneka60ed472010-11-16 08:15:36 +00003818 return MakeCursorOverloadedDeclRef(Ovl, tu);
Douglas Gregor1f60d9e2010-09-13 22:52:57 +00003819
Douglas Gregor97b98722010-01-19 23:20:36 +00003820 return clang_getNullCursor();
3821 }
3822
Douglas Gregor36897b02010-09-10 00:22:18 +00003823 if (clang_isStatement(C.kind)) {
3824 Stmt *S = getCursorStmt(C);
3825 if (GotoStmt *Goto = dyn_cast_or_null<GotoStmt>(S))
Ted Kremenek37c2e962011-03-15 23:47:49 +00003826 if (LabelDecl *label = Goto->getLabel())
3827 if (LabelStmt *labelS = label->getStmt())
3828 return MakeCXCursor(labelS, getCursorDecl(C), tu);
Douglas Gregor36897b02010-09-10 00:22:18 +00003829
3830 return clang_getNullCursor();
3831 }
3832
Douglas Gregorbf7efa22010-03-18 18:23:03 +00003833 if (C.kind == CXCursor_MacroInstantiation) {
3834 if (MacroDefinition *Def = getCursorMacroInstantiation(C)->getDefinition())
Ted Kremeneka60ed472010-11-16 08:15:36 +00003835 return MakeMacroDefinitionCursor(Def, tu);
Douglas Gregorbf7efa22010-03-18 18:23:03 +00003836 }
3837
Douglas Gregorc5d1e932010-01-19 01:20:04 +00003838 if (!clang_isReference(C.kind))
3839 return clang_getNullCursor();
Ted Kremenekf0e23e82010-02-17 00:41:40 +00003840
Douglas Gregorc5d1e932010-01-19 01:20:04 +00003841 switch (C.kind) {
3842 case CXCursor_ObjCSuperClassRef:
Ted Kremeneka60ed472010-11-16 08:15:36 +00003843 return MakeCXCursor(getCursorObjCSuperClassRef(C).first, tu);
Ted Kremenekf0e23e82010-02-17 00:41:40 +00003844
3845 case CXCursor_ObjCProtocolRef: {
Ted Kremeneka60ed472010-11-16 08:15:36 +00003846 return MakeCXCursor(getCursorObjCProtocolRef(C).first, tu);
Ted Kremenekf0e23e82010-02-17 00:41:40 +00003847
3848 case CXCursor_ObjCClassRef:
Ted Kremeneka60ed472010-11-16 08:15:36 +00003849 return MakeCXCursor(getCursorObjCClassRef(C).first, tu );
Douglas Gregor7d0d40e2010-01-21 16:28:34 +00003850
Ted Kremenekf0e23e82010-02-17 00:41:40 +00003851 case CXCursor_TypeRef:
Ted Kremeneka60ed472010-11-16 08:15:36 +00003852 return MakeCXCursor(getCursorTypeRef(C).first, tu );
Douglas Gregor0b36e612010-08-31 20:37:03 +00003853
3854 case CXCursor_TemplateRef:
Ted Kremeneka60ed472010-11-16 08:15:36 +00003855 return MakeCXCursor(getCursorTemplateRef(C).first, tu );
Douglas Gregor0b36e612010-08-31 20:37:03 +00003856
Douglas Gregor69319002010-08-31 23:48:11 +00003857 case CXCursor_NamespaceRef:
Ted Kremeneka60ed472010-11-16 08:15:36 +00003858 return MakeCXCursor(getCursorNamespaceRef(C).first, tu );
Douglas Gregor69319002010-08-31 23:48:11 +00003859
Douglas Gregora67e03f2010-09-09 21:42:20 +00003860 case CXCursor_MemberRef:
Ted Kremeneka60ed472010-11-16 08:15:36 +00003861 return MakeCXCursor(getCursorMemberRef(C).first, tu );
Douglas Gregora67e03f2010-09-09 21:42:20 +00003862
Ted Kremenek3064ef92010-08-27 21:34:58 +00003863 case CXCursor_CXXBaseSpecifier: {
3864 CXXBaseSpecifier *B = cxcursor::getCursorCXXBaseSpecifier(C);
3865 return clang_getTypeDeclaration(cxtype::MakeCXType(B->getType(),
Ted Kremeneka60ed472010-11-16 08:15:36 +00003866 tu ));
Ted Kremenek3064ef92010-08-27 21:34:58 +00003867 }
Ted Kremenekf0e23e82010-02-17 00:41:40 +00003868
Douglas Gregor36897b02010-09-10 00:22:18 +00003869 case CXCursor_LabelRef:
3870 // FIXME: We end up faking the "parent" declaration here because we
3871 // don't want to make CXCursor larger.
3872 return MakeCXCursor(getCursorLabelRef(C).first,
Ted Kremeneka60ed472010-11-16 08:15:36 +00003873 static_cast<ASTUnit*>(tu->TUData)->getASTContext()
3874 .getTranslationUnitDecl(),
3875 tu);
Douglas Gregor36897b02010-09-10 00:22:18 +00003876
Douglas Gregor1f60d9e2010-09-13 22:52:57 +00003877 case CXCursor_OverloadedDeclRef:
3878 return C;
3879
Douglas Gregorc5d1e932010-01-19 01:20:04 +00003880 default:
3881 // We would prefer to enumerate all non-reference cursor kinds here.
3882 llvm_unreachable("Unhandled reference cursor kind");
3883 break;
3884 }
3885 }
Ted Kremenekf0e23e82010-02-17 00:41:40 +00003886
Douglas Gregorc5d1e932010-01-19 01:20:04 +00003887 return clang_getNullCursor();
3888}
3889
Douglas Gregorb6998662010-01-19 19:34:47 +00003890CXCursor clang_getCursorDefinition(CXCursor C) {
Douglas Gregorb2cd4872010-01-20 23:57:43 +00003891 if (clang_isInvalid(C.kind))
3892 return clang_getNullCursor();
Ted Kremenekf0e23e82010-02-17 00:41:40 +00003893
Ted Kremeneka60ed472010-11-16 08:15:36 +00003894 CXTranslationUnit TU = getCursorTU(C);
Ted Kremenekf0e23e82010-02-17 00:41:40 +00003895
Douglas Gregorb6998662010-01-19 19:34:47 +00003896 bool WasReference = false;
Douglas Gregor97b98722010-01-19 23:20:36 +00003897 if (clang_isReference(C.kind) || clang_isExpression(C.kind)) {
Douglas Gregorb6998662010-01-19 19:34:47 +00003898 C = clang_getCursorReferenced(C);
3899 WasReference = true;
3900 }
3901
Douglas Gregorbf7efa22010-03-18 18:23:03 +00003902 if (C.kind == CXCursor_MacroInstantiation)
3903 return clang_getCursorReferenced(C);
3904
Douglas Gregorb6998662010-01-19 19:34:47 +00003905 if (!clang_isDeclaration(C.kind))
3906 return clang_getNullCursor();
3907
3908 Decl *D = getCursorDecl(C);
3909 if (!D)
3910 return clang_getNullCursor();
Ted Kremenekf0e23e82010-02-17 00:41:40 +00003911
Douglas Gregorb6998662010-01-19 19:34:47 +00003912 switch (D->getKind()) {
3913 // Declaration kinds that don't really separate the notions of
3914 // declaration and definition.
3915 case Decl::Namespace:
3916 case Decl::Typedef:
Richard Smith162e1c12011-04-15 14:24:37 +00003917 case Decl::TypeAlias:
Richard Smith3e4c6c42011-05-05 21:57:07 +00003918 case Decl::TypeAliasTemplate:
Douglas Gregorb6998662010-01-19 19:34:47 +00003919 case Decl::TemplateTypeParm:
3920 case Decl::EnumConstant:
3921 case Decl::Field:
Benjamin Kramerd9811462010-11-21 14:11:41 +00003922 case Decl::IndirectField:
Douglas Gregorb6998662010-01-19 19:34:47 +00003923 case Decl::ObjCIvar:
3924 case Decl::ObjCAtDefsField:
3925 case Decl::ImplicitParam:
3926 case Decl::ParmVar:
3927 case Decl::NonTypeTemplateParm:
3928 case Decl::TemplateTemplateParm:
3929 case Decl::ObjCCategoryImpl:
3930 case Decl::ObjCImplementation:
Abramo Bagnara6206d532010-06-05 05:09:32 +00003931 case Decl::AccessSpec:
Douglas Gregorb6998662010-01-19 19:34:47 +00003932 case Decl::LinkageSpec:
3933 case Decl::ObjCPropertyImpl:
3934 case Decl::FileScopeAsm:
3935 case Decl::StaticAssert:
3936 case Decl::Block:
Chris Lattnerad8dcf42011-02-17 07:39:24 +00003937 case Decl::Label: // FIXME: Is this right??
Douglas Gregorb6998662010-01-19 19:34:47 +00003938 return C;
3939
3940 // Declaration kinds that don't make any sense here, but are
3941 // nonetheless harmless.
3942 case Decl::TranslationUnit:
Douglas Gregorb6998662010-01-19 19:34:47 +00003943 break;
3944
3945 // Declaration kinds for which the definition is not resolvable.
3946 case Decl::UnresolvedUsingTypename:
3947 case Decl::UnresolvedUsingValue:
3948 break;
3949
3950 case Decl::UsingDirective:
Douglas Gregorb2cd4872010-01-20 23:57:43 +00003951 return MakeCXCursor(cast<UsingDirectiveDecl>(D)->getNominatedNamespace(),
Ted Kremeneka60ed472010-11-16 08:15:36 +00003952 TU);
Douglas Gregorb6998662010-01-19 19:34:47 +00003953
3954 case Decl::NamespaceAlias:
Ted Kremeneka60ed472010-11-16 08:15:36 +00003955 return MakeCXCursor(cast<NamespaceAliasDecl>(D)->getNamespace(), TU);
Douglas Gregorb6998662010-01-19 19:34:47 +00003956
3957 case Decl::Enum:
3958 case Decl::Record:
3959 case Decl::CXXRecord:
3960 case Decl::ClassTemplateSpecialization:
3961 case Decl::ClassTemplatePartialSpecialization:
Douglas Gregor952b0172010-02-11 01:04:33 +00003962 if (TagDecl *Def = cast<TagDecl>(D)->getDefinition())
Ted Kremeneka60ed472010-11-16 08:15:36 +00003963 return MakeCXCursor(Def, TU);
Douglas Gregorb6998662010-01-19 19:34:47 +00003964 return clang_getNullCursor();
3965
3966 case Decl::Function:
3967 case Decl::CXXMethod:
3968 case Decl::CXXConstructor:
3969 case Decl::CXXDestructor:
3970 case Decl::CXXConversion: {
3971 const FunctionDecl *Def = 0;
3972 if (cast<FunctionDecl>(D)->getBody(Def))
Ted Kremeneka60ed472010-11-16 08:15:36 +00003973 return MakeCXCursor(const_cast<FunctionDecl *>(Def), TU);
Douglas Gregorb6998662010-01-19 19:34:47 +00003974 return clang_getNullCursor();
3975 }
3976
3977 case Decl::Var: {
Sebastian Redl31310a22010-02-01 20:16:42 +00003978 // Ask the variable if it has a definition.
3979 if (VarDecl *Def = cast<VarDecl>(D)->getDefinition())
Ted Kremeneka60ed472010-11-16 08:15:36 +00003980 return MakeCXCursor(Def, TU);
Sebastian Redl31310a22010-02-01 20:16:42 +00003981 return clang_getNullCursor();
Douglas Gregorb6998662010-01-19 19:34:47 +00003982 }
Ted Kremenekf0e23e82010-02-17 00:41:40 +00003983
Douglas Gregorb6998662010-01-19 19:34:47 +00003984 case Decl::FunctionTemplate: {
3985 const FunctionDecl *Def = 0;
3986 if (cast<FunctionTemplateDecl>(D)->getTemplatedDecl()->getBody(Def))
Ted Kremeneka60ed472010-11-16 08:15:36 +00003987 return MakeCXCursor(Def->getDescribedFunctionTemplate(), TU);
Douglas Gregorb6998662010-01-19 19:34:47 +00003988 return clang_getNullCursor();
3989 }
Ted Kremenekf0e23e82010-02-17 00:41:40 +00003990
Douglas Gregorb6998662010-01-19 19:34:47 +00003991 case Decl::ClassTemplate: {
3992 if (RecordDecl *Def = cast<ClassTemplateDecl>(D)->getTemplatedDecl()
Douglas Gregor952b0172010-02-11 01:04:33 +00003993 ->getDefinition())
Douglas Gregor0b36e612010-08-31 20:37:03 +00003994 return MakeCXCursor(cast<CXXRecordDecl>(Def)->getDescribedClassTemplate(),
Ted Kremeneka60ed472010-11-16 08:15:36 +00003995 TU);
Douglas Gregorb6998662010-01-19 19:34:47 +00003996 return clang_getNullCursor();
3997 }
3998
Douglas Gregor1f60d9e2010-09-13 22:52:57 +00003999 case Decl::Using:
4000 return MakeCursorOverloadedDeclRef(cast<UsingDecl>(D),
Ted Kremeneka60ed472010-11-16 08:15:36 +00004001 D->getLocation(), TU);
Douglas Gregorb6998662010-01-19 19:34:47 +00004002
4003 case Decl::UsingShadow:
4004 return clang_getCursorDefinition(
Ted Kremenekf0e23e82010-02-17 00:41:40 +00004005 MakeCXCursor(cast<UsingShadowDecl>(D)->getTargetDecl(),
Ted Kremeneka60ed472010-11-16 08:15:36 +00004006 TU));
Douglas Gregorb6998662010-01-19 19:34:47 +00004007
4008 case Decl::ObjCMethod: {
4009 ObjCMethodDecl *Method = cast<ObjCMethodDecl>(D);
4010 if (Method->isThisDeclarationADefinition())
4011 return C;
4012
4013 // Dig out the method definition in the associated
4014 // @implementation, if we have it.
4015 // FIXME: The ASTs should make finding the definition easier.
4016 if (ObjCInterfaceDecl *Class
4017 = dyn_cast<ObjCInterfaceDecl>(Method->getDeclContext()))
4018 if (ObjCImplementationDecl *ClassImpl = Class->getImplementation())
4019 if (ObjCMethodDecl *Def = ClassImpl->getMethod(Method->getSelector(),
4020 Method->isInstanceMethod()))
4021 if (Def->isThisDeclarationADefinition())
Ted Kremeneka60ed472010-11-16 08:15:36 +00004022 return MakeCXCursor(Def, TU);
Douglas Gregorb6998662010-01-19 19:34:47 +00004023
4024 return clang_getNullCursor();
4025 }
4026
4027 case Decl::ObjCCategory:
4028 if (ObjCCategoryImplDecl *Impl
4029 = cast<ObjCCategoryDecl>(D)->getImplementation())
Ted Kremeneka60ed472010-11-16 08:15:36 +00004030 return MakeCXCursor(Impl, TU);
Douglas Gregorb6998662010-01-19 19:34:47 +00004031 return clang_getNullCursor();
4032
4033 case Decl::ObjCProtocol:
4034 if (!cast<ObjCProtocolDecl>(D)->isForwardDecl())
4035 return C;
4036 return clang_getNullCursor();
4037
4038 case Decl::ObjCInterface:
4039 // There are two notions of a "definition" for an Objective-C
4040 // class: the interface and its implementation. When we resolved a
4041 // reference to an Objective-C class, produce the @interface as
4042 // the definition; when we were provided with the interface,
4043 // produce the @implementation as the definition.
4044 if (WasReference) {
4045 if (!cast<ObjCInterfaceDecl>(D)->isForwardDecl())
4046 return C;
4047 } else if (ObjCImplementationDecl *Impl
4048 = cast<ObjCInterfaceDecl>(D)->getImplementation())
Ted Kremeneka60ed472010-11-16 08:15:36 +00004049 return MakeCXCursor(Impl, TU);
Douglas Gregorb6998662010-01-19 19:34:47 +00004050 return clang_getNullCursor();
Ted Kremenekf0e23e82010-02-17 00:41:40 +00004051
Douglas Gregorb6998662010-01-19 19:34:47 +00004052 case Decl::ObjCProperty:
4053 // FIXME: We don't really know where to find the
4054 // ObjCPropertyImplDecls that implement this property.
4055 return clang_getNullCursor();
4056
4057 case Decl::ObjCCompatibleAlias:
4058 if (ObjCInterfaceDecl *Class
4059 = cast<ObjCCompatibleAliasDecl>(D)->getClassInterface())
4060 if (!Class->isForwardDecl())
Ted Kremeneka60ed472010-11-16 08:15:36 +00004061 return MakeCXCursor(Class, TU);
Ted Kremenekf0e23e82010-02-17 00:41:40 +00004062
Douglas Gregorb6998662010-01-19 19:34:47 +00004063 return clang_getNullCursor();
4064
Douglas Gregor1f60d9e2010-09-13 22:52:57 +00004065 case Decl::ObjCForwardProtocol:
4066 return MakeCursorOverloadedDeclRef(cast<ObjCForwardProtocolDecl>(D),
Ted Kremeneka60ed472010-11-16 08:15:36 +00004067 D->getLocation(), TU);
Douglas Gregorb6998662010-01-19 19:34:47 +00004068
Douglas Gregor1f60d9e2010-09-13 22:52:57 +00004069 case Decl::ObjCClass:
Daniel Dunbar9e1ebdd2010-11-05 07:19:21 +00004070 return MakeCursorOverloadedDeclRef(cast<ObjCClassDecl>(D), D->getLocation(),
Ted Kremeneka60ed472010-11-16 08:15:36 +00004071 TU);
Douglas Gregorb6998662010-01-19 19:34:47 +00004072
4073 case Decl::Friend:
4074 if (NamedDecl *Friend = cast<FriendDecl>(D)->getFriendDecl())
Ted Kremeneka60ed472010-11-16 08:15:36 +00004075 return clang_getCursorDefinition(MakeCXCursor(Friend, TU));
Douglas Gregorb6998662010-01-19 19:34:47 +00004076 return clang_getNullCursor();
4077
4078 case Decl::FriendTemplate:
4079 if (NamedDecl *Friend = cast<FriendTemplateDecl>(D)->getFriendDecl())
Ted Kremeneka60ed472010-11-16 08:15:36 +00004080 return clang_getCursorDefinition(MakeCXCursor(Friend, TU));
Douglas Gregorb6998662010-01-19 19:34:47 +00004081 return clang_getNullCursor();
4082 }
4083
4084 return clang_getNullCursor();
4085}
4086
4087unsigned clang_isCursorDefinition(CXCursor C) {
4088 if (!clang_isDeclaration(C.kind))
4089 return 0;
4090
4091 return clang_getCursorDefinition(C) == C;
4092}
4093
Douglas Gregor1a9d0502010-11-19 23:44:15 +00004094CXCursor clang_getCanonicalCursor(CXCursor C) {
4095 if (!clang_isDeclaration(C.kind))
4096 return C;
4097
4098 if (Decl *D = getCursorDecl(C))
4099 return MakeCXCursor(D->getCanonicalDecl(), getCursorTU(C));
4100
4101 return C;
4102}
4103
Douglas Gregor1f60d9e2010-09-13 22:52:57 +00004104unsigned clang_getNumOverloadedDecls(CXCursor C) {
Douglas Gregor7c432dd2010-09-16 13:54:00 +00004105 if (C.kind != CXCursor_OverloadedDeclRef)
Douglas Gregor1f60d9e2010-09-13 22:52:57 +00004106 return 0;
4107
4108 OverloadedDeclRefStorage Storage = getCursorOverloadedDeclRef(C).first;
4109 if (OverloadExpr *E = Storage.dyn_cast<OverloadExpr *>())
4110 return E->getNumDecls();
4111
4112 if (OverloadedTemplateStorage *S
4113 = Storage.dyn_cast<OverloadedTemplateStorage*>())
4114 return S->size();
4115
4116 Decl *D = Storage.get<Decl*>();
4117 if (UsingDecl *Using = dyn_cast<UsingDecl>(D))
Argyrios Kyrtzidis826faa22010-11-10 05:40:41 +00004118 return Using->shadow_size();
Douglas Gregor1f60d9e2010-09-13 22:52:57 +00004119 if (ObjCClassDecl *Classes = dyn_cast<ObjCClassDecl>(D))
4120 return Classes->size();
4121 if (ObjCForwardProtocolDecl *Protocols =dyn_cast<ObjCForwardProtocolDecl>(D))
4122 return Protocols->protocol_size();
4123
4124 return 0;
4125}
4126
4127CXCursor clang_getOverloadedDecl(CXCursor cursor, unsigned index) {
Douglas Gregor7c432dd2010-09-16 13:54:00 +00004128 if (cursor.kind != CXCursor_OverloadedDeclRef)
Douglas Gregor1f60d9e2010-09-13 22:52:57 +00004129 return clang_getNullCursor();
4130
4131 if (index >= clang_getNumOverloadedDecls(cursor))
4132 return clang_getNullCursor();
4133
Ted Kremeneka60ed472010-11-16 08:15:36 +00004134 CXTranslationUnit TU = getCursorTU(cursor);
Douglas Gregor1f60d9e2010-09-13 22:52:57 +00004135 OverloadedDeclRefStorage Storage = getCursorOverloadedDeclRef(cursor).first;
4136 if (OverloadExpr *E = Storage.dyn_cast<OverloadExpr *>())
Ted Kremeneka60ed472010-11-16 08:15:36 +00004137 return MakeCXCursor(E->decls_begin()[index], TU);
Douglas Gregor1f60d9e2010-09-13 22:52:57 +00004138
4139 if (OverloadedTemplateStorage *S
4140 = Storage.dyn_cast<OverloadedTemplateStorage*>())
Ted Kremeneka60ed472010-11-16 08:15:36 +00004141 return MakeCXCursor(S->begin()[index], TU);
Douglas Gregor1f60d9e2010-09-13 22:52:57 +00004142
4143 Decl *D = Storage.get<Decl*>();
4144 if (UsingDecl *Using = dyn_cast<UsingDecl>(D)) {
4145 // FIXME: This is, unfortunately, linear time.
4146 UsingDecl::shadow_iterator Pos = Using->shadow_begin();
4147 std::advance(Pos, index);
Ted Kremeneka60ed472010-11-16 08:15:36 +00004148 return MakeCXCursor(cast<UsingShadowDecl>(*Pos)->getTargetDecl(), TU);
Douglas Gregor1f60d9e2010-09-13 22:52:57 +00004149 }
4150
4151 if (ObjCClassDecl *Classes = dyn_cast<ObjCClassDecl>(D))
Ted Kremeneka60ed472010-11-16 08:15:36 +00004152 return MakeCXCursor(Classes->begin()[index].getInterface(), TU);
Douglas Gregor1f60d9e2010-09-13 22:52:57 +00004153
4154 if (ObjCForwardProtocolDecl *Protocols = dyn_cast<ObjCForwardProtocolDecl>(D))
Ted Kremeneka60ed472010-11-16 08:15:36 +00004155 return MakeCXCursor(Protocols->protocol_begin()[index], TU);
Douglas Gregor1f60d9e2010-09-13 22:52:57 +00004156
4157 return clang_getNullCursor();
4158}
4159
Daniel Dunbar0d7dd222009-11-30 20:42:43 +00004160void clang_getDefinitionSpellingAndExtent(CXCursor C,
Steve Naroff4ade6d62009-09-23 17:52:52 +00004161 const char **startBuf,
4162 const char **endBuf,
4163 unsigned *startLine,
4164 unsigned *startColumn,
4165 unsigned *endLine,
Daniel Dunbar9ebfa312009-12-01 03:14:51 +00004166 unsigned *endColumn) {
Douglas Gregor283cae32010-01-15 21:56:13 +00004167 assert(getCursorDecl(C) && "CXCursor has null decl");
4168 NamedDecl *ND = static_cast<NamedDecl *>(getCursorDecl(C));
Steve Naroff4ade6d62009-09-23 17:52:52 +00004169 FunctionDecl *FD = dyn_cast<FunctionDecl>(ND);
4170 CompoundStmt *Body = dyn_cast<CompoundStmt>(FD->getBody());
Ted Kremenekf0e23e82010-02-17 00:41:40 +00004171
Steve Naroff4ade6d62009-09-23 17:52:52 +00004172 SourceManager &SM = FD->getASTContext().getSourceManager();
4173 *startBuf = SM.getCharacterData(Body->getLBracLoc());
4174 *endBuf = SM.getCharacterData(Body->getRBracLoc());
4175 *startLine = SM.getSpellingLineNumber(Body->getLBracLoc());
4176 *startColumn = SM.getSpellingColumnNumber(Body->getLBracLoc());
4177 *endLine = SM.getSpellingLineNumber(Body->getRBracLoc());
4178 *endColumn = SM.getSpellingColumnNumber(Body->getRBracLoc());
4179}
Ted Kremenekf0e23e82010-02-17 00:41:40 +00004180
Douglas Gregor0a812cf2010-02-18 23:07:20 +00004181void clang_enableStackTraces(void) {
4182 llvm::sys::PrintStackTraceOnErrorSignal();
4183}
4184
Daniel Dunbar995aaf92010-11-04 01:26:29 +00004185void clang_executeOnThread(void (*fn)(void*), void *user_data,
4186 unsigned stack_size) {
4187 llvm::llvm_execute_on_thread(fn, user_data, stack_size);
4188}
4189
Ted Kremenekfb480492010-01-13 21:46:36 +00004190} // end: extern "C"
Steve Naroff4ade6d62009-09-23 17:52:52 +00004191
Ted Kremenekfb480492010-01-13 21:46:36 +00004192//===----------------------------------------------------------------------===//
Douglas Gregorfc8ea232010-01-26 17:06:03 +00004193// Token-based Operations.
4194//===----------------------------------------------------------------------===//
4195
4196/* CXToken layout:
4197 * int_data[0]: a CXTokenKind
4198 * int_data[1]: starting token location
4199 * int_data[2]: token length
4200 * int_data[3]: reserved
Ted Kremenekf0e23e82010-02-17 00:41:40 +00004201 * ptr_data: for identifiers and keywords, an IdentifierInfo*.
Douglas Gregorfc8ea232010-01-26 17:06:03 +00004202 * otherwise unused.
4203 */
4204extern "C" {
4205
4206CXTokenKind clang_getTokenKind(CXToken CXTok) {
4207 return static_cast<CXTokenKind>(CXTok.int_data[0]);
4208}
4209
4210CXString clang_getTokenSpelling(CXTranslationUnit TU, CXToken CXTok) {
4211 switch (clang_getTokenKind(CXTok)) {
4212 case CXToken_Identifier:
4213 case CXToken_Keyword:
4214 // We know we have an IdentifierInfo*, so use that.
Ted Kremenekee4db4f2010-02-17 00:41:08 +00004215 return createCXString(static_cast<IdentifierInfo *>(CXTok.ptr_data)
4216 ->getNameStart());
Douglas Gregorfc8ea232010-01-26 17:06:03 +00004217
4218 case CXToken_Literal: {
4219 // We have stashed the starting pointer in the ptr_data field. Use it.
4220 const char *Text = static_cast<const char *>(CXTok.ptr_data);
Ted Kremenekee4db4f2010-02-17 00:41:08 +00004221 return createCXString(llvm::StringRef(Text, CXTok.int_data[2]));
Douglas Gregorfc8ea232010-01-26 17:06:03 +00004222 }
Ted Kremenekf0e23e82010-02-17 00:41:40 +00004223
Douglas Gregorfc8ea232010-01-26 17:06:03 +00004224 case CXToken_Punctuation:
4225 case CXToken_Comment:
4226 break;
4227 }
Ted Kremenekf0e23e82010-02-17 00:41:40 +00004228
4229 // We have to find the starting buffer pointer the hard way, by
Douglas Gregorfc8ea232010-01-26 17:06:03 +00004230 // deconstructing the source location.
Ted Kremeneka60ed472010-11-16 08:15:36 +00004231 ASTUnit *CXXUnit = static_cast<ASTUnit *>(TU->TUData);
Douglas Gregorfc8ea232010-01-26 17:06:03 +00004232 if (!CXXUnit)
Ted Kremenekee4db4f2010-02-17 00:41:08 +00004233 return createCXString("");
Ted Kremenekf0e23e82010-02-17 00:41:40 +00004234
Douglas Gregorfc8ea232010-01-26 17:06:03 +00004235 SourceLocation Loc = SourceLocation::getFromRawEncoding(CXTok.int_data[1]);
4236 std::pair<FileID, unsigned> LocInfo
4237 = CXXUnit->getSourceManager().getDecomposedLoc(Loc);
Douglas Gregorf715ca12010-03-16 00:06:06 +00004238 bool Invalid = false;
Benjamin Kramerf6ac97b2010-03-16 14:14:31 +00004239 llvm::StringRef Buffer
Douglas Gregorf715ca12010-03-16 00:06:06 +00004240 = CXXUnit->getSourceManager().getBufferData(LocInfo.first, &Invalid);
4241 if (Invalid)
Douglas Gregoraea67db2010-03-15 22:54:52 +00004242 return createCXString("");
Douglas Gregorfc8ea232010-01-26 17:06:03 +00004243
Benjamin Kramerf6ac97b2010-03-16 14:14:31 +00004244 return createCXString(Buffer.substr(LocInfo.second, CXTok.int_data[2]));
Douglas Gregorfc8ea232010-01-26 17:06:03 +00004245}
Ted Kremenekf0e23e82010-02-17 00:41:40 +00004246
Douglas Gregorfc8ea232010-01-26 17:06:03 +00004247CXSourceLocation clang_getTokenLocation(CXTranslationUnit TU, CXToken CXTok) {
Ted Kremeneka60ed472010-11-16 08:15:36 +00004248 ASTUnit *CXXUnit = static_cast<ASTUnit *>(TU->TUData);
Douglas Gregorfc8ea232010-01-26 17:06:03 +00004249 if (!CXXUnit)
4250 return clang_getNullLocation();
Ted Kremenekf0e23e82010-02-17 00:41:40 +00004251
Douglas Gregorfc8ea232010-01-26 17:06:03 +00004252 return cxloc::translateSourceLocation(CXXUnit->getASTContext(),
4253 SourceLocation::getFromRawEncoding(CXTok.int_data[1]));
4254}
4255
4256CXSourceRange clang_getTokenExtent(CXTranslationUnit TU, CXToken CXTok) {
Ted Kremeneka60ed472010-11-16 08:15:36 +00004257 ASTUnit *CXXUnit = static_cast<ASTUnit *>(TU->TUData);
Douglas Gregor5352ac02010-01-28 00:27:43 +00004258 if (!CXXUnit)
4259 return clang_getNullRange();
Ted Kremenekf0e23e82010-02-17 00:41:40 +00004260
4261 return cxloc::translateSourceRange(CXXUnit->getASTContext(),
Douglas Gregorfc8ea232010-01-26 17:06:03 +00004262 SourceLocation::getFromRawEncoding(CXTok.int_data[1]));
4263}
Ted Kremenekf0e23e82010-02-17 00:41:40 +00004264
Douglas Gregorfc8ea232010-01-26 17:06:03 +00004265void clang_tokenize(CXTranslationUnit TU, CXSourceRange Range,
4266 CXToken **Tokens, unsigned *NumTokens) {
4267 if (Tokens)
4268 *Tokens = 0;
4269 if (NumTokens)
4270 *NumTokens = 0;
Ted Kremenekf0e23e82010-02-17 00:41:40 +00004271
Ted Kremeneka60ed472010-11-16 08:15:36 +00004272 ASTUnit *CXXUnit = static_cast<ASTUnit *>(TU->TUData);
Douglas Gregorfc8ea232010-01-26 17:06:03 +00004273 if (!CXXUnit || !Tokens || !NumTokens)
4274 return;
Ted Kremenekf0e23e82010-02-17 00:41:40 +00004275
Douglas Gregorbdf60622010-03-05 21:16:25 +00004276 ASTUnit::ConcurrencyCheck Check(*CXXUnit);
4277
Daniel Dunbar85b988f2010-02-14 08:31:57 +00004278 SourceRange R = cxloc::translateCXSourceRange(Range);
Douglas Gregorfc8ea232010-01-26 17:06:03 +00004279 if (R.isInvalid())
4280 return;
Ted Kremenekf0e23e82010-02-17 00:41:40 +00004281
Douglas Gregorfc8ea232010-01-26 17:06:03 +00004282 SourceManager &SourceMgr = CXXUnit->getSourceManager();
4283 std::pair<FileID, unsigned> BeginLocInfo
4284 = SourceMgr.getDecomposedLoc(R.getBegin());
4285 std::pair<FileID, unsigned> EndLocInfo
4286 = SourceMgr.getDecomposedLoc(R.getEnd());
Ted Kremenekf0e23e82010-02-17 00:41:40 +00004287
Douglas Gregorfc8ea232010-01-26 17:06:03 +00004288 // Cannot tokenize across files.
4289 if (BeginLocInfo.first != EndLocInfo.first)
4290 return;
Ted Kremenekf0e23e82010-02-17 00:41:40 +00004291
4292 // Create a lexer
Douglas Gregorf715ca12010-03-16 00:06:06 +00004293 bool Invalid = false;
Benjamin Kramerf6ac97b2010-03-16 14:14:31 +00004294 llvm::StringRef Buffer
Douglas Gregorf715ca12010-03-16 00:06:06 +00004295 = SourceMgr.getBufferData(BeginLocInfo.first, &Invalid);
Douglas Gregor47a3fcd2010-03-16 20:26:15 +00004296 if (Invalid)
4297 return;
Douglas Gregoraea67db2010-03-15 22:54:52 +00004298
Douglas Gregorfc8ea232010-01-26 17:06:03 +00004299 Lexer Lex(SourceMgr.getLocForStartOfFile(BeginLocInfo.first),
4300 CXXUnit->getASTContext().getLangOptions(),
Benjamin Kramerf6ac97b2010-03-16 14:14:31 +00004301 Buffer.begin(), Buffer.data() + BeginLocInfo.second, Buffer.end());
Douglas Gregorfc8ea232010-01-26 17:06:03 +00004302 Lex.SetCommentRetentionState(true);
Ted Kremenekf0e23e82010-02-17 00:41:40 +00004303
Douglas Gregorfc8ea232010-01-26 17:06:03 +00004304 // Lex tokens until we hit the end of the range.
Benjamin Kramerf6ac97b2010-03-16 14:14:31 +00004305 const char *EffectiveBufferEnd = Buffer.data() + EndLocInfo.second;
Douglas Gregorfc8ea232010-01-26 17:06:03 +00004306 llvm::SmallVector<CXToken, 32> CXTokens;
4307 Token Tok;
David Chisnall096428b2010-10-13 21:44:48 +00004308 bool previousWasAt = false;
Douglas Gregorfc8ea232010-01-26 17:06:03 +00004309 do {
4310 // Lex the next token
4311 Lex.LexFromRawLexer(Tok);
4312 if (Tok.is(tok::eof))
4313 break;
Ted Kremenekf0e23e82010-02-17 00:41:40 +00004314
Douglas Gregorfc8ea232010-01-26 17:06:03 +00004315 // Initialize the CXToken.
4316 CXToken CXTok;
Ted Kremenekf0e23e82010-02-17 00:41:40 +00004317
Douglas Gregorfc8ea232010-01-26 17:06:03 +00004318 // - Common fields
4319 CXTok.int_data[1] = Tok.getLocation().getRawEncoding();
4320 CXTok.int_data[2] = Tok.getLength();
4321 CXTok.int_data[3] = 0;
Ted Kremenekf0e23e82010-02-17 00:41:40 +00004322
Douglas Gregorfc8ea232010-01-26 17:06:03 +00004323 // - Kind-specific fields
4324 if (Tok.isLiteral()) {
4325 CXTok.int_data[0] = CXToken_Literal;
4326 CXTok.ptr_data = (void *)Tok.getLiteralData();
Abramo Bagnarac4bf2b92010-12-22 08:23:18 +00004327 } else if (Tok.is(tok::raw_identifier)) {
Douglas Gregoraea67db2010-03-15 22:54:52 +00004328 // Lookup the identifier to determine whether we have a keyword.
Douglas Gregorfc8ea232010-01-26 17:06:03 +00004329 IdentifierInfo *II
Abramo Bagnarac4bf2b92010-12-22 08:23:18 +00004330 = CXXUnit->getPreprocessor().LookUpIdentifierInfo(Tok);
Ted Kremenekaa8a66d2010-05-05 00:55:20 +00004331
David Chisnall096428b2010-10-13 21:44:48 +00004332 if ((II->getObjCKeywordID() != tok::objc_not_keyword) && previousWasAt) {
Ted Kremenekaa8a66d2010-05-05 00:55:20 +00004333 CXTok.int_data[0] = CXToken_Keyword;
4334 }
4335 else {
Abramo Bagnarac4bf2b92010-12-22 08:23:18 +00004336 CXTok.int_data[0] = Tok.is(tok::identifier)
4337 ? CXToken_Identifier
4338 : CXToken_Keyword;
Ted Kremenekaa8a66d2010-05-05 00:55:20 +00004339 }
Douglas Gregorfc8ea232010-01-26 17:06:03 +00004340 CXTok.ptr_data = II;
4341 } else if (Tok.is(tok::comment)) {
4342 CXTok.int_data[0] = CXToken_Comment;
4343 CXTok.ptr_data = 0;
4344 } else {
4345 CXTok.int_data[0] = CXToken_Punctuation;
4346 CXTok.ptr_data = 0;
4347 }
4348 CXTokens.push_back(CXTok);
David Chisnall096428b2010-10-13 21:44:48 +00004349 previousWasAt = Tok.is(tok::at);
Douglas Gregorfc8ea232010-01-26 17:06:03 +00004350 } while (Lex.getBufferLocation() <= EffectiveBufferEnd);
Ted Kremenekf0e23e82010-02-17 00:41:40 +00004351
Douglas Gregorfc8ea232010-01-26 17:06:03 +00004352 if (CXTokens.empty())
4353 return;
Ted Kremenekf0e23e82010-02-17 00:41:40 +00004354
Douglas Gregorfc8ea232010-01-26 17:06:03 +00004355 *Tokens = (CXToken *)malloc(sizeof(CXToken) * CXTokens.size());
4356 memmove(*Tokens, CXTokens.data(), sizeof(CXToken) * CXTokens.size());
4357 *NumTokens = CXTokens.size();
4358}
Douglas Gregor0045e9f2010-01-26 18:31:56 +00004359
Ted Kremenek6db61092010-05-05 00:55:15 +00004360void clang_disposeTokens(CXTranslationUnit TU,
4361 CXToken *Tokens, unsigned NumTokens) {
4362 free(Tokens);
4363}
4364
4365} // end: extern "C"
4366
4367//===----------------------------------------------------------------------===//
4368// Token annotation APIs.
4369//===----------------------------------------------------------------------===//
4370
Douglas Gregor0045e9f2010-01-26 18:31:56 +00004371typedef llvm::DenseMap<unsigned, CXCursor> AnnotateTokensData;
Ted Kremenekfbd84ca2010-05-05 00:55:23 +00004372static enum CXChildVisitResult AnnotateTokensVisitor(CXCursor cursor,
4373 CXCursor parent,
4374 CXClientData client_data);
Ted Kremenek6db61092010-05-05 00:55:15 +00004375namespace {
4376class AnnotateTokensWorker {
4377 AnnotateTokensData &Annotated;
Ted Kremenek11949cb2010-05-05 00:55:17 +00004378 CXToken *Tokens;
4379 CXCursor *Cursors;
4380 unsigned NumTokens;
Ted Kremenekfbd84ca2010-05-05 00:55:23 +00004381 unsigned TokIdx;
Douglas Gregor4419b672010-10-21 06:10:04 +00004382 unsigned PreprocessingTokIdx;
Ted Kremenekfbd84ca2010-05-05 00:55:23 +00004383 CursorVisitor AnnotateVis;
4384 SourceManager &SrcMgr;
Douglas Gregorf5251602011-03-08 17:10:18 +00004385 bool HasContextSensitiveKeywords;
4386
Ted Kremenekfbd84ca2010-05-05 00:55:23 +00004387 bool MoreTokens() const { return TokIdx < NumTokens; }
4388 unsigned NextToken() const { return TokIdx; }
4389 void AdvanceToken() { ++TokIdx; }
4390 SourceLocation GetTokenLoc(unsigned tokI) {
4391 return SourceLocation::getFromRawEncoding(Tokens[tokI].int_data[1]);
4392 }
4393
Ted Kremenek6db61092010-05-05 00:55:15 +00004394public:
Ted Kremenek11949cb2010-05-05 00:55:17 +00004395 AnnotateTokensWorker(AnnotateTokensData &annotated,
Ted Kremenekfbd84ca2010-05-05 00:55:23 +00004396 CXToken *tokens, CXCursor *cursors, unsigned numTokens,
Ted Kremeneka60ed472010-11-16 08:15:36 +00004397 CXTranslationUnit tu, SourceRange RegionOfInterest)
Ted Kremenek11949cb2010-05-05 00:55:17 +00004398 : Annotated(annotated), Tokens(tokens), Cursors(cursors),
Douglas Gregor4419b672010-10-21 06:10:04 +00004399 NumTokens(numTokens), TokIdx(0), PreprocessingTokIdx(0),
Ted Kremeneka60ed472010-11-16 08:15:36 +00004400 AnnotateVis(tu,
4401 AnnotateTokensVisitor, this,
Douglas Gregor04a9eb32011-03-16 23:23:30 +00004402 Decl::MaxPCHLevel, true, RegionOfInterest),
Douglas Gregorf5251602011-03-08 17:10:18 +00004403 SrcMgr(static_cast<ASTUnit*>(tu->TUData)->getSourceManager()),
4404 HasContextSensitiveKeywords(false) { }
Ted Kremenek11949cb2010-05-05 00:55:17 +00004405
Ted Kremenekfbd84ca2010-05-05 00:55:23 +00004406 void VisitChildren(CXCursor C) { AnnotateVis.VisitChildren(C); }
Ted Kremenek6db61092010-05-05 00:55:15 +00004407 enum CXChildVisitResult Visit(CXCursor cursor, CXCursor parent);
Ted Kremenekfbd84ca2010-05-05 00:55:23 +00004408 void AnnotateTokens(CXCursor parent);
Ted Kremenekab979612010-11-11 08:05:23 +00004409 void AnnotateTokens() {
Ted Kremeneka60ed472010-11-16 08:15:36 +00004410 AnnotateTokens(clang_getTranslationUnitCursor(AnnotateVis.getTU()));
Ted Kremenekab979612010-11-11 08:05:23 +00004411 }
Douglas Gregorf5251602011-03-08 17:10:18 +00004412
4413 /// \brief Determine whether the annotator saw any cursors that have
4414 /// context-sensitive keywords.
4415 bool hasContextSensitiveKeywords() const {
4416 return HasContextSensitiveKeywords;
4417 }
Ted Kremenek6db61092010-05-05 00:55:15 +00004418};
4419}
Douglas Gregor0045e9f2010-01-26 18:31:56 +00004420
Ted Kremenekfbd84ca2010-05-05 00:55:23 +00004421void AnnotateTokensWorker::AnnotateTokens(CXCursor parent) {
4422 // Walk the AST within the region of interest, annotating tokens
4423 // along the way.
4424 VisitChildren(parent);
Ted Kremenek11949cb2010-05-05 00:55:17 +00004425
Ted Kremenekfbd84ca2010-05-05 00:55:23 +00004426 for (unsigned I = 0 ; I < TokIdx ; ++I) {
4427 AnnotateTokensData::iterator Pos = Annotated.find(Tokens[I].int_data[1]);
Douglas Gregor4419b672010-10-21 06:10:04 +00004428 if (Pos != Annotated.end() &&
4429 (clang_isInvalid(Cursors[I].kind) ||
4430 Pos->second.kind != CXCursor_PreprocessingDirective))
Ted Kremenekfbd84ca2010-05-05 00:55:23 +00004431 Cursors[I] = Pos->second;
4432 }
4433
4434 // Finish up annotating any tokens left.
4435 if (!MoreTokens())
4436 return;
4437
4438 const CXCursor &C = clang_getNullCursor();
4439 for (unsigned I = TokIdx ; I < NumTokens ; ++I) {
4440 AnnotateTokensData::iterator Pos = Annotated.find(Tokens[I].int_data[1]);
4441 Cursors[I] = (Pos == Annotated.end()) ? C : Pos->second;
Ted Kremenek11949cb2010-05-05 00:55:17 +00004442 }
4443}
4444
Ted Kremenek6db61092010-05-05 00:55:15 +00004445enum CXChildVisitResult
Douglas Gregor4419b672010-10-21 06:10:04 +00004446AnnotateTokensWorker::Visit(CXCursor cursor, CXCursor parent) {
Ted Kremenekfbd84ca2010-05-05 00:55:23 +00004447 CXSourceLocation Loc = clang_getCursorLocation(cursor);
Douglas Gregor4419b672010-10-21 06:10:04 +00004448 SourceRange cursorRange = getRawCursorExtent(cursor);
Douglas Gregor81d3c042010-11-01 20:13:04 +00004449 if (cursorRange.isInvalid())
4450 return CXChildVisit_Recurse;
Douglas Gregorf5251602011-03-08 17:10:18 +00004451
4452 if (!HasContextSensitiveKeywords) {
4453 // Objective-C properties can have context-sensitive keywords.
4454 if (cursor.kind == CXCursor_ObjCPropertyDecl) {
4455 if (ObjCPropertyDecl *Property
4456 = dyn_cast_or_null<ObjCPropertyDecl>(getCursorDecl(cursor)))
4457 HasContextSensitiveKeywords = Property->getPropertyAttributesAsWritten() != 0;
4458 }
4459 // Objective-C methods can have context-sensitive keywords.
4460 else if (cursor.kind == CXCursor_ObjCInstanceMethodDecl ||
4461 cursor.kind == CXCursor_ObjCClassMethodDecl) {
4462 if (ObjCMethodDecl *Method
4463 = dyn_cast_or_null<ObjCMethodDecl>(getCursorDecl(cursor))) {
4464 if (Method->getObjCDeclQualifier())
4465 HasContextSensitiveKeywords = true;
4466 else {
4467 for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
4468 PEnd = Method->param_end();
4469 P != PEnd; ++P) {
4470 if ((*P)->getObjCDeclQualifier()) {
4471 HasContextSensitiveKeywords = true;
4472 break;
4473 }
4474 }
4475 }
4476 }
4477 }
4478 // C++ methods can have context-sensitive keywords.
4479 else if (cursor.kind == CXCursor_CXXMethod) {
4480 if (CXXMethodDecl *Method
4481 = dyn_cast_or_null<CXXMethodDecl>(getCursorDecl(cursor))) {
4482 if (Method->hasAttr<FinalAttr>() || Method->hasAttr<OverrideAttr>())
4483 HasContextSensitiveKeywords = true;
4484 }
4485 }
4486 // C++ classes can have context-sensitive keywords.
4487 else if (cursor.kind == CXCursor_StructDecl ||
4488 cursor.kind == CXCursor_ClassDecl ||
4489 cursor.kind == CXCursor_ClassTemplate ||
4490 cursor.kind == CXCursor_ClassTemplatePartialSpecialization) {
4491 if (Decl *D = getCursorDecl(cursor))
4492 if (D->hasAttr<FinalAttr>())
4493 HasContextSensitiveKeywords = true;
4494 }
4495 }
4496
Douglas Gregor4419b672010-10-21 06:10:04 +00004497 if (clang_isPreprocessing(cursor.kind)) {
4498 // For macro instantiations, just note where the beginning of the macro
4499 // instantiation occurs.
4500 if (cursor.kind == CXCursor_MacroInstantiation) {
4501 Annotated[Loc.int_data] = cursor;
4502 return CXChildVisit_Recurse;
4503 }
4504
Douglas Gregor4419b672010-10-21 06:10:04 +00004505 // Items in the preprocessing record are kept separate from items in
4506 // declarations, so we keep a separate token index.
4507 unsigned SavedTokIdx = TokIdx;
4508 TokIdx = PreprocessingTokIdx;
4509
4510 // Skip tokens up until we catch up to the beginning of the preprocessing
4511 // entry.
4512 while (MoreTokens()) {
4513 const unsigned I = NextToken();
4514 SourceLocation TokLoc = GetTokenLoc(I);
4515 switch (LocationCompare(SrcMgr, TokLoc, cursorRange)) {
4516 case RangeBefore:
4517 AdvanceToken();
4518 continue;
4519 case RangeAfter:
4520 case RangeOverlap:
4521 break;
4522 }
4523 break;
4524 }
4525
4526 // Look at all of the tokens within this range.
4527 while (MoreTokens()) {
4528 const unsigned I = NextToken();
4529 SourceLocation TokLoc = GetTokenLoc(I);
4530 switch (LocationCompare(SrcMgr, TokLoc, cursorRange)) {
4531 case RangeBefore:
4532 assert(0 && "Infeasible");
4533 case RangeAfter:
4534 break;
4535 case RangeOverlap:
4536 Cursors[I] = cursor;
4537 AdvanceToken();
4538 continue;
4539 }
4540 break;
4541 }
4542
4543 // Save the preprocessing token index; restore the non-preprocessing
4544 // token index.
4545 PreprocessingTokIdx = TokIdx;
4546 TokIdx = SavedTokIdx;
Douglas Gregor0045e9f2010-01-26 18:31:56 +00004547 return CXChildVisit_Recurse;
4548 }
Ted Kremenekfbd84ca2010-05-05 00:55:23 +00004549
Ted Kremenekfbd84ca2010-05-05 00:55:23 +00004550 if (cursorRange.isInvalid())
4551 return CXChildVisit_Continue;
Ted Kremeneka333c662010-05-12 05:29:33 +00004552
Ted Kremenekfbd84ca2010-05-05 00:55:23 +00004553 SourceLocation L = SourceLocation::getFromRawEncoding(Loc.int_data);
4554
Ted Kremeneka333c662010-05-12 05:29:33 +00004555 // Adjust the annotated range based specific declarations.
4556 const enum CXCursorKind cursorK = clang_getCursorKind(cursor);
4557 if (cursorK >= CXCursor_FirstDecl && cursorK <= CXCursor_LastDecl) {
Ted Kremenek23173d72010-05-18 21:09:07 +00004558 Decl *D = cxcursor::getCursorDecl(cursor);
4559 // Don't visit synthesized ObjC methods, since they have no syntatic
4560 // representation in the source.
4561 if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
4562 if (MD->isSynthesized())
4563 return CXChildVisit_Continue;
4564 }
Douglas Gregor2494dd02011-03-01 01:34:45 +00004565
4566 SourceLocation StartLoc;
Ted Kremenek23173d72010-05-18 21:09:07 +00004567 if (const DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(D)) {
Douglas Gregor2494dd02011-03-01 01:34:45 +00004568 if (TypeSourceInfo *TI = DD->getTypeSourceInfo())
4569 StartLoc = TI->getTypeLoc().getSourceRange().getBegin();
4570 } else if (TypedefDecl *Typedef = dyn_cast<TypedefDecl>(D)) {
4571 if (TypeSourceInfo *TI = Typedef->getTypeSourceInfo())
4572 StartLoc = TI->getTypeLoc().getSourceRange().getBegin();
Ted Kremeneka333c662010-05-12 05:29:33 +00004573 }
Douglas Gregor2494dd02011-03-01 01:34:45 +00004574
4575 if (StartLoc.isValid() && L.isValid() &&
4576 SrcMgr.isBeforeInTranslationUnit(StartLoc, L))
4577 cursorRange.setBegin(StartLoc);
Ted Kremeneka333c662010-05-12 05:29:33 +00004578 }
Douglas Gregor81d3c042010-11-01 20:13:04 +00004579
Ted Kremenek3f404602010-08-14 01:14:06 +00004580 // If the location of the cursor occurs within a macro instantiation, record
4581 // the spelling location of the cursor in our annotation map. We can then
4582 // paper over the token labelings during a post-processing step to try and
4583 // get cursor mappings for tokens that are the *arguments* of a macro
4584 // instantiation.
4585 if (L.isMacroID()) {
4586 unsigned rawEncoding = SrcMgr.getSpellingLoc(L).getRawEncoding();
4587 // Only invalidate the old annotation if it isn't part of a preprocessing
4588 // directive. Here we assume that the default construction of CXCursor
4589 // results in CXCursor.kind being an initialized value (i.e., 0). If
4590 // this isn't the case, we can fix by doing lookup + insertion.
Douglas Gregor4419b672010-10-21 06:10:04 +00004591
Ted Kremenek3f404602010-08-14 01:14:06 +00004592 CXCursor &oldC = Annotated[rawEncoding];
4593 if (!clang_isPreprocessing(oldC.kind))
4594 oldC = cursor;
4595 }
4596
Ted Kremenekfbd84ca2010-05-05 00:55:23 +00004597 const enum CXCursorKind K = clang_getCursorKind(parent);
4598 const CXCursor updateC =
Ted Kremenekd8b0a842010-08-25 22:16:02 +00004599 (clang_isInvalid(K) || K == CXCursor_TranslationUnit)
4600 ? clang_getNullCursor() : parent;
Ted Kremenekfbd84ca2010-05-05 00:55:23 +00004601
4602 while (MoreTokens()) {
4603 const unsigned I = NextToken();
4604 SourceLocation TokLoc = GetTokenLoc(I);
4605 switch (LocationCompare(SrcMgr, TokLoc, cursorRange)) {
4606 case RangeBefore:
4607 Cursors[I] = updateC;
4608 AdvanceToken();
4609 continue;
4610 case RangeAfter:
Ted Kremenekfbd84ca2010-05-05 00:55:23 +00004611 case RangeOverlap:
4612 break;
4613 }
4614 break;
4615 }
4616
4617 // Visit children to get their cursor information.
4618 const unsigned BeforeChildren = NextToken();
4619 VisitChildren(cursor);
4620 const unsigned AfterChildren = NextToken();
4621
4622 // Adjust 'Last' to the last token within the extent of the cursor.
4623 while (MoreTokens()) {
4624 const unsigned I = NextToken();
4625 SourceLocation TokLoc = GetTokenLoc(I);
4626 switch (LocationCompare(SrcMgr, TokLoc, cursorRange)) {
4627 case RangeBefore:
4628 assert(0 && "Infeasible");
4629 case RangeAfter:
4630 break;
4631 case RangeOverlap:
4632 Cursors[I] = updateC;
4633 AdvanceToken();
4634 continue;
4635 }
4636 break;
4637 }
4638 const unsigned Last = NextToken();
Ted Kremenek6db61092010-05-05 00:55:15 +00004639
Ted Kremenekfbd84ca2010-05-05 00:55:23 +00004640 // Scan the tokens that are at the beginning of the cursor, but are not
4641 // capture by the child cursors.
4642
4643 // For AST elements within macros, rely on a post-annotate pass to
4644 // to correctly annotate the tokens with cursors. Otherwise we can
4645 // get confusing results of having tokens that map to cursors that really
4646 // are expanded by an instantiation.
4647 if (L.isMacroID())
4648 cursor = clang_getNullCursor();
4649
4650 for (unsigned I = BeforeChildren; I != AfterChildren; ++I) {
4651 if (!clang_isInvalid(clang_getCursorKind(Cursors[I])))
4652 break;
Douglas Gregor4419b672010-10-21 06:10:04 +00004653
Ted Kremenekfbd84ca2010-05-05 00:55:23 +00004654 Cursors[I] = cursor;
4655 }
4656 // Scan the tokens that are at the end of the cursor, but are not captured
4657 // but the child cursors.
4658 for (unsigned I = AfterChildren; I != Last; ++I)
4659 Cursors[I] = cursor;
4660
4661 TokIdx = Last;
4662 return CXChildVisit_Continue;
Douglas Gregor0045e9f2010-01-26 18:31:56 +00004663}
4664
Ted Kremenek6db61092010-05-05 00:55:15 +00004665static enum CXChildVisitResult AnnotateTokensVisitor(CXCursor cursor,
4666 CXCursor parent,
4667 CXClientData client_data) {
4668 return static_cast<AnnotateTokensWorker*>(client_data)->Visit(cursor, parent);
4669}
4670
Ted Kremenek6628a612011-03-18 22:51:30 +00004671namespace {
4672 struct clang_annotateTokens_Data {
4673 CXTranslationUnit TU;
4674 ASTUnit *CXXUnit;
4675 CXToken *Tokens;
4676 unsigned NumTokens;
4677 CXCursor *Cursors;
4678 };
4679}
4680
Ted Kremenekab979612010-11-11 08:05:23 +00004681// This gets run a separate thread to avoid stack blowout.
Ted Kremenek6628a612011-03-18 22:51:30 +00004682static void clang_annotateTokensImpl(void *UserData) {
4683 CXTranslationUnit TU = ((clang_annotateTokens_Data*)UserData)->TU;
4684 ASTUnit *CXXUnit = ((clang_annotateTokens_Data*)UserData)->CXXUnit;
4685 CXToken *Tokens = ((clang_annotateTokens_Data*)UserData)->Tokens;
4686 const unsigned NumTokens = ((clang_annotateTokens_Data*)UserData)->NumTokens;
4687 CXCursor *Cursors = ((clang_annotateTokens_Data*)UserData)->Cursors;
4688
4689 // Determine the region of interest, which contains all of the tokens.
4690 SourceRange RegionOfInterest;
4691 RegionOfInterest.setBegin(
4692 cxloc::translateSourceLocation(clang_getTokenLocation(TU, Tokens[0])));
4693 RegionOfInterest.setEnd(
4694 cxloc::translateSourceLocation(clang_getTokenLocation(TU,
4695 Tokens[NumTokens-1])));
4696
4697 // A mapping from the source locations found when re-lexing or traversing the
4698 // region of interest to the corresponding cursors.
4699 AnnotateTokensData Annotated;
4700
4701 // Relex the tokens within the source range to look for preprocessing
4702 // directives.
4703 SourceManager &SourceMgr = CXXUnit->getSourceManager();
4704 std::pair<FileID, unsigned> BeginLocInfo
4705 = SourceMgr.getDecomposedLoc(RegionOfInterest.getBegin());
4706 std::pair<FileID, unsigned> EndLocInfo
4707 = SourceMgr.getDecomposedLoc(RegionOfInterest.getEnd());
4708
4709 llvm::StringRef Buffer;
4710 bool Invalid = false;
4711 if (BeginLocInfo.first == EndLocInfo.first &&
4712 ((Buffer = SourceMgr.getBufferData(BeginLocInfo.first, &Invalid)),true) &&
4713 !Invalid) {
4714 Lexer Lex(SourceMgr.getLocForStartOfFile(BeginLocInfo.first),
4715 CXXUnit->getASTContext().getLangOptions(),
4716 Buffer.begin(), Buffer.data() + BeginLocInfo.second,
4717 Buffer.end());
4718 Lex.SetCommentRetentionState(true);
4719
4720 // Lex tokens in raw mode until we hit the end of the range, to avoid
4721 // entering #includes or expanding macros.
4722 while (true) {
4723 Token Tok;
4724 Lex.LexFromRawLexer(Tok);
4725
4726 reprocess:
4727 if (Tok.is(tok::hash) && Tok.isAtStartOfLine()) {
4728 // We have found a preprocessing directive. Gobble it up so that we
4729 // don't see it while preprocessing these tokens later, but keep track
4730 // of all of the token locations inside this preprocessing directive so
4731 // that we can annotate them appropriately.
4732 //
4733 // FIXME: Some simple tests here could identify macro definitions and
4734 // #undefs, to provide specific cursor kinds for those.
4735 llvm::SmallVector<SourceLocation, 32> Locations;
4736 do {
4737 Locations.push_back(Tok.getLocation());
4738 Lex.LexFromRawLexer(Tok);
4739 } while (!Tok.isAtStartOfLine() && !Tok.is(tok::eof));
4740
4741 using namespace cxcursor;
4742 CXCursor Cursor
4743 = MakePreprocessingDirectiveCursor(SourceRange(Locations.front(),
4744 Locations.back()),
4745 TU);
4746 for (unsigned I = 0, N = Locations.size(); I != N; ++I) {
4747 Annotated[Locations[I].getRawEncoding()] = Cursor;
4748 }
4749
4750 if (Tok.isAtStartOfLine())
4751 goto reprocess;
4752
4753 continue;
4754 }
4755
4756 if (Tok.is(tok::eof))
4757 break;
4758 }
4759 }
4760
4761 // Annotate all of the source locations in the region of interest that map to
4762 // a specific cursor.
4763 AnnotateTokensWorker W(Annotated, Tokens, Cursors, NumTokens,
4764 TU, RegionOfInterest);
4765
4766 // FIXME: We use a ridiculous stack size here because the data-recursion
4767 // algorithm uses a large stack frame than the non-data recursive version,
4768 // and AnnotationTokensWorker currently transforms the data-recursion
4769 // algorithm back into a traditional recursion by explicitly calling
4770 // VisitChildren(). We will need to remove this explicit recursive call.
4771 W.AnnotateTokens();
4772
4773 // If we ran into any entities that involve context-sensitive keywords,
4774 // take another pass through the tokens to mark them as such.
4775 if (W.hasContextSensitiveKeywords()) {
4776 for (unsigned I = 0; I != NumTokens; ++I) {
4777 if (clang_getTokenKind(Tokens[I]) != CXToken_Identifier)
4778 continue;
4779
4780 if (Cursors[I].kind == CXCursor_ObjCPropertyDecl) {
4781 IdentifierInfo *II = static_cast<IdentifierInfo *>(Tokens[I].ptr_data);
4782 if (ObjCPropertyDecl *Property
4783 = dyn_cast_or_null<ObjCPropertyDecl>(getCursorDecl(Cursors[I]))) {
4784 if (Property->getPropertyAttributesAsWritten() != 0 &&
4785 llvm::StringSwitch<bool>(II->getName())
4786 .Case("readonly", true)
4787 .Case("assign", true)
4788 .Case("readwrite", true)
4789 .Case("retain", true)
4790 .Case("copy", true)
4791 .Case("nonatomic", true)
4792 .Case("atomic", true)
4793 .Case("getter", true)
4794 .Case("setter", true)
4795 .Default(false))
4796 Tokens[I].int_data[0] = CXToken_Keyword;
4797 }
4798 continue;
4799 }
4800
4801 if (Cursors[I].kind == CXCursor_ObjCInstanceMethodDecl ||
4802 Cursors[I].kind == CXCursor_ObjCClassMethodDecl) {
4803 IdentifierInfo *II = static_cast<IdentifierInfo *>(Tokens[I].ptr_data);
4804 if (llvm::StringSwitch<bool>(II->getName())
4805 .Case("in", true)
4806 .Case("out", true)
4807 .Case("inout", true)
4808 .Case("oneway", true)
4809 .Case("bycopy", true)
4810 .Case("byref", true)
4811 .Default(false))
4812 Tokens[I].int_data[0] = CXToken_Keyword;
4813 continue;
4814 }
4815
4816 if (Cursors[I].kind == CXCursor_CXXMethod) {
4817 IdentifierInfo *II = static_cast<IdentifierInfo *>(Tokens[I].ptr_data);
4818 if (CXXMethodDecl *Method
4819 = dyn_cast_or_null<CXXMethodDecl>(getCursorDecl(Cursors[I]))) {
4820 if ((Method->hasAttr<FinalAttr>() ||
4821 Method->hasAttr<OverrideAttr>()) &&
4822 Method->getLocation().getRawEncoding() != Tokens[I].int_data[1] &&
4823 llvm::StringSwitch<bool>(II->getName())
4824 .Case("final", true)
4825 .Case("override", true)
4826 .Default(false))
4827 Tokens[I].int_data[0] = CXToken_Keyword;
4828 }
4829 continue;
4830 }
4831
4832 if (Cursors[I].kind == CXCursor_ClassDecl ||
4833 Cursors[I].kind == CXCursor_StructDecl ||
4834 Cursors[I].kind == CXCursor_ClassTemplate) {
4835 IdentifierInfo *II = static_cast<IdentifierInfo *>(Tokens[I].ptr_data);
4836 if (II->getName() == "final") {
4837 // We have to be careful with 'final', since it could be the name
4838 // of a member class rather than the context-sensitive keyword.
4839 // So, check whether the cursor associated with this
4840 Decl *D = getCursorDecl(Cursors[I]);
4841 if (CXXRecordDecl *Record = dyn_cast_or_null<CXXRecordDecl>(D)) {
4842 if ((Record->hasAttr<FinalAttr>()) &&
4843 Record->getIdentifier() != II)
4844 Tokens[I].int_data[0] = CXToken_Keyword;
4845 } else if (ClassTemplateDecl *ClassTemplate
4846 = dyn_cast_or_null<ClassTemplateDecl>(D)) {
4847 CXXRecordDecl *Record = ClassTemplate->getTemplatedDecl();
4848 if ((Record->hasAttr<FinalAttr>()) &&
4849 Record->getIdentifier() != II)
4850 Tokens[I].int_data[0] = CXToken_Keyword;
4851 }
4852 }
4853 continue;
4854 }
4855 }
4856 }
Ted Kremenekab979612010-11-11 08:05:23 +00004857}
4858
Ted Kremenek6db61092010-05-05 00:55:15 +00004859extern "C" {
4860
Douglas Gregorfc8ea232010-01-26 17:06:03 +00004861void clang_annotateTokens(CXTranslationUnit TU,
4862 CXToken *Tokens, unsigned NumTokens,
4863 CXCursor *Cursors) {
Ted Kremenekfbd84ca2010-05-05 00:55:23 +00004864
4865 if (NumTokens == 0 || !Tokens || !Cursors)
Douglas Gregor0045e9f2010-01-26 18:31:56 +00004866 return;
Ted Kremenekfbd84ca2010-05-05 00:55:23 +00004867
Douglas Gregor4419b672010-10-21 06:10:04 +00004868 // Any token we don't specifically annotate will have a NULL cursor.
4869 CXCursor C = clang_getNullCursor();
4870 for (unsigned I = 0; I != NumTokens; ++I)
4871 Cursors[I] = C;
4872
Ted Kremeneka60ed472010-11-16 08:15:36 +00004873 ASTUnit *CXXUnit = static_cast<ASTUnit *>(TU->TUData);
Douglas Gregor4419b672010-10-21 06:10:04 +00004874 if (!CXXUnit)
Douglas Gregor0045e9f2010-01-26 18:31:56 +00004875 return;
Ted Kremenekfbd84ca2010-05-05 00:55:23 +00004876
Douglas Gregorbdf60622010-03-05 21:16:25 +00004877 ASTUnit::ConcurrencyCheck Check(*CXXUnit);
Ted Kremenek6628a612011-03-18 22:51:30 +00004878
4879 clang_annotateTokens_Data data = { TU, CXXUnit, Tokens, NumTokens, Cursors };
Ted Kremenekab979612010-11-11 08:05:23 +00004880 llvm::CrashRecoveryContext CRC;
Ted Kremenek6628a612011-03-18 22:51:30 +00004881 if (!RunSafely(CRC, clang_annotateTokensImpl, &data,
Ted Kremenek6c53fdd2010-11-14 17:47:35 +00004882 GetSafetyThreadStackSize() * 2)) {
Ted Kremenekab979612010-11-11 08:05:23 +00004883 fprintf(stderr, "libclang: crash detected while annotating tokens\n");
4884 }
Douglas Gregorfc8ea232010-01-26 17:06:03 +00004885}
Ted Kremenek6628a612011-03-18 22:51:30 +00004886
Douglas Gregorfc8ea232010-01-26 17:06:03 +00004887} // end: extern "C"
4888
4889//===----------------------------------------------------------------------===//
Ted Kremenek16b42592010-03-03 06:36:57 +00004890// Operations for querying linkage of a cursor.
4891//===----------------------------------------------------------------------===//
4892
4893extern "C" {
4894CXLinkageKind clang_getCursorLinkage(CXCursor cursor) {
Douglas Gregor0396f462010-03-19 05:22:59 +00004895 if (!clang_isDeclaration(cursor.kind))
4896 return CXLinkage_Invalid;
4897
Ted Kremenek16b42592010-03-03 06:36:57 +00004898 Decl *D = cxcursor::getCursorDecl(cursor);
4899 if (NamedDecl *ND = dyn_cast_or_null<NamedDecl>(D))
4900 switch (ND->getLinkage()) {
4901 case NoLinkage: return CXLinkage_NoLinkage;
4902 case InternalLinkage: return CXLinkage_Internal;
4903 case UniqueExternalLinkage: return CXLinkage_UniqueExternal;
4904 case ExternalLinkage: return CXLinkage_External;
4905 };
4906
4907 return CXLinkage_Invalid;
4908}
4909} // end: extern "C"
4910
4911//===----------------------------------------------------------------------===//
Ted Kremenek45e1dae2010-04-12 21:22:16 +00004912// Operations for querying language of a cursor.
4913//===----------------------------------------------------------------------===//
4914
4915static CXLanguageKind getDeclLanguage(const Decl *D) {
4916 switch (D->getKind()) {
4917 default:
4918 break;
4919 case Decl::ImplicitParam:
4920 case Decl::ObjCAtDefsField:
4921 case Decl::ObjCCategory:
4922 case Decl::ObjCCategoryImpl:
4923 case Decl::ObjCClass:
4924 case Decl::ObjCCompatibleAlias:
Ted Kremenek45e1dae2010-04-12 21:22:16 +00004925 case Decl::ObjCForwardProtocol:
4926 case Decl::ObjCImplementation:
4927 case Decl::ObjCInterface:
4928 case Decl::ObjCIvar:
4929 case Decl::ObjCMethod:
4930 case Decl::ObjCProperty:
4931 case Decl::ObjCPropertyImpl:
4932 case Decl::ObjCProtocol:
4933 return CXLanguage_ObjC;
4934 case Decl::CXXConstructor:
4935 case Decl::CXXConversion:
4936 case Decl::CXXDestructor:
4937 case Decl::CXXMethod:
4938 case Decl::CXXRecord:
4939 case Decl::ClassTemplate:
4940 case Decl::ClassTemplatePartialSpecialization:
4941 case Decl::ClassTemplateSpecialization:
4942 case Decl::Friend:
4943 case Decl::FriendTemplate:
4944 case Decl::FunctionTemplate:
4945 case Decl::LinkageSpec:
4946 case Decl::Namespace:
4947 case Decl::NamespaceAlias:
4948 case Decl::NonTypeTemplateParm:
4949 case Decl::StaticAssert:
Ted Kremenek45e1dae2010-04-12 21:22:16 +00004950 case Decl::TemplateTemplateParm:
4951 case Decl::TemplateTypeParm:
4952 case Decl::UnresolvedUsingTypename:
4953 case Decl::UnresolvedUsingValue:
4954 case Decl::Using:
4955 case Decl::UsingDirective:
4956 case Decl::UsingShadow:
4957 return CXLanguage_CPlusPlus;
4958 }
4959
4960 return CXLanguage_C;
4961}
4962
4963extern "C" {
Douglas Gregor58ddb602010-08-23 23:00:57 +00004964
4965enum CXAvailabilityKind clang_getCursorAvailability(CXCursor cursor) {
4966 if (clang_isDeclaration(cursor.kind))
4967 if (Decl *D = cxcursor::getCursorDecl(cursor)) {
Douglas Gregor0a0d2b12011-03-23 00:50:03 +00004968 if (isa<FunctionDecl>(D) && cast<FunctionDecl>(D)->isDeleted())
Douglas Gregor58ddb602010-08-23 23:00:57 +00004969 return CXAvailability_Available;
4970
Douglas Gregor0a0d2b12011-03-23 00:50:03 +00004971 switch (D->getAvailability()) {
4972 case AR_Available:
4973 case AR_NotYetIntroduced:
4974 return CXAvailability_Available;
4975
4976 case AR_Deprecated:
Douglas Gregor58ddb602010-08-23 23:00:57 +00004977 return CXAvailability_Deprecated;
Douglas Gregor0a0d2b12011-03-23 00:50:03 +00004978
4979 case AR_Unavailable:
4980 return CXAvailability_NotAvailable;
4981 }
Douglas Gregor58ddb602010-08-23 23:00:57 +00004982 }
Douglas Gregor0a0d2b12011-03-23 00:50:03 +00004983
Douglas Gregor58ddb602010-08-23 23:00:57 +00004984 return CXAvailability_Available;
4985}
4986
Ted Kremenek45e1dae2010-04-12 21:22:16 +00004987CXLanguageKind clang_getCursorLanguage(CXCursor cursor) {
4988 if (clang_isDeclaration(cursor.kind))
4989 return getDeclLanguage(cxcursor::getCursorDecl(cursor));
4990
4991 return CXLanguage_Invalid;
4992}
Douglas Gregor3910cfd2010-12-21 07:55:45 +00004993
4994 /// \brief If the given cursor is the "templated" declaration
4995 /// descibing a class or function template, return the class or
4996 /// function template.
4997static Decl *maybeGetTemplateCursor(Decl *D) {
4998 if (!D)
4999 return 0;
5000
5001 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
5002 if (FunctionTemplateDecl *FunTmpl = FD->getDescribedFunctionTemplate())
5003 return FunTmpl;
5004
5005 if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D))
5006 if (ClassTemplateDecl *ClassTmpl = RD->getDescribedClassTemplate())
5007 return ClassTmpl;
5008
5009 return D;
5010}
5011
Douglas Gregor2be5bc92010-09-22 21:22:29 +00005012CXCursor clang_getCursorSemanticParent(CXCursor cursor) {
5013 if (clang_isDeclaration(cursor.kind)) {
5014 if (Decl *D = getCursorDecl(cursor)) {
5015 DeclContext *DC = D->getDeclContext();
Douglas Gregor3910cfd2010-12-21 07:55:45 +00005016 if (!DC)
5017 return clang_getNullCursor();
5018
5019 return MakeCXCursor(maybeGetTemplateCursor(cast<Decl>(DC)),
5020 getCursorTU(cursor));
Douglas Gregor2be5bc92010-09-22 21:22:29 +00005021 }
5022 }
5023
5024 if (clang_isStatement(cursor.kind) || clang_isExpression(cursor.kind)) {
5025 if (Decl *D = getCursorDecl(cursor))
Ted Kremeneka60ed472010-11-16 08:15:36 +00005026 return MakeCXCursor(D, getCursorTU(cursor));
Douglas Gregor2be5bc92010-09-22 21:22:29 +00005027 }
5028
5029 return clang_getNullCursor();
5030}
5031
5032CXCursor clang_getCursorLexicalParent(CXCursor cursor) {
5033 if (clang_isDeclaration(cursor.kind)) {
5034 if (Decl *D = getCursorDecl(cursor)) {
5035 DeclContext *DC = D->getLexicalDeclContext();
Douglas Gregor3910cfd2010-12-21 07:55:45 +00005036 if (!DC)
5037 return clang_getNullCursor();
5038
5039 return MakeCXCursor(maybeGetTemplateCursor(cast<Decl>(DC)),
5040 getCursorTU(cursor));
Douglas Gregor2be5bc92010-09-22 21:22:29 +00005041 }
5042 }
5043
5044 // FIXME: Note that we can't easily compute the lexical context of a
5045 // statement or expression, so we return nothing.
5046 return clang_getNullCursor();
5047}
5048
Douglas Gregor9f592342010-10-01 20:25:15 +00005049static void CollectOverriddenMethods(DeclContext *Ctx,
5050 ObjCMethodDecl *Method,
5051 llvm::SmallVectorImpl<ObjCMethodDecl *> &Methods) {
5052 if (!Ctx)
5053 return;
5054
5055 // If we have a class or category implementation, jump straight to the
5056 // interface.
5057 if (ObjCImplDecl *Impl = dyn_cast<ObjCImplDecl>(Ctx))
5058 return CollectOverriddenMethods(Impl->getClassInterface(), Method, Methods);
5059
5060 ObjCContainerDecl *Container = dyn_cast<ObjCContainerDecl>(Ctx);
5061 if (!Container)
5062 return;
5063
5064 // Check whether we have a matching method at this level.
5065 if (ObjCMethodDecl *Overridden = Container->getMethod(Method->getSelector(),
5066 Method->isInstanceMethod()))
5067 if (Method != Overridden) {
5068 // We found an override at this level; there is no need to look
5069 // into other protocols or categories.
5070 Methods.push_back(Overridden);
5071 return;
5072 }
5073
5074 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
5075 for (ObjCProtocolDecl::protocol_iterator P = Protocol->protocol_begin(),
5076 PEnd = Protocol->protocol_end();
5077 P != PEnd; ++P)
5078 CollectOverriddenMethods(*P, Method, Methods);
5079 }
5080
5081 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Container)) {
5082 for (ObjCCategoryDecl::protocol_iterator P = Category->protocol_begin(),
5083 PEnd = Category->protocol_end();
5084 P != PEnd; ++P)
5085 CollectOverriddenMethods(*P, Method, Methods);
5086 }
5087
5088 if (ObjCInterfaceDecl *Interface = dyn_cast<ObjCInterfaceDecl>(Container)) {
5089 for (ObjCInterfaceDecl::protocol_iterator P = Interface->protocol_begin(),
5090 PEnd = Interface->protocol_end();
5091 P != PEnd; ++P)
5092 CollectOverriddenMethods(*P, Method, Methods);
5093
5094 for (ObjCCategoryDecl *Category = Interface->getCategoryList();
5095 Category; Category = Category->getNextClassCategory())
5096 CollectOverriddenMethods(Category, Method, Methods);
5097
5098 // We only look into the superclass if we haven't found anything yet.
5099 if (Methods.empty())
5100 if (ObjCInterfaceDecl *Super = Interface->getSuperClass())
5101 return CollectOverriddenMethods(Super, Method, Methods);
5102 }
5103}
5104
5105void clang_getOverriddenCursors(CXCursor cursor,
5106 CXCursor **overridden,
5107 unsigned *num_overridden) {
5108 if (overridden)
5109 *overridden = 0;
5110 if (num_overridden)
5111 *num_overridden = 0;
5112 if (!overridden || !num_overridden)
5113 return;
5114
5115 if (!clang_isDeclaration(cursor.kind))
5116 return;
5117
5118 Decl *D = getCursorDecl(cursor);
5119 if (!D)
5120 return;
5121
5122 // Handle C++ member functions.
Ted Kremeneka60ed472010-11-16 08:15:36 +00005123 CXTranslationUnit TU = getCursorTU(cursor);
Douglas Gregor9f592342010-10-01 20:25:15 +00005124 if (CXXMethodDecl *CXXMethod = dyn_cast<CXXMethodDecl>(D)) {
5125 *num_overridden = CXXMethod->size_overridden_methods();
5126 if (!*num_overridden)
5127 return;
5128
5129 *overridden = new CXCursor [*num_overridden];
5130 unsigned I = 0;
5131 for (CXXMethodDecl::method_iterator
5132 M = CXXMethod->begin_overridden_methods(),
5133 MEnd = CXXMethod->end_overridden_methods();
5134 M != MEnd; (void)++M, ++I)
Ted Kremeneka60ed472010-11-16 08:15:36 +00005135 (*overridden)[I] = MakeCXCursor(const_cast<CXXMethodDecl*>(*M), TU);
Douglas Gregor9f592342010-10-01 20:25:15 +00005136 return;
5137 }
5138
5139 ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(D);
5140 if (!Method)
5141 return;
5142
5143 // Handle Objective-C methods.
5144 llvm::SmallVector<ObjCMethodDecl *, 4> Methods;
5145 CollectOverriddenMethods(Method->getDeclContext(), Method, Methods);
5146
5147 if (Methods.empty())
5148 return;
5149
5150 *num_overridden = Methods.size();
5151 *overridden = new CXCursor [Methods.size()];
5152 for (unsigned I = 0, N = Methods.size(); I != N; ++I)
Ted Kremeneka60ed472010-11-16 08:15:36 +00005153 (*overridden)[I] = MakeCXCursor(Methods[I], TU);
Douglas Gregor9f592342010-10-01 20:25:15 +00005154}
5155
5156void clang_disposeOverriddenCursors(CXCursor *overridden) {
5157 delete [] overridden;
5158}
5159
Douglas Gregorecdcb882010-10-20 22:00:55 +00005160CXFile clang_getIncludedFile(CXCursor cursor) {
5161 if (cursor.kind != CXCursor_InclusionDirective)
5162 return 0;
5163
5164 InclusionDirective *ID = getCursorInclusionDirective(cursor);
5165 return (void *)ID->getFile();
5166}
5167
Ted Kremenek45e1dae2010-04-12 21:22:16 +00005168} // end: extern "C"
5169
Ted Kremenek9ada39a2010-05-17 20:06:56 +00005170
5171//===----------------------------------------------------------------------===//
5172// C++ AST instrospection.
5173//===----------------------------------------------------------------------===//
5174
5175extern "C" {
5176unsigned clang_CXXMethod_isStatic(CXCursor C) {
5177 if (!clang_isDeclaration(C.kind))
5178 return 0;
Douglas Gregor49f6f542010-08-31 22:12:17 +00005179
5180 CXXMethodDecl *Method = 0;
5181 Decl *D = cxcursor::getCursorDecl(C);
5182 if (FunctionTemplateDecl *FunTmpl = dyn_cast_or_null<FunctionTemplateDecl>(D))
5183 Method = dyn_cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl());
5184 else
5185 Method = dyn_cast_or_null<CXXMethodDecl>(D);
5186 return (Method && Method->isStatic()) ? 1 : 0;
Ted Kremenek40b492a2010-05-17 20:12:45 +00005187}
Ted Kremenekb12903e2010-05-18 22:32:15 +00005188
Douglas Gregor211924b2011-05-12 15:17:24 +00005189unsigned clang_CXXMethod_isVirtual(CXCursor C) {
5190 if (!clang_isDeclaration(C.kind))
5191 return 0;
5192
5193 CXXMethodDecl *Method = 0;
5194 Decl *D = cxcursor::getCursorDecl(C);
5195 if (FunctionTemplateDecl *FunTmpl = dyn_cast_or_null<FunctionTemplateDecl>(D))
5196 Method = dyn_cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl());
5197 else
5198 Method = dyn_cast_or_null<CXXMethodDecl>(D);
5199 return (Method && Method->isVirtual()) ? 1 : 0;
5200}
5201
Ted Kremenek9ada39a2010-05-17 20:06:56 +00005202} // end: extern "C"
5203
Ted Kremenek45e1dae2010-04-12 21:22:16 +00005204//===----------------------------------------------------------------------===//
Ted Kremenek95f33552010-08-26 01:42:22 +00005205// Attribute introspection.
5206//===----------------------------------------------------------------------===//
5207
5208extern "C" {
5209CXType clang_getIBOutletCollectionType(CXCursor C) {
5210 if (C.kind != CXCursor_IBOutletCollectionAttr)
Ted Kremeneka60ed472010-11-16 08:15:36 +00005211 return cxtype::MakeCXType(QualType(), cxcursor::getCursorTU(C));
Ted Kremenek95f33552010-08-26 01:42:22 +00005212
5213 IBOutletCollectionAttr *A =
5214 cast<IBOutletCollectionAttr>(cxcursor::getCursorAttr(C));
5215
Douglas Gregor841b2382011-03-06 18:55:32 +00005216 return cxtype::MakeCXType(A->getInterFace(), cxcursor::getCursorTU(C));
Ted Kremenek95f33552010-08-26 01:42:22 +00005217}
5218} // end: extern "C"
5219
5220//===----------------------------------------------------------------------===//
Ted Kremenek59fc1e52011-04-18 22:47:10 +00005221// Inspecting memory usage.
5222//===----------------------------------------------------------------------===//
5223
Ted Kremenekf7870022011-04-20 16:41:07 +00005224typedef std::vector<CXTUResourceUsageEntry> MemUsageEntries;
Ted Kremenek59fc1e52011-04-18 22:47:10 +00005225
Ted Kremenekf7870022011-04-20 16:41:07 +00005226static inline void createCXTUResourceUsageEntry(MemUsageEntries &entries,
5227 enum CXTUResourceUsageKind k,
Ted Kremenekba29bd22011-04-28 04:53:38 +00005228 unsigned long amount) {
Ted Kremenekf7870022011-04-20 16:41:07 +00005229 CXTUResourceUsageEntry entry = { k, amount };
Ted Kremenek59fc1e52011-04-18 22:47:10 +00005230 entries.push_back(entry);
5231}
5232
5233extern "C" {
5234
Ted Kremenekf7870022011-04-20 16:41:07 +00005235const char *clang_getTUResourceUsageName(CXTUResourceUsageKind kind) {
Ted Kremenek59fc1e52011-04-18 22:47:10 +00005236 const char *str = "";
5237 switch (kind) {
Ted Kremenekf7870022011-04-20 16:41:07 +00005238 case CXTUResourceUsage_AST:
Ted Kremenek59fc1e52011-04-18 22:47:10 +00005239 str = "ASTContext: expressions, declarations, and types";
5240 break;
Ted Kremenekf7870022011-04-20 16:41:07 +00005241 case CXTUResourceUsage_Identifiers:
Ted Kremenek59fc1e52011-04-18 22:47:10 +00005242 str = "ASTContext: identifiers";
5243 break;
Ted Kremenekf7870022011-04-20 16:41:07 +00005244 case CXTUResourceUsage_Selectors:
Ted Kremenek59fc1e52011-04-18 22:47:10 +00005245 str = "ASTContext: selectors";
Ted Kremeneke294ab72011-04-19 04:36:17 +00005246 break;
Ted Kremenekf7870022011-04-20 16:41:07 +00005247 case CXTUResourceUsage_GlobalCompletionResults:
Ted Kremenek4e6a3f72011-04-18 23:42:53 +00005248 str = "Code completion: cached global results";
Ted Kremeneke294ab72011-04-19 04:36:17 +00005249 break;
Ted Kremenek457aaf02011-04-28 04:10:31 +00005250 case CXTUResourceUsage_SourceManagerContentCache:
5251 str = "SourceManager: content cache allocator";
5252 break;
Ted Kremenekba29bd22011-04-28 04:53:38 +00005253 case CXTUResourceUsage_AST_SideTables:
5254 str = "ASTContext: side tables";
5255 break;
Ted Kremenekf61b8312011-04-28 20:36:42 +00005256 case CXTUResourceUsage_SourceManager_Membuffer_Malloc:
5257 str = "SourceManager: malloc'ed memory buffers";
5258 break;
5259 case CXTUResourceUsage_SourceManager_Membuffer_MMap:
5260 str = "SourceManager: mmap'ed memory buffers";
5261 break;
Ted Kremeneke9b5f3d2011-04-28 23:46:20 +00005262 case CXTUResourceUsage_ExternalASTSource_Membuffer_Malloc:
5263 str = "ExternalASTSource: malloc'ed memory buffers";
5264 break;
5265 case CXTUResourceUsage_ExternalASTSource_Membuffer_MMap:
5266 str = "ExternalASTSource: mmap'ed memory buffers";
5267 break;
Ted Kremenek5e1db6a2011-05-04 01:38:46 +00005268 case CXTUResourceUsage_Preprocessor:
5269 str = "Preprocessor: malloc'ed memory";
5270 break;
5271 case CXTUResourceUsage_PreprocessingRecord:
5272 str = "Preprocessor: PreprocessingRecord";
5273 break;
Ted Kremenek59fc1e52011-04-18 22:47:10 +00005274 }
5275 return str;
5276}
5277
Ted Kremenekf7870022011-04-20 16:41:07 +00005278CXTUResourceUsage clang_getCXTUResourceUsage(CXTranslationUnit TU) {
Ted Kremenek59fc1e52011-04-18 22:47:10 +00005279 if (!TU) {
Ted Kremenekf7870022011-04-20 16:41:07 +00005280 CXTUResourceUsage usage = { (void*) 0, 0, 0 };
Ted Kremenek59fc1e52011-04-18 22:47:10 +00005281 return usage;
5282 }
5283
5284 ASTUnit *astUnit = static_cast<ASTUnit*>(TU->TUData);
5285 llvm::OwningPtr<MemUsageEntries> entries(new MemUsageEntries());
5286 ASTContext &astContext = astUnit->getASTContext();
5287
5288 // How much memory is used by AST nodes and types?
Ted Kremenekf7870022011-04-20 16:41:07 +00005289 createCXTUResourceUsageEntry(*entries, CXTUResourceUsage_AST,
Ted Kremenekba29bd22011-04-28 04:53:38 +00005290 (unsigned long) astContext.getASTAllocatedMemory());
Ted Kremenek59fc1e52011-04-18 22:47:10 +00005291
5292 // How much memory is used by identifiers?
Ted Kremenekf7870022011-04-20 16:41:07 +00005293 createCXTUResourceUsageEntry(*entries, CXTUResourceUsage_Identifiers,
Ted Kremenek59fc1e52011-04-18 22:47:10 +00005294 (unsigned long) astContext.Idents.getAllocator().getTotalMemory());
5295
5296 // How much memory is used for selectors?
Ted Kremenekf7870022011-04-20 16:41:07 +00005297 createCXTUResourceUsageEntry(*entries, CXTUResourceUsage_Selectors,
Ted Kremenek59fc1e52011-04-18 22:47:10 +00005298 (unsigned long) astContext.Selectors.getTotalMemory());
5299
Ted Kremenekba29bd22011-04-28 04:53:38 +00005300 // How much memory is used by ASTContext's side tables?
5301 createCXTUResourceUsageEntry(*entries, CXTUResourceUsage_AST_SideTables,
5302 (unsigned long) astContext.getSideTableAllocatedMemory());
5303
Ted Kremenek4e6a3f72011-04-18 23:42:53 +00005304 // How much memory is used for caching global code completion results?
5305 unsigned long completionBytes = 0;
5306 if (GlobalCodeCompletionAllocator *completionAllocator =
5307 astUnit->getCachedCompletionAllocator().getPtr()) {
Ted Kremenek5e1db6a2011-05-04 01:38:46 +00005308 completionBytes = completionAllocator->getTotalMemory();
Ted Kremenek4e6a3f72011-04-18 23:42:53 +00005309 }
Ted Kremenek457aaf02011-04-28 04:10:31 +00005310 createCXTUResourceUsageEntry(*entries,
5311 CXTUResourceUsage_GlobalCompletionResults,
5312 completionBytes);
5313
5314 // How much memory is being used by SourceManager's content cache?
5315 createCXTUResourceUsageEntry(*entries,
5316 CXTUResourceUsage_SourceManagerContentCache,
5317 (unsigned long) astContext.getSourceManager().getContentCacheSize());
Ted Kremenekf61b8312011-04-28 20:36:42 +00005318
5319 // How much memory is being used by the MemoryBuffer's in SourceManager?
5320 const SourceManager::MemoryBufferSizes &srcBufs =
5321 astUnit->getSourceManager().getMemoryBufferSizes();
5322
5323 createCXTUResourceUsageEntry(*entries,
5324 CXTUResourceUsage_SourceManager_Membuffer_Malloc,
5325 (unsigned long) srcBufs.malloc_bytes);
Ted Kremeneke9b5f3d2011-04-28 23:46:20 +00005326 createCXTUResourceUsageEntry(*entries,
Ted Kremenekf61b8312011-04-28 20:36:42 +00005327 CXTUResourceUsage_SourceManager_Membuffer_MMap,
5328 (unsigned long) srcBufs.mmap_bytes);
Ted Kremeneke9b5f3d2011-04-28 23:46:20 +00005329
5330 // How much memory is being used by the ExternalASTSource?
5331 if (ExternalASTSource *esrc = astContext.getExternalSource()) {
5332 const ExternalASTSource::MemoryBufferSizes &sizes =
5333 esrc->getMemoryBufferSizes();
5334
5335 createCXTUResourceUsageEntry(*entries,
5336 CXTUResourceUsage_ExternalASTSource_Membuffer_Malloc,
5337 (unsigned long) sizes.malloc_bytes);
5338 createCXTUResourceUsageEntry(*entries,
5339 CXTUResourceUsage_ExternalASTSource_Membuffer_MMap,
5340 (unsigned long) sizes.mmap_bytes);
5341 }
Ted Kremenek5e1db6a2011-05-04 01:38:46 +00005342
5343 // How much memory is being used by the Preprocessor?
5344 Preprocessor &pp = astUnit->getPreprocessor();
5345 const llvm::BumpPtrAllocator &ppAlloc = pp.getPreprocessorAllocator();
5346 createCXTUResourceUsageEntry(*entries,
5347 CXTUResourceUsage_Preprocessor,
5348 ppAlloc.getTotalMemory());
5349
5350 if (PreprocessingRecord *pRec = pp.getPreprocessingRecord()) {
5351 createCXTUResourceUsageEntry(*entries,
5352 CXTUResourceUsage_PreprocessingRecord,
5353 pRec->getTotalMemory());
5354 }
5355
5356
Ted Kremenekf7870022011-04-20 16:41:07 +00005357 CXTUResourceUsage usage = { (void*) entries.get(),
Ted Kremenek59fc1e52011-04-18 22:47:10 +00005358 (unsigned) entries->size(),
5359 entries->size() ? &(*entries)[0] : 0 };
5360 entries.take();
5361 return usage;
5362}
5363
Ted Kremenekf7870022011-04-20 16:41:07 +00005364void clang_disposeCXTUResourceUsage(CXTUResourceUsage usage) {
Ted Kremenek59fc1e52011-04-18 22:47:10 +00005365 if (usage.data)
5366 delete (MemUsageEntries*) usage.data;
5367}
5368
5369} // end extern "C"
5370
Douglas Gregor6df78732011-05-05 20:27:22 +00005371void clang::PrintLibclangResourceUsage(CXTranslationUnit TU) {
5372 CXTUResourceUsage Usage = clang_getCXTUResourceUsage(TU);
5373 for (unsigned I = 0; I != Usage.numEntries; ++I)
5374 fprintf(stderr, " %s: %lu\n",
5375 clang_getTUResourceUsageName(Usage.entries[I].kind),
5376 Usage.entries[I].amount);
5377
5378 clang_disposeCXTUResourceUsage(Usage);
5379}
5380
Ted Kremenek59fc1e52011-04-18 22:47:10 +00005381//===----------------------------------------------------------------------===//
Ted Kremenek04bb7162010-01-22 22:44:15 +00005382// Misc. utility functions.
5383//===----------------------------------------------------------------------===//
Ted Kremenekf0e23e82010-02-17 00:41:40 +00005384
Daniel Dunbarabdce7a2010-11-05 17:21:46 +00005385/// Default to using an 8 MB stack size on "safety" threads.
5386static unsigned SafetyStackThreadSize = 8 << 20;
Daniel Dunbarbf44c3b2010-11-05 07:19:31 +00005387
5388namespace clang {
5389
5390bool RunSafely(llvm::CrashRecoveryContext &CRC,
Ted Kremenek6c53fdd2010-11-14 17:47:35 +00005391 void (*Fn)(void*), void *UserData,
5392 unsigned Size) {
5393 if (!Size)
5394 Size = GetSafetyThreadStackSize();
5395 if (Size)
Daniel Dunbarbf44c3b2010-11-05 07:19:31 +00005396 return CRC.RunSafelyOnThread(Fn, UserData, Size);
5397 return CRC.RunSafely(Fn, UserData);
5398}
5399
5400unsigned GetSafetyThreadStackSize() {
5401 return SafetyStackThreadSize;
5402}
5403
5404void SetSafetyThreadStackSize(unsigned Value) {
5405 SafetyStackThreadSize = Value;
5406}
5407
5408}
5409
Ted Kremenek04bb7162010-01-22 22:44:15 +00005410extern "C" {
5411
Ted Kremeneka2a9d6e2010-02-12 22:54:40 +00005412CXString clang_getClangVersion() {
Ted Kremenekee4db4f2010-02-17 00:41:08 +00005413 return createCXString(getClangFullVersion());
Ted Kremenek04bb7162010-01-22 22:44:15 +00005414}
5415
5416} // end: extern "C"
Ted Kremenek59fc1e52011-04-18 22:47:10 +00005417