106f32e7eSjoerg //===- CIndex.cpp - Clang-C Source Indexing Library -----------------------===//
206f32e7eSjoerg //
306f32e7eSjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
406f32e7eSjoerg // See https://llvm.org/LICENSE.txt for license information.
506f32e7eSjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
606f32e7eSjoerg //
706f32e7eSjoerg //===----------------------------------------------------------------------===//
806f32e7eSjoerg //
906f32e7eSjoerg // This file implements the main API hooks in the Clang-C Source Indexing
1006f32e7eSjoerg // library.
1106f32e7eSjoerg //
1206f32e7eSjoerg //===----------------------------------------------------------------------===//
1306f32e7eSjoerg
1406f32e7eSjoerg #include "CIndexDiagnostic.h"
1506f32e7eSjoerg #include "CIndexer.h"
1606f32e7eSjoerg #include "CLog.h"
1706f32e7eSjoerg #include "CXCursor.h"
1806f32e7eSjoerg #include "CXSourceLocation.h"
1906f32e7eSjoerg #include "CXString.h"
2006f32e7eSjoerg #include "CXTranslationUnit.h"
2106f32e7eSjoerg #include "CXType.h"
2206f32e7eSjoerg #include "CursorVisitor.h"
2306f32e7eSjoerg #include "clang-c/FatalErrorHandler.h"
2406f32e7eSjoerg #include "clang/AST/Attr.h"
25*13fbcb42Sjoerg #include "clang/AST/DeclObjCCommon.h"
2606f32e7eSjoerg #include "clang/AST/Mangle.h"
27*13fbcb42Sjoerg #include "clang/AST/OpenMPClause.h"
2806f32e7eSjoerg #include "clang/AST/StmtVisitor.h"
2906f32e7eSjoerg #include "clang/Basic/Diagnostic.h"
3006f32e7eSjoerg #include "clang/Basic/DiagnosticCategories.h"
3106f32e7eSjoerg #include "clang/Basic/DiagnosticIDs.h"
3206f32e7eSjoerg #include "clang/Basic/Stack.h"
3306f32e7eSjoerg #include "clang/Basic/TargetInfo.h"
3406f32e7eSjoerg #include "clang/Basic/Version.h"
3506f32e7eSjoerg #include "clang/Frontend/ASTUnit.h"
3606f32e7eSjoerg #include "clang/Frontend/CompilerInstance.h"
3706f32e7eSjoerg #include "clang/Index/CommentToXML.h"
3806f32e7eSjoerg #include "clang/Lex/HeaderSearch.h"
3906f32e7eSjoerg #include "clang/Lex/Lexer.h"
4006f32e7eSjoerg #include "clang/Lex/PreprocessingRecord.h"
4106f32e7eSjoerg #include "clang/Lex/Preprocessor.h"
4206f32e7eSjoerg #include "llvm/ADT/Optional.h"
4306f32e7eSjoerg #include "llvm/ADT/STLExtras.h"
4406f32e7eSjoerg #include "llvm/ADT/StringSwitch.h"
4506f32e7eSjoerg #include "llvm/Config/llvm-config.h"
4606f32e7eSjoerg #include "llvm/Support/Compiler.h"
4706f32e7eSjoerg #include "llvm/Support/CrashRecoveryContext.h"
4806f32e7eSjoerg #include "llvm/Support/Format.h"
4906f32e7eSjoerg #include "llvm/Support/ManagedStatic.h"
5006f32e7eSjoerg #include "llvm/Support/MemoryBuffer.h"
5106f32e7eSjoerg #include "llvm/Support/Program.h"
5206f32e7eSjoerg #include "llvm/Support/SaveAndRestore.h"
5306f32e7eSjoerg #include "llvm/Support/Signals.h"
5406f32e7eSjoerg #include "llvm/Support/TargetSelect.h"
5506f32e7eSjoerg #include "llvm/Support/Threading.h"
5606f32e7eSjoerg #include "llvm/Support/Timer.h"
5706f32e7eSjoerg #include "llvm/Support/raw_ostream.h"
5806f32e7eSjoerg #include <mutex>
5906f32e7eSjoerg
6006f32e7eSjoerg #if LLVM_ENABLE_THREADS != 0 && defined(__APPLE__)
6106f32e7eSjoerg #define USE_DARWIN_THREADS
6206f32e7eSjoerg #endif
6306f32e7eSjoerg
6406f32e7eSjoerg #ifdef USE_DARWIN_THREADS
6506f32e7eSjoerg #include <pthread.h>
6606f32e7eSjoerg #endif
6706f32e7eSjoerg
6806f32e7eSjoerg using namespace clang;
6906f32e7eSjoerg using namespace clang::cxcursor;
7006f32e7eSjoerg using namespace clang::cxtu;
7106f32e7eSjoerg using namespace clang::cxindex;
7206f32e7eSjoerg
MakeCXTranslationUnit(CIndexer * CIdx,std::unique_ptr<ASTUnit> AU)7306f32e7eSjoerg CXTranslationUnit cxtu::MakeCXTranslationUnit(CIndexer *CIdx,
7406f32e7eSjoerg std::unique_ptr<ASTUnit> AU) {
7506f32e7eSjoerg if (!AU)
7606f32e7eSjoerg return nullptr;
7706f32e7eSjoerg assert(CIdx);
7806f32e7eSjoerg CXTranslationUnit D = new CXTranslationUnitImpl();
7906f32e7eSjoerg D->CIdx = CIdx;
8006f32e7eSjoerg D->TheASTUnit = AU.release();
8106f32e7eSjoerg D->StringPool = new cxstring::CXStringPool();
8206f32e7eSjoerg D->Diagnostics = nullptr;
8306f32e7eSjoerg D->OverridenCursorsPool = createOverridenCXCursorsPool();
8406f32e7eSjoerg D->CommentToXML = nullptr;
8506f32e7eSjoerg D->ParsingOptions = 0;
8606f32e7eSjoerg D->Arguments = {};
8706f32e7eSjoerg return D;
8806f32e7eSjoerg }
8906f32e7eSjoerg
isASTReadError(ASTUnit * AU)9006f32e7eSjoerg bool cxtu::isASTReadError(ASTUnit *AU) {
9106f32e7eSjoerg for (ASTUnit::stored_diag_iterator D = AU->stored_diag_begin(),
9206f32e7eSjoerg DEnd = AU->stored_diag_end();
9306f32e7eSjoerg D != DEnd; ++D) {
9406f32e7eSjoerg if (D->getLevel() >= DiagnosticsEngine::Error &&
9506f32e7eSjoerg DiagnosticIDs::getCategoryNumberForDiag(D->getID()) ==
9606f32e7eSjoerg diag::DiagCat_AST_Deserialization_Issue)
9706f32e7eSjoerg return true;
9806f32e7eSjoerg }
9906f32e7eSjoerg return false;
10006f32e7eSjoerg }
10106f32e7eSjoerg
~CXTUOwner()10206f32e7eSjoerg cxtu::CXTUOwner::~CXTUOwner() {
10306f32e7eSjoerg if (TU)
10406f32e7eSjoerg clang_disposeTranslationUnit(TU);
10506f32e7eSjoerg }
10606f32e7eSjoerg
10706f32e7eSjoerg /// Compare two source ranges to determine their relative position in
10806f32e7eSjoerg /// the translation unit.
RangeCompare(SourceManager & SM,SourceRange R1,SourceRange R2)109*13fbcb42Sjoerg static RangeComparisonResult RangeCompare(SourceManager &SM, SourceRange R1,
11006f32e7eSjoerg SourceRange R2) {
11106f32e7eSjoerg assert(R1.isValid() && "First range is invalid?");
11206f32e7eSjoerg assert(R2.isValid() && "Second range is invalid?");
11306f32e7eSjoerg if (R1.getEnd() != R2.getBegin() &&
11406f32e7eSjoerg SM.isBeforeInTranslationUnit(R1.getEnd(), R2.getBegin()))
11506f32e7eSjoerg return RangeBefore;
11606f32e7eSjoerg if (R2.getEnd() != R1.getBegin() &&
11706f32e7eSjoerg SM.isBeforeInTranslationUnit(R2.getEnd(), R1.getBegin()))
11806f32e7eSjoerg return RangeAfter;
11906f32e7eSjoerg return RangeOverlap;
12006f32e7eSjoerg }
12106f32e7eSjoerg
12206f32e7eSjoerg /// Determine if a source location falls within, before, or after a
12306f32e7eSjoerg /// a given source range.
LocationCompare(SourceManager & SM,SourceLocation L,SourceRange R)12406f32e7eSjoerg static RangeComparisonResult LocationCompare(SourceManager &SM,
12506f32e7eSjoerg SourceLocation L, SourceRange R) {
12606f32e7eSjoerg assert(R.isValid() && "First range is invalid?");
12706f32e7eSjoerg assert(L.isValid() && "Second range is invalid?");
12806f32e7eSjoerg if (L == R.getBegin() || L == R.getEnd())
12906f32e7eSjoerg return RangeOverlap;
13006f32e7eSjoerg if (SM.isBeforeInTranslationUnit(L, R.getBegin()))
13106f32e7eSjoerg return RangeBefore;
13206f32e7eSjoerg if (SM.isBeforeInTranslationUnit(R.getEnd(), L))
13306f32e7eSjoerg return RangeAfter;
13406f32e7eSjoerg return RangeOverlap;
13506f32e7eSjoerg }
13606f32e7eSjoerg
13706f32e7eSjoerg /// Translate a Clang source range into a CIndex source range.
13806f32e7eSjoerg ///
13906f32e7eSjoerg /// Clang internally represents ranges where the end location points to the
14006f32e7eSjoerg /// start of the token at the end. However, for external clients it is more
14106f32e7eSjoerg /// useful to have a CXSourceRange be a proper half-open interval. This routine
14206f32e7eSjoerg /// does the appropriate translation.
translateSourceRange(const SourceManager & SM,const LangOptions & LangOpts,const CharSourceRange & R)14306f32e7eSjoerg CXSourceRange cxloc::translateSourceRange(const SourceManager &SM,
14406f32e7eSjoerg const LangOptions &LangOpts,
14506f32e7eSjoerg const CharSourceRange &R) {
14606f32e7eSjoerg // We want the last character in this location, so we will adjust the
14706f32e7eSjoerg // location accordingly.
14806f32e7eSjoerg SourceLocation EndLoc = R.getEnd();
14906f32e7eSjoerg bool IsTokenRange = R.isTokenRange();
150*13fbcb42Sjoerg if (EndLoc.isValid() && EndLoc.isMacroID() &&
151*13fbcb42Sjoerg !SM.isMacroArgExpansion(EndLoc)) {
15206f32e7eSjoerg CharSourceRange Expansion = SM.getExpansionRange(EndLoc);
15306f32e7eSjoerg EndLoc = Expansion.getEnd();
15406f32e7eSjoerg IsTokenRange = Expansion.isTokenRange();
15506f32e7eSjoerg }
15606f32e7eSjoerg if (IsTokenRange && EndLoc.isValid()) {
157*13fbcb42Sjoerg unsigned Length =
158*13fbcb42Sjoerg Lexer::MeasureTokenLength(SM.getSpellingLoc(EndLoc), SM, LangOpts);
15906f32e7eSjoerg EndLoc = EndLoc.getLocWithOffset(Length);
16006f32e7eSjoerg }
16106f32e7eSjoerg
16206f32e7eSjoerg CXSourceRange Result = {
163*13fbcb42Sjoerg {&SM, &LangOpts}, R.getBegin().getRawEncoding(), EndLoc.getRawEncoding()};
16406f32e7eSjoerg return Result;
16506f32e7eSjoerg }
16606f32e7eSjoerg
translateCXRangeToCharRange(CXSourceRange R)167*13fbcb42Sjoerg CharSourceRange cxloc::translateCXRangeToCharRange(CXSourceRange R) {
168*13fbcb42Sjoerg return CharSourceRange::getCharRange(
169*13fbcb42Sjoerg SourceLocation::getFromRawEncoding(R.begin_int_data),
170*13fbcb42Sjoerg SourceLocation::getFromRawEncoding(R.end_int_data));
171*13fbcb42Sjoerg }
172*13fbcb42Sjoerg
17306f32e7eSjoerg //===----------------------------------------------------------------------===//
17406f32e7eSjoerg // Cursor visitor.
17506f32e7eSjoerg //===----------------------------------------------------------------------===//
17606f32e7eSjoerg
17706f32e7eSjoerg static SourceRange getRawCursorExtent(CXCursor C);
17806f32e7eSjoerg static SourceRange getFullCursorExtent(CXCursor C, SourceManager &SrcMgr);
17906f32e7eSjoerg
CompareRegionOfInterest(SourceRange R)18006f32e7eSjoerg RangeComparisonResult CursorVisitor::CompareRegionOfInterest(SourceRange R) {
18106f32e7eSjoerg return RangeCompare(AU->getSourceManager(), R, RegionOfInterest);
18206f32e7eSjoerg }
18306f32e7eSjoerg
18406f32e7eSjoerg /// Visit the given cursor and, if requested by the visitor,
18506f32e7eSjoerg /// its children.
18606f32e7eSjoerg ///
18706f32e7eSjoerg /// \param Cursor the cursor to visit.
18806f32e7eSjoerg ///
18906f32e7eSjoerg /// \param CheckedRegionOfInterest if true, then the caller already checked
19006f32e7eSjoerg /// that this cursor is within the region of interest.
19106f32e7eSjoerg ///
19206f32e7eSjoerg /// \returns true if the visitation should be aborted, false if it
19306f32e7eSjoerg /// should continue.
Visit(CXCursor Cursor,bool CheckedRegionOfInterest)19406f32e7eSjoerg bool CursorVisitor::Visit(CXCursor Cursor, bool CheckedRegionOfInterest) {
19506f32e7eSjoerg if (clang_isInvalid(Cursor.kind))
19606f32e7eSjoerg return false;
19706f32e7eSjoerg
19806f32e7eSjoerg if (clang_isDeclaration(Cursor.kind)) {
19906f32e7eSjoerg const Decl *D = getCursorDecl(Cursor);
20006f32e7eSjoerg if (!D) {
20106f32e7eSjoerg assert(0 && "Invalid declaration cursor");
20206f32e7eSjoerg return true; // abort.
20306f32e7eSjoerg }
20406f32e7eSjoerg
20506f32e7eSjoerg // Ignore implicit declarations, unless it's an objc method because
20606f32e7eSjoerg // currently we should report implicit methods for properties when indexing.
20706f32e7eSjoerg if (D->isImplicit() && !isa<ObjCMethodDecl>(D))
20806f32e7eSjoerg return false;
20906f32e7eSjoerg }
21006f32e7eSjoerg
21106f32e7eSjoerg // If we have a range of interest, and this cursor doesn't intersect with it,
21206f32e7eSjoerg // we're done.
21306f32e7eSjoerg if (RegionOfInterest.isValid() && !CheckedRegionOfInterest) {
21406f32e7eSjoerg SourceRange Range = getRawCursorExtent(Cursor);
21506f32e7eSjoerg if (Range.isInvalid() || CompareRegionOfInterest(Range))
21606f32e7eSjoerg return false;
21706f32e7eSjoerg }
21806f32e7eSjoerg
21906f32e7eSjoerg switch (Visitor(Cursor, Parent, ClientData)) {
22006f32e7eSjoerg case CXChildVisit_Break:
22106f32e7eSjoerg return true;
22206f32e7eSjoerg
22306f32e7eSjoerg case CXChildVisit_Continue:
22406f32e7eSjoerg return false;
22506f32e7eSjoerg
22606f32e7eSjoerg case CXChildVisit_Recurse: {
22706f32e7eSjoerg bool ret = VisitChildren(Cursor);
22806f32e7eSjoerg if (PostChildrenVisitor)
22906f32e7eSjoerg if (PostChildrenVisitor(Cursor, ClientData))
23006f32e7eSjoerg return true;
23106f32e7eSjoerg return ret;
23206f32e7eSjoerg }
23306f32e7eSjoerg }
23406f32e7eSjoerg
23506f32e7eSjoerg llvm_unreachable("Invalid CXChildVisitResult!");
23606f32e7eSjoerg }
23706f32e7eSjoerg
visitPreprocessedEntitiesInRange(SourceRange R,PreprocessingRecord & PPRec,CursorVisitor & Visitor)23806f32e7eSjoerg static bool visitPreprocessedEntitiesInRange(SourceRange R,
23906f32e7eSjoerg PreprocessingRecord &PPRec,
24006f32e7eSjoerg CursorVisitor &Visitor) {
24106f32e7eSjoerg SourceManager &SM = Visitor.getASTUnit()->getSourceManager();
24206f32e7eSjoerg FileID FID;
24306f32e7eSjoerg
24406f32e7eSjoerg if (!Visitor.shouldVisitIncludedEntities()) {
24506f32e7eSjoerg // If the begin/end of the range lie in the same FileID, do the optimization
246*13fbcb42Sjoerg // where we skip preprocessed entities that do not come from the same
247*13fbcb42Sjoerg // FileID.
24806f32e7eSjoerg FID = SM.getFileID(SM.getFileLoc(R.getBegin()));
24906f32e7eSjoerg if (FID != SM.getFileID(SM.getFileLoc(R.getEnd())))
25006f32e7eSjoerg FID = FileID();
25106f32e7eSjoerg }
25206f32e7eSjoerg
25306f32e7eSjoerg const auto &Entities = PPRec.getPreprocessedEntitiesInRange(R);
25406f32e7eSjoerg return Visitor.visitPreprocessedEntities(Entities.begin(), Entities.end(),
25506f32e7eSjoerg PPRec, FID);
25606f32e7eSjoerg }
25706f32e7eSjoerg
visitFileRegion()25806f32e7eSjoerg bool CursorVisitor::visitFileRegion() {
25906f32e7eSjoerg if (RegionOfInterest.isInvalid())
26006f32e7eSjoerg return false;
26106f32e7eSjoerg
26206f32e7eSjoerg ASTUnit *Unit = cxtu::getASTUnit(TU);
26306f32e7eSjoerg SourceManager &SM = Unit->getSourceManager();
26406f32e7eSjoerg
265*13fbcb42Sjoerg std::pair<FileID, unsigned> Begin = SM.getDecomposedLoc(
266*13fbcb42Sjoerg SM.getFileLoc(RegionOfInterest.getBegin())),
267*13fbcb42Sjoerg End = SM.getDecomposedLoc(
268*13fbcb42Sjoerg SM.getFileLoc(RegionOfInterest.getEnd()));
26906f32e7eSjoerg
27006f32e7eSjoerg if (End.first != Begin.first) {
27106f32e7eSjoerg // If the end does not reside in the same file, try to recover by
27206f32e7eSjoerg // picking the end of the file of begin location.
27306f32e7eSjoerg End.first = Begin.first;
27406f32e7eSjoerg End.second = SM.getFileIDSize(Begin.first);
27506f32e7eSjoerg }
27606f32e7eSjoerg
27706f32e7eSjoerg assert(Begin.first == End.first);
27806f32e7eSjoerg if (Begin.second > End.second)
27906f32e7eSjoerg return false;
28006f32e7eSjoerg
28106f32e7eSjoerg FileID File = Begin.first;
28206f32e7eSjoerg unsigned Offset = Begin.second;
28306f32e7eSjoerg unsigned Length = End.second - Begin.second;
28406f32e7eSjoerg
28506f32e7eSjoerg if (!VisitDeclsOnly && !VisitPreprocessorLast)
28606f32e7eSjoerg if (visitPreprocessedEntitiesInRegion())
28706f32e7eSjoerg return true; // visitation break.
28806f32e7eSjoerg
28906f32e7eSjoerg if (visitDeclsFromFileRegion(File, Offset, Length))
29006f32e7eSjoerg return true; // visitation break.
29106f32e7eSjoerg
29206f32e7eSjoerg if (!VisitDeclsOnly && VisitPreprocessorLast)
29306f32e7eSjoerg return visitPreprocessedEntitiesInRegion();
29406f32e7eSjoerg
29506f32e7eSjoerg return false;
29606f32e7eSjoerg }
29706f32e7eSjoerg
isInLexicalContext(Decl * D,DeclContext * DC)29806f32e7eSjoerg static bool isInLexicalContext(Decl *D, DeclContext *DC) {
29906f32e7eSjoerg if (!DC)
30006f32e7eSjoerg return false;
30106f32e7eSjoerg
302*13fbcb42Sjoerg for (DeclContext *DeclDC = D->getLexicalDeclContext(); DeclDC;
303*13fbcb42Sjoerg DeclDC = DeclDC->getLexicalParent()) {
30406f32e7eSjoerg if (DeclDC == DC)
30506f32e7eSjoerg return true;
30606f32e7eSjoerg }
30706f32e7eSjoerg return false;
30806f32e7eSjoerg }
30906f32e7eSjoerg
visitDeclsFromFileRegion(FileID File,unsigned Offset,unsigned Length)310*13fbcb42Sjoerg bool CursorVisitor::visitDeclsFromFileRegion(FileID File, unsigned Offset,
311*13fbcb42Sjoerg unsigned Length) {
31206f32e7eSjoerg ASTUnit *Unit = cxtu::getASTUnit(TU);
31306f32e7eSjoerg SourceManager &SM = Unit->getSourceManager();
31406f32e7eSjoerg SourceRange Range = RegionOfInterest;
31506f32e7eSjoerg
31606f32e7eSjoerg SmallVector<Decl *, 16> Decls;
31706f32e7eSjoerg Unit->findFileRegionDecls(File, Offset, Length, Decls);
31806f32e7eSjoerg
31906f32e7eSjoerg // If we didn't find any file level decls for the file, try looking at the
32006f32e7eSjoerg // file that it was included from.
32106f32e7eSjoerg while (Decls.empty() || Decls.front()->isTopLevelDeclInObjCContainer()) {
32206f32e7eSjoerg bool Invalid = false;
32306f32e7eSjoerg const SrcMgr::SLocEntry &SLEntry = SM.getSLocEntry(File, &Invalid);
32406f32e7eSjoerg if (Invalid)
32506f32e7eSjoerg return false;
32606f32e7eSjoerg
32706f32e7eSjoerg SourceLocation Outer;
32806f32e7eSjoerg if (SLEntry.isFile())
32906f32e7eSjoerg Outer = SLEntry.getFile().getIncludeLoc();
33006f32e7eSjoerg else
33106f32e7eSjoerg Outer = SLEntry.getExpansion().getExpansionLocStart();
33206f32e7eSjoerg if (Outer.isInvalid())
33306f32e7eSjoerg return false;
33406f32e7eSjoerg
33506f32e7eSjoerg std::tie(File, Offset) = SM.getDecomposedExpansionLoc(Outer);
33606f32e7eSjoerg Length = 0;
33706f32e7eSjoerg Unit->findFileRegionDecls(File, Offset, Length, Decls);
33806f32e7eSjoerg }
33906f32e7eSjoerg
34006f32e7eSjoerg assert(!Decls.empty());
34106f32e7eSjoerg
34206f32e7eSjoerg bool VisitedAtLeastOnce = false;
34306f32e7eSjoerg DeclContext *CurDC = nullptr;
34406f32e7eSjoerg SmallVectorImpl<Decl *>::iterator DIt = Decls.begin();
34506f32e7eSjoerg for (SmallVectorImpl<Decl *>::iterator DE = Decls.end(); DIt != DE; ++DIt) {
34606f32e7eSjoerg Decl *D = *DIt;
34706f32e7eSjoerg if (D->getSourceRange().isInvalid())
34806f32e7eSjoerg continue;
34906f32e7eSjoerg
35006f32e7eSjoerg if (isInLexicalContext(D, CurDC))
35106f32e7eSjoerg continue;
35206f32e7eSjoerg
35306f32e7eSjoerg CurDC = dyn_cast<DeclContext>(D);
35406f32e7eSjoerg
35506f32e7eSjoerg if (TagDecl *TD = dyn_cast<TagDecl>(D))
35606f32e7eSjoerg if (!TD->isFreeStanding())
35706f32e7eSjoerg continue;
35806f32e7eSjoerg
359*13fbcb42Sjoerg RangeComparisonResult CompRes =
360*13fbcb42Sjoerg RangeCompare(SM, D->getSourceRange(), Range);
36106f32e7eSjoerg if (CompRes == RangeBefore)
36206f32e7eSjoerg continue;
36306f32e7eSjoerg if (CompRes == RangeAfter)
36406f32e7eSjoerg break;
36506f32e7eSjoerg
36606f32e7eSjoerg assert(CompRes == RangeOverlap);
36706f32e7eSjoerg VisitedAtLeastOnce = true;
36806f32e7eSjoerg
36906f32e7eSjoerg if (isa<ObjCContainerDecl>(D)) {
37006f32e7eSjoerg FileDI_current = &DIt;
37106f32e7eSjoerg FileDE_current = DE;
37206f32e7eSjoerg } else {
37306f32e7eSjoerg FileDI_current = nullptr;
37406f32e7eSjoerg }
37506f32e7eSjoerg
37606f32e7eSjoerg if (Visit(MakeCXCursor(D, TU, Range), /*CheckedRegionOfInterest=*/true))
37706f32e7eSjoerg return true; // visitation break.
37806f32e7eSjoerg }
37906f32e7eSjoerg
38006f32e7eSjoerg if (VisitedAtLeastOnce)
38106f32e7eSjoerg return false;
38206f32e7eSjoerg
38306f32e7eSjoerg // No Decls overlapped with the range. Move up the lexical context until there
38406f32e7eSjoerg // is a context that contains the range or we reach the translation unit
38506f32e7eSjoerg // level.
386*13fbcb42Sjoerg DeclContext *DC = DIt == Decls.begin()
387*13fbcb42Sjoerg ? (*DIt)->getLexicalDeclContext()
38806f32e7eSjoerg : (*(DIt - 1))->getLexicalDeclContext();
38906f32e7eSjoerg
39006f32e7eSjoerg while (DC && !DC->isTranslationUnit()) {
39106f32e7eSjoerg Decl *D = cast<Decl>(DC);
39206f32e7eSjoerg SourceRange CurDeclRange = D->getSourceRange();
39306f32e7eSjoerg if (CurDeclRange.isInvalid())
39406f32e7eSjoerg break;
39506f32e7eSjoerg
39606f32e7eSjoerg if (RangeCompare(SM, CurDeclRange, Range) == RangeOverlap) {
39706f32e7eSjoerg if (Visit(MakeCXCursor(D, TU, Range), /*CheckedRegionOfInterest=*/true))
39806f32e7eSjoerg return true; // visitation break.
39906f32e7eSjoerg }
40006f32e7eSjoerg
40106f32e7eSjoerg DC = D->getLexicalDeclContext();
40206f32e7eSjoerg }
40306f32e7eSjoerg
40406f32e7eSjoerg return false;
40506f32e7eSjoerg }
40606f32e7eSjoerg
visitPreprocessedEntitiesInRegion()40706f32e7eSjoerg bool CursorVisitor::visitPreprocessedEntitiesInRegion() {
40806f32e7eSjoerg if (!AU->getPreprocessor().getPreprocessingRecord())
40906f32e7eSjoerg return false;
41006f32e7eSjoerg
411*13fbcb42Sjoerg PreprocessingRecord &PPRec = *AU->getPreprocessor().getPreprocessingRecord();
41206f32e7eSjoerg SourceManager &SM = AU->getSourceManager();
41306f32e7eSjoerg
41406f32e7eSjoerg if (RegionOfInterest.isValid()) {
41506f32e7eSjoerg SourceRange MappedRange = AU->mapRangeToPreamble(RegionOfInterest);
41606f32e7eSjoerg SourceLocation B = MappedRange.getBegin();
41706f32e7eSjoerg SourceLocation E = MappedRange.getEnd();
41806f32e7eSjoerg
41906f32e7eSjoerg if (AU->isInPreambleFileID(B)) {
42006f32e7eSjoerg if (SM.isLoadedSourceLocation(E))
421*13fbcb42Sjoerg return visitPreprocessedEntitiesInRange(SourceRange(B, E), PPRec,
422*13fbcb42Sjoerg *this);
42306f32e7eSjoerg
42406f32e7eSjoerg // Beginning of range lies in the preamble but it also extends beyond
42506f32e7eSjoerg // it into the main file. Split the range into 2 parts, one covering
42606f32e7eSjoerg // the preamble and another covering the main file. This allows subsequent
42706f32e7eSjoerg // calls to visitPreprocessedEntitiesInRange to accept a source range that
42806f32e7eSjoerg // lies in the same FileID, allowing it to skip preprocessed entities that
42906f32e7eSjoerg // do not come from the same FileID.
430*13fbcb42Sjoerg bool breaked = visitPreprocessedEntitiesInRange(
431*13fbcb42Sjoerg SourceRange(B, AU->getEndOfPreambleFileID()), PPRec, *this);
432*13fbcb42Sjoerg if (breaked)
433*13fbcb42Sjoerg return true;
43406f32e7eSjoerg return visitPreprocessedEntitiesInRange(
435*13fbcb42Sjoerg SourceRange(AU->getStartOfMainFileID(), E), PPRec, *this);
43606f32e7eSjoerg }
43706f32e7eSjoerg
43806f32e7eSjoerg return visitPreprocessedEntitiesInRange(SourceRange(B, E), PPRec, *this);
43906f32e7eSjoerg }
44006f32e7eSjoerg
441*13fbcb42Sjoerg bool OnlyLocalDecls = !AU->isMainFileAST() && AU->getOnlyLocalDecls();
44206f32e7eSjoerg
44306f32e7eSjoerg if (OnlyLocalDecls)
44406f32e7eSjoerg return visitPreprocessedEntities(PPRec.local_begin(), PPRec.local_end(),
44506f32e7eSjoerg PPRec);
44606f32e7eSjoerg
44706f32e7eSjoerg return visitPreprocessedEntities(PPRec.begin(), PPRec.end(), PPRec);
44806f32e7eSjoerg }
44906f32e7eSjoerg
45006f32e7eSjoerg template <typename InputIterator>
visitPreprocessedEntities(InputIterator First,InputIterator Last,PreprocessingRecord & PPRec,FileID FID)45106f32e7eSjoerg bool CursorVisitor::visitPreprocessedEntities(InputIterator First,
45206f32e7eSjoerg InputIterator Last,
45306f32e7eSjoerg PreprocessingRecord &PPRec,
45406f32e7eSjoerg FileID FID) {
45506f32e7eSjoerg for (; First != Last; ++First) {
45606f32e7eSjoerg if (!FID.isInvalid() && !PPRec.isEntityInFileID(First, FID))
45706f32e7eSjoerg continue;
45806f32e7eSjoerg
45906f32e7eSjoerg PreprocessedEntity *PPE = *First;
46006f32e7eSjoerg if (!PPE)
46106f32e7eSjoerg continue;
46206f32e7eSjoerg
46306f32e7eSjoerg if (MacroExpansion *ME = dyn_cast<MacroExpansion>(PPE)) {
46406f32e7eSjoerg if (Visit(MakeMacroExpansionCursor(ME, TU)))
46506f32e7eSjoerg return true;
46606f32e7eSjoerg
46706f32e7eSjoerg continue;
46806f32e7eSjoerg }
46906f32e7eSjoerg
47006f32e7eSjoerg if (MacroDefinitionRecord *MD = dyn_cast<MacroDefinitionRecord>(PPE)) {
47106f32e7eSjoerg if (Visit(MakeMacroDefinitionCursor(MD, TU)))
47206f32e7eSjoerg return true;
47306f32e7eSjoerg
47406f32e7eSjoerg continue;
47506f32e7eSjoerg }
47606f32e7eSjoerg
47706f32e7eSjoerg if (InclusionDirective *ID = dyn_cast<InclusionDirective>(PPE)) {
47806f32e7eSjoerg if (Visit(MakeInclusionDirectiveCursor(ID, TU)))
47906f32e7eSjoerg return true;
48006f32e7eSjoerg
48106f32e7eSjoerg continue;
48206f32e7eSjoerg }
48306f32e7eSjoerg }
48406f32e7eSjoerg
48506f32e7eSjoerg return false;
48606f32e7eSjoerg }
48706f32e7eSjoerg
48806f32e7eSjoerg /// Visit the children of the given cursor.
48906f32e7eSjoerg ///
49006f32e7eSjoerg /// \returns true if the visitation should be aborted, false if it
49106f32e7eSjoerg /// should continue.
VisitChildren(CXCursor Cursor)49206f32e7eSjoerg bool CursorVisitor::VisitChildren(CXCursor Cursor) {
49306f32e7eSjoerg if (clang_isReference(Cursor.kind) &&
49406f32e7eSjoerg Cursor.kind != CXCursor_CXXBaseSpecifier) {
49506f32e7eSjoerg // By definition, references have no children.
49606f32e7eSjoerg return false;
49706f32e7eSjoerg }
49806f32e7eSjoerg
49906f32e7eSjoerg // Set the Parent field to Cursor, then back to its old value once we're
50006f32e7eSjoerg // done.
50106f32e7eSjoerg SetParentRAII SetParent(Parent, StmtParent, Cursor);
50206f32e7eSjoerg
50306f32e7eSjoerg if (clang_isDeclaration(Cursor.kind)) {
50406f32e7eSjoerg Decl *D = const_cast<Decl *>(getCursorDecl(Cursor));
50506f32e7eSjoerg if (!D)
50606f32e7eSjoerg return false;
50706f32e7eSjoerg
50806f32e7eSjoerg return VisitAttributes(D) || Visit(D);
50906f32e7eSjoerg }
51006f32e7eSjoerg
51106f32e7eSjoerg if (clang_isStatement(Cursor.kind)) {
51206f32e7eSjoerg if (const Stmt *S = getCursorStmt(Cursor))
51306f32e7eSjoerg return Visit(S);
51406f32e7eSjoerg
51506f32e7eSjoerg return false;
51606f32e7eSjoerg }
51706f32e7eSjoerg
51806f32e7eSjoerg if (clang_isExpression(Cursor.kind)) {
51906f32e7eSjoerg if (const Expr *E = getCursorExpr(Cursor))
52006f32e7eSjoerg return Visit(E);
52106f32e7eSjoerg
52206f32e7eSjoerg return false;
52306f32e7eSjoerg }
52406f32e7eSjoerg
52506f32e7eSjoerg if (clang_isTranslationUnit(Cursor.kind)) {
52606f32e7eSjoerg CXTranslationUnit TU = getCursorTU(Cursor);
52706f32e7eSjoerg ASTUnit *CXXUnit = cxtu::getASTUnit(TU);
52806f32e7eSjoerg
52906f32e7eSjoerg int VisitOrder[2] = {VisitPreprocessorLast, !VisitPreprocessorLast};
53006f32e7eSjoerg for (unsigned I = 0; I != 2; ++I) {
53106f32e7eSjoerg if (VisitOrder[I]) {
53206f32e7eSjoerg if (!CXXUnit->isMainFileAST() && CXXUnit->getOnlyLocalDecls() &&
53306f32e7eSjoerg RegionOfInterest.isInvalid()) {
53406f32e7eSjoerg for (ASTUnit::top_level_iterator TL = CXXUnit->top_level_begin(),
53506f32e7eSjoerg TLEnd = CXXUnit->top_level_end();
53606f32e7eSjoerg TL != TLEnd; ++TL) {
53706f32e7eSjoerg const Optional<bool> V = handleDeclForVisitation(*TL);
53806f32e7eSjoerg if (!V.hasValue())
53906f32e7eSjoerg continue;
54006f32e7eSjoerg return V.getValue();
54106f32e7eSjoerg }
54206f32e7eSjoerg } else if (VisitDeclContext(
54306f32e7eSjoerg CXXUnit->getASTContext().getTranslationUnitDecl()))
54406f32e7eSjoerg return true;
54506f32e7eSjoerg continue;
54606f32e7eSjoerg }
54706f32e7eSjoerg
54806f32e7eSjoerg // Walk the preprocessing record.
54906f32e7eSjoerg if (CXXUnit->getPreprocessor().getPreprocessingRecord())
55006f32e7eSjoerg visitPreprocessedEntitiesInRegion();
55106f32e7eSjoerg }
55206f32e7eSjoerg
55306f32e7eSjoerg return false;
55406f32e7eSjoerg }
55506f32e7eSjoerg
55606f32e7eSjoerg if (Cursor.kind == CXCursor_CXXBaseSpecifier) {
55706f32e7eSjoerg if (const CXXBaseSpecifier *Base = getCursorCXXBaseSpecifier(Cursor)) {
55806f32e7eSjoerg if (TypeSourceInfo *BaseTSInfo = Base->getTypeSourceInfo()) {
55906f32e7eSjoerg return Visit(BaseTSInfo->getTypeLoc());
56006f32e7eSjoerg }
56106f32e7eSjoerg }
56206f32e7eSjoerg }
56306f32e7eSjoerg
56406f32e7eSjoerg if (Cursor.kind == CXCursor_IBOutletCollectionAttr) {
56506f32e7eSjoerg const IBOutletCollectionAttr *A =
56606f32e7eSjoerg cast<IBOutletCollectionAttr>(cxcursor::getCursorAttr(Cursor));
56706f32e7eSjoerg if (const ObjCObjectType *ObjT = A->getInterface()->getAs<ObjCObjectType>())
56806f32e7eSjoerg return Visit(cxcursor::MakeCursorObjCClassRef(
56906f32e7eSjoerg ObjT->getInterface(),
57006f32e7eSjoerg A->getInterfaceLoc()->getTypeLoc().getBeginLoc(), TU));
57106f32e7eSjoerg }
57206f32e7eSjoerg
57306f32e7eSjoerg // If pointing inside a macro definition, check if the token is an identifier
57406f32e7eSjoerg // that was ever defined as a macro. In such a case, create a "pseudo" macro
57506f32e7eSjoerg // expansion cursor for that token.
57606f32e7eSjoerg SourceLocation BeginLoc = RegionOfInterest.getBegin();
57706f32e7eSjoerg if (Cursor.kind == CXCursor_MacroDefinition &&
57806f32e7eSjoerg BeginLoc == RegionOfInterest.getEnd()) {
57906f32e7eSjoerg SourceLocation Loc = AU->mapLocationToPreamble(BeginLoc);
58006f32e7eSjoerg const MacroInfo *MI =
58106f32e7eSjoerg getMacroInfo(cxcursor::getCursorMacroDefinition(Cursor), TU);
58206f32e7eSjoerg if (MacroDefinitionRecord *MacroDef =
58306f32e7eSjoerg checkForMacroInMacroDefinition(MI, Loc, TU))
58406f32e7eSjoerg return Visit(cxcursor::MakeMacroExpansionCursor(MacroDef, BeginLoc, TU));
58506f32e7eSjoerg }
58606f32e7eSjoerg
58706f32e7eSjoerg // Nothing to visit at the moment.
58806f32e7eSjoerg return false;
58906f32e7eSjoerg }
59006f32e7eSjoerg
VisitBlockDecl(BlockDecl * B)59106f32e7eSjoerg bool CursorVisitor::VisitBlockDecl(BlockDecl *B) {
59206f32e7eSjoerg if (TypeSourceInfo *TSInfo = B->getSignatureAsWritten())
59306f32e7eSjoerg if (Visit(TSInfo->getTypeLoc()))
59406f32e7eSjoerg return true;
59506f32e7eSjoerg
59606f32e7eSjoerg if (Stmt *Body = B->getBody())
59706f32e7eSjoerg return Visit(MakeCXCursor(Body, StmtParent, TU, RegionOfInterest));
59806f32e7eSjoerg
59906f32e7eSjoerg return false;
60006f32e7eSjoerg }
60106f32e7eSjoerg
shouldVisitCursor(CXCursor Cursor)60206f32e7eSjoerg Optional<bool> CursorVisitor::shouldVisitCursor(CXCursor Cursor) {
60306f32e7eSjoerg if (RegionOfInterest.isValid()) {
60406f32e7eSjoerg SourceRange Range = getFullCursorExtent(Cursor, AU->getSourceManager());
60506f32e7eSjoerg if (Range.isInvalid())
60606f32e7eSjoerg return None;
60706f32e7eSjoerg
60806f32e7eSjoerg switch (CompareRegionOfInterest(Range)) {
60906f32e7eSjoerg case RangeBefore:
61006f32e7eSjoerg // This declaration comes before the region of interest; skip it.
61106f32e7eSjoerg return None;
61206f32e7eSjoerg
61306f32e7eSjoerg case RangeAfter:
61406f32e7eSjoerg // This declaration comes after the region of interest; we're done.
61506f32e7eSjoerg return false;
61606f32e7eSjoerg
61706f32e7eSjoerg case RangeOverlap:
61806f32e7eSjoerg // This declaration overlaps the region of interest; visit it.
61906f32e7eSjoerg break;
62006f32e7eSjoerg }
62106f32e7eSjoerg }
62206f32e7eSjoerg return true;
62306f32e7eSjoerg }
62406f32e7eSjoerg
VisitDeclContext(DeclContext * DC)62506f32e7eSjoerg bool CursorVisitor::VisitDeclContext(DeclContext *DC) {
62606f32e7eSjoerg DeclContext::decl_iterator I = DC->decls_begin(), E = DC->decls_end();
62706f32e7eSjoerg
62806f32e7eSjoerg // FIXME: Eventually remove. This part of a hack to support proper
62906f32e7eSjoerg // iteration over all Decls contained lexically within an ObjC container.
63006f32e7eSjoerg SaveAndRestore<DeclContext::decl_iterator *> DI_saved(DI_current, &I);
63106f32e7eSjoerg SaveAndRestore<DeclContext::decl_iterator> DE_saved(DE_current, E);
63206f32e7eSjoerg
63306f32e7eSjoerg for (; I != E; ++I) {
63406f32e7eSjoerg Decl *D = *I;
63506f32e7eSjoerg if (D->getLexicalDeclContext() != DC)
63606f32e7eSjoerg continue;
637*13fbcb42Sjoerg // Filter out synthesized property accessor redeclarations.
638*13fbcb42Sjoerg if (isa<ObjCImplDecl>(DC))
639*13fbcb42Sjoerg if (auto *OMD = dyn_cast<ObjCMethodDecl>(D))
640*13fbcb42Sjoerg if (OMD->isSynthesizedAccessorStub())
641*13fbcb42Sjoerg continue;
64206f32e7eSjoerg const Optional<bool> V = handleDeclForVisitation(D);
64306f32e7eSjoerg if (!V.hasValue())
64406f32e7eSjoerg continue;
64506f32e7eSjoerg return V.getValue();
64606f32e7eSjoerg }
64706f32e7eSjoerg return false;
64806f32e7eSjoerg }
64906f32e7eSjoerg
handleDeclForVisitation(const Decl * D)65006f32e7eSjoerg Optional<bool> CursorVisitor::handleDeclForVisitation(const Decl *D) {
65106f32e7eSjoerg CXCursor Cursor = MakeCXCursor(D, TU, RegionOfInterest);
65206f32e7eSjoerg
65306f32e7eSjoerg // Ignore synthesized ivars here, otherwise if we have something like:
65406f32e7eSjoerg // @synthesize prop = _prop;
65506f32e7eSjoerg // and '_prop' is not declared, we will encounter a '_prop' ivar before
65606f32e7eSjoerg // encountering the 'prop' synthesize declaration and we will think that
65706f32e7eSjoerg // we passed the region-of-interest.
65806f32e7eSjoerg if (auto *ivarD = dyn_cast<ObjCIvarDecl>(D)) {
65906f32e7eSjoerg if (ivarD->getSynthesize())
66006f32e7eSjoerg return None;
66106f32e7eSjoerg }
66206f32e7eSjoerg
66306f32e7eSjoerg // FIXME: ObjCClassRef/ObjCProtocolRef for forward class/protocol
66406f32e7eSjoerg // declarations is a mismatch with the compiler semantics.
66506f32e7eSjoerg if (Cursor.kind == CXCursor_ObjCInterfaceDecl) {
66606f32e7eSjoerg auto *ID = cast<ObjCInterfaceDecl>(D);
66706f32e7eSjoerg if (!ID->isThisDeclarationADefinition())
66806f32e7eSjoerg Cursor = MakeCursorObjCClassRef(ID, ID->getLocation(), TU);
66906f32e7eSjoerg
67006f32e7eSjoerg } else if (Cursor.kind == CXCursor_ObjCProtocolDecl) {
67106f32e7eSjoerg auto *PD = cast<ObjCProtocolDecl>(D);
67206f32e7eSjoerg if (!PD->isThisDeclarationADefinition())
67306f32e7eSjoerg Cursor = MakeCursorObjCProtocolRef(PD, PD->getLocation(), TU);
67406f32e7eSjoerg }
67506f32e7eSjoerg
67606f32e7eSjoerg const Optional<bool> V = shouldVisitCursor(Cursor);
67706f32e7eSjoerg if (!V.hasValue())
67806f32e7eSjoerg return None;
67906f32e7eSjoerg if (!V.getValue())
68006f32e7eSjoerg return false;
68106f32e7eSjoerg if (Visit(Cursor, true))
68206f32e7eSjoerg return true;
68306f32e7eSjoerg return None;
68406f32e7eSjoerg }
68506f32e7eSjoerg
VisitTranslationUnitDecl(TranslationUnitDecl * D)68606f32e7eSjoerg bool CursorVisitor::VisitTranslationUnitDecl(TranslationUnitDecl *D) {
68706f32e7eSjoerg llvm_unreachable("Translation units are visited directly by Visit()");
68806f32e7eSjoerg }
68906f32e7eSjoerg
VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl * D)69006f32e7eSjoerg bool CursorVisitor::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) {
69106f32e7eSjoerg if (VisitTemplateParameters(D->getTemplateParameters()))
69206f32e7eSjoerg return true;
69306f32e7eSjoerg
69406f32e7eSjoerg return Visit(MakeCXCursor(D->getTemplatedDecl(), TU, RegionOfInterest));
69506f32e7eSjoerg }
69606f32e7eSjoerg
VisitTypeAliasDecl(TypeAliasDecl * D)69706f32e7eSjoerg bool CursorVisitor::VisitTypeAliasDecl(TypeAliasDecl *D) {
69806f32e7eSjoerg if (TypeSourceInfo *TSInfo = D->getTypeSourceInfo())
69906f32e7eSjoerg return Visit(TSInfo->getTypeLoc());
70006f32e7eSjoerg
70106f32e7eSjoerg return false;
70206f32e7eSjoerg }
70306f32e7eSjoerg
VisitTypedefDecl(TypedefDecl * D)70406f32e7eSjoerg bool CursorVisitor::VisitTypedefDecl(TypedefDecl *D) {
70506f32e7eSjoerg if (TypeSourceInfo *TSInfo = D->getTypeSourceInfo())
70606f32e7eSjoerg return Visit(TSInfo->getTypeLoc());
70706f32e7eSjoerg
70806f32e7eSjoerg return false;
70906f32e7eSjoerg }
71006f32e7eSjoerg
VisitTagDecl(TagDecl * D)711*13fbcb42Sjoerg bool CursorVisitor::VisitTagDecl(TagDecl *D) { return VisitDeclContext(D); }
71206f32e7eSjoerg
VisitClassTemplateSpecializationDecl(ClassTemplateSpecializationDecl * D)71306f32e7eSjoerg bool CursorVisitor::VisitClassTemplateSpecializationDecl(
71406f32e7eSjoerg ClassTemplateSpecializationDecl *D) {
71506f32e7eSjoerg bool ShouldVisitBody = false;
71606f32e7eSjoerg switch (D->getSpecializationKind()) {
71706f32e7eSjoerg case TSK_Undeclared:
71806f32e7eSjoerg case TSK_ImplicitInstantiation:
71906f32e7eSjoerg // Nothing to visit
72006f32e7eSjoerg return false;
72106f32e7eSjoerg
72206f32e7eSjoerg case TSK_ExplicitInstantiationDeclaration:
72306f32e7eSjoerg case TSK_ExplicitInstantiationDefinition:
72406f32e7eSjoerg break;
72506f32e7eSjoerg
72606f32e7eSjoerg case TSK_ExplicitSpecialization:
72706f32e7eSjoerg ShouldVisitBody = true;
72806f32e7eSjoerg break;
72906f32e7eSjoerg }
73006f32e7eSjoerg
73106f32e7eSjoerg // Visit the template arguments used in the specialization.
73206f32e7eSjoerg if (TypeSourceInfo *SpecType = D->getTypeAsWritten()) {
73306f32e7eSjoerg TypeLoc TL = SpecType->getTypeLoc();
73406f32e7eSjoerg if (TemplateSpecializationTypeLoc TSTLoc =
73506f32e7eSjoerg TL.getAs<TemplateSpecializationTypeLoc>()) {
73606f32e7eSjoerg for (unsigned I = 0, N = TSTLoc.getNumArgs(); I != N; ++I)
73706f32e7eSjoerg if (VisitTemplateArgumentLoc(TSTLoc.getArgLoc(I)))
73806f32e7eSjoerg return true;
73906f32e7eSjoerg }
74006f32e7eSjoerg }
74106f32e7eSjoerg
74206f32e7eSjoerg return ShouldVisitBody && VisitCXXRecordDecl(D);
74306f32e7eSjoerg }
74406f32e7eSjoerg
VisitClassTemplatePartialSpecializationDecl(ClassTemplatePartialSpecializationDecl * D)74506f32e7eSjoerg bool CursorVisitor::VisitClassTemplatePartialSpecializationDecl(
74606f32e7eSjoerg ClassTemplatePartialSpecializationDecl *D) {
74706f32e7eSjoerg // FIXME: Visit the "outer" template parameter lists on the TagDecl
74806f32e7eSjoerg // before visiting these template parameters.
74906f32e7eSjoerg if (VisitTemplateParameters(D->getTemplateParameters()))
75006f32e7eSjoerg return true;
75106f32e7eSjoerg
75206f32e7eSjoerg // Visit the partial specialization arguments.
75306f32e7eSjoerg const ASTTemplateArgumentListInfo *Info = D->getTemplateArgsAsWritten();
75406f32e7eSjoerg const TemplateArgumentLoc *TemplateArgs = Info->getTemplateArgs();
75506f32e7eSjoerg for (unsigned I = 0, N = Info->NumTemplateArgs; I != N; ++I)
75606f32e7eSjoerg if (VisitTemplateArgumentLoc(TemplateArgs[I]))
75706f32e7eSjoerg return true;
75806f32e7eSjoerg
75906f32e7eSjoerg return VisitCXXRecordDecl(D);
76006f32e7eSjoerg }
76106f32e7eSjoerg
VisitTemplateTypeParmDecl(TemplateTypeParmDecl * D)76206f32e7eSjoerg bool CursorVisitor::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
763*13fbcb42Sjoerg if (const auto *TC = D->getTypeConstraint())
764*13fbcb42Sjoerg if (Visit(MakeCXCursor(TC->getImmediatelyDeclaredConstraint(), StmtParent,
765*13fbcb42Sjoerg TU, RegionOfInterest)))
766*13fbcb42Sjoerg return true;
767*13fbcb42Sjoerg
76806f32e7eSjoerg // Visit the default argument.
76906f32e7eSjoerg if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited())
77006f32e7eSjoerg if (TypeSourceInfo *DefArg = D->getDefaultArgumentInfo())
77106f32e7eSjoerg if (Visit(DefArg->getTypeLoc()))
77206f32e7eSjoerg return true;
77306f32e7eSjoerg
77406f32e7eSjoerg return false;
77506f32e7eSjoerg }
77606f32e7eSjoerg
VisitEnumConstantDecl(EnumConstantDecl * D)77706f32e7eSjoerg bool CursorVisitor::VisitEnumConstantDecl(EnumConstantDecl *D) {
77806f32e7eSjoerg if (Expr *Init = D->getInitExpr())
77906f32e7eSjoerg return Visit(MakeCXCursor(Init, StmtParent, TU, RegionOfInterest));
78006f32e7eSjoerg return false;
78106f32e7eSjoerg }
78206f32e7eSjoerg
VisitDeclaratorDecl(DeclaratorDecl * DD)78306f32e7eSjoerg bool CursorVisitor::VisitDeclaratorDecl(DeclaratorDecl *DD) {
78406f32e7eSjoerg unsigned NumParamList = DD->getNumTemplateParameterLists();
78506f32e7eSjoerg for (unsigned i = 0; i < NumParamList; i++) {
78606f32e7eSjoerg TemplateParameterList *Params = DD->getTemplateParameterList(i);
78706f32e7eSjoerg if (VisitTemplateParameters(Params))
78806f32e7eSjoerg return true;
78906f32e7eSjoerg }
79006f32e7eSjoerg
79106f32e7eSjoerg if (TypeSourceInfo *TSInfo = DD->getTypeSourceInfo())
79206f32e7eSjoerg if (Visit(TSInfo->getTypeLoc()))
79306f32e7eSjoerg return true;
79406f32e7eSjoerg
79506f32e7eSjoerg // Visit the nested-name-specifier, if present.
79606f32e7eSjoerg if (NestedNameSpecifierLoc QualifierLoc = DD->getQualifierLoc())
79706f32e7eSjoerg if (VisitNestedNameSpecifierLoc(QualifierLoc))
79806f32e7eSjoerg return true;
79906f32e7eSjoerg
80006f32e7eSjoerg return false;
80106f32e7eSjoerg }
80206f32e7eSjoerg
HasTrailingReturnType(FunctionDecl * ND)80306f32e7eSjoerg static bool HasTrailingReturnType(FunctionDecl *ND) {
80406f32e7eSjoerg const QualType Ty = ND->getType();
80506f32e7eSjoerg if (const FunctionType *AFT = Ty->getAs<FunctionType>()) {
80606f32e7eSjoerg if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(AFT))
80706f32e7eSjoerg return FT->hasTrailingReturn();
80806f32e7eSjoerg }
80906f32e7eSjoerg
81006f32e7eSjoerg return false;
81106f32e7eSjoerg }
81206f32e7eSjoerg
81306f32e7eSjoerg /// Compare two base or member initializers based on their source order.
CompareCXXCtorInitializers(CXXCtorInitializer * const * X,CXXCtorInitializer * const * Y)81406f32e7eSjoerg static int CompareCXXCtorInitializers(CXXCtorInitializer *const *X,
81506f32e7eSjoerg CXXCtorInitializer *const *Y) {
81606f32e7eSjoerg return (*X)->getSourceOrder() - (*Y)->getSourceOrder();
81706f32e7eSjoerg }
81806f32e7eSjoerg
VisitFunctionDecl(FunctionDecl * ND)81906f32e7eSjoerg bool CursorVisitor::VisitFunctionDecl(FunctionDecl *ND) {
82006f32e7eSjoerg unsigned NumParamList = ND->getNumTemplateParameterLists();
82106f32e7eSjoerg for (unsigned i = 0; i < NumParamList; i++) {
82206f32e7eSjoerg TemplateParameterList *Params = ND->getTemplateParameterList(i);
82306f32e7eSjoerg if (VisitTemplateParameters(Params))
82406f32e7eSjoerg return true;
82506f32e7eSjoerg }
82606f32e7eSjoerg
82706f32e7eSjoerg if (TypeSourceInfo *TSInfo = ND->getTypeSourceInfo()) {
82806f32e7eSjoerg // Visit the function declaration's syntactic components in the order
82906f32e7eSjoerg // written. This requires a bit of work.
83006f32e7eSjoerg TypeLoc TL = TSInfo->getTypeLoc().IgnoreParens();
83106f32e7eSjoerg FunctionTypeLoc FTL = TL.getAs<FunctionTypeLoc>();
83206f32e7eSjoerg const bool HasTrailingRT = HasTrailingReturnType(ND);
83306f32e7eSjoerg
83406f32e7eSjoerg // If we have a function declared directly (without the use of a typedef),
83506f32e7eSjoerg // visit just the return type. Otherwise, just visit the function's type
83606f32e7eSjoerg // now.
83706f32e7eSjoerg if ((FTL && !isa<CXXConversionDecl>(ND) && !HasTrailingRT &&
83806f32e7eSjoerg Visit(FTL.getReturnLoc())) ||
83906f32e7eSjoerg (!FTL && Visit(TL)))
84006f32e7eSjoerg return true;
84106f32e7eSjoerg
84206f32e7eSjoerg // Visit the nested-name-specifier, if present.
84306f32e7eSjoerg if (NestedNameSpecifierLoc QualifierLoc = ND->getQualifierLoc())
84406f32e7eSjoerg if (VisitNestedNameSpecifierLoc(QualifierLoc))
84506f32e7eSjoerg return true;
84606f32e7eSjoerg
84706f32e7eSjoerg // Visit the declaration name.
84806f32e7eSjoerg if (!isa<CXXDestructorDecl>(ND))
84906f32e7eSjoerg if (VisitDeclarationNameInfo(ND->getNameInfo()))
85006f32e7eSjoerg return true;
85106f32e7eSjoerg
85206f32e7eSjoerg // FIXME: Visit explicitly-specified template arguments!
85306f32e7eSjoerg
85406f32e7eSjoerg // Visit the function parameters, if we have a function type.
85506f32e7eSjoerg if (FTL && VisitFunctionTypeLoc(FTL, true))
85606f32e7eSjoerg return true;
85706f32e7eSjoerg
85806f32e7eSjoerg // Visit the function's trailing return type.
85906f32e7eSjoerg if (FTL && HasTrailingRT && Visit(FTL.getReturnLoc()))
86006f32e7eSjoerg return true;
86106f32e7eSjoerg
86206f32e7eSjoerg // FIXME: Attributes?
86306f32e7eSjoerg }
86406f32e7eSjoerg
86506f32e7eSjoerg if (ND->doesThisDeclarationHaveABody() && !ND->isLateTemplateParsed()) {
86606f32e7eSjoerg if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(ND)) {
86706f32e7eSjoerg // Find the initializers that were written in the source.
86806f32e7eSjoerg SmallVector<CXXCtorInitializer *, 4> WrittenInits;
86906f32e7eSjoerg for (auto *I : Constructor->inits()) {
87006f32e7eSjoerg if (!I->isWritten())
87106f32e7eSjoerg continue;
87206f32e7eSjoerg
87306f32e7eSjoerg WrittenInits.push_back(I);
87406f32e7eSjoerg }
87506f32e7eSjoerg
87606f32e7eSjoerg // Sort the initializers in source order
87706f32e7eSjoerg llvm::array_pod_sort(WrittenInits.begin(), WrittenInits.end(),
87806f32e7eSjoerg &CompareCXXCtorInitializers);
87906f32e7eSjoerg
88006f32e7eSjoerg // Visit the initializers in source order
88106f32e7eSjoerg for (unsigned I = 0, N = WrittenInits.size(); I != N; ++I) {
88206f32e7eSjoerg CXXCtorInitializer *Init = WrittenInits[I];
88306f32e7eSjoerg if (Init->isAnyMemberInitializer()) {
88406f32e7eSjoerg if (Visit(MakeCursorMemberRef(Init->getAnyMember(),
88506f32e7eSjoerg Init->getMemberLocation(), TU)))
88606f32e7eSjoerg return true;
88706f32e7eSjoerg } else if (TypeSourceInfo *TInfo = Init->getTypeSourceInfo()) {
88806f32e7eSjoerg if (Visit(TInfo->getTypeLoc()))
88906f32e7eSjoerg return true;
89006f32e7eSjoerg }
89106f32e7eSjoerg
89206f32e7eSjoerg // Visit the initializer value.
89306f32e7eSjoerg if (Expr *Initializer = Init->getInit())
89406f32e7eSjoerg if (Visit(MakeCXCursor(Initializer, ND, TU, RegionOfInterest)))
89506f32e7eSjoerg return true;
89606f32e7eSjoerg }
89706f32e7eSjoerg }
89806f32e7eSjoerg
89906f32e7eSjoerg if (Visit(MakeCXCursor(ND->getBody(), StmtParent, TU, RegionOfInterest)))
90006f32e7eSjoerg return true;
90106f32e7eSjoerg }
90206f32e7eSjoerg
90306f32e7eSjoerg return false;
90406f32e7eSjoerg }
90506f32e7eSjoerg
VisitFieldDecl(FieldDecl * D)90606f32e7eSjoerg bool CursorVisitor::VisitFieldDecl(FieldDecl *D) {
90706f32e7eSjoerg if (VisitDeclaratorDecl(D))
90806f32e7eSjoerg return true;
90906f32e7eSjoerg
91006f32e7eSjoerg if (Expr *BitWidth = D->getBitWidth())
91106f32e7eSjoerg return Visit(MakeCXCursor(BitWidth, StmtParent, TU, RegionOfInterest));
91206f32e7eSjoerg
91306f32e7eSjoerg if (Expr *Init = D->getInClassInitializer())
91406f32e7eSjoerg return Visit(MakeCXCursor(Init, StmtParent, TU, RegionOfInterest));
91506f32e7eSjoerg
91606f32e7eSjoerg return false;
91706f32e7eSjoerg }
91806f32e7eSjoerg
VisitVarDecl(VarDecl * D)91906f32e7eSjoerg bool CursorVisitor::VisitVarDecl(VarDecl *D) {
92006f32e7eSjoerg if (VisitDeclaratorDecl(D))
92106f32e7eSjoerg return true;
92206f32e7eSjoerg
92306f32e7eSjoerg if (Expr *Init = D->getInit())
92406f32e7eSjoerg return Visit(MakeCXCursor(Init, StmtParent, TU, RegionOfInterest));
92506f32e7eSjoerg
92606f32e7eSjoerg return false;
92706f32e7eSjoerg }
92806f32e7eSjoerg
VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl * D)92906f32e7eSjoerg bool CursorVisitor::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) {
93006f32e7eSjoerg if (VisitDeclaratorDecl(D))
93106f32e7eSjoerg return true;
93206f32e7eSjoerg
93306f32e7eSjoerg if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited())
93406f32e7eSjoerg if (Expr *DefArg = D->getDefaultArgument())
93506f32e7eSjoerg return Visit(MakeCXCursor(DefArg, StmtParent, TU, RegionOfInterest));
93606f32e7eSjoerg
93706f32e7eSjoerg return false;
93806f32e7eSjoerg }
93906f32e7eSjoerg
VisitFunctionTemplateDecl(FunctionTemplateDecl * D)94006f32e7eSjoerg bool CursorVisitor::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
94106f32e7eSjoerg // FIXME: Visit the "outer" template parameter lists on the FunctionDecl
94206f32e7eSjoerg // before visiting these template parameters.
94306f32e7eSjoerg if (VisitTemplateParameters(D->getTemplateParameters()))
94406f32e7eSjoerg return true;
94506f32e7eSjoerg
94606f32e7eSjoerg auto *FD = D->getTemplatedDecl();
94706f32e7eSjoerg return VisitAttributes(FD) || VisitFunctionDecl(FD);
94806f32e7eSjoerg }
94906f32e7eSjoerg
VisitClassTemplateDecl(ClassTemplateDecl * D)95006f32e7eSjoerg bool CursorVisitor::VisitClassTemplateDecl(ClassTemplateDecl *D) {
95106f32e7eSjoerg // FIXME: Visit the "outer" template parameter lists on the TagDecl
95206f32e7eSjoerg // before visiting these template parameters.
95306f32e7eSjoerg if (VisitTemplateParameters(D->getTemplateParameters()))
95406f32e7eSjoerg return true;
95506f32e7eSjoerg
95606f32e7eSjoerg auto *CD = D->getTemplatedDecl();
95706f32e7eSjoerg return VisitAttributes(CD) || VisitCXXRecordDecl(CD);
95806f32e7eSjoerg }
95906f32e7eSjoerg
VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl * D)96006f32e7eSjoerg bool CursorVisitor::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) {
96106f32e7eSjoerg if (VisitTemplateParameters(D->getTemplateParameters()))
96206f32e7eSjoerg return true;
96306f32e7eSjoerg
96406f32e7eSjoerg if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited() &&
96506f32e7eSjoerg VisitTemplateArgumentLoc(D->getDefaultArgument()))
96606f32e7eSjoerg return true;
96706f32e7eSjoerg
96806f32e7eSjoerg return false;
96906f32e7eSjoerg }
97006f32e7eSjoerg
VisitObjCTypeParamDecl(ObjCTypeParamDecl * D)97106f32e7eSjoerg bool CursorVisitor::VisitObjCTypeParamDecl(ObjCTypeParamDecl *D) {
97206f32e7eSjoerg // Visit the bound, if it's explicit.
97306f32e7eSjoerg if (D->hasExplicitBound()) {
97406f32e7eSjoerg if (auto TInfo = D->getTypeSourceInfo()) {
97506f32e7eSjoerg if (Visit(TInfo->getTypeLoc()))
97606f32e7eSjoerg return true;
97706f32e7eSjoerg }
97806f32e7eSjoerg }
97906f32e7eSjoerg
98006f32e7eSjoerg return false;
98106f32e7eSjoerg }
98206f32e7eSjoerg
VisitObjCMethodDecl(ObjCMethodDecl * ND)98306f32e7eSjoerg bool CursorVisitor::VisitObjCMethodDecl(ObjCMethodDecl *ND) {
98406f32e7eSjoerg if (TypeSourceInfo *TSInfo = ND->getReturnTypeSourceInfo())
98506f32e7eSjoerg if (Visit(TSInfo->getTypeLoc()))
98606f32e7eSjoerg return true;
98706f32e7eSjoerg
98806f32e7eSjoerg for (const auto *P : ND->parameters()) {
98906f32e7eSjoerg if (Visit(MakeCXCursor(P, TU, RegionOfInterest)))
99006f32e7eSjoerg return true;
99106f32e7eSjoerg }
99206f32e7eSjoerg
99306f32e7eSjoerg return ND->isThisDeclarationADefinition() &&
99406f32e7eSjoerg Visit(MakeCXCursor(ND->getBody(), StmtParent, TU, RegionOfInterest));
99506f32e7eSjoerg }
99606f32e7eSjoerg
99706f32e7eSjoerg template <typename DeclIt>
addRangedDeclsInContainer(DeclIt * DI_current,DeclIt DE_current,SourceManager & SM,SourceLocation EndLoc,SmallVectorImpl<Decl * > & Decls)99806f32e7eSjoerg static void addRangedDeclsInContainer(DeclIt *DI_current, DeclIt DE_current,
99906f32e7eSjoerg SourceManager &SM, SourceLocation EndLoc,
100006f32e7eSjoerg SmallVectorImpl<Decl *> &Decls) {
100106f32e7eSjoerg DeclIt next = *DI_current;
100206f32e7eSjoerg while (++next != DE_current) {
100306f32e7eSjoerg Decl *D_next = *next;
100406f32e7eSjoerg if (!D_next)
100506f32e7eSjoerg break;
100606f32e7eSjoerg SourceLocation L = D_next->getBeginLoc();
100706f32e7eSjoerg if (!L.isValid())
100806f32e7eSjoerg break;
100906f32e7eSjoerg if (SM.isBeforeInTranslationUnit(L, EndLoc)) {
101006f32e7eSjoerg *DI_current = next;
101106f32e7eSjoerg Decls.push_back(D_next);
101206f32e7eSjoerg continue;
101306f32e7eSjoerg }
101406f32e7eSjoerg break;
101506f32e7eSjoerg }
101606f32e7eSjoerg }
101706f32e7eSjoerg
VisitObjCContainerDecl(ObjCContainerDecl * D)101806f32e7eSjoerg bool CursorVisitor::VisitObjCContainerDecl(ObjCContainerDecl *D) {
101906f32e7eSjoerg // FIXME: Eventually convert back to just 'VisitDeclContext()'. Essentially
102006f32e7eSjoerg // an @implementation can lexically contain Decls that are not properly
102106f32e7eSjoerg // nested in the AST. When we identify such cases, we need to retrofit
102206f32e7eSjoerg // this nesting here.
102306f32e7eSjoerg if (!DI_current && !FileDI_current)
102406f32e7eSjoerg return VisitDeclContext(D);
102506f32e7eSjoerg
102606f32e7eSjoerg // Scan the Decls that immediately come after the container
102706f32e7eSjoerg // in the current DeclContext. If any fall within the
102806f32e7eSjoerg // container's lexical region, stash them into a vector
102906f32e7eSjoerg // for later processing.
103006f32e7eSjoerg SmallVector<Decl *, 24> DeclsInContainer;
103106f32e7eSjoerg SourceLocation EndLoc = D->getSourceRange().getEnd();
103206f32e7eSjoerg SourceManager &SM = AU->getSourceManager();
103306f32e7eSjoerg if (EndLoc.isValid()) {
103406f32e7eSjoerg if (DI_current) {
103506f32e7eSjoerg addRangedDeclsInContainer(DI_current, DE_current, SM, EndLoc,
103606f32e7eSjoerg DeclsInContainer);
103706f32e7eSjoerg } else {
103806f32e7eSjoerg addRangedDeclsInContainer(FileDI_current, FileDE_current, SM, EndLoc,
103906f32e7eSjoerg DeclsInContainer);
104006f32e7eSjoerg }
104106f32e7eSjoerg }
104206f32e7eSjoerg
104306f32e7eSjoerg // The common case.
104406f32e7eSjoerg if (DeclsInContainer.empty())
104506f32e7eSjoerg return VisitDeclContext(D);
104606f32e7eSjoerg
104706f32e7eSjoerg // Get all the Decls in the DeclContext, and sort them with the
104806f32e7eSjoerg // additional ones we've collected. Then visit them.
104906f32e7eSjoerg for (auto *SubDecl : D->decls()) {
105006f32e7eSjoerg if (!SubDecl || SubDecl->getLexicalDeclContext() != D ||
105106f32e7eSjoerg SubDecl->getBeginLoc().isInvalid())
105206f32e7eSjoerg continue;
105306f32e7eSjoerg DeclsInContainer.push_back(SubDecl);
105406f32e7eSjoerg }
105506f32e7eSjoerg
105606f32e7eSjoerg // Now sort the Decls so that they appear in lexical order.
1057*13fbcb42Sjoerg llvm::sort(DeclsInContainer, [&SM](Decl *A, Decl *B) {
105806f32e7eSjoerg SourceLocation L_A = A->getBeginLoc();
105906f32e7eSjoerg SourceLocation L_B = B->getBeginLoc();
1060*13fbcb42Sjoerg return L_A != L_B
1061*13fbcb42Sjoerg ? SM.isBeforeInTranslationUnit(L_A, L_B)
1062*13fbcb42Sjoerg : SM.isBeforeInTranslationUnit(A->getEndLoc(), B->getEndLoc());
106306f32e7eSjoerg });
106406f32e7eSjoerg
106506f32e7eSjoerg // Now visit the decls.
106606f32e7eSjoerg for (SmallVectorImpl<Decl *>::iterator I = DeclsInContainer.begin(),
1067*13fbcb42Sjoerg E = DeclsInContainer.end();
1068*13fbcb42Sjoerg I != E; ++I) {
106906f32e7eSjoerg CXCursor Cursor = MakeCXCursor(*I, TU, RegionOfInterest);
107006f32e7eSjoerg const Optional<bool> &V = shouldVisitCursor(Cursor);
107106f32e7eSjoerg if (!V.hasValue())
107206f32e7eSjoerg continue;
107306f32e7eSjoerg if (!V.getValue())
107406f32e7eSjoerg return false;
107506f32e7eSjoerg if (Visit(Cursor, true))
107606f32e7eSjoerg return true;
107706f32e7eSjoerg }
107806f32e7eSjoerg return false;
107906f32e7eSjoerg }
108006f32e7eSjoerg
VisitObjCCategoryDecl(ObjCCategoryDecl * ND)108106f32e7eSjoerg bool CursorVisitor::VisitObjCCategoryDecl(ObjCCategoryDecl *ND) {
108206f32e7eSjoerg if (Visit(MakeCursorObjCClassRef(ND->getClassInterface(), ND->getLocation(),
108306f32e7eSjoerg TU)))
108406f32e7eSjoerg return true;
108506f32e7eSjoerg
108606f32e7eSjoerg if (VisitObjCTypeParamList(ND->getTypeParamList()))
108706f32e7eSjoerg return true;
108806f32e7eSjoerg
108906f32e7eSjoerg ObjCCategoryDecl::protocol_loc_iterator PL = ND->protocol_loc_begin();
109006f32e7eSjoerg for (ObjCCategoryDecl::protocol_iterator I = ND->protocol_begin(),
1091*13fbcb42Sjoerg E = ND->protocol_end();
1092*13fbcb42Sjoerg I != E; ++I, ++PL)
109306f32e7eSjoerg if (Visit(MakeCursorObjCProtocolRef(*I, *PL, TU)))
109406f32e7eSjoerg return true;
109506f32e7eSjoerg
109606f32e7eSjoerg return VisitObjCContainerDecl(ND);
109706f32e7eSjoerg }
109806f32e7eSjoerg
VisitObjCProtocolDecl(ObjCProtocolDecl * PID)109906f32e7eSjoerg bool CursorVisitor::VisitObjCProtocolDecl(ObjCProtocolDecl *PID) {
110006f32e7eSjoerg if (!PID->isThisDeclarationADefinition())
110106f32e7eSjoerg return Visit(MakeCursorObjCProtocolRef(PID, PID->getLocation(), TU));
110206f32e7eSjoerg
110306f32e7eSjoerg ObjCProtocolDecl::protocol_loc_iterator PL = PID->protocol_loc_begin();
110406f32e7eSjoerg for (ObjCProtocolDecl::protocol_iterator I = PID->protocol_begin(),
1105*13fbcb42Sjoerg E = PID->protocol_end();
1106*13fbcb42Sjoerg I != E; ++I, ++PL)
110706f32e7eSjoerg if (Visit(MakeCursorObjCProtocolRef(*I, *PL, TU)))
110806f32e7eSjoerg return true;
110906f32e7eSjoerg
111006f32e7eSjoerg return VisitObjCContainerDecl(PID);
111106f32e7eSjoerg }
111206f32e7eSjoerg
VisitObjCPropertyDecl(ObjCPropertyDecl * PD)111306f32e7eSjoerg bool CursorVisitor::VisitObjCPropertyDecl(ObjCPropertyDecl *PD) {
111406f32e7eSjoerg if (PD->getTypeSourceInfo() && Visit(PD->getTypeSourceInfo()->getTypeLoc()))
111506f32e7eSjoerg return true;
111606f32e7eSjoerg
111706f32e7eSjoerg // FIXME: This implements a workaround with @property declarations also being
111806f32e7eSjoerg // installed in the DeclContext for the @interface. Eventually this code
111906f32e7eSjoerg // should be removed.
112006f32e7eSjoerg ObjCCategoryDecl *CDecl = dyn_cast<ObjCCategoryDecl>(PD->getDeclContext());
112106f32e7eSjoerg if (!CDecl || !CDecl->IsClassExtension())
112206f32e7eSjoerg return false;
112306f32e7eSjoerg
112406f32e7eSjoerg ObjCInterfaceDecl *ID = CDecl->getClassInterface();
112506f32e7eSjoerg if (!ID)
112606f32e7eSjoerg return false;
112706f32e7eSjoerg
112806f32e7eSjoerg IdentifierInfo *PropertyId = PD->getIdentifier();
1129*13fbcb42Sjoerg ObjCPropertyDecl *prevDecl = ObjCPropertyDecl::findPropertyDecl(
1130*13fbcb42Sjoerg cast<DeclContext>(ID), PropertyId, PD->getQueryKind());
113106f32e7eSjoerg
113206f32e7eSjoerg if (!prevDecl)
113306f32e7eSjoerg return false;
113406f32e7eSjoerg
113506f32e7eSjoerg // Visit synthesized methods since they will be skipped when visiting
113606f32e7eSjoerg // the @interface.
113706f32e7eSjoerg if (ObjCMethodDecl *MD = prevDecl->getGetterMethodDecl())
113806f32e7eSjoerg if (MD->isPropertyAccessor() && MD->getLexicalDeclContext() == CDecl)
113906f32e7eSjoerg if (Visit(MakeCXCursor(MD, TU, RegionOfInterest)))
114006f32e7eSjoerg return true;
114106f32e7eSjoerg
114206f32e7eSjoerg if (ObjCMethodDecl *MD = prevDecl->getSetterMethodDecl())
114306f32e7eSjoerg if (MD->isPropertyAccessor() && MD->getLexicalDeclContext() == CDecl)
114406f32e7eSjoerg if (Visit(MakeCXCursor(MD, TU, RegionOfInterest)))
114506f32e7eSjoerg return true;
114606f32e7eSjoerg
114706f32e7eSjoerg return false;
114806f32e7eSjoerg }
114906f32e7eSjoerg
VisitObjCTypeParamList(ObjCTypeParamList * typeParamList)115006f32e7eSjoerg bool CursorVisitor::VisitObjCTypeParamList(ObjCTypeParamList *typeParamList) {
115106f32e7eSjoerg if (!typeParamList)
115206f32e7eSjoerg return false;
115306f32e7eSjoerg
115406f32e7eSjoerg for (auto *typeParam : *typeParamList) {
115506f32e7eSjoerg // Visit the type parameter.
115606f32e7eSjoerg if (Visit(MakeCXCursor(typeParam, TU, RegionOfInterest)))
115706f32e7eSjoerg return true;
115806f32e7eSjoerg }
115906f32e7eSjoerg
116006f32e7eSjoerg return false;
116106f32e7eSjoerg }
116206f32e7eSjoerg
VisitObjCInterfaceDecl(ObjCInterfaceDecl * D)116306f32e7eSjoerg bool CursorVisitor::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
116406f32e7eSjoerg if (!D->isThisDeclarationADefinition()) {
116506f32e7eSjoerg // Forward declaration is treated like a reference.
116606f32e7eSjoerg return Visit(MakeCursorObjCClassRef(D, D->getLocation(), TU));
116706f32e7eSjoerg }
116806f32e7eSjoerg
116906f32e7eSjoerg // Objective-C type parameters.
117006f32e7eSjoerg if (VisitObjCTypeParamList(D->getTypeParamListAsWritten()))
117106f32e7eSjoerg return true;
117206f32e7eSjoerg
117306f32e7eSjoerg // Issue callbacks for super class.
1174*13fbcb42Sjoerg if (D->getSuperClass() && Visit(MakeCursorObjCSuperClassRef(
1175*13fbcb42Sjoerg D->getSuperClass(), D->getSuperClassLoc(), TU)))
117606f32e7eSjoerg return true;
117706f32e7eSjoerg
117806f32e7eSjoerg if (TypeSourceInfo *SuperClassTInfo = D->getSuperClassTInfo())
117906f32e7eSjoerg if (Visit(SuperClassTInfo->getTypeLoc()))
118006f32e7eSjoerg return true;
118106f32e7eSjoerg
118206f32e7eSjoerg ObjCInterfaceDecl::protocol_loc_iterator PL = D->protocol_loc_begin();
118306f32e7eSjoerg for (ObjCInterfaceDecl::protocol_iterator I = D->protocol_begin(),
1184*13fbcb42Sjoerg E = D->protocol_end();
1185*13fbcb42Sjoerg I != E; ++I, ++PL)
118606f32e7eSjoerg if (Visit(MakeCursorObjCProtocolRef(*I, *PL, TU)))
118706f32e7eSjoerg return true;
118806f32e7eSjoerg
118906f32e7eSjoerg return VisitObjCContainerDecl(D);
119006f32e7eSjoerg }
119106f32e7eSjoerg
VisitObjCImplDecl(ObjCImplDecl * D)119206f32e7eSjoerg bool CursorVisitor::VisitObjCImplDecl(ObjCImplDecl *D) {
119306f32e7eSjoerg return VisitObjCContainerDecl(D);
119406f32e7eSjoerg }
119506f32e7eSjoerg
VisitObjCCategoryImplDecl(ObjCCategoryImplDecl * D)119606f32e7eSjoerg bool CursorVisitor::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) {
119706f32e7eSjoerg // 'ID' could be null when dealing with invalid code.
119806f32e7eSjoerg if (ObjCInterfaceDecl *ID = D->getClassInterface())
119906f32e7eSjoerg if (Visit(MakeCursorObjCClassRef(ID, D->getLocation(), TU)))
120006f32e7eSjoerg return true;
120106f32e7eSjoerg
120206f32e7eSjoerg return VisitObjCImplDecl(D);
120306f32e7eSjoerg }
120406f32e7eSjoerg
VisitObjCImplementationDecl(ObjCImplementationDecl * D)120506f32e7eSjoerg bool CursorVisitor::VisitObjCImplementationDecl(ObjCImplementationDecl *D) {
120606f32e7eSjoerg #if 0
120706f32e7eSjoerg // Issue callbacks for super class.
120806f32e7eSjoerg // FIXME: No source location information!
120906f32e7eSjoerg if (D->getSuperClass() &&
121006f32e7eSjoerg Visit(MakeCursorObjCSuperClassRef(D->getSuperClass(),
121106f32e7eSjoerg D->getSuperClassLoc(),
121206f32e7eSjoerg TU)))
121306f32e7eSjoerg return true;
121406f32e7eSjoerg #endif
121506f32e7eSjoerg
121606f32e7eSjoerg return VisitObjCImplDecl(D);
121706f32e7eSjoerg }
121806f32e7eSjoerg
VisitObjCPropertyImplDecl(ObjCPropertyImplDecl * PD)121906f32e7eSjoerg bool CursorVisitor::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *PD) {
122006f32e7eSjoerg if (ObjCIvarDecl *Ivar = PD->getPropertyIvarDecl())
122106f32e7eSjoerg if (PD->isIvarNameSpecified())
122206f32e7eSjoerg return Visit(MakeCursorMemberRef(Ivar, PD->getPropertyIvarDeclLoc(), TU));
122306f32e7eSjoerg
122406f32e7eSjoerg return false;
122506f32e7eSjoerg }
122606f32e7eSjoerg
VisitNamespaceDecl(NamespaceDecl * D)122706f32e7eSjoerg bool CursorVisitor::VisitNamespaceDecl(NamespaceDecl *D) {
122806f32e7eSjoerg return VisitDeclContext(D);
122906f32e7eSjoerg }
123006f32e7eSjoerg
VisitNamespaceAliasDecl(NamespaceAliasDecl * D)123106f32e7eSjoerg bool CursorVisitor::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
123206f32e7eSjoerg // Visit nested-name-specifier.
123306f32e7eSjoerg if (NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc())
123406f32e7eSjoerg if (VisitNestedNameSpecifierLoc(QualifierLoc))
123506f32e7eSjoerg return true;
123606f32e7eSjoerg
123706f32e7eSjoerg return Visit(MakeCursorNamespaceRef(D->getAliasedNamespace(),
123806f32e7eSjoerg D->getTargetNameLoc(), TU));
123906f32e7eSjoerg }
124006f32e7eSjoerg
VisitUsingDecl(UsingDecl * D)124106f32e7eSjoerg bool CursorVisitor::VisitUsingDecl(UsingDecl *D) {
124206f32e7eSjoerg // Visit nested-name-specifier.
124306f32e7eSjoerg if (NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc()) {
124406f32e7eSjoerg if (VisitNestedNameSpecifierLoc(QualifierLoc))
124506f32e7eSjoerg return true;
124606f32e7eSjoerg }
124706f32e7eSjoerg
124806f32e7eSjoerg if (Visit(MakeCursorOverloadedDeclRef(D, D->getLocation(), TU)))
124906f32e7eSjoerg return true;
125006f32e7eSjoerg
125106f32e7eSjoerg return VisitDeclarationNameInfo(D->getNameInfo());
125206f32e7eSjoerg }
125306f32e7eSjoerg
VisitUsingDirectiveDecl(UsingDirectiveDecl * D)125406f32e7eSjoerg bool CursorVisitor::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
125506f32e7eSjoerg // Visit nested-name-specifier.
125606f32e7eSjoerg if (NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc())
125706f32e7eSjoerg if (VisitNestedNameSpecifierLoc(QualifierLoc))
125806f32e7eSjoerg return true;
125906f32e7eSjoerg
126006f32e7eSjoerg return Visit(MakeCursorNamespaceRef(D->getNominatedNamespaceAsWritten(),
126106f32e7eSjoerg D->getIdentLocation(), TU));
126206f32e7eSjoerg }
126306f32e7eSjoerg
VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl * D)126406f32e7eSjoerg bool CursorVisitor::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) {
126506f32e7eSjoerg // Visit nested-name-specifier.
126606f32e7eSjoerg if (NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc()) {
126706f32e7eSjoerg if (VisitNestedNameSpecifierLoc(QualifierLoc))
126806f32e7eSjoerg return true;
126906f32e7eSjoerg }
127006f32e7eSjoerg
127106f32e7eSjoerg return VisitDeclarationNameInfo(D->getNameInfo());
127206f32e7eSjoerg }
127306f32e7eSjoerg
VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl * D)127406f32e7eSjoerg bool CursorVisitor::VisitUnresolvedUsingTypenameDecl(
127506f32e7eSjoerg UnresolvedUsingTypenameDecl *D) {
127606f32e7eSjoerg // Visit nested-name-specifier.
127706f32e7eSjoerg if (NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc())
127806f32e7eSjoerg if (VisitNestedNameSpecifierLoc(QualifierLoc))
127906f32e7eSjoerg return true;
128006f32e7eSjoerg
128106f32e7eSjoerg return false;
128206f32e7eSjoerg }
128306f32e7eSjoerg
VisitStaticAssertDecl(StaticAssertDecl * D)128406f32e7eSjoerg bool CursorVisitor::VisitStaticAssertDecl(StaticAssertDecl *D) {
128506f32e7eSjoerg if (Visit(MakeCXCursor(D->getAssertExpr(), StmtParent, TU, RegionOfInterest)))
128606f32e7eSjoerg return true;
128706f32e7eSjoerg if (StringLiteral *Message = D->getMessage())
128806f32e7eSjoerg if (Visit(MakeCXCursor(Message, StmtParent, TU, RegionOfInterest)))
128906f32e7eSjoerg return true;
129006f32e7eSjoerg return false;
129106f32e7eSjoerg }
129206f32e7eSjoerg
VisitFriendDecl(FriendDecl * D)129306f32e7eSjoerg bool CursorVisitor::VisitFriendDecl(FriendDecl *D) {
129406f32e7eSjoerg if (NamedDecl *FriendD = D->getFriendDecl()) {
129506f32e7eSjoerg if (Visit(MakeCXCursor(FriendD, TU, RegionOfInterest)))
129606f32e7eSjoerg return true;
129706f32e7eSjoerg } else if (TypeSourceInfo *TI = D->getFriendType()) {
129806f32e7eSjoerg if (Visit(TI->getTypeLoc()))
129906f32e7eSjoerg return true;
130006f32e7eSjoerg }
130106f32e7eSjoerg return false;
130206f32e7eSjoerg }
130306f32e7eSjoerg
VisitDecompositionDecl(DecompositionDecl * D)1304*13fbcb42Sjoerg bool CursorVisitor::VisitDecompositionDecl(DecompositionDecl *D) {
1305*13fbcb42Sjoerg for (auto *B : D->bindings()) {
1306*13fbcb42Sjoerg if (Visit(MakeCXCursor(B, TU, RegionOfInterest)))
1307*13fbcb42Sjoerg return true;
1308*13fbcb42Sjoerg }
1309*13fbcb42Sjoerg return VisitVarDecl(D);
1310*13fbcb42Sjoerg }
1311*13fbcb42Sjoerg
VisitDeclarationNameInfo(DeclarationNameInfo Name)131206f32e7eSjoerg bool CursorVisitor::VisitDeclarationNameInfo(DeclarationNameInfo Name) {
131306f32e7eSjoerg switch (Name.getName().getNameKind()) {
131406f32e7eSjoerg case clang::DeclarationName::Identifier:
131506f32e7eSjoerg case clang::DeclarationName::CXXLiteralOperatorName:
131606f32e7eSjoerg case clang::DeclarationName::CXXDeductionGuideName:
131706f32e7eSjoerg case clang::DeclarationName::CXXOperatorName:
131806f32e7eSjoerg case clang::DeclarationName::CXXUsingDirective:
131906f32e7eSjoerg return false;
132006f32e7eSjoerg
132106f32e7eSjoerg case clang::DeclarationName::CXXConstructorName:
132206f32e7eSjoerg case clang::DeclarationName::CXXDestructorName:
132306f32e7eSjoerg case clang::DeclarationName::CXXConversionFunctionName:
132406f32e7eSjoerg if (TypeSourceInfo *TSInfo = Name.getNamedTypeInfo())
132506f32e7eSjoerg return Visit(TSInfo->getTypeLoc());
132606f32e7eSjoerg return false;
132706f32e7eSjoerg
132806f32e7eSjoerg case clang::DeclarationName::ObjCZeroArgSelector:
132906f32e7eSjoerg case clang::DeclarationName::ObjCOneArgSelector:
133006f32e7eSjoerg case clang::DeclarationName::ObjCMultiArgSelector:
133106f32e7eSjoerg // FIXME: Per-identifier location info?
133206f32e7eSjoerg return false;
133306f32e7eSjoerg }
133406f32e7eSjoerg
133506f32e7eSjoerg llvm_unreachable("Invalid DeclarationName::Kind!");
133606f32e7eSjoerg }
133706f32e7eSjoerg
VisitNestedNameSpecifier(NestedNameSpecifier * NNS,SourceRange Range)133806f32e7eSjoerg bool CursorVisitor::VisitNestedNameSpecifier(NestedNameSpecifier *NNS,
133906f32e7eSjoerg SourceRange Range) {
134006f32e7eSjoerg // FIXME: This whole routine is a hack to work around the lack of proper
134106f32e7eSjoerg // source information in nested-name-specifiers (PR5791). Since we do have
134206f32e7eSjoerg // a beginning source location, we can visit the first component of the
134306f32e7eSjoerg // nested-name-specifier, if it's a single-token component.
134406f32e7eSjoerg if (!NNS)
134506f32e7eSjoerg return false;
134606f32e7eSjoerg
134706f32e7eSjoerg // Get the first component in the nested-name-specifier.
134806f32e7eSjoerg while (NestedNameSpecifier *Prefix = NNS->getPrefix())
134906f32e7eSjoerg NNS = Prefix;
135006f32e7eSjoerg
135106f32e7eSjoerg switch (NNS->getKind()) {
135206f32e7eSjoerg case NestedNameSpecifier::Namespace:
1353*13fbcb42Sjoerg return Visit(
1354*13fbcb42Sjoerg MakeCursorNamespaceRef(NNS->getAsNamespace(), Range.getBegin(), TU));
135506f32e7eSjoerg
135606f32e7eSjoerg case NestedNameSpecifier::NamespaceAlias:
135706f32e7eSjoerg return Visit(MakeCursorNamespaceRef(NNS->getAsNamespaceAlias(),
135806f32e7eSjoerg Range.getBegin(), TU));
135906f32e7eSjoerg
136006f32e7eSjoerg case NestedNameSpecifier::TypeSpec: {
136106f32e7eSjoerg // If the type has a form where we know that the beginning of the source
136206f32e7eSjoerg // range matches up with a reference cursor. Visit the appropriate reference
136306f32e7eSjoerg // cursor.
136406f32e7eSjoerg const Type *T = NNS->getAsType();
136506f32e7eSjoerg if (const TypedefType *Typedef = dyn_cast<TypedefType>(T))
136606f32e7eSjoerg return Visit(MakeCursorTypeRef(Typedef->getDecl(), Range.getBegin(), TU));
136706f32e7eSjoerg if (const TagType *Tag = dyn_cast<TagType>(T))
136806f32e7eSjoerg return Visit(MakeCursorTypeRef(Tag->getDecl(), Range.getBegin(), TU));
1369*13fbcb42Sjoerg if (const TemplateSpecializationType *TST =
1370*13fbcb42Sjoerg dyn_cast<TemplateSpecializationType>(T))
137106f32e7eSjoerg return VisitTemplateName(TST->getTemplateName(), Range.getBegin());
137206f32e7eSjoerg break;
137306f32e7eSjoerg }
137406f32e7eSjoerg
137506f32e7eSjoerg case NestedNameSpecifier::TypeSpecWithTemplate:
137606f32e7eSjoerg case NestedNameSpecifier::Global:
137706f32e7eSjoerg case NestedNameSpecifier::Identifier:
137806f32e7eSjoerg case NestedNameSpecifier::Super:
137906f32e7eSjoerg break;
138006f32e7eSjoerg }
138106f32e7eSjoerg
138206f32e7eSjoerg return false;
138306f32e7eSjoerg }
138406f32e7eSjoerg
VisitNestedNameSpecifierLoc(NestedNameSpecifierLoc Qualifier)1385*13fbcb42Sjoerg bool CursorVisitor::VisitNestedNameSpecifierLoc(
1386*13fbcb42Sjoerg NestedNameSpecifierLoc Qualifier) {
138706f32e7eSjoerg SmallVector<NestedNameSpecifierLoc, 4> Qualifiers;
138806f32e7eSjoerg for (; Qualifier; Qualifier = Qualifier.getPrefix())
138906f32e7eSjoerg Qualifiers.push_back(Qualifier);
139006f32e7eSjoerg
139106f32e7eSjoerg while (!Qualifiers.empty()) {
139206f32e7eSjoerg NestedNameSpecifierLoc Q = Qualifiers.pop_back_val();
139306f32e7eSjoerg NestedNameSpecifier *NNS = Q.getNestedNameSpecifier();
139406f32e7eSjoerg switch (NNS->getKind()) {
139506f32e7eSjoerg case NestedNameSpecifier::Namespace:
139606f32e7eSjoerg if (Visit(MakeCursorNamespaceRef(NNS->getAsNamespace(),
1397*13fbcb42Sjoerg Q.getLocalBeginLoc(), TU)))
139806f32e7eSjoerg return true;
139906f32e7eSjoerg
140006f32e7eSjoerg break;
140106f32e7eSjoerg
140206f32e7eSjoerg case NestedNameSpecifier::NamespaceAlias:
140306f32e7eSjoerg if (Visit(MakeCursorNamespaceRef(NNS->getAsNamespaceAlias(),
1404*13fbcb42Sjoerg Q.getLocalBeginLoc(), TU)))
140506f32e7eSjoerg return true;
140606f32e7eSjoerg
140706f32e7eSjoerg break;
140806f32e7eSjoerg
140906f32e7eSjoerg case NestedNameSpecifier::TypeSpec:
141006f32e7eSjoerg case NestedNameSpecifier::TypeSpecWithTemplate:
141106f32e7eSjoerg if (Visit(Q.getTypeLoc()))
141206f32e7eSjoerg return true;
141306f32e7eSjoerg
141406f32e7eSjoerg break;
141506f32e7eSjoerg
141606f32e7eSjoerg case NestedNameSpecifier::Global:
141706f32e7eSjoerg case NestedNameSpecifier::Identifier:
141806f32e7eSjoerg case NestedNameSpecifier::Super:
141906f32e7eSjoerg break;
142006f32e7eSjoerg }
142106f32e7eSjoerg }
142206f32e7eSjoerg
142306f32e7eSjoerg return false;
142406f32e7eSjoerg }
142506f32e7eSjoerg
VisitTemplateParameters(const TemplateParameterList * Params)142606f32e7eSjoerg bool CursorVisitor::VisitTemplateParameters(
142706f32e7eSjoerg const TemplateParameterList *Params) {
142806f32e7eSjoerg if (!Params)
142906f32e7eSjoerg return false;
143006f32e7eSjoerg
143106f32e7eSjoerg for (TemplateParameterList::const_iterator P = Params->begin(),
143206f32e7eSjoerg PEnd = Params->end();
143306f32e7eSjoerg P != PEnd; ++P) {
143406f32e7eSjoerg if (Visit(MakeCXCursor(*P, TU, RegionOfInterest)))
143506f32e7eSjoerg return true;
143606f32e7eSjoerg }
143706f32e7eSjoerg
143806f32e7eSjoerg return false;
143906f32e7eSjoerg }
144006f32e7eSjoerg
VisitTemplateName(TemplateName Name,SourceLocation Loc)144106f32e7eSjoerg bool CursorVisitor::VisitTemplateName(TemplateName Name, SourceLocation Loc) {
144206f32e7eSjoerg switch (Name.getKind()) {
144306f32e7eSjoerg case TemplateName::Template:
144406f32e7eSjoerg return Visit(MakeCursorTemplateRef(Name.getAsTemplateDecl(), Loc, TU));
144506f32e7eSjoerg
144606f32e7eSjoerg case TemplateName::OverloadedTemplate:
144706f32e7eSjoerg // Visit the overloaded template set.
144806f32e7eSjoerg if (Visit(MakeCursorOverloadedDeclRef(Name, Loc, TU)))
144906f32e7eSjoerg return true;
145006f32e7eSjoerg
145106f32e7eSjoerg return false;
145206f32e7eSjoerg
145306f32e7eSjoerg case TemplateName::AssumedTemplate:
145406f32e7eSjoerg // FIXME: Visit DeclarationName?
145506f32e7eSjoerg return false;
145606f32e7eSjoerg
145706f32e7eSjoerg case TemplateName::DependentTemplate:
145806f32e7eSjoerg // FIXME: Visit nested-name-specifier.
145906f32e7eSjoerg return false;
146006f32e7eSjoerg
146106f32e7eSjoerg case TemplateName::QualifiedTemplate:
146206f32e7eSjoerg // FIXME: Visit nested-name-specifier.
146306f32e7eSjoerg return Visit(MakeCursorTemplateRef(
1464*13fbcb42Sjoerg Name.getAsQualifiedTemplateName()->getDecl(), Loc, TU));
146506f32e7eSjoerg
146606f32e7eSjoerg case TemplateName::SubstTemplateTemplateParm:
146706f32e7eSjoerg return Visit(MakeCursorTemplateRef(
1468*13fbcb42Sjoerg Name.getAsSubstTemplateTemplateParm()->getParameter(), Loc, TU));
146906f32e7eSjoerg
147006f32e7eSjoerg case TemplateName::SubstTemplateTemplateParmPack:
147106f32e7eSjoerg return Visit(MakeCursorTemplateRef(
1472*13fbcb42Sjoerg Name.getAsSubstTemplateTemplateParmPack()->getParameterPack(), Loc,
1473*13fbcb42Sjoerg TU));
147406f32e7eSjoerg }
147506f32e7eSjoerg
147606f32e7eSjoerg llvm_unreachable("Invalid TemplateName::Kind!");
147706f32e7eSjoerg }
147806f32e7eSjoerg
VisitTemplateArgumentLoc(const TemplateArgumentLoc & TAL)147906f32e7eSjoerg bool CursorVisitor::VisitTemplateArgumentLoc(const TemplateArgumentLoc &TAL) {
148006f32e7eSjoerg switch (TAL.getArgument().getKind()) {
148106f32e7eSjoerg case TemplateArgument::Null:
148206f32e7eSjoerg case TemplateArgument::Integral:
148306f32e7eSjoerg case TemplateArgument::Pack:
148406f32e7eSjoerg return false;
148506f32e7eSjoerg
148606f32e7eSjoerg case TemplateArgument::Type:
148706f32e7eSjoerg if (TypeSourceInfo *TSInfo = TAL.getTypeSourceInfo())
148806f32e7eSjoerg return Visit(TSInfo->getTypeLoc());
148906f32e7eSjoerg return false;
149006f32e7eSjoerg
149106f32e7eSjoerg case TemplateArgument::Declaration:
149206f32e7eSjoerg if (Expr *E = TAL.getSourceDeclExpression())
149306f32e7eSjoerg return Visit(MakeCXCursor(E, StmtParent, TU, RegionOfInterest));
149406f32e7eSjoerg return false;
149506f32e7eSjoerg
149606f32e7eSjoerg case TemplateArgument::NullPtr:
149706f32e7eSjoerg if (Expr *E = TAL.getSourceNullPtrExpression())
149806f32e7eSjoerg return Visit(MakeCXCursor(E, StmtParent, TU, RegionOfInterest));
149906f32e7eSjoerg return false;
150006f32e7eSjoerg
150106f32e7eSjoerg case TemplateArgument::Expression:
150206f32e7eSjoerg if (Expr *E = TAL.getSourceExpression())
150306f32e7eSjoerg return Visit(MakeCXCursor(E, StmtParent, TU, RegionOfInterest));
150406f32e7eSjoerg return false;
150506f32e7eSjoerg
150606f32e7eSjoerg case TemplateArgument::Template:
150706f32e7eSjoerg case TemplateArgument::TemplateExpansion:
150806f32e7eSjoerg if (VisitNestedNameSpecifierLoc(TAL.getTemplateQualifierLoc()))
150906f32e7eSjoerg return true;
151006f32e7eSjoerg
151106f32e7eSjoerg return VisitTemplateName(TAL.getArgument().getAsTemplateOrTemplatePattern(),
151206f32e7eSjoerg TAL.getTemplateNameLoc());
151306f32e7eSjoerg }
151406f32e7eSjoerg
151506f32e7eSjoerg llvm_unreachable("Invalid TemplateArgument::Kind!");
151606f32e7eSjoerg }
151706f32e7eSjoerg
VisitLinkageSpecDecl(LinkageSpecDecl * D)151806f32e7eSjoerg bool CursorVisitor::VisitLinkageSpecDecl(LinkageSpecDecl *D) {
151906f32e7eSjoerg return VisitDeclContext(D);
152006f32e7eSjoerg }
152106f32e7eSjoerg
VisitQualifiedTypeLoc(QualifiedTypeLoc TL)152206f32e7eSjoerg bool CursorVisitor::VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {
152306f32e7eSjoerg return Visit(TL.getUnqualifiedLoc());
152406f32e7eSjoerg }
152506f32e7eSjoerg
VisitBuiltinTypeLoc(BuiltinTypeLoc TL)152606f32e7eSjoerg bool CursorVisitor::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) {
152706f32e7eSjoerg ASTContext &Context = AU->getASTContext();
152806f32e7eSjoerg
152906f32e7eSjoerg // Some builtin types (such as Objective-C's "id", "sel", and
153006f32e7eSjoerg // "Class") have associated declarations. Create cursors for those.
153106f32e7eSjoerg QualType VisitType;
153206f32e7eSjoerg switch (TL.getTypePtr()->getKind()) {
153306f32e7eSjoerg
153406f32e7eSjoerg case BuiltinType::Void:
153506f32e7eSjoerg case BuiltinType::NullPtr:
153606f32e7eSjoerg case BuiltinType::Dependent:
153706f32e7eSjoerg #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
153806f32e7eSjoerg case BuiltinType::Id:
153906f32e7eSjoerg #include "clang/Basic/OpenCLImageTypes.def"
1540*13fbcb42Sjoerg #define EXT_OPAQUE_TYPE(ExtTYpe, Id, Ext) case BuiltinType::Id:
154106f32e7eSjoerg #include "clang/Basic/OpenCLExtensionTypes.def"
154206f32e7eSjoerg case BuiltinType::OCLSampler:
154306f32e7eSjoerg case BuiltinType::OCLEvent:
154406f32e7eSjoerg case BuiltinType::OCLClkEvent:
154506f32e7eSjoerg case BuiltinType::OCLQueue:
154606f32e7eSjoerg case BuiltinType::OCLReserveID:
1547*13fbcb42Sjoerg #define SVE_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
154806f32e7eSjoerg #include "clang/Basic/AArch64SVEACLETypes.def"
1549*13fbcb42Sjoerg #define PPC_VECTOR_TYPE(Name, Id, Size) case BuiltinType::Id:
1550*13fbcb42Sjoerg #include "clang/Basic/PPCTypes.def"
1551*13fbcb42Sjoerg #define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
1552*13fbcb42Sjoerg #include "clang/Basic/RISCVVTypes.def"
155306f32e7eSjoerg #define BUILTIN_TYPE(Id, SingletonId)
155406f32e7eSjoerg #define SIGNED_TYPE(Id, SingletonId) case BuiltinType::Id:
155506f32e7eSjoerg #define UNSIGNED_TYPE(Id, SingletonId) case BuiltinType::Id:
155606f32e7eSjoerg #define FLOATING_TYPE(Id, SingletonId) case BuiltinType::Id:
155706f32e7eSjoerg #define PLACEHOLDER_TYPE(Id, SingletonId) case BuiltinType::Id:
155806f32e7eSjoerg #include "clang/AST/BuiltinTypes.def"
155906f32e7eSjoerg break;
156006f32e7eSjoerg
156106f32e7eSjoerg case BuiltinType::ObjCId:
156206f32e7eSjoerg VisitType = Context.getObjCIdType();
156306f32e7eSjoerg break;
156406f32e7eSjoerg
156506f32e7eSjoerg case BuiltinType::ObjCClass:
156606f32e7eSjoerg VisitType = Context.getObjCClassType();
156706f32e7eSjoerg break;
156806f32e7eSjoerg
156906f32e7eSjoerg case BuiltinType::ObjCSel:
157006f32e7eSjoerg VisitType = Context.getObjCSelType();
157106f32e7eSjoerg break;
157206f32e7eSjoerg }
157306f32e7eSjoerg
157406f32e7eSjoerg if (!VisitType.isNull()) {
157506f32e7eSjoerg if (const TypedefType *Typedef = VisitType->getAs<TypedefType>())
1576*13fbcb42Sjoerg return Visit(
1577*13fbcb42Sjoerg MakeCursorTypeRef(Typedef->getDecl(), TL.getBuiltinLoc(), TU));
157806f32e7eSjoerg }
157906f32e7eSjoerg
158006f32e7eSjoerg return false;
158106f32e7eSjoerg }
158206f32e7eSjoerg
VisitTypedefTypeLoc(TypedefTypeLoc TL)158306f32e7eSjoerg bool CursorVisitor::VisitTypedefTypeLoc(TypedefTypeLoc TL) {
158406f32e7eSjoerg return Visit(MakeCursorTypeRef(TL.getTypedefNameDecl(), TL.getNameLoc(), TU));
158506f32e7eSjoerg }
158606f32e7eSjoerg
VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc TL)158706f32e7eSjoerg bool CursorVisitor::VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc TL) {
158806f32e7eSjoerg return Visit(MakeCursorTypeRef(TL.getDecl(), TL.getNameLoc(), TU));
158906f32e7eSjoerg }
159006f32e7eSjoerg
VisitTagTypeLoc(TagTypeLoc TL)159106f32e7eSjoerg bool CursorVisitor::VisitTagTypeLoc(TagTypeLoc TL) {
159206f32e7eSjoerg if (TL.isDefinition())
159306f32e7eSjoerg return Visit(MakeCXCursor(TL.getDecl(), TU, RegionOfInterest));
159406f32e7eSjoerg
159506f32e7eSjoerg return Visit(MakeCursorTypeRef(TL.getDecl(), TL.getNameLoc(), TU));
159606f32e7eSjoerg }
159706f32e7eSjoerg
VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL)159806f32e7eSjoerg bool CursorVisitor::VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) {
159906f32e7eSjoerg return Visit(MakeCursorTypeRef(TL.getDecl(), TL.getNameLoc(), TU));
160006f32e7eSjoerg }
160106f32e7eSjoerg
VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL)160206f32e7eSjoerg bool CursorVisitor::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
160306f32e7eSjoerg return Visit(MakeCursorObjCClassRef(TL.getIFaceDecl(), TL.getNameLoc(), TU));
160406f32e7eSjoerg }
160506f32e7eSjoerg
VisitObjCTypeParamTypeLoc(ObjCTypeParamTypeLoc TL)160606f32e7eSjoerg bool CursorVisitor::VisitObjCTypeParamTypeLoc(ObjCTypeParamTypeLoc TL) {
160706f32e7eSjoerg if (Visit(MakeCursorTypeRef(TL.getDecl(), TL.getBeginLoc(), TU)))
160806f32e7eSjoerg return true;
160906f32e7eSjoerg for (unsigned I = 0, N = TL.getNumProtocols(); I != N; ++I) {
161006f32e7eSjoerg if (Visit(MakeCursorObjCProtocolRef(TL.getProtocol(I), TL.getProtocolLoc(I),
161106f32e7eSjoerg TU)))
161206f32e7eSjoerg return true;
161306f32e7eSjoerg }
161406f32e7eSjoerg
161506f32e7eSjoerg return false;
161606f32e7eSjoerg }
161706f32e7eSjoerg
VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL)161806f32e7eSjoerg bool CursorVisitor::VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) {
161906f32e7eSjoerg if (TL.hasBaseTypeAsWritten() && Visit(TL.getBaseLoc()))
162006f32e7eSjoerg return true;
162106f32e7eSjoerg
162206f32e7eSjoerg for (unsigned I = 0, N = TL.getNumTypeArgs(); I != N; ++I) {
162306f32e7eSjoerg if (Visit(TL.getTypeArgTInfo(I)->getTypeLoc()))
162406f32e7eSjoerg return true;
162506f32e7eSjoerg }
162606f32e7eSjoerg
162706f32e7eSjoerg for (unsigned I = 0, N = TL.getNumProtocols(); I != N; ++I) {
162806f32e7eSjoerg if (Visit(MakeCursorObjCProtocolRef(TL.getProtocol(I), TL.getProtocolLoc(I),
162906f32e7eSjoerg TU)))
163006f32e7eSjoerg return true;
163106f32e7eSjoerg }
163206f32e7eSjoerg
163306f32e7eSjoerg return false;
163406f32e7eSjoerg }
163506f32e7eSjoerg
VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL)163606f32e7eSjoerg bool CursorVisitor::VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) {
163706f32e7eSjoerg return Visit(TL.getPointeeLoc());
163806f32e7eSjoerg }
163906f32e7eSjoerg
VisitParenTypeLoc(ParenTypeLoc TL)164006f32e7eSjoerg bool CursorVisitor::VisitParenTypeLoc(ParenTypeLoc TL) {
164106f32e7eSjoerg return Visit(TL.getInnerLoc());
164206f32e7eSjoerg }
164306f32e7eSjoerg
VisitMacroQualifiedTypeLoc(MacroQualifiedTypeLoc TL)164406f32e7eSjoerg bool CursorVisitor::VisitMacroQualifiedTypeLoc(MacroQualifiedTypeLoc TL) {
164506f32e7eSjoerg return Visit(TL.getInnerLoc());
164606f32e7eSjoerg }
164706f32e7eSjoerg
VisitPointerTypeLoc(PointerTypeLoc TL)164806f32e7eSjoerg bool CursorVisitor::VisitPointerTypeLoc(PointerTypeLoc TL) {
164906f32e7eSjoerg return Visit(TL.getPointeeLoc());
165006f32e7eSjoerg }
165106f32e7eSjoerg
VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL)165206f32e7eSjoerg bool CursorVisitor::VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL) {
165306f32e7eSjoerg return Visit(TL.getPointeeLoc());
165406f32e7eSjoerg }
165506f32e7eSjoerg
VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL)165606f32e7eSjoerg bool CursorVisitor::VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) {
165706f32e7eSjoerg return Visit(TL.getPointeeLoc());
165806f32e7eSjoerg }
165906f32e7eSjoerg
VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL)166006f32e7eSjoerg bool CursorVisitor::VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL) {
166106f32e7eSjoerg return Visit(TL.getPointeeLoc());
166206f32e7eSjoerg }
166306f32e7eSjoerg
VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL)166406f32e7eSjoerg bool CursorVisitor::VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL) {
166506f32e7eSjoerg return Visit(TL.getPointeeLoc());
166606f32e7eSjoerg }
166706f32e7eSjoerg
VisitAttributedTypeLoc(AttributedTypeLoc TL)166806f32e7eSjoerg bool CursorVisitor::VisitAttributedTypeLoc(AttributedTypeLoc TL) {
166906f32e7eSjoerg return Visit(TL.getModifiedLoc());
167006f32e7eSjoerg }
167106f32e7eSjoerg
VisitFunctionTypeLoc(FunctionTypeLoc TL,bool SkipResultType)167206f32e7eSjoerg bool CursorVisitor::VisitFunctionTypeLoc(FunctionTypeLoc TL,
167306f32e7eSjoerg bool SkipResultType) {
167406f32e7eSjoerg if (!SkipResultType && Visit(TL.getReturnLoc()))
167506f32e7eSjoerg return true;
167606f32e7eSjoerg
167706f32e7eSjoerg for (unsigned I = 0, N = TL.getNumParams(); I != N; ++I)
167806f32e7eSjoerg if (Decl *D = TL.getParam(I))
167906f32e7eSjoerg if (Visit(MakeCXCursor(D, TU, RegionOfInterest)))
168006f32e7eSjoerg return true;
168106f32e7eSjoerg
168206f32e7eSjoerg return false;
168306f32e7eSjoerg }
168406f32e7eSjoerg
VisitArrayTypeLoc(ArrayTypeLoc TL)168506f32e7eSjoerg bool CursorVisitor::VisitArrayTypeLoc(ArrayTypeLoc TL) {
168606f32e7eSjoerg if (Visit(TL.getElementLoc()))
168706f32e7eSjoerg return true;
168806f32e7eSjoerg
168906f32e7eSjoerg if (Expr *Size = TL.getSizeExpr())
169006f32e7eSjoerg return Visit(MakeCXCursor(Size, StmtParent, TU, RegionOfInterest));
169106f32e7eSjoerg
169206f32e7eSjoerg return false;
169306f32e7eSjoerg }
169406f32e7eSjoerg
VisitDecayedTypeLoc(DecayedTypeLoc TL)169506f32e7eSjoerg bool CursorVisitor::VisitDecayedTypeLoc(DecayedTypeLoc TL) {
169606f32e7eSjoerg return Visit(TL.getOriginalLoc());
169706f32e7eSjoerg }
169806f32e7eSjoerg
VisitAdjustedTypeLoc(AdjustedTypeLoc TL)169906f32e7eSjoerg bool CursorVisitor::VisitAdjustedTypeLoc(AdjustedTypeLoc TL) {
170006f32e7eSjoerg return Visit(TL.getOriginalLoc());
170106f32e7eSjoerg }
170206f32e7eSjoerg
VisitDeducedTemplateSpecializationTypeLoc(DeducedTemplateSpecializationTypeLoc TL)170306f32e7eSjoerg bool CursorVisitor::VisitDeducedTemplateSpecializationTypeLoc(
170406f32e7eSjoerg DeducedTemplateSpecializationTypeLoc TL) {
170506f32e7eSjoerg if (VisitTemplateName(TL.getTypePtr()->getTemplateName(),
170606f32e7eSjoerg TL.getTemplateNameLoc()))
170706f32e7eSjoerg return true;
170806f32e7eSjoerg
170906f32e7eSjoerg return false;
171006f32e7eSjoerg }
171106f32e7eSjoerg
VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL)171206f32e7eSjoerg bool CursorVisitor::VisitTemplateSpecializationTypeLoc(
171306f32e7eSjoerg TemplateSpecializationTypeLoc TL) {
171406f32e7eSjoerg // Visit the template name.
171506f32e7eSjoerg if (VisitTemplateName(TL.getTypePtr()->getTemplateName(),
171606f32e7eSjoerg TL.getTemplateNameLoc()))
171706f32e7eSjoerg return true;
171806f32e7eSjoerg
171906f32e7eSjoerg // Visit the template arguments.
172006f32e7eSjoerg for (unsigned I = 0, N = TL.getNumArgs(); I != N; ++I)
172106f32e7eSjoerg if (VisitTemplateArgumentLoc(TL.getArgLoc(I)))
172206f32e7eSjoerg return true;
172306f32e7eSjoerg
172406f32e7eSjoerg return false;
172506f32e7eSjoerg }
172606f32e7eSjoerg
VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL)172706f32e7eSjoerg bool CursorVisitor::VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) {
172806f32e7eSjoerg return Visit(MakeCXCursor(TL.getUnderlyingExpr(), StmtParent, TU));
172906f32e7eSjoerg }
173006f32e7eSjoerg
VisitTypeOfTypeLoc(TypeOfTypeLoc TL)173106f32e7eSjoerg bool CursorVisitor::VisitTypeOfTypeLoc(TypeOfTypeLoc TL) {
173206f32e7eSjoerg if (TypeSourceInfo *TSInfo = TL.getUnderlyingTInfo())
173306f32e7eSjoerg return Visit(TSInfo->getTypeLoc());
173406f32e7eSjoerg
173506f32e7eSjoerg return false;
173606f32e7eSjoerg }
173706f32e7eSjoerg
VisitUnaryTransformTypeLoc(UnaryTransformTypeLoc TL)173806f32e7eSjoerg bool CursorVisitor::VisitUnaryTransformTypeLoc(UnaryTransformTypeLoc TL) {
173906f32e7eSjoerg if (TypeSourceInfo *TSInfo = TL.getUnderlyingTInfo())
174006f32e7eSjoerg return Visit(TSInfo->getTypeLoc());
174106f32e7eSjoerg
174206f32e7eSjoerg return false;
174306f32e7eSjoerg }
174406f32e7eSjoerg
VisitDependentNameTypeLoc(DependentNameTypeLoc TL)174506f32e7eSjoerg bool CursorVisitor::VisitDependentNameTypeLoc(DependentNameTypeLoc TL) {
174606f32e7eSjoerg return VisitNestedNameSpecifierLoc(TL.getQualifierLoc());
174706f32e7eSjoerg }
174806f32e7eSjoerg
VisitDependentTemplateSpecializationTypeLoc(DependentTemplateSpecializationTypeLoc TL)174906f32e7eSjoerg bool CursorVisitor::VisitDependentTemplateSpecializationTypeLoc(
175006f32e7eSjoerg DependentTemplateSpecializationTypeLoc TL) {
175106f32e7eSjoerg // Visit the nested-name-specifier, if there is one.
1752*13fbcb42Sjoerg if (TL.getQualifierLoc() && VisitNestedNameSpecifierLoc(TL.getQualifierLoc()))
175306f32e7eSjoerg return true;
175406f32e7eSjoerg
175506f32e7eSjoerg // Visit the template arguments.
175606f32e7eSjoerg for (unsigned I = 0, N = TL.getNumArgs(); I != N; ++I)
175706f32e7eSjoerg if (VisitTemplateArgumentLoc(TL.getArgLoc(I)))
175806f32e7eSjoerg return true;
175906f32e7eSjoerg
176006f32e7eSjoerg return false;
176106f32e7eSjoerg }
176206f32e7eSjoerg
VisitElaboratedTypeLoc(ElaboratedTypeLoc TL)176306f32e7eSjoerg bool CursorVisitor::VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) {
176406f32e7eSjoerg if (VisitNestedNameSpecifierLoc(TL.getQualifierLoc()))
176506f32e7eSjoerg return true;
176606f32e7eSjoerg
176706f32e7eSjoerg return Visit(TL.getNamedTypeLoc());
176806f32e7eSjoerg }
176906f32e7eSjoerg
VisitPackExpansionTypeLoc(PackExpansionTypeLoc TL)177006f32e7eSjoerg bool CursorVisitor::VisitPackExpansionTypeLoc(PackExpansionTypeLoc TL) {
177106f32e7eSjoerg return Visit(TL.getPatternLoc());
177206f32e7eSjoerg }
177306f32e7eSjoerg
VisitDecltypeTypeLoc(DecltypeTypeLoc TL)177406f32e7eSjoerg bool CursorVisitor::VisitDecltypeTypeLoc(DecltypeTypeLoc TL) {
177506f32e7eSjoerg if (Expr *E = TL.getUnderlyingExpr())
177606f32e7eSjoerg return Visit(MakeCXCursor(E, StmtParent, TU));
177706f32e7eSjoerg
177806f32e7eSjoerg return false;
177906f32e7eSjoerg }
178006f32e7eSjoerg
VisitInjectedClassNameTypeLoc(InjectedClassNameTypeLoc TL)178106f32e7eSjoerg bool CursorVisitor::VisitInjectedClassNameTypeLoc(InjectedClassNameTypeLoc TL) {
178206f32e7eSjoerg return Visit(MakeCursorTypeRef(TL.getDecl(), TL.getNameLoc(), TU));
178306f32e7eSjoerg }
178406f32e7eSjoerg
VisitAtomicTypeLoc(AtomicTypeLoc TL)178506f32e7eSjoerg bool CursorVisitor::VisitAtomicTypeLoc(AtomicTypeLoc TL) {
178606f32e7eSjoerg return Visit(TL.getValueLoc());
178706f32e7eSjoerg }
178806f32e7eSjoerg
VisitPipeTypeLoc(PipeTypeLoc TL)178906f32e7eSjoerg bool CursorVisitor::VisitPipeTypeLoc(PipeTypeLoc TL) {
179006f32e7eSjoerg return Visit(TL.getValueLoc());
179106f32e7eSjoerg }
179206f32e7eSjoerg
179306f32e7eSjoerg #define DEFAULT_TYPELOC_IMPL(CLASS, PARENT) \
179406f32e7eSjoerg bool CursorVisitor::Visit##CLASS##TypeLoc(CLASS##TypeLoc TL) { \
179506f32e7eSjoerg return Visit##PARENT##Loc(TL); \
179606f32e7eSjoerg }
179706f32e7eSjoerg
DEFAULT_TYPELOC_IMPL(Complex,Type)179806f32e7eSjoerg DEFAULT_TYPELOC_IMPL(Complex, Type)
179906f32e7eSjoerg DEFAULT_TYPELOC_IMPL(ConstantArray, ArrayType)
180006f32e7eSjoerg DEFAULT_TYPELOC_IMPL(IncompleteArray, ArrayType)
180106f32e7eSjoerg DEFAULT_TYPELOC_IMPL(VariableArray, ArrayType)
180206f32e7eSjoerg DEFAULT_TYPELOC_IMPL(DependentSizedArray, ArrayType)
180306f32e7eSjoerg DEFAULT_TYPELOC_IMPL(DependentAddressSpace, Type)
180406f32e7eSjoerg DEFAULT_TYPELOC_IMPL(DependentVector, Type)
180506f32e7eSjoerg DEFAULT_TYPELOC_IMPL(DependentSizedExtVector, Type)
180606f32e7eSjoerg DEFAULT_TYPELOC_IMPL(Vector, Type)
180706f32e7eSjoerg DEFAULT_TYPELOC_IMPL(ExtVector, VectorType)
1808*13fbcb42Sjoerg DEFAULT_TYPELOC_IMPL(ConstantMatrix, MatrixType)
1809*13fbcb42Sjoerg DEFAULT_TYPELOC_IMPL(DependentSizedMatrix, MatrixType)
181006f32e7eSjoerg DEFAULT_TYPELOC_IMPL(FunctionProto, FunctionType)
181106f32e7eSjoerg DEFAULT_TYPELOC_IMPL(FunctionNoProto, FunctionType)
181206f32e7eSjoerg DEFAULT_TYPELOC_IMPL(Record, TagType)
181306f32e7eSjoerg DEFAULT_TYPELOC_IMPL(Enum, TagType)
181406f32e7eSjoerg DEFAULT_TYPELOC_IMPL(SubstTemplateTypeParm, Type)
181506f32e7eSjoerg DEFAULT_TYPELOC_IMPL(SubstTemplateTypeParmPack, Type)
181606f32e7eSjoerg DEFAULT_TYPELOC_IMPL(Auto, Type)
1817*13fbcb42Sjoerg DEFAULT_TYPELOC_IMPL(ExtInt, Type)
1818*13fbcb42Sjoerg DEFAULT_TYPELOC_IMPL(DependentExtInt, Type)
181906f32e7eSjoerg
182006f32e7eSjoerg bool CursorVisitor::VisitCXXRecordDecl(CXXRecordDecl *D) {
182106f32e7eSjoerg // Visit the nested-name-specifier, if present.
182206f32e7eSjoerg if (NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc())
182306f32e7eSjoerg if (VisitNestedNameSpecifierLoc(QualifierLoc))
182406f32e7eSjoerg return true;
182506f32e7eSjoerg
182606f32e7eSjoerg if (D->isCompleteDefinition()) {
182706f32e7eSjoerg for (const auto &I : D->bases()) {
182806f32e7eSjoerg if (Visit(cxcursor::MakeCursorCXXBaseSpecifier(&I, TU)))
182906f32e7eSjoerg return true;
183006f32e7eSjoerg }
183106f32e7eSjoerg }
183206f32e7eSjoerg
183306f32e7eSjoerg return VisitTagDecl(D);
183406f32e7eSjoerg }
183506f32e7eSjoerg
VisitAttributes(Decl * D)183606f32e7eSjoerg bool CursorVisitor::VisitAttributes(Decl *D) {
183706f32e7eSjoerg for (const auto *I : D->attrs())
183806f32e7eSjoerg if ((TU->ParsingOptions & CXTranslationUnit_VisitImplicitAttributes ||
183906f32e7eSjoerg !I->isImplicit()) &&
184006f32e7eSjoerg Visit(MakeCXCursor(I, D, TU)))
184106f32e7eSjoerg return true;
184206f32e7eSjoerg
184306f32e7eSjoerg return false;
184406f32e7eSjoerg }
184506f32e7eSjoerg
184606f32e7eSjoerg //===----------------------------------------------------------------------===//
184706f32e7eSjoerg // Data-recursive visitor methods.
184806f32e7eSjoerg //===----------------------------------------------------------------------===//
184906f32e7eSjoerg
185006f32e7eSjoerg namespace {
185106f32e7eSjoerg #define DEF_JOB(NAME, DATA, KIND) \
185206f32e7eSjoerg class NAME : public VisitorJob { \
185306f32e7eSjoerg public: \
1854*13fbcb42Sjoerg NAME(const DATA *d, CXCursor parent) \
1855*13fbcb42Sjoerg : VisitorJob(parent, VisitorJob::KIND, d) {} \
1856*13fbcb42Sjoerg static bool classof(const VisitorJob *VJ) { \
1857*13fbcb42Sjoerg return VJ->getKind() == KIND; \
1858*13fbcb42Sjoerg } \
185906f32e7eSjoerg const DATA *get() const { return static_cast<const DATA *>(data[0]); } \
186006f32e7eSjoerg };
186106f32e7eSjoerg
186206f32e7eSjoerg DEF_JOB(StmtVisit, Stmt, StmtVisitKind)
186306f32e7eSjoerg DEF_JOB(MemberExprParts, MemberExpr, MemberExprPartsKind)
186406f32e7eSjoerg DEF_JOB(DeclRefExprParts, DeclRefExpr, DeclRefExprPartsKind)
186506f32e7eSjoerg DEF_JOB(OverloadExprParts, OverloadExpr, OverloadExprPartsKind)
186606f32e7eSjoerg DEF_JOB(SizeOfPackExprParts, SizeOfPackExpr, SizeOfPackExprPartsKind)
186706f32e7eSjoerg DEF_JOB(LambdaExprParts, LambdaExpr, LambdaExprPartsKind)
186806f32e7eSjoerg DEF_JOB(PostChildrenVisit, void, PostChildrenVisitKind)
186906f32e7eSjoerg #undef DEF_JOB
187006f32e7eSjoerg
187106f32e7eSjoerg class ExplicitTemplateArgsVisit : public VisitorJob {
187206f32e7eSjoerg public:
ExplicitTemplateArgsVisit(const TemplateArgumentLoc * Begin,const TemplateArgumentLoc * End,CXCursor parent)187306f32e7eSjoerg ExplicitTemplateArgsVisit(const TemplateArgumentLoc *Begin,
187406f32e7eSjoerg const TemplateArgumentLoc *End, CXCursor parent)
187506f32e7eSjoerg : VisitorJob(parent, VisitorJob::ExplicitTemplateArgsVisitKind, Begin,
187606f32e7eSjoerg End) {}
classof(const VisitorJob * VJ)187706f32e7eSjoerg static bool classof(const VisitorJob *VJ) {
187806f32e7eSjoerg return VJ->getKind() == ExplicitTemplateArgsVisitKind;
187906f32e7eSjoerg }
begin() const188006f32e7eSjoerg const TemplateArgumentLoc *begin() const {
188106f32e7eSjoerg return static_cast<const TemplateArgumentLoc *>(data[0]);
188206f32e7eSjoerg }
end()188306f32e7eSjoerg const TemplateArgumentLoc *end() {
188406f32e7eSjoerg return static_cast<const TemplateArgumentLoc *>(data[1]);
188506f32e7eSjoerg }
188606f32e7eSjoerg };
188706f32e7eSjoerg class DeclVisit : public VisitorJob {
188806f32e7eSjoerg public:
DeclVisit(const Decl * D,CXCursor parent,bool isFirst)1889*13fbcb42Sjoerg DeclVisit(const Decl *D, CXCursor parent, bool isFirst)
1890*13fbcb42Sjoerg : VisitorJob(parent, VisitorJob::DeclVisitKind, D,
1891*13fbcb42Sjoerg isFirst ? (void *)1 : (void *)nullptr) {}
classof(const VisitorJob * VJ)189206f32e7eSjoerg static bool classof(const VisitorJob *VJ) {
189306f32e7eSjoerg return VJ->getKind() == DeclVisitKind;
189406f32e7eSjoerg }
get() const189506f32e7eSjoerg const Decl *get() const { return static_cast<const Decl *>(data[0]); }
isFirst() const189606f32e7eSjoerg bool isFirst() const { return data[1] != nullptr; }
189706f32e7eSjoerg };
189806f32e7eSjoerg class TypeLocVisit : public VisitorJob {
189906f32e7eSjoerg public:
TypeLocVisit(TypeLoc tl,CXCursor parent)1900*13fbcb42Sjoerg TypeLocVisit(TypeLoc tl, CXCursor parent)
1901*13fbcb42Sjoerg : VisitorJob(parent, VisitorJob::TypeLocVisitKind,
190206f32e7eSjoerg tl.getType().getAsOpaquePtr(), tl.getOpaqueData()) {}
190306f32e7eSjoerg
classof(const VisitorJob * VJ)190406f32e7eSjoerg static bool classof(const VisitorJob *VJ) {
190506f32e7eSjoerg return VJ->getKind() == TypeLocVisitKind;
190606f32e7eSjoerg }
190706f32e7eSjoerg
get() const190806f32e7eSjoerg TypeLoc get() const {
190906f32e7eSjoerg QualType T = QualType::getFromOpaquePtr(data[0]);
191006f32e7eSjoerg return TypeLoc(T, const_cast<void *>(data[1]));
191106f32e7eSjoerg }
191206f32e7eSjoerg };
191306f32e7eSjoerg
191406f32e7eSjoerg class LabelRefVisit : public VisitorJob {
191506f32e7eSjoerg public:
LabelRefVisit(LabelDecl * LD,SourceLocation labelLoc,CXCursor parent)191606f32e7eSjoerg LabelRefVisit(LabelDecl *LD, SourceLocation labelLoc, CXCursor parent)
191706f32e7eSjoerg : VisitorJob(parent, VisitorJob::LabelRefVisitKind, LD,
191806f32e7eSjoerg labelLoc.getPtrEncoding()) {}
191906f32e7eSjoerg
classof(const VisitorJob * VJ)192006f32e7eSjoerg static bool classof(const VisitorJob *VJ) {
192106f32e7eSjoerg return VJ->getKind() == VisitorJob::LabelRefVisitKind;
192206f32e7eSjoerg }
get() const192306f32e7eSjoerg const LabelDecl *get() const {
192406f32e7eSjoerg return static_cast<const LabelDecl *>(data[0]);
192506f32e7eSjoerg }
getLoc() const192606f32e7eSjoerg SourceLocation getLoc() const {
1927*13fbcb42Sjoerg return SourceLocation::getFromPtrEncoding(data[1]);
1928*13fbcb42Sjoerg }
192906f32e7eSjoerg };
193006f32e7eSjoerg
193106f32e7eSjoerg class NestedNameSpecifierLocVisit : public VisitorJob {
193206f32e7eSjoerg public:
NestedNameSpecifierLocVisit(NestedNameSpecifierLoc Qualifier,CXCursor parent)193306f32e7eSjoerg NestedNameSpecifierLocVisit(NestedNameSpecifierLoc Qualifier, CXCursor parent)
193406f32e7eSjoerg : VisitorJob(parent, VisitorJob::NestedNameSpecifierLocVisitKind,
193506f32e7eSjoerg Qualifier.getNestedNameSpecifier(),
193606f32e7eSjoerg Qualifier.getOpaqueData()) {}
193706f32e7eSjoerg
classof(const VisitorJob * VJ)193806f32e7eSjoerg static bool classof(const VisitorJob *VJ) {
193906f32e7eSjoerg return VJ->getKind() == VisitorJob::NestedNameSpecifierLocVisitKind;
194006f32e7eSjoerg }
194106f32e7eSjoerg
get() const194206f32e7eSjoerg NestedNameSpecifierLoc get() const {
194306f32e7eSjoerg return NestedNameSpecifierLoc(
194406f32e7eSjoerg const_cast<NestedNameSpecifier *>(
194506f32e7eSjoerg static_cast<const NestedNameSpecifier *>(data[0])),
194606f32e7eSjoerg const_cast<void *>(data[1]));
194706f32e7eSjoerg }
194806f32e7eSjoerg };
194906f32e7eSjoerg
195006f32e7eSjoerg class DeclarationNameInfoVisit : public VisitorJob {
195106f32e7eSjoerg public:
DeclarationNameInfoVisit(const Stmt * S,CXCursor parent)195206f32e7eSjoerg DeclarationNameInfoVisit(const Stmt *S, CXCursor parent)
195306f32e7eSjoerg : VisitorJob(parent, VisitorJob::DeclarationNameInfoVisitKind, S) {}
classof(const VisitorJob * VJ)195406f32e7eSjoerg static bool classof(const VisitorJob *VJ) {
195506f32e7eSjoerg return VJ->getKind() == VisitorJob::DeclarationNameInfoVisitKind;
195606f32e7eSjoerg }
get() const195706f32e7eSjoerg DeclarationNameInfo get() const {
195806f32e7eSjoerg const Stmt *S = static_cast<const Stmt *>(data[0]);
195906f32e7eSjoerg switch (S->getStmtClass()) {
196006f32e7eSjoerg default:
196106f32e7eSjoerg llvm_unreachable("Unhandled Stmt");
196206f32e7eSjoerg case clang::Stmt::MSDependentExistsStmtClass:
196306f32e7eSjoerg return cast<MSDependentExistsStmt>(S)->getNameInfo();
196406f32e7eSjoerg case Stmt::CXXDependentScopeMemberExprClass:
196506f32e7eSjoerg return cast<CXXDependentScopeMemberExpr>(S)->getMemberNameInfo();
196606f32e7eSjoerg case Stmt::DependentScopeDeclRefExprClass:
196706f32e7eSjoerg return cast<DependentScopeDeclRefExpr>(S)->getNameInfo();
196806f32e7eSjoerg case Stmt::OMPCriticalDirectiveClass:
196906f32e7eSjoerg return cast<OMPCriticalDirective>(S)->getDirectiveName();
197006f32e7eSjoerg }
197106f32e7eSjoerg }
197206f32e7eSjoerg };
197306f32e7eSjoerg class MemberRefVisit : public VisitorJob {
197406f32e7eSjoerg public:
MemberRefVisit(const FieldDecl * D,SourceLocation L,CXCursor parent)197506f32e7eSjoerg MemberRefVisit(const FieldDecl *D, SourceLocation L, CXCursor parent)
197606f32e7eSjoerg : VisitorJob(parent, VisitorJob::MemberRefVisitKind, D,
197706f32e7eSjoerg L.getPtrEncoding()) {}
classof(const VisitorJob * VJ)197806f32e7eSjoerg static bool classof(const VisitorJob *VJ) {
197906f32e7eSjoerg return VJ->getKind() == VisitorJob::MemberRefVisitKind;
198006f32e7eSjoerg }
get() const198106f32e7eSjoerg const FieldDecl *get() const {
198206f32e7eSjoerg return static_cast<const FieldDecl *>(data[0]);
198306f32e7eSjoerg }
getLoc() const198406f32e7eSjoerg SourceLocation getLoc() const {
198506f32e7eSjoerg return SourceLocation::getFromRawEncoding((unsigned)(uintptr_t)data[1]);
198606f32e7eSjoerg }
198706f32e7eSjoerg };
198806f32e7eSjoerg class EnqueueVisitor : public ConstStmtVisitor<EnqueueVisitor, void> {
198906f32e7eSjoerg friend class OMPClauseEnqueue;
199006f32e7eSjoerg VisitorWorkList &WL;
199106f32e7eSjoerg CXCursor Parent;
1992*13fbcb42Sjoerg
199306f32e7eSjoerg public:
EnqueueVisitor(VisitorWorkList & wl,CXCursor parent)199406f32e7eSjoerg EnqueueVisitor(VisitorWorkList &wl, CXCursor parent)
199506f32e7eSjoerg : WL(wl), Parent(parent) {}
199606f32e7eSjoerg
199706f32e7eSjoerg void VisitAddrLabelExpr(const AddrLabelExpr *E);
199806f32e7eSjoerg void VisitBlockExpr(const BlockExpr *B);
199906f32e7eSjoerg void VisitCompoundLiteralExpr(const CompoundLiteralExpr *E);
200006f32e7eSjoerg void VisitCompoundStmt(const CompoundStmt *S);
VisitCXXDefaultArgExpr(const CXXDefaultArgExpr * E)2001*13fbcb42Sjoerg void VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *E) { /* Do nothing. */
2002*13fbcb42Sjoerg }
200306f32e7eSjoerg void VisitMSDependentExistsStmt(const MSDependentExistsStmt *S);
200406f32e7eSjoerg void VisitCXXDependentScopeMemberExpr(const CXXDependentScopeMemberExpr *E);
200506f32e7eSjoerg void VisitCXXNewExpr(const CXXNewExpr *E);
200606f32e7eSjoerg void VisitCXXScalarValueInitExpr(const CXXScalarValueInitExpr *E);
200706f32e7eSjoerg void VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *E);
200806f32e7eSjoerg void VisitCXXPseudoDestructorExpr(const CXXPseudoDestructorExpr *E);
200906f32e7eSjoerg void VisitCXXTemporaryObjectExpr(const CXXTemporaryObjectExpr *E);
201006f32e7eSjoerg void VisitCXXTypeidExpr(const CXXTypeidExpr *E);
201106f32e7eSjoerg void VisitCXXUnresolvedConstructExpr(const CXXUnresolvedConstructExpr *E);
201206f32e7eSjoerg void VisitCXXUuidofExpr(const CXXUuidofExpr *E);
201306f32e7eSjoerg void VisitCXXCatchStmt(const CXXCatchStmt *S);
201406f32e7eSjoerg void VisitCXXForRangeStmt(const CXXForRangeStmt *S);
201506f32e7eSjoerg void VisitDeclRefExpr(const DeclRefExpr *D);
201606f32e7eSjoerg void VisitDeclStmt(const DeclStmt *S);
201706f32e7eSjoerg void VisitDependentScopeDeclRefExpr(const DependentScopeDeclRefExpr *E);
201806f32e7eSjoerg void VisitDesignatedInitExpr(const DesignatedInitExpr *E);
201906f32e7eSjoerg void VisitExplicitCastExpr(const ExplicitCastExpr *E);
202006f32e7eSjoerg void VisitForStmt(const ForStmt *FS);
202106f32e7eSjoerg void VisitGotoStmt(const GotoStmt *GS);
202206f32e7eSjoerg void VisitIfStmt(const IfStmt *If);
202306f32e7eSjoerg void VisitInitListExpr(const InitListExpr *IE);
202406f32e7eSjoerg void VisitMemberExpr(const MemberExpr *M);
202506f32e7eSjoerg void VisitOffsetOfExpr(const OffsetOfExpr *E);
202606f32e7eSjoerg void VisitObjCEncodeExpr(const ObjCEncodeExpr *E);
202706f32e7eSjoerg void VisitObjCMessageExpr(const ObjCMessageExpr *M);
202806f32e7eSjoerg void VisitOverloadExpr(const OverloadExpr *E);
202906f32e7eSjoerg void VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *E);
203006f32e7eSjoerg void VisitStmt(const Stmt *S);
203106f32e7eSjoerg void VisitSwitchStmt(const SwitchStmt *S);
203206f32e7eSjoerg void VisitWhileStmt(const WhileStmt *W);
203306f32e7eSjoerg void VisitTypeTraitExpr(const TypeTraitExpr *E);
203406f32e7eSjoerg void VisitArrayTypeTraitExpr(const ArrayTypeTraitExpr *E);
203506f32e7eSjoerg void VisitExpressionTraitExpr(const ExpressionTraitExpr *E);
203606f32e7eSjoerg void VisitUnresolvedMemberExpr(const UnresolvedMemberExpr *U);
203706f32e7eSjoerg void VisitVAArgExpr(const VAArgExpr *E);
203806f32e7eSjoerg void VisitSizeOfPackExpr(const SizeOfPackExpr *E);
203906f32e7eSjoerg void VisitPseudoObjectExpr(const PseudoObjectExpr *E);
204006f32e7eSjoerg void VisitOpaqueValueExpr(const OpaqueValueExpr *E);
204106f32e7eSjoerg void VisitLambdaExpr(const LambdaExpr *E);
204206f32e7eSjoerg void VisitOMPExecutableDirective(const OMPExecutableDirective *D);
2043*13fbcb42Sjoerg void VisitOMPLoopBasedDirective(const OMPLoopBasedDirective *D);
204406f32e7eSjoerg void VisitOMPLoopDirective(const OMPLoopDirective *D);
204506f32e7eSjoerg void VisitOMPParallelDirective(const OMPParallelDirective *D);
204606f32e7eSjoerg void VisitOMPSimdDirective(const OMPSimdDirective *D);
2047*13fbcb42Sjoerg void VisitOMPTileDirective(const OMPTileDirective *D);
204806f32e7eSjoerg void VisitOMPForDirective(const OMPForDirective *D);
204906f32e7eSjoerg void VisitOMPForSimdDirective(const OMPForSimdDirective *D);
205006f32e7eSjoerg void VisitOMPSectionsDirective(const OMPSectionsDirective *D);
205106f32e7eSjoerg void VisitOMPSectionDirective(const OMPSectionDirective *D);
205206f32e7eSjoerg void VisitOMPSingleDirective(const OMPSingleDirective *D);
205306f32e7eSjoerg void VisitOMPMasterDirective(const OMPMasterDirective *D);
205406f32e7eSjoerg void VisitOMPCriticalDirective(const OMPCriticalDirective *D);
205506f32e7eSjoerg void VisitOMPParallelForDirective(const OMPParallelForDirective *D);
205606f32e7eSjoerg void VisitOMPParallelForSimdDirective(const OMPParallelForSimdDirective *D);
2057*13fbcb42Sjoerg void VisitOMPParallelMasterDirective(const OMPParallelMasterDirective *D);
205806f32e7eSjoerg void VisitOMPParallelSectionsDirective(const OMPParallelSectionsDirective *D);
205906f32e7eSjoerg void VisitOMPTaskDirective(const OMPTaskDirective *D);
206006f32e7eSjoerg void VisitOMPTaskyieldDirective(const OMPTaskyieldDirective *D);
206106f32e7eSjoerg void VisitOMPBarrierDirective(const OMPBarrierDirective *D);
206206f32e7eSjoerg void VisitOMPTaskwaitDirective(const OMPTaskwaitDirective *D);
206306f32e7eSjoerg void VisitOMPTaskgroupDirective(const OMPTaskgroupDirective *D);
206406f32e7eSjoerg void
206506f32e7eSjoerg VisitOMPCancellationPointDirective(const OMPCancellationPointDirective *D);
206606f32e7eSjoerg void VisitOMPCancelDirective(const OMPCancelDirective *D);
206706f32e7eSjoerg void VisitOMPFlushDirective(const OMPFlushDirective *D);
2068*13fbcb42Sjoerg void VisitOMPDepobjDirective(const OMPDepobjDirective *D);
2069*13fbcb42Sjoerg void VisitOMPScanDirective(const OMPScanDirective *D);
207006f32e7eSjoerg void VisitOMPOrderedDirective(const OMPOrderedDirective *D);
207106f32e7eSjoerg void VisitOMPAtomicDirective(const OMPAtomicDirective *D);
207206f32e7eSjoerg void VisitOMPTargetDirective(const OMPTargetDirective *D);
207306f32e7eSjoerg void VisitOMPTargetDataDirective(const OMPTargetDataDirective *D);
207406f32e7eSjoerg void VisitOMPTargetEnterDataDirective(const OMPTargetEnterDataDirective *D);
207506f32e7eSjoerg void VisitOMPTargetExitDataDirective(const OMPTargetExitDataDirective *D);
207606f32e7eSjoerg void VisitOMPTargetParallelDirective(const OMPTargetParallelDirective *D);
207706f32e7eSjoerg void
207806f32e7eSjoerg VisitOMPTargetParallelForDirective(const OMPTargetParallelForDirective *D);
207906f32e7eSjoerg void VisitOMPTeamsDirective(const OMPTeamsDirective *D);
208006f32e7eSjoerg void VisitOMPTaskLoopDirective(const OMPTaskLoopDirective *D);
208106f32e7eSjoerg void VisitOMPTaskLoopSimdDirective(const OMPTaskLoopSimdDirective *D);
208206f32e7eSjoerg void VisitOMPMasterTaskLoopDirective(const OMPMasterTaskLoopDirective *D);
208306f32e7eSjoerg void
208406f32e7eSjoerg VisitOMPMasterTaskLoopSimdDirective(const OMPMasterTaskLoopSimdDirective *D);
208506f32e7eSjoerg void VisitOMPParallelMasterTaskLoopDirective(
208606f32e7eSjoerg const OMPParallelMasterTaskLoopDirective *D);
2087*13fbcb42Sjoerg void VisitOMPParallelMasterTaskLoopSimdDirective(
2088*13fbcb42Sjoerg const OMPParallelMasterTaskLoopSimdDirective *D);
208906f32e7eSjoerg void VisitOMPDistributeDirective(const OMPDistributeDirective *D);
209006f32e7eSjoerg void VisitOMPDistributeParallelForDirective(
209106f32e7eSjoerg const OMPDistributeParallelForDirective *D);
209206f32e7eSjoerg void VisitOMPDistributeParallelForSimdDirective(
209306f32e7eSjoerg const OMPDistributeParallelForSimdDirective *D);
209406f32e7eSjoerg void VisitOMPDistributeSimdDirective(const OMPDistributeSimdDirective *D);
209506f32e7eSjoerg void VisitOMPTargetParallelForSimdDirective(
209606f32e7eSjoerg const OMPTargetParallelForSimdDirective *D);
209706f32e7eSjoerg void VisitOMPTargetSimdDirective(const OMPTargetSimdDirective *D);
209806f32e7eSjoerg void VisitOMPTeamsDistributeDirective(const OMPTeamsDistributeDirective *D);
209906f32e7eSjoerg void VisitOMPTeamsDistributeSimdDirective(
210006f32e7eSjoerg const OMPTeamsDistributeSimdDirective *D);
210106f32e7eSjoerg void VisitOMPTeamsDistributeParallelForSimdDirective(
210206f32e7eSjoerg const OMPTeamsDistributeParallelForSimdDirective *D);
210306f32e7eSjoerg void VisitOMPTeamsDistributeParallelForDirective(
210406f32e7eSjoerg const OMPTeamsDistributeParallelForDirective *D);
210506f32e7eSjoerg void VisitOMPTargetTeamsDirective(const OMPTargetTeamsDirective *D);
210606f32e7eSjoerg void VisitOMPTargetTeamsDistributeDirective(
210706f32e7eSjoerg const OMPTargetTeamsDistributeDirective *D);
210806f32e7eSjoerg void VisitOMPTargetTeamsDistributeParallelForDirective(
210906f32e7eSjoerg const OMPTargetTeamsDistributeParallelForDirective *D);
211006f32e7eSjoerg void VisitOMPTargetTeamsDistributeParallelForSimdDirective(
211106f32e7eSjoerg const OMPTargetTeamsDistributeParallelForSimdDirective *D);
211206f32e7eSjoerg void VisitOMPTargetTeamsDistributeSimdDirective(
211306f32e7eSjoerg const OMPTargetTeamsDistributeSimdDirective *D);
211406f32e7eSjoerg
211506f32e7eSjoerg private:
211606f32e7eSjoerg void AddDeclarationNameInfo(const Stmt *S);
211706f32e7eSjoerg void AddNestedNameSpecifierLoc(NestedNameSpecifierLoc Qualifier);
211806f32e7eSjoerg void AddExplicitTemplateArgs(const TemplateArgumentLoc *A,
211906f32e7eSjoerg unsigned NumTemplateArgs);
212006f32e7eSjoerg void AddMemberRef(const FieldDecl *D, SourceLocation L);
212106f32e7eSjoerg void AddStmt(const Stmt *S);
212206f32e7eSjoerg void AddDecl(const Decl *D, bool isFirst = true);
212306f32e7eSjoerg void AddTypeLoc(TypeSourceInfo *TI);
212406f32e7eSjoerg void EnqueueChildren(const Stmt *S);
212506f32e7eSjoerg void EnqueueChildren(const OMPClause *S);
212606f32e7eSjoerg };
2127*13fbcb42Sjoerg } // namespace
212806f32e7eSjoerg
AddDeclarationNameInfo(const Stmt * S)212906f32e7eSjoerg void EnqueueVisitor::AddDeclarationNameInfo(const Stmt *S) {
213006f32e7eSjoerg // 'S' should always be non-null, since it comes from the
213106f32e7eSjoerg // statement we are visiting.
213206f32e7eSjoerg WL.push_back(DeclarationNameInfoVisit(S, Parent));
213306f32e7eSjoerg }
213406f32e7eSjoerg
AddNestedNameSpecifierLoc(NestedNameSpecifierLoc Qualifier)2135*13fbcb42Sjoerg void EnqueueVisitor::AddNestedNameSpecifierLoc(
2136*13fbcb42Sjoerg NestedNameSpecifierLoc Qualifier) {
213706f32e7eSjoerg if (Qualifier)
213806f32e7eSjoerg WL.push_back(NestedNameSpecifierLocVisit(Qualifier, Parent));
213906f32e7eSjoerg }
214006f32e7eSjoerg
AddStmt(const Stmt * S)214106f32e7eSjoerg void EnqueueVisitor::AddStmt(const Stmt *S) {
214206f32e7eSjoerg if (S)
214306f32e7eSjoerg WL.push_back(StmtVisit(S, Parent));
214406f32e7eSjoerg }
AddDecl(const Decl * D,bool isFirst)214506f32e7eSjoerg void EnqueueVisitor::AddDecl(const Decl *D, bool isFirst) {
214606f32e7eSjoerg if (D)
214706f32e7eSjoerg WL.push_back(DeclVisit(D, Parent, isFirst));
214806f32e7eSjoerg }
AddExplicitTemplateArgs(const TemplateArgumentLoc * A,unsigned NumTemplateArgs)214906f32e7eSjoerg void EnqueueVisitor::AddExplicitTemplateArgs(const TemplateArgumentLoc *A,
215006f32e7eSjoerg unsigned NumTemplateArgs) {
215106f32e7eSjoerg WL.push_back(ExplicitTemplateArgsVisit(A, A + NumTemplateArgs, Parent));
215206f32e7eSjoerg }
AddMemberRef(const FieldDecl * D,SourceLocation L)215306f32e7eSjoerg void EnqueueVisitor::AddMemberRef(const FieldDecl *D, SourceLocation L) {
215406f32e7eSjoerg if (D)
215506f32e7eSjoerg WL.push_back(MemberRefVisit(D, L, Parent));
215606f32e7eSjoerg }
AddTypeLoc(TypeSourceInfo * TI)215706f32e7eSjoerg void EnqueueVisitor::AddTypeLoc(TypeSourceInfo *TI) {
215806f32e7eSjoerg if (TI)
215906f32e7eSjoerg WL.push_back(TypeLocVisit(TI->getTypeLoc(), Parent));
216006f32e7eSjoerg }
EnqueueChildren(const Stmt * S)216106f32e7eSjoerg void EnqueueVisitor::EnqueueChildren(const Stmt *S) {
216206f32e7eSjoerg unsigned size = WL.size();
216306f32e7eSjoerg for (const Stmt *SubStmt : S->children()) {
216406f32e7eSjoerg AddStmt(SubStmt);
216506f32e7eSjoerg }
216606f32e7eSjoerg if (size == WL.size())
216706f32e7eSjoerg return;
216806f32e7eSjoerg // Now reverse the entries we just added. This will match the DFS
216906f32e7eSjoerg // ordering performed by the worklist.
217006f32e7eSjoerg VisitorWorkList::iterator I = WL.begin() + size, E = WL.end();
217106f32e7eSjoerg std::reverse(I, E);
217206f32e7eSjoerg }
217306f32e7eSjoerg namespace {
217406f32e7eSjoerg class OMPClauseEnqueue : public ConstOMPClauseVisitor<OMPClauseEnqueue> {
217506f32e7eSjoerg EnqueueVisitor *Visitor;
217606f32e7eSjoerg /// Process clauses with list of variables.
2177*13fbcb42Sjoerg template <typename T> void VisitOMPClauseList(T *Node);
2178*13fbcb42Sjoerg
217906f32e7eSjoerg public:
OMPClauseEnqueue(EnqueueVisitor * Visitor)218006f32e7eSjoerg OMPClauseEnqueue(EnqueueVisitor *Visitor) : Visitor(Visitor) {}
2181*13fbcb42Sjoerg #define GEN_CLANG_CLAUSE_CLASS
2182*13fbcb42Sjoerg #define CLAUSE_CLASS(Enum, Str, Class) void Visit##Class(const Class *C);
2183*13fbcb42Sjoerg #include "llvm/Frontend/OpenMP/OMP.inc"
218406f32e7eSjoerg void VisitOMPClauseWithPreInit(const OMPClauseWithPreInit *C);
218506f32e7eSjoerg void VisitOMPClauseWithPostUpdate(const OMPClauseWithPostUpdate *C);
218606f32e7eSjoerg };
218706f32e7eSjoerg
VisitOMPClauseWithPreInit(const OMPClauseWithPreInit * C)218806f32e7eSjoerg void OMPClauseEnqueue::VisitOMPClauseWithPreInit(
218906f32e7eSjoerg const OMPClauseWithPreInit *C) {
219006f32e7eSjoerg Visitor->AddStmt(C->getPreInitStmt());
219106f32e7eSjoerg }
219206f32e7eSjoerg
VisitOMPClauseWithPostUpdate(const OMPClauseWithPostUpdate * C)219306f32e7eSjoerg void OMPClauseEnqueue::VisitOMPClauseWithPostUpdate(
219406f32e7eSjoerg const OMPClauseWithPostUpdate *C) {
219506f32e7eSjoerg VisitOMPClauseWithPreInit(C);
219606f32e7eSjoerg Visitor->AddStmt(C->getPostUpdateExpr());
219706f32e7eSjoerg }
219806f32e7eSjoerg
VisitOMPIfClause(const OMPIfClause * C)219906f32e7eSjoerg void OMPClauseEnqueue::VisitOMPIfClause(const OMPIfClause *C) {
220006f32e7eSjoerg VisitOMPClauseWithPreInit(C);
220106f32e7eSjoerg Visitor->AddStmt(C->getCondition());
220206f32e7eSjoerg }
220306f32e7eSjoerg
VisitOMPFinalClause(const OMPFinalClause * C)220406f32e7eSjoerg void OMPClauseEnqueue::VisitOMPFinalClause(const OMPFinalClause *C) {
220506f32e7eSjoerg Visitor->AddStmt(C->getCondition());
220606f32e7eSjoerg }
220706f32e7eSjoerg
VisitOMPNumThreadsClause(const OMPNumThreadsClause * C)220806f32e7eSjoerg void OMPClauseEnqueue::VisitOMPNumThreadsClause(const OMPNumThreadsClause *C) {
220906f32e7eSjoerg VisitOMPClauseWithPreInit(C);
221006f32e7eSjoerg Visitor->AddStmt(C->getNumThreads());
221106f32e7eSjoerg }
221206f32e7eSjoerg
VisitOMPSafelenClause(const OMPSafelenClause * C)221306f32e7eSjoerg void OMPClauseEnqueue::VisitOMPSafelenClause(const OMPSafelenClause *C) {
221406f32e7eSjoerg Visitor->AddStmt(C->getSafelen());
221506f32e7eSjoerg }
221606f32e7eSjoerg
VisitOMPSimdlenClause(const OMPSimdlenClause * C)221706f32e7eSjoerg void OMPClauseEnqueue::VisitOMPSimdlenClause(const OMPSimdlenClause *C) {
221806f32e7eSjoerg Visitor->AddStmt(C->getSimdlen());
221906f32e7eSjoerg }
222006f32e7eSjoerg
VisitOMPSizesClause(const OMPSizesClause * C)2221*13fbcb42Sjoerg void OMPClauseEnqueue::VisitOMPSizesClause(const OMPSizesClause *C) {
2222*13fbcb42Sjoerg for (auto E : C->getSizesRefs())
2223*13fbcb42Sjoerg Visitor->AddStmt(E);
2224*13fbcb42Sjoerg }
2225*13fbcb42Sjoerg
VisitOMPAllocatorClause(const OMPAllocatorClause * C)222606f32e7eSjoerg void OMPClauseEnqueue::VisitOMPAllocatorClause(const OMPAllocatorClause *C) {
222706f32e7eSjoerg Visitor->AddStmt(C->getAllocator());
222806f32e7eSjoerg }
222906f32e7eSjoerg
VisitOMPCollapseClause(const OMPCollapseClause * C)223006f32e7eSjoerg void OMPClauseEnqueue::VisitOMPCollapseClause(const OMPCollapseClause *C) {
223106f32e7eSjoerg Visitor->AddStmt(C->getNumForLoops());
223206f32e7eSjoerg }
223306f32e7eSjoerg
VisitOMPDefaultClause(const OMPDefaultClause * C)223406f32e7eSjoerg void OMPClauseEnqueue::VisitOMPDefaultClause(const OMPDefaultClause *C) {}
223506f32e7eSjoerg
VisitOMPProcBindClause(const OMPProcBindClause * C)223606f32e7eSjoerg void OMPClauseEnqueue::VisitOMPProcBindClause(const OMPProcBindClause *C) {}
223706f32e7eSjoerg
VisitOMPScheduleClause(const OMPScheduleClause * C)223806f32e7eSjoerg void OMPClauseEnqueue::VisitOMPScheduleClause(const OMPScheduleClause *C) {
223906f32e7eSjoerg VisitOMPClauseWithPreInit(C);
224006f32e7eSjoerg Visitor->AddStmt(C->getChunkSize());
224106f32e7eSjoerg }
224206f32e7eSjoerg
VisitOMPOrderedClause(const OMPOrderedClause * C)224306f32e7eSjoerg void OMPClauseEnqueue::VisitOMPOrderedClause(const OMPOrderedClause *C) {
224406f32e7eSjoerg Visitor->AddStmt(C->getNumForLoops());
224506f32e7eSjoerg }
224606f32e7eSjoerg
VisitOMPDetachClause(const OMPDetachClause * C)2247*13fbcb42Sjoerg void OMPClauseEnqueue::VisitOMPDetachClause(const OMPDetachClause *C) {
2248*13fbcb42Sjoerg Visitor->AddStmt(C->getEventHandler());
2249*13fbcb42Sjoerg }
2250*13fbcb42Sjoerg
VisitOMPNowaitClause(const OMPNowaitClause *)225106f32e7eSjoerg void OMPClauseEnqueue::VisitOMPNowaitClause(const OMPNowaitClause *) {}
225206f32e7eSjoerg
VisitOMPUntiedClause(const OMPUntiedClause *)225306f32e7eSjoerg void OMPClauseEnqueue::VisitOMPUntiedClause(const OMPUntiedClause *) {}
225406f32e7eSjoerg
VisitOMPMergeableClause(const OMPMergeableClause *)225506f32e7eSjoerg void OMPClauseEnqueue::VisitOMPMergeableClause(const OMPMergeableClause *) {}
225606f32e7eSjoerg
VisitOMPReadClause(const OMPReadClause *)225706f32e7eSjoerg void OMPClauseEnqueue::VisitOMPReadClause(const OMPReadClause *) {}
225806f32e7eSjoerg
VisitOMPWriteClause(const OMPWriteClause *)225906f32e7eSjoerg void OMPClauseEnqueue::VisitOMPWriteClause(const OMPWriteClause *) {}
226006f32e7eSjoerg
VisitOMPUpdateClause(const OMPUpdateClause *)226106f32e7eSjoerg void OMPClauseEnqueue::VisitOMPUpdateClause(const OMPUpdateClause *) {}
226206f32e7eSjoerg
VisitOMPCaptureClause(const OMPCaptureClause *)226306f32e7eSjoerg void OMPClauseEnqueue::VisitOMPCaptureClause(const OMPCaptureClause *) {}
226406f32e7eSjoerg
VisitOMPSeqCstClause(const OMPSeqCstClause *)226506f32e7eSjoerg void OMPClauseEnqueue::VisitOMPSeqCstClause(const OMPSeqCstClause *) {}
226606f32e7eSjoerg
VisitOMPAcqRelClause(const OMPAcqRelClause *)2267*13fbcb42Sjoerg void OMPClauseEnqueue::VisitOMPAcqRelClause(const OMPAcqRelClause *) {}
2268*13fbcb42Sjoerg
VisitOMPAcquireClause(const OMPAcquireClause *)2269*13fbcb42Sjoerg void OMPClauseEnqueue::VisitOMPAcquireClause(const OMPAcquireClause *) {}
2270*13fbcb42Sjoerg
VisitOMPReleaseClause(const OMPReleaseClause *)2271*13fbcb42Sjoerg void OMPClauseEnqueue::VisitOMPReleaseClause(const OMPReleaseClause *) {}
2272*13fbcb42Sjoerg
VisitOMPRelaxedClause(const OMPRelaxedClause *)2273*13fbcb42Sjoerg void OMPClauseEnqueue::VisitOMPRelaxedClause(const OMPRelaxedClause *) {}
2274*13fbcb42Sjoerg
VisitOMPThreadsClause(const OMPThreadsClause *)227506f32e7eSjoerg void OMPClauseEnqueue::VisitOMPThreadsClause(const OMPThreadsClause *) {}
227606f32e7eSjoerg
VisitOMPSIMDClause(const OMPSIMDClause *)227706f32e7eSjoerg void OMPClauseEnqueue::VisitOMPSIMDClause(const OMPSIMDClause *) {}
227806f32e7eSjoerg
VisitOMPNogroupClause(const OMPNogroupClause *)227906f32e7eSjoerg void OMPClauseEnqueue::VisitOMPNogroupClause(const OMPNogroupClause *) {}
228006f32e7eSjoerg
VisitOMPInitClause(const OMPInitClause * C)2281*13fbcb42Sjoerg void OMPClauseEnqueue::VisitOMPInitClause(const OMPInitClause *C) {
2282*13fbcb42Sjoerg VisitOMPClauseList(C);
2283*13fbcb42Sjoerg }
2284*13fbcb42Sjoerg
VisitOMPUseClause(const OMPUseClause * C)2285*13fbcb42Sjoerg void OMPClauseEnqueue::VisitOMPUseClause(const OMPUseClause *C) {
2286*13fbcb42Sjoerg Visitor->AddStmt(C->getInteropVar());
2287*13fbcb42Sjoerg }
2288*13fbcb42Sjoerg
VisitOMPDestroyClause(const OMPDestroyClause * C)2289*13fbcb42Sjoerg void OMPClauseEnqueue::VisitOMPDestroyClause(const OMPDestroyClause *C) {
2290*13fbcb42Sjoerg if (C->getInteropVar())
2291*13fbcb42Sjoerg Visitor->AddStmt(C->getInteropVar());
2292*13fbcb42Sjoerg }
2293*13fbcb42Sjoerg
VisitOMPNovariantsClause(const OMPNovariantsClause * C)2294*13fbcb42Sjoerg void OMPClauseEnqueue::VisitOMPNovariantsClause(const OMPNovariantsClause *C) {
2295*13fbcb42Sjoerg Visitor->AddStmt(C->getCondition());
2296*13fbcb42Sjoerg }
2297*13fbcb42Sjoerg
VisitOMPNocontextClause(const OMPNocontextClause * C)2298*13fbcb42Sjoerg void OMPClauseEnqueue::VisitOMPNocontextClause(const OMPNocontextClause *C) {
2299*13fbcb42Sjoerg Visitor->AddStmt(C->getCondition());
2300*13fbcb42Sjoerg }
2301*13fbcb42Sjoerg
VisitOMPFilterClause(const OMPFilterClause * C)2302*13fbcb42Sjoerg void OMPClauseEnqueue::VisitOMPFilterClause(const OMPFilterClause *C) {
2303*13fbcb42Sjoerg VisitOMPClauseWithPreInit(C);
2304*13fbcb42Sjoerg Visitor->AddStmt(C->getThreadID());
2305*13fbcb42Sjoerg }
2306*13fbcb42Sjoerg
VisitOMPUnifiedAddressClause(const OMPUnifiedAddressClause *)230706f32e7eSjoerg void OMPClauseEnqueue::VisitOMPUnifiedAddressClause(
230806f32e7eSjoerg const OMPUnifiedAddressClause *) {}
230906f32e7eSjoerg
VisitOMPUnifiedSharedMemoryClause(const OMPUnifiedSharedMemoryClause *)231006f32e7eSjoerg void OMPClauseEnqueue::VisitOMPUnifiedSharedMemoryClause(
231106f32e7eSjoerg const OMPUnifiedSharedMemoryClause *) {}
231206f32e7eSjoerg
VisitOMPReverseOffloadClause(const OMPReverseOffloadClause *)231306f32e7eSjoerg void OMPClauseEnqueue::VisitOMPReverseOffloadClause(
231406f32e7eSjoerg const OMPReverseOffloadClause *) {}
231506f32e7eSjoerg
VisitOMPDynamicAllocatorsClause(const OMPDynamicAllocatorsClause *)231606f32e7eSjoerg void OMPClauseEnqueue::VisitOMPDynamicAllocatorsClause(
231706f32e7eSjoerg const OMPDynamicAllocatorsClause *) {}
231806f32e7eSjoerg
VisitOMPAtomicDefaultMemOrderClause(const OMPAtomicDefaultMemOrderClause *)231906f32e7eSjoerg void OMPClauseEnqueue::VisitOMPAtomicDefaultMemOrderClause(
232006f32e7eSjoerg const OMPAtomicDefaultMemOrderClause *) {}
232106f32e7eSjoerg
VisitOMPDeviceClause(const OMPDeviceClause * C)232206f32e7eSjoerg void OMPClauseEnqueue::VisitOMPDeviceClause(const OMPDeviceClause *C) {
232306f32e7eSjoerg Visitor->AddStmt(C->getDevice());
232406f32e7eSjoerg }
232506f32e7eSjoerg
VisitOMPNumTeamsClause(const OMPNumTeamsClause * C)232606f32e7eSjoerg void OMPClauseEnqueue::VisitOMPNumTeamsClause(const OMPNumTeamsClause *C) {
232706f32e7eSjoerg VisitOMPClauseWithPreInit(C);
232806f32e7eSjoerg Visitor->AddStmt(C->getNumTeams());
232906f32e7eSjoerg }
233006f32e7eSjoerg
VisitOMPThreadLimitClause(const OMPThreadLimitClause * C)2331*13fbcb42Sjoerg void OMPClauseEnqueue::VisitOMPThreadLimitClause(
2332*13fbcb42Sjoerg const OMPThreadLimitClause *C) {
233306f32e7eSjoerg VisitOMPClauseWithPreInit(C);
233406f32e7eSjoerg Visitor->AddStmt(C->getThreadLimit());
233506f32e7eSjoerg }
233606f32e7eSjoerg
VisitOMPPriorityClause(const OMPPriorityClause * C)233706f32e7eSjoerg void OMPClauseEnqueue::VisitOMPPriorityClause(const OMPPriorityClause *C) {
233806f32e7eSjoerg Visitor->AddStmt(C->getPriority());
233906f32e7eSjoerg }
234006f32e7eSjoerg
VisitOMPGrainsizeClause(const OMPGrainsizeClause * C)234106f32e7eSjoerg void OMPClauseEnqueue::VisitOMPGrainsizeClause(const OMPGrainsizeClause *C) {
234206f32e7eSjoerg Visitor->AddStmt(C->getGrainsize());
234306f32e7eSjoerg }
234406f32e7eSjoerg
VisitOMPNumTasksClause(const OMPNumTasksClause * C)234506f32e7eSjoerg void OMPClauseEnqueue::VisitOMPNumTasksClause(const OMPNumTasksClause *C) {
234606f32e7eSjoerg Visitor->AddStmt(C->getNumTasks());
234706f32e7eSjoerg }
234806f32e7eSjoerg
VisitOMPHintClause(const OMPHintClause * C)234906f32e7eSjoerg void OMPClauseEnqueue::VisitOMPHintClause(const OMPHintClause *C) {
235006f32e7eSjoerg Visitor->AddStmt(C->getHint());
235106f32e7eSjoerg }
235206f32e7eSjoerg
VisitOMPClauseList(T * Node)2353*13fbcb42Sjoerg template <typename T> void OMPClauseEnqueue::VisitOMPClauseList(T *Node) {
235406f32e7eSjoerg for (const auto *I : Node->varlists()) {
235506f32e7eSjoerg Visitor->AddStmt(I);
235606f32e7eSjoerg }
235706f32e7eSjoerg }
235806f32e7eSjoerg
VisitOMPInclusiveClause(const OMPInclusiveClause * C)2359*13fbcb42Sjoerg void OMPClauseEnqueue::VisitOMPInclusiveClause(const OMPInclusiveClause *C) {
2360*13fbcb42Sjoerg VisitOMPClauseList(C);
2361*13fbcb42Sjoerg }
VisitOMPExclusiveClause(const OMPExclusiveClause * C)2362*13fbcb42Sjoerg void OMPClauseEnqueue::VisitOMPExclusiveClause(const OMPExclusiveClause *C) {
2363*13fbcb42Sjoerg VisitOMPClauseList(C);
2364*13fbcb42Sjoerg }
VisitOMPAllocateClause(const OMPAllocateClause * C)236506f32e7eSjoerg void OMPClauseEnqueue::VisitOMPAllocateClause(const OMPAllocateClause *C) {
236606f32e7eSjoerg VisitOMPClauseList(C);
236706f32e7eSjoerg Visitor->AddStmt(C->getAllocator());
236806f32e7eSjoerg }
VisitOMPPrivateClause(const OMPPrivateClause * C)236906f32e7eSjoerg void OMPClauseEnqueue::VisitOMPPrivateClause(const OMPPrivateClause *C) {
237006f32e7eSjoerg VisitOMPClauseList(C);
237106f32e7eSjoerg for (const auto *E : C->private_copies()) {
237206f32e7eSjoerg Visitor->AddStmt(E);
237306f32e7eSjoerg }
237406f32e7eSjoerg }
VisitOMPFirstprivateClause(const OMPFirstprivateClause * C)237506f32e7eSjoerg void OMPClauseEnqueue::VisitOMPFirstprivateClause(
237606f32e7eSjoerg const OMPFirstprivateClause *C) {
237706f32e7eSjoerg VisitOMPClauseList(C);
237806f32e7eSjoerg VisitOMPClauseWithPreInit(C);
237906f32e7eSjoerg for (const auto *E : C->private_copies()) {
238006f32e7eSjoerg Visitor->AddStmt(E);
238106f32e7eSjoerg }
238206f32e7eSjoerg for (const auto *E : C->inits()) {
238306f32e7eSjoerg Visitor->AddStmt(E);
238406f32e7eSjoerg }
238506f32e7eSjoerg }
VisitOMPLastprivateClause(const OMPLastprivateClause * C)238606f32e7eSjoerg void OMPClauseEnqueue::VisitOMPLastprivateClause(
238706f32e7eSjoerg const OMPLastprivateClause *C) {
238806f32e7eSjoerg VisitOMPClauseList(C);
238906f32e7eSjoerg VisitOMPClauseWithPostUpdate(C);
239006f32e7eSjoerg for (auto *E : C->private_copies()) {
239106f32e7eSjoerg Visitor->AddStmt(E);
239206f32e7eSjoerg }
239306f32e7eSjoerg for (auto *E : C->source_exprs()) {
239406f32e7eSjoerg Visitor->AddStmt(E);
239506f32e7eSjoerg }
239606f32e7eSjoerg for (auto *E : C->destination_exprs()) {
239706f32e7eSjoerg Visitor->AddStmt(E);
239806f32e7eSjoerg }
239906f32e7eSjoerg for (auto *E : C->assignment_ops()) {
240006f32e7eSjoerg Visitor->AddStmt(E);
240106f32e7eSjoerg }
240206f32e7eSjoerg }
VisitOMPSharedClause(const OMPSharedClause * C)240306f32e7eSjoerg void OMPClauseEnqueue::VisitOMPSharedClause(const OMPSharedClause *C) {
240406f32e7eSjoerg VisitOMPClauseList(C);
240506f32e7eSjoerg }
VisitOMPReductionClause(const OMPReductionClause * C)240606f32e7eSjoerg void OMPClauseEnqueue::VisitOMPReductionClause(const OMPReductionClause *C) {
240706f32e7eSjoerg VisitOMPClauseList(C);
240806f32e7eSjoerg VisitOMPClauseWithPostUpdate(C);
240906f32e7eSjoerg for (auto *E : C->privates()) {
241006f32e7eSjoerg Visitor->AddStmt(E);
241106f32e7eSjoerg }
241206f32e7eSjoerg for (auto *E : C->lhs_exprs()) {
241306f32e7eSjoerg Visitor->AddStmt(E);
241406f32e7eSjoerg }
241506f32e7eSjoerg for (auto *E : C->rhs_exprs()) {
241606f32e7eSjoerg Visitor->AddStmt(E);
241706f32e7eSjoerg }
241806f32e7eSjoerg for (auto *E : C->reduction_ops()) {
241906f32e7eSjoerg Visitor->AddStmt(E);
242006f32e7eSjoerg }
2421*13fbcb42Sjoerg if (C->getModifier() == clang::OMPC_REDUCTION_inscan) {
2422*13fbcb42Sjoerg for (auto *E : C->copy_ops()) {
2423*13fbcb42Sjoerg Visitor->AddStmt(E);
2424*13fbcb42Sjoerg }
2425*13fbcb42Sjoerg for (auto *E : C->copy_array_temps()) {
2426*13fbcb42Sjoerg Visitor->AddStmt(E);
2427*13fbcb42Sjoerg }
2428*13fbcb42Sjoerg for (auto *E : C->copy_array_elems()) {
2429*13fbcb42Sjoerg Visitor->AddStmt(E);
2430*13fbcb42Sjoerg }
2431*13fbcb42Sjoerg }
243206f32e7eSjoerg }
VisitOMPTaskReductionClause(const OMPTaskReductionClause * C)243306f32e7eSjoerg void OMPClauseEnqueue::VisitOMPTaskReductionClause(
243406f32e7eSjoerg const OMPTaskReductionClause *C) {
243506f32e7eSjoerg VisitOMPClauseList(C);
243606f32e7eSjoerg VisitOMPClauseWithPostUpdate(C);
243706f32e7eSjoerg for (auto *E : C->privates()) {
243806f32e7eSjoerg Visitor->AddStmt(E);
243906f32e7eSjoerg }
244006f32e7eSjoerg for (auto *E : C->lhs_exprs()) {
244106f32e7eSjoerg Visitor->AddStmt(E);
244206f32e7eSjoerg }
244306f32e7eSjoerg for (auto *E : C->rhs_exprs()) {
244406f32e7eSjoerg Visitor->AddStmt(E);
244506f32e7eSjoerg }
244606f32e7eSjoerg for (auto *E : C->reduction_ops()) {
244706f32e7eSjoerg Visitor->AddStmt(E);
244806f32e7eSjoerg }
244906f32e7eSjoerg }
VisitOMPInReductionClause(const OMPInReductionClause * C)245006f32e7eSjoerg void OMPClauseEnqueue::VisitOMPInReductionClause(
245106f32e7eSjoerg const OMPInReductionClause *C) {
245206f32e7eSjoerg VisitOMPClauseList(C);
245306f32e7eSjoerg VisitOMPClauseWithPostUpdate(C);
245406f32e7eSjoerg for (auto *E : C->privates()) {
245506f32e7eSjoerg Visitor->AddStmt(E);
245606f32e7eSjoerg }
245706f32e7eSjoerg for (auto *E : C->lhs_exprs()) {
245806f32e7eSjoerg Visitor->AddStmt(E);
245906f32e7eSjoerg }
246006f32e7eSjoerg for (auto *E : C->rhs_exprs()) {
246106f32e7eSjoerg Visitor->AddStmt(E);
246206f32e7eSjoerg }
246306f32e7eSjoerg for (auto *E : C->reduction_ops()) {
246406f32e7eSjoerg Visitor->AddStmt(E);
246506f32e7eSjoerg }
246606f32e7eSjoerg for (auto *E : C->taskgroup_descriptors())
246706f32e7eSjoerg Visitor->AddStmt(E);
246806f32e7eSjoerg }
VisitOMPLinearClause(const OMPLinearClause * C)246906f32e7eSjoerg void OMPClauseEnqueue::VisitOMPLinearClause(const OMPLinearClause *C) {
247006f32e7eSjoerg VisitOMPClauseList(C);
247106f32e7eSjoerg VisitOMPClauseWithPostUpdate(C);
247206f32e7eSjoerg for (const auto *E : C->privates()) {
247306f32e7eSjoerg Visitor->AddStmt(E);
247406f32e7eSjoerg }
247506f32e7eSjoerg for (const auto *E : C->inits()) {
247606f32e7eSjoerg Visitor->AddStmt(E);
247706f32e7eSjoerg }
247806f32e7eSjoerg for (const auto *E : C->updates()) {
247906f32e7eSjoerg Visitor->AddStmt(E);
248006f32e7eSjoerg }
248106f32e7eSjoerg for (const auto *E : C->finals()) {
248206f32e7eSjoerg Visitor->AddStmt(E);
248306f32e7eSjoerg }
248406f32e7eSjoerg Visitor->AddStmt(C->getStep());
248506f32e7eSjoerg Visitor->AddStmt(C->getCalcStep());
248606f32e7eSjoerg }
VisitOMPAlignedClause(const OMPAlignedClause * C)248706f32e7eSjoerg void OMPClauseEnqueue::VisitOMPAlignedClause(const OMPAlignedClause *C) {
248806f32e7eSjoerg VisitOMPClauseList(C);
248906f32e7eSjoerg Visitor->AddStmt(C->getAlignment());
249006f32e7eSjoerg }
VisitOMPCopyinClause(const OMPCopyinClause * C)249106f32e7eSjoerg void OMPClauseEnqueue::VisitOMPCopyinClause(const OMPCopyinClause *C) {
249206f32e7eSjoerg VisitOMPClauseList(C);
249306f32e7eSjoerg for (auto *E : C->source_exprs()) {
249406f32e7eSjoerg Visitor->AddStmt(E);
249506f32e7eSjoerg }
249606f32e7eSjoerg for (auto *E : C->destination_exprs()) {
249706f32e7eSjoerg Visitor->AddStmt(E);
249806f32e7eSjoerg }
249906f32e7eSjoerg for (auto *E : C->assignment_ops()) {
250006f32e7eSjoerg Visitor->AddStmt(E);
250106f32e7eSjoerg }
250206f32e7eSjoerg }
VisitOMPCopyprivateClause(const OMPCopyprivateClause * C)2503*13fbcb42Sjoerg void OMPClauseEnqueue::VisitOMPCopyprivateClause(
2504*13fbcb42Sjoerg const OMPCopyprivateClause *C) {
250506f32e7eSjoerg VisitOMPClauseList(C);
250606f32e7eSjoerg for (auto *E : C->source_exprs()) {
250706f32e7eSjoerg Visitor->AddStmt(E);
250806f32e7eSjoerg }
250906f32e7eSjoerg for (auto *E : C->destination_exprs()) {
251006f32e7eSjoerg Visitor->AddStmt(E);
251106f32e7eSjoerg }
251206f32e7eSjoerg for (auto *E : C->assignment_ops()) {
251306f32e7eSjoerg Visitor->AddStmt(E);
251406f32e7eSjoerg }
251506f32e7eSjoerg }
VisitOMPFlushClause(const OMPFlushClause * C)251606f32e7eSjoerg void OMPClauseEnqueue::VisitOMPFlushClause(const OMPFlushClause *C) {
251706f32e7eSjoerg VisitOMPClauseList(C);
251806f32e7eSjoerg }
VisitOMPDepobjClause(const OMPDepobjClause * C)2519*13fbcb42Sjoerg void OMPClauseEnqueue::VisitOMPDepobjClause(const OMPDepobjClause *C) {
2520*13fbcb42Sjoerg Visitor->AddStmt(C->getDepobj());
2521*13fbcb42Sjoerg }
VisitOMPDependClause(const OMPDependClause * C)252206f32e7eSjoerg void OMPClauseEnqueue::VisitOMPDependClause(const OMPDependClause *C) {
252306f32e7eSjoerg VisitOMPClauseList(C);
252406f32e7eSjoerg }
VisitOMPMapClause(const OMPMapClause * C)252506f32e7eSjoerg void OMPClauseEnqueue::VisitOMPMapClause(const OMPMapClause *C) {
252606f32e7eSjoerg VisitOMPClauseList(C);
252706f32e7eSjoerg }
VisitOMPDistScheduleClause(const OMPDistScheduleClause * C)252806f32e7eSjoerg void OMPClauseEnqueue::VisitOMPDistScheduleClause(
252906f32e7eSjoerg const OMPDistScheduleClause *C) {
253006f32e7eSjoerg VisitOMPClauseWithPreInit(C);
253106f32e7eSjoerg Visitor->AddStmt(C->getChunkSize());
253206f32e7eSjoerg }
VisitOMPDefaultmapClause(const OMPDefaultmapClause *)253306f32e7eSjoerg void OMPClauseEnqueue::VisitOMPDefaultmapClause(
253406f32e7eSjoerg const OMPDefaultmapClause * /*C*/) {}
VisitOMPToClause(const OMPToClause * C)253506f32e7eSjoerg void OMPClauseEnqueue::VisitOMPToClause(const OMPToClause *C) {
253606f32e7eSjoerg VisitOMPClauseList(C);
253706f32e7eSjoerg }
VisitOMPFromClause(const OMPFromClause * C)253806f32e7eSjoerg void OMPClauseEnqueue::VisitOMPFromClause(const OMPFromClause *C) {
253906f32e7eSjoerg VisitOMPClauseList(C);
254006f32e7eSjoerg }
VisitOMPUseDevicePtrClause(const OMPUseDevicePtrClause * C)2541*13fbcb42Sjoerg void OMPClauseEnqueue::VisitOMPUseDevicePtrClause(
2542*13fbcb42Sjoerg const OMPUseDevicePtrClause *C) {
254306f32e7eSjoerg VisitOMPClauseList(C);
254406f32e7eSjoerg }
VisitOMPUseDeviceAddrClause(const OMPUseDeviceAddrClause * C)2545*13fbcb42Sjoerg void OMPClauseEnqueue::VisitOMPUseDeviceAddrClause(
2546*13fbcb42Sjoerg const OMPUseDeviceAddrClause *C) {
254706f32e7eSjoerg VisitOMPClauseList(C);
254806f32e7eSjoerg }
VisitOMPIsDevicePtrClause(const OMPIsDevicePtrClause * C)2549*13fbcb42Sjoerg void OMPClauseEnqueue::VisitOMPIsDevicePtrClause(
2550*13fbcb42Sjoerg const OMPIsDevicePtrClause *C) {
2551*13fbcb42Sjoerg VisitOMPClauseList(C);
255206f32e7eSjoerg }
VisitOMPNontemporalClause(const OMPNontemporalClause * C)2553*13fbcb42Sjoerg void OMPClauseEnqueue::VisitOMPNontemporalClause(
2554*13fbcb42Sjoerg const OMPNontemporalClause *C) {
2555*13fbcb42Sjoerg VisitOMPClauseList(C);
2556*13fbcb42Sjoerg for (const auto *E : C->private_refs())
2557*13fbcb42Sjoerg Visitor->AddStmt(E);
2558*13fbcb42Sjoerg }
VisitOMPOrderClause(const OMPOrderClause * C)2559*13fbcb42Sjoerg void OMPClauseEnqueue::VisitOMPOrderClause(const OMPOrderClause *C) {}
VisitOMPUsesAllocatorsClause(const OMPUsesAllocatorsClause * C)2560*13fbcb42Sjoerg void OMPClauseEnqueue::VisitOMPUsesAllocatorsClause(
2561*13fbcb42Sjoerg const OMPUsesAllocatorsClause *C) {
2562*13fbcb42Sjoerg for (unsigned I = 0, E = C->getNumberOfAllocators(); I < E; ++I) {
2563*13fbcb42Sjoerg const OMPUsesAllocatorsClause::Data &D = C->getAllocatorData(I);
2564*13fbcb42Sjoerg Visitor->AddStmt(D.Allocator);
2565*13fbcb42Sjoerg Visitor->AddStmt(D.AllocatorTraits);
2566*13fbcb42Sjoerg }
2567*13fbcb42Sjoerg }
VisitOMPAffinityClause(const OMPAffinityClause * C)2568*13fbcb42Sjoerg void OMPClauseEnqueue::VisitOMPAffinityClause(const OMPAffinityClause *C) {
2569*13fbcb42Sjoerg Visitor->AddStmt(C->getModifier());
2570*13fbcb42Sjoerg for (const Expr *E : C->varlists())
2571*13fbcb42Sjoerg Visitor->AddStmt(E);
2572*13fbcb42Sjoerg }
2573*13fbcb42Sjoerg } // namespace
257406f32e7eSjoerg
EnqueueChildren(const OMPClause * S)257506f32e7eSjoerg void EnqueueVisitor::EnqueueChildren(const OMPClause *S) {
257606f32e7eSjoerg unsigned size = WL.size();
257706f32e7eSjoerg OMPClauseEnqueue Visitor(this);
257806f32e7eSjoerg Visitor.Visit(S);
257906f32e7eSjoerg if (size == WL.size())
258006f32e7eSjoerg return;
258106f32e7eSjoerg // Now reverse the entries we just added. This will match the DFS
258206f32e7eSjoerg // ordering performed by the worklist.
258306f32e7eSjoerg VisitorWorkList::iterator I = WL.begin() + size, E = WL.end();
258406f32e7eSjoerg std::reverse(I, E);
258506f32e7eSjoerg }
VisitAddrLabelExpr(const AddrLabelExpr * E)258606f32e7eSjoerg void EnqueueVisitor::VisitAddrLabelExpr(const AddrLabelExpr *E) {
258706f32e7eSjoerg WL.push_back(LabelRefVisit(E->getLabel(), E->getLabelLoc(), Parent));
258806f32e7eSjoerg }
VisitBlockExpr(const BlockExpr * B)258906f32e7eSjoerg void EnqueueVisitor::VisitBlockExpr(const BlockExpr *B) {
259006f32e7eSjoerg AddDecl(B->getBlockDecl());
259106f32e7eSjoerg }
VisitCompoundLiteralExpr(const CompoundLiteralExpr * E)259206f32e7eSjoerg void EnqueueVisitor::VisitCompoundLiteralExpr(const CompoundLiteralExpr *E) {
259306f32e7eSjoerg EnqueueChildren(E);
259406f32e7eSjoerg AddTypeLoc(E->getTypeSourceInfo());
259506f32e7eSjoerg }
VisitCompoundStmt(const CompoundStmt * S)259606f32e7eSjoerg void EnqueueVisitor::VisitCompoundStmt(const CompoundStmt *S) {
259706f32e7eSjoerg for (auto &I : llvm::reverse(S->body()))
259806f32e7eSjoerg AddStmt(I);
259906f32e7eSjoerg }
VisitMSDependentExistsStmt(const MSDependentExistsStmt * S)2600*13fbcb42Sjoerg void EnqueueVisitor::VisitMSDependentExistsStmt(
2601*13fbcb42Sjoerg const MSDependentExistsStmt *S) {
260206f32e7eSjoerg AddStmt(S->getSubStmt());
260306f32e7eSjoerg AddDeclarationNameInfo(S);
260406f32e7eSjoerg if (NestedNameSpecifierLoc QualifierLoc = S->getQualifierLoc())
260506f32e7eSjoerg AddNestedNameSpecifierLoc(QualifierLoc);
260606f32e7eSjoerg }
260706f32e7eSjoerg
VisitCXXDependentScopeMemberExpr(const CXXDependentScopeMemberExpr * E)2608*13fbcb42Sjoerg void EnqueueVisitor::VisitCXXDependentScopeMemberExpr(
2609*13fbcb42Sjoerg const CXXDependentScopeMemberExpr *E) {
261006f32e7eSjoerg if (E->hasExplicitTemplateArgs())
261106f32e7eSjoerg AddExplicitTemplateArgs(E->getTemplateArgs(), E->getNumTemplateArgs());
261206f32e7eSjoerg AddDeclarationNameInfo(E);
261306f32e7eSjoerg if (NestedNameSpecifierLoc QualifierLoc = E->getQualifierLoc())
261406f32e7eSjoerg AddNestedNameSpecifierLoc(QualifierLoc);
261506f32e7eSjoerg if (!E->isImplicitAccess())
261606f32e7eSjoerg AddStmt(E->getBase());
261706f32e7eSjoerg }
VisitCXXNewExpr(const CXXNewExpr * E)261806f32e7eSjoerg void EnqueueVisitor::VisitCXXNewExpr(const CXXNewExpr *E) {
261906f32e7eSjoerg // Enqueue the initializer , if any.
262006f32e7eSjoerg AddStmt(E->getInitializer());
262106f32e7eSjoerg // Enqueue the array size, if any.
262206f32e7eSjoerg AddStmt(E->getArraySize().getValueOr(nullptr));
262306f32e7eSjoerg // Enqueue the allocated type.
262406f32e7eSjoerg AddTypeLoc(E->getAllocatedTypeSourceInfo());
262506f32e7eSjoerg // Enqueue the placement arguments.
262606f32e7eSjoerg for (unsigned I = E->getNumPlacementArgs(); I > 0; --I)
262706f32e7eSjoerg AddStmt(E->getPlacementArg(I - 1));
262806f32e7eSjoerg }
VisitCXXOperatorCallExpr(const CXXOperatorCallExpr * CE)262906f32e7eSjoerg void EnqueueVisitor::VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *CE) {
263006f32e7eSjoerg for (unsigned I = CE->getNumArgs(); I > 1 /* Yes, this is 1 */; --I)
263106f32e7eSjoerg AddStmt(CE->getArg(I - 1));
263206f32e7eSjoerg AddStmt(CE->getCallee());
263306f32e7eSjoerg AddStmt(CE->getArg(0));
263406f32e7eSjoerg }
VisitCXXPseudoDestructorExpr(const CXXPseudoDestructorExpr * E)263506f32e7eSjoerg void EnqueueVisitor::VisitCXXPseudoDestructorExpr(
263606f32e7eSjoerg const CXXPseudoDestructorExpr *E) {
263706f32e7eSjoerg // Visit the name of the type being destroyed.
263806f32e7eSjoerg AddTypeLoc(E->getDestroyedTypeInfo());
263906f32e7eSjoerg // Visit the scope type that looks disturbingly like the nested-name-specifier
264006f32e7eSjoerg // but isn't.
264106f32e7eSjoerg AddTypeLoc(E->getScopeTypeInfo());
264206f32e7eSjoerg // Visit the nested-name-specifier.
264306f32e7eSjoerg if (NestedNameSpecifierLoc QualifierLoc = E->getQualifierLoc())
264406f32e7eSjoerg AddNestedNameSpecifierLoc(QualifierLoc);
264506f32e7eSjoerg // Visit base expression.
264606f32e7eSjoerg AddStmt(E->getBase());
264706f32e7eSjoerg }
VisitCXXScalarValueInitExpr(const CXXScalarValueInitExpr * E)264806f32e7eSjoerg void EnqueueVisitor::VisitCXXScalarValueInitExpr(
264906f32e7eSjoerg const CXXScalarValueInitExpr *E) {
265006f32e7eSjoerg AddTypeLoc(E->getTypeSourceInfo());
265106f32e7eSjoerg }
VisitCXXTemporaryObjectExpr(const CXXTemporaryObjectExpr * E)265206f32e7eSjoerg void EnqueueVisitor::VisitCXXTemporaryObjectExpr(
265306f32e7eSjoerg const CXXTemporaryObjectExpr *E) {
265406f32e7eSjoerg EnqueueChildren(E);
265506f32e7eSjoerg AddTypeLoc(E->getTypeSourceInfo());
265606f32e7eSjoerg }
VisitCXXTypeidExpr(const CXXTypeidExpr * E)265706f32e7eSjoerg void EnqueueVisitor::VisitCXXTypeidExpr(const CXXTypeidExpr *E) {
265806f32e7eSjoerg EnqueueChildren(E);
265906f32e7eSjoerg if (E->isTypeOperand())
266006f32e7eSjoerg AddTypeLoc(E->getTypeOperandSourceInfo());
266106f32e7eSjoerg }
266206f32e7eSjoerg
VisitCXXUnresolvedConstructExpr(const CXXUnresolvedConstructExpr * E)266306f32e7eSjoerg void EnqueueVisitor::VisitCXXUnresolvedConstructExpr(
266406f32e7eSjoerg const CXXUnresolvedConstructExpr *E) {
266506f32e7eSjoerg EnqueueChildren(E);
266606f32e7eSjoerg AddTypeLoc(E->getTypeSourceInfo());
266706f32e7eSjoerg }
VisitCXXUuidofExpr(const CXXUuidofExpr * E)266806f32e7eSjoerg void EnqueueVisitor::VisitCXXUuidofExpr(const CXXUuidofExpr *E) {
266906f32e7eSjoerg EnqueueChildren(E);
267006f32e7eSjoerg if (E->isTypeOperand())
267106f32e7eSjoerg AddTypeLoc(E->getTypeOperandSourceInfo());
267206f32e7eSjoerg }
267306f32e7eSjoerg
VisitCXXCatchStmt(const CXXCatchStmt * S)267406f32e7eSjoerg void EnqueueVisitor::VisitCXXCatchStmt(const CXXCatchStmt *S) {
267506f32e7eSjoerg EnqueueChildren(S);
267606f32e7eSjoerg AddDecl(S->getExceptionDecl());
267706f32e7eSjoerg }
267806f32e7eSjoerg
VisitCXXForRangeStmt(const CXXForRangeStmt * S)267906f32e7eSjoerg void EnqueueVisitor::VisitCXXForRangeStmt(const CXXForRangeStmt *S) {
268006f32e7eSjoerg AddStmt(S->getBody());
268106f32e7eSjoerg AddStmt(S->getRangeInit());
268206f32e7eSjoerg AddDecl(S->getLoopVariable());
268306f32e7eSjoerg }
268406f32e7eSjoerg
VisitDeclRefExpr(const DeclRefExpr * DR)268506f32e7eSjoerg void EnqueueVisitor::VisitDeclRefExpr(const DeclRefExpr *DR) {
268606f32e7eSjoerg if (DR->hasExplicitTemplateArgs())
268706f32e7eSjoerg AddExplicitTemplateArgs(DR->getTemplateArgs(), DR->getNumTemplateArgs());
268806f32e7eSjoerg WL.push_back(DeclRefExprParts(DR, Parent));
268906f32e7eSjoerg }
VisitDependentScopeDeclRefExpr(const DependentScopeDeclRefExpr * E)269006f32e7eSjoerg void EnqueueVisitor::VisitDependentScopeDeclRefExpr(
269106f32e7eSjoerg const DependentScopeDeclRefExpr *E) {
269206f32e7eSjoerg if (E->hasExplicitTemplateArgs())
269306f32e7eSjoerg AddExplicitTemplateArgs(E->getTemplateArgs(), E->getNumTemplateArgs());
269406f32e7eSjoerg AddDeclarationNameInfo(E);
269506f32e7eSjoerg AddNestedNameSpecifierLoc(E->getQualifierLoc());
269606f32e7eSjoerg }
VisitDeclStmt(const DeclStmt * S)269706f32e7eSjoerg void EnqueueVisitor::VisitDeclStmt(const DeclStmt *S) {
269806f32e7eSjoerg unsigned size = WL.size();
269906f32e7eSjoerg bool isFirst = true;
270006f32e7eSjoerg for (const auto *D : S->decls()) {
270106f32e7eSjoerg AddDecl(D, isFirst);
270206f32e7eSjoerg isFirst = false;
270306f32e7eSjoerg }
270406f32e7eSjoerg if (size == WL.size())
270506f32e7eSjoerg return;
270606f32e7eSjoerg // Now reverse the entries we just added. This will match the DFS
270706f32e7eSjoerg // ordering performed by the worklist.
270806f32e7eSjoerg VisitorWorkList::iterator I = WL.begin() + size, E = WL.end();
270906f32e7eSjoerg std::reverse(I, E);
271006f32e7eSjoerg }
VisitDesignatedInitExpr(const DesignatedInitExpr * E)271106f32e7eSjoerg void EnqueueVisitor::VisitDesignatedInitExpr(const DesignatedInitExpr *E) {
271206f32e7eSjoerg AddStmt(E->getInit());
271306f32e7eSjoerg for (const DesignatedInitExpr::Designator &D :
271406f32e7eSjoerg llvm::reverse(E->designators())) {
271506f32e7eSjoerg if (D.isFieldDesignator()) {
271606f32e7eSjoerg if (FieldDecl *Field = D.getField())
271706f32e7eSjoerg AddMemberRef(Field, D.getFieldLoc());
271806f32e7eSjoerg continue;
271906f32e7eSjoerg }
272006f32e7eSjoerg if (D.isArrayDesignator()) {
272106f32e7eSjoerg AddStmt(E->getArrayIndex(D));
272206f32e7eSjoerg continue;
272306f32e7eSjoerg }
272406f32e7eSjoerg assert(D.isArrayRangeDesignator() && "Unknown designator kind");
272506f32e7eSjoerg AddStmt(E->getArrayRangeEnd(D));
272606f32e7eSjoerg AddStmt(E->getArrayRangeStart(D));
272706f32e7eSjoerg }
272806f32e7eSjoerg }
VisitExplicitCastExpr(const ExplicitCastExpr * E)272906f32e7eSjoerg void EnqueueVisitor::VisitExplicitCastExpr(const ExplicitCastExpr *E) {
273006f32e7eSjoerg EnqueueChildren(E);
273106f32e7eSjoerg AddTypeLoc(E->getTypeInfoAsWritten());
273206f32e7eSjoerg }
VisitForStmt(const ForStmt * FS)273306f32e7eSjoerg void EnqueueVisitor::VisitForStmt(const ForStmt *FS) {
273406f32e7eSjoerg AddStmt(FS->getBody());
273506f32e7eSjoerg AddStmt(FS->getInc());
273606f32e7eSjoerg AddStmt(FS->getCond());
273706f32e7eSjoerg AddDecl(FS->getConditionVariable());
273806f32e7eSjoerg AddStmt(FS->getInit());
273906f32e7eSjoerg }
VisitGotoStmt(const GotoStmt * GS)274006f32e7eSjoerg void EnqueueVisitor::VisitGotoStmt(const GotoStmt *GS) {
274106f32e7eSjoerg WL.push_back(LabelRefVisit(GS->getLabel(), GS->getLabelLoc(), Parent));
274206f32e7eSjoerg }
VisitIfStmt(const IfStmt * If)274306f32e7eSjoerg void EnqueueVisitor::VisitIfStmt(const IfStmt *If) {
274406f32e7eSjoerg AddStmt(If->getElse());
274506f32e7eSjoerg AddStmt(If->getThen());
274606f32e7eSjoerg AddStmt(If->getCond());
2747*13fbcb42Sjoerg AddStmt(If->getInit());
274806f32e7eSjoerg AddDecl(If->getConditionVariable());
274906f32e7eSjoerg }
VisitInitListExpr(const InitListExpr * IE)275006f32e7eSjoerg void EnqueueVisitor::VisitInitListExpr(const InitListExpr *IE) {
275106f32e7eSjoerg // We care about the syntactic form of the initializer list, only.
275206f32e7eSjoerg if (InitListExpr *Syntactic = IE->getSyntacticForm())
275306f32e7eSjoerg IE = Syntactic;
275406f32e7eSjoerg EnqueueChildren(IE);
275506f32e7eSjoerg }
VisitMemberExpr(const MemberExpr * M)275606f32e7eSjoerg void EnqueueVisitor::VisitMemberExpr(const MemberExpr *M) {
275706f32e7eSjoerg WL.push_back(MemberExprParts(M, Parent));
275806f32e7eSjoerg
275906f32e7eSjoerg // If the base of the member access expression is an implicit 'this', don't
276006f32e7eSjoerg // visit it.
276106f32e7eSjoerg // FIXME: If we ever want to show these implicit accesses, this will be
276206f32e7eSjoerg // unfortunate. However, clang_getCursor() relies on this behavior.
276306f32e7eSjoerg if (M->isImplicitAccess())
276406f32e7eSjoerg return;
276506f32e7eSjoerg
276606f32e7eSjoerg // Ignore base anonymous struct/union fields, otherwise they will shadow the
276706f32e7eSjoerg // real field that we are interested in.
276806f32e7eSjoerg if (auto *SubME = dyn_cast<MemberExpr>(M->getBase())) {
276906f32e7eSjoerg if (auto *FD = dyn_cast_or_null<FieldDecl>(SubME->getMemberDecl())) {
277006f32e7eSjoerg if (FD->isAnonymousStructOrUnion()) {
277106f32e7eSjoerg AddStmt(SubME->getBase());
277206f32e7eSjoerg return;
277306f32e7eSjoerg }
277406f32e7eSjoerg }
277506f32e7eSjoerg }
277606f32e7eSjoerg
277706f32e7eSjoerg AddStmt(M->getBase());
277806f32e7eSjoerg }
VisitObjCEncodeExpr(const ObjCEncodeExpr * E)277906f32e7eSjoerg void EnqueueVisitor::VisitObjCEncodeExpr(const ObjCEncodeExpr *E) {
278006f32e7eSjoerg AddTypeLoc(E->getEncodedTypeSourceInfo());
278106f32e7eSjoerg }
VisitObjCMessageExpr(const ObjCMessageExpr * M)278206f32e7eSjoerg void EnqueueVisitor::VisitObjCMessageExpr(const ObjCMessageExpr *M) {
278306f32e7eSjoerg EnqueueChildren(M);
278406f32e7eSjoerg AddTypeLoc(M->getClassReceiverTypeInfo());
278506f32e7eSjoerg }
VisitOffsetOfExpr(const OffsetOfExpr * E)278606f32e7eSjoerg void EnqueueVisitor::VisitOffsetOfExpr(const OffsetOfExpr *E) {
278706f32e7eSjoerg // Visit the components of the offsetof expression.
278806f32e7eSjoerg for (unsigned N = E->getNumComponents(), I = N; I > 0; --I) {
278906f32e7eSjoerg const OffsetOfNode &Node = E->getComponent(I - 1);
279006f32e7eSjoerg switch (Node.getKind()) {
279106f32e7eSjoerg case OffsetOfNode::Array:
279206f32e7eSjoerg AddStmt(E->getIndexExpr(Node.getArrayExprIndex()));
279306f32e7eSjoerg break;
279406f32e7eSjoerg case OffsetOfNode::Field:
279506f32e7eSjoerg AddMemberRef(Node.getField(), Node.getSourceRange().getEnd());
279606f32e7eSjoerg break;
279706f32e7eSjoerg case OffsetOfNode::Identifier:
279806f32e7eSjoerg case OffsetOfNode::Base:
279906f32e7eSjoerg continue;
280006f32e7eSjoerg }
280106f32e7eSjoerg }
280206f32e7eSjoerg // Visit the type into which we're computing the offset.
280306f32e7eSjoerg AddTypeLoc(E->getTypeSourceInfo());
280406f32e7eSjoerg }
VisitOverloadExpr(const OverloadExpr * E)280506f32e7eSjoerg void EnqueueVisitor::VisitOverloadExpr(const OverloadExpr *E) {
280606f32e7eSjoerg if (E->hasExplicitTemplateArgs())
280706f32e7eSjoerg AddExplicitTemplateArgs(E->getTemplateArgs(), E->getNumTemplateArgs());
280806f32e7eSjoerg WL.push_back(OverloadExprParts(E, Parent));
280906f32e7eSjoerg }
VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr * E)281006f32e7eSjoerg void EnqueueVisitor::VisitUnaryExprOrTypeTraitExpr(
281106f32e7eSjoerg const UnaryExprOrTypeTraitExpr *E) {
281206f32e7eSjoerg EnqueueChildren(E);
281306f32e7eSjoerg if (E->isArgumentType())
281406f32e7eSjoerg AddTypeLoc(E->getArgumentTypeInfo());
281506f32e7eSjoerg }
VisitStmt(const Stmt * S)2816*13fbcb42Sjoerg void EnqueueVisitor::VisitStmt(const Stmt *S) { EnqueueChildren(S); }
VisitSwitchStmt(const SwitchStmt * S)281706f32e7eSjoerg void EnqueueVisitor::VisitSwitchStmt(const SwitchStmt *S) {
281806f32e7eSjoerg AddStmt(S->getBody());
281906f32e7eSjoerg AddStmt(S->getCond());
282006f32e7eSjoerg AddDecl(S->getConditionVariable());
282106f32e7eSjoerg }
282206f32e7eSjoerg
VisitWhileStmt(const WhileStmt * W)282306f32e7eSjoerg void EnqueueVisitor::VisitWhileStmt(const WhileStmt *W) {
282406f32e7eSjoerg AddStmt(W->getBody());
282506f32e7eSjoerg AddStmt(W->getCond());
282606f32e7eSjoerg AddDecl(W->getConditionVariable());
282706f32e7eSjoerg }
282806f32e7eSjoerg
VisitTypeTraitExpr(const TypeTraitExpr * E)282906f32e7eSjoerg void EnqueueVisitor::VisitTypeTraitExpr(const TypeTraitExpr *E) {
283006f32e7eSjoerg for (unsigned I = E->getNumArgs(); I > 0; --I)
283106f32e7eSjoerg AddTypeLoc(E->getArg(I - 1));
283206f32e7eSjoerg }
283306f32e7eSjoerg
VisitArrayTypeTraitExpr(const ArrayTypeTraitExpr * E)283406f32e7eSjoerg void EnqueueVisitor::VisitArrayTypeTraitExpr(const ArrayTypeTraitExpr *E) {
283506f32e7eSjoerg AddTypeLoc(E->getQueriedTypeSourceInfo());
283606f32e7eSjoerg }
283706f32e7eSjoerg
VisitExpressionTraitExpr(const ExpressionTraitExpr * E)283806f32e7eSjoerg void EnqueueVisitor::VisitExpressionTraitExpr(const ExpressionTraitExpr *E) {
283906f32e7eSjoerg EnqueueChildren(E);
284006f32e7eSjoerg }
284106f32e7eSjoerg
VisitUnresolvedMemberExpr(const UnresolvedMemberExpr * U)284206f32e7eSjoerg void EnqueueVisitor::VisitUnresolvedMemberExpr(const UnresolvedMemberExpr *U) {
284306f32e7eSjoerg VisitOverloadExpr(U);
284406f32e7eSjoerg if (!U->isImplicitAccess())
284506f32e7eSjoerg AddStmt(U->getBase());
284606f32e7eSjoerg }
VisitVAArgExpr(const VAArgExpr * E)284706f32e7eSjoerg void EnqueueVisitor::VisitVAArgExpr(const VAArgExpr *E) {
284806f32e7eSjoerg AddStmt(E->getSubExpr());
284906f32e7eSjoerg AddTypeLoc(E->getWrittenTypeInfo());
285006f32e7eSjoerg }
VisitSizeOfPackExpr(const SizeOfPackExpr * E)285106f32e7eSjoerg void EnqueueVisitor::VisitSizeOfPackExpr(const SizeOfPackExpr *E) {
285206f32e7eSjoerg WL.push_back(SizeOfPackExprParts(E, Parent));
285306f32e7eSjoerg }
VisitOpaqueValueExpr(const OpaqueValueExpr * E)285406f32e7eSjoerg void EnqueueVisitor::VisitOpaqueValueExpr(const OpaqueValueExpr *E) {
285506f32e7eSjoerg // If the opaque value has a source expression, just transparently
285606f32e7eSjoerg // visit that. This is useful for (e.g.) pseudo-object expressions.
285706f32e7eSjoerg if (Expr *SourceExpr = E->getSourceExpr())
285806f32e7eSjoerg return Visit(SourceExpr);
285906f32e7eSjoerg }
VisitLambdaExpr(const LambdaExpr * E)286006f32e7eSjoerg void EnqueueVisitor::VisitLambdaExpr(const LambdaExpr *E) {
286106f32e7eSjoerg AddStmt(E->getBody());
286206f32e7eSjoerg WL.push_back(LambdaExprParts(E, Parent));
286306f32e7eSjoerg }
VisitPseudoObjectExpr(const PseudoObjectExpr * E)286406f32e7eSjoerg void EnqueueVisitor::VisitPseudoObjectExpr(const PseudoObjectExpr *E) {
286506f32e7eSjoerg // Treat the expression like its syntactic form.
286606f32e7eSjoerg Visit(E->getSyntacticForm());
286706f32e7eSjoerg }
286806f32e7eSjoerg
VisitOMPExecutableDirective(const OMPExecutableDirective * D)286906f32e7eSjoerg void EnqueueVisitor::VisitOMPExecutableDirective(
287006f32e7eSjoerg const OMPExecutableDirective *D) {
287106f32e7eSjoerg EnqueueChildren(D);
287206f32e7eSjoerg for (ArrayRef<OMPClause *>::iterator I = D->clauses().begin(),
287306f32e7eSjoerg E = D->clauses().end();
287406f32e7eSjoerg I != E; ++I)
287506f32e7eSjoerg EnqueueChildren(*I);
287606f32e7eSjoerg }
287706f32e7eSjoerg
VisitOMPLoopBasedDirective(const OMPLoopBasedDirective * D)2878*13fbcb42Sjoerg void EnqueueVisitor::VisitOMPLoopBasedDirective(
2879*13fbcb42Sjoerg const OMPLoopBasedDirective *D) {
288006f32e7eSjoerg VisitOMPExecutableDirective(D);
288106f32e7eSjoerg }
288206f32e7eSjoerg
VisitOMPLoopDirective(const OMPLoopDirective * D)2883*13fbcb42Sjoerg void EnqueueVisitor::VisitOMPLoopDirective(const OMPLoopDirective *D) {
2884*13fbcb42Sjoerg VisitOMPLoopBasedDirective(D);
2885*13fbcb42Sjoerg }
2886*13fbcb42Sjoerg
VisitOMPParallelDirective(const OMPParallelDirective * D)288706f32e7eSjoerg void EnqueueVisitor::VisitOMPParallelDirective(const OMPParallelDirective *D) {
288806f32e7eSjoerg VisitOMPExecutableDirective(D);
288906f32e7eSjoerg }
289006f32e7eSjoerg
VisitOMPSimdDirective(const OMPSimdDirective * D)289106f32e7eSjoerg void EnqueueVisitor::VisitOMPSimdDirective(const OMPSimdDirective *D) {
289206f32e7eSjoerg VisitOMPLoopDirective(D);
289306f32e7eSjoerg }
289406f32e7eSjoerg
VisitOMPTileDirective(const OMPTileDirective * D)2895*13fbcb42Sjoerg void EnqueueVisitor::VisitOMPTileDirective(const OMPTileDirective *D) {
2896*13fbcb42Sjoerg VisitOMPLoopBasedDirective(D);
2897*13fbcb42Sjoerg }
2898*13fbcb42Sjoerg
VisitOMPForDirective(const OMPForDirective * D)289906f32e7eSjoerg void EnqueueVisitor::VisitOMPForDirective(const OMPForDirective *D) {
290006f32e7eSjoerg VisitOMPLoopDirective(D);
290106f32e7eSjoerg }
290206f32e7eSjoerg
VisitOMPForSimdDirective(const OMPForSimdDirective * D)290306f32e7eSjoerg void EnqueueVisitor::VisitOMPForSimdDirective(const OMPForSimdDirective *D) {
290406f32e7eSjoerg VisitOMPLoopDirective(D);
290506f32e7eSjoerg }
290606f32e7eSjoerg
VisitOMPSectionsDirective(const OMPSectionsDirective * D)290706f32e7eSjoerg void EnqueueVisitor::VisitOMPSectionsDirective(const OMPSectionsDirective *D) {
290806f32e7eSjoerg VisitOMPExecutableDirective(D);
290906f32e7eSjoerg }
291006f32e7eSjoerg
VisitOMPSectionDirective(const OMPSectionDirective * D)291106f32e7eSjoerg void EnqueueVisitor::VisitOMPSectionDirective(const OMPSectionDirective *D) {
291206f32e7eSjoerg VisitOMPExecutableDirective(D);
291306f32e7eSjoerg }
291406f32e7eSjoerg
VisitOMPSingleDirective(const OMPSingleDirective * D)291506f32e7eSjoerg void EnqueueVisitor::VisitOMPSingleDirective(const OMPSingleDirective *D) {
291606f32e7eSjoerg VisitOMPExecutableDirective(D);
291706f32e7eSjoerg }
291806f32e7eSjoerg
VisitOMPMasterDirective(const OMPMasterDirective * D)291906f32e7eSjoerg void EnqueueVisitor::VisitOMPMasterDirective(const OMPMasterDirective *D) {
292006f32e7eSjoerg VisitOMPExecutableDirective(D);
292106f32e7eSjoerg }
292206f32e7eSjoerg
VisitOMPCriticalDirective(const OMPCriticalDirective * D)292306f32e7eSjoerg void EnqueueVisitor::VisitOMPCriticalDirective(const OMPCriticalDirective *D) {
292406f32e7eSjoerg VisitOMPExecutableDirective(D);
292506f32e7eSjoerg AddDeclarationNameInfo(D);
292606f32e7eSjoerg }
292706f32e7eSjoerg
VisitOMPParallelForDirective(const OMPParallelForDirective * D)2928*13fbcb42Sjoerg void EnqueueVisitor::VisitOMPParallelForDirective(
2929*13fbcb42Sjoerg const OMPParallelForDirective *D) {
293006f32e7eSjoerg VisitOMPLoopDirective(D);
293106f32e7eSjoerg }
293206f32e7eSjoerg
VisitOMPParallelForSimdDirective(const OMPParallelForSimdDirective * D)293306f32e7eSjoerg void EnqueueVisitor::VisitOMPParallelForSimdDirective(
293406f32e7eSjoerg const OMPParallelForSimdDirective *D) {
293506f32e7eSjoerg VisitOMPLoopDirective(D);
293606f32e7eSjoerg }
293706f32e7eSjoerg
VisitOMPParallelMasterDirective(const OMPParallelMasterDirective * D)2938*13fbcb42Sjoerg void EnqueueVisitor::VisitOMPParallelMasterDirective(
2939*13fbcb42Sjoerg const OMPParallelMasterDirective *D) {
2940*13fbcb42Sjoerg VisitOMPExecutableDirective(D);
2941*13fbcb42Sjoerg }
2942*13fbcb42Sjoerg
VisitOMPParallelSectionsDirective(const OMPParallelSectionsDirective * D)294306f32e7eSjoerg void EnqueueVisitor::VisitOMPParallelSectionsDirective(
294406f32e7eSjoerg const OMPParallelSectionsDirective *D) {
294506f32e7eSjoerg VisitOMPExecutableDirective(D);
294606f32e7eSjoerg }
294706f32e7eSjoerg
VisitOMPTaskDirective(const OMPTaskDirective * D)294806f32e7eSjoerg void EnqueueVisitor::VisitOMPTaskDirective(const OMPTaskDirective *D) {
294906f32e7eSjoerg VisitOMPExecutableDirective(D);
295006f32e7eSjoerg }
295106f32e7eSjoerg
VisitOMPTaskyieldDirective(const OMPTaskyieldDirective * D)2952*13fbcb42Sjoerg void EnqueueVisitor::VisitOMPTaskyieldDirective(
2953*13fbcb42Sjoerg const OMPTaskyieldDirective *D) {
295406f32e7eSjoerg VisitOMPExecutableDirective(D);
295506f32e7eSjoerg }
295606f32e7eSjoerg
VisitOMPBarrierDirective(const OMPBarrierDirective * D)295706f32e7eSjoerg void EnqueueVisitor::VisitOMPBarrierDirective(const OMPBarrierDirective *D) {
295806f32e7eSjoerg VisitOMPExecutableDirective(D);
295906f32e7eSjoerg }
296006f32e7eSjoerg
VisitOMPTaskwaitDirective(const OMPTaskwaitDirective * D)296106f32e7eSjoerg void EnqueueVisitor::VisitOMPTaskwaitDirective(const OMPTaskwaitDirective *D) {
296206f32e7eSjoerg VisitOMPExecutableDirective(D);
296306f32e7eSjoerg }
296406f32e7eSjoerg
VisitOMPTaskgroupDirective(const OMPTaskgroupDirective * D)296506f32e7eSjoerg void EnqueueVisitor::VisitOMPTaskgroupDirective(
296606f32e7eSjoerg const OMPTaskgroupDirective *D) {
296706f32e7eSjoerg VisitOMPExecutableDirective(D);
296806f32e7eSjoerg if (const Expr *E = D->getReductionRef())
296906f32e7eSjoerg VisitStmt(E);
297006f32e7eSjoerg }
297106f32e7eSjoerg
VisitOMPFlushDirective(const OMPFlushDirective * D)297206f32e7eSjoerg void EnqueueVisitor::VisitOMPFlushDirective(const OMPFlushDirective *D) {
297306f32e7eSjoerg VisitOMPExecutableDirective(D);
297406f32e7eSjoerg }
297506f32e7eSjoerg
VisitOMPDepobjDirective(const OMPDepobjDirective * D)2976*13fbcb42Sjoerg void EnqueueVisitor::VisitOMPDepobjDirective(const OMPDepobjDirective *D) {
2977*13fbcb42Sjoerg VisitOMPExecutableDirective(D);
2978*13fbcb42Sjoerg }
2979*13fbcb42Sjoerg
VisitOMPScanDirective(const OMPScanDirective * D)2980*13fbcb42Sjoerg void EnqueueVisitor::VisitOMPScanDirective(const OMPScanDirective *D) {
2981*13fbcb42Sjoerg VisitOMPExecutableDirective(D);
2982*13fbcb42Sjoerg }
2983*13fbcb42Sjoerg
VisitOMPOrderedDirective(const OMPOrderedDirective * D)298406f32e7eSjoerg void EnqueueVisitor::VisitOMPOrderedDirective(const OMPOrderedDirective *D) {
298506f32e7eSjoerg VisitOMPExecutableDirective(D);
298606f32e7eSjoerg }
298706f32e7eSjoerg
VisitOMPAtomicDirective(const OMPAtomicDirective * D)298806f32e7eSjoerg void EnqueueVisitor::VisitOMPAtomicDirective(const OMPAtomicDirective *D) {
298906f32e7eSjoerg VisitOMPExecutableDirective(D);
299006f32e7eSjoerg }
299106f32e7eSjoerg
VisitOMPTargetDirective(const OMPTargetDirective * D)299206f32e7eSjoerg void EnqueueVisitor::VisitOMPTargetDirective(const OMPTargetDirective *D) {
299306f32e7eSjoerg VisitOMPExecutableDirective(D);
299406f32e7eSjoerg }
299506f32e7eSjoerg
VisitOMPTargetDataDirective(const OMPTargetDataDirective * D)2996*13fbcb42Sjoerg void EnqueueVisitor::VisitOMPTargetDataDirective(
2997*13fbcb42Sjoerg const OMPTargetDataDirective *D) {
299806f32e7eSjoerg VisitOMPExecutableDirective(D);
299906f32e7eSjoerg }
300006f32e7eSjoerg
VisitOMPTargetEnterDataDirective(const OMPTargetEnterDataDirective * D)300106f32e7eSjoerg void EnqueueVisitor::VisitOMPTargetEnterDataDirective(
300206f32e7eSjoerg const OMPTargetEnterDataDirective *D) {
300306f32e7eSjoerg VisitOMPExecutableDirective(D);
300406f32e7eSjoerg }
300506f32e7eSjoerg
VisitOMPTargetExitDataDirective(const OMPTargetExitDataDirective * D)300606f32e7eSjoerg void EnqueueVisitor::VisitOMPTargetExitDataDirective(
300706f32e7eSjoerg const OMPTargetExitDataDirective *D) {
300806f32e7eSjoerg VisitOMPExecutableDirective(D);
300906f32e7eSjoerg }
301006f32e7eSjoerg
VisitOMPTargetParallelDirective(const OMPTargetParallelDirective * D)301106f32e7eSjoerg void EnqueueVisitor::VisitOMPTargetParallelDirective(
301206f32e7eSjoerg const OMPTargetParallelDirective *D) {
301306f32e7eSjoerg VisitOMPExecutableDirective(D);
301406f32e7eSjoerg }
301506f32e7eSjoerg
VisitOMPTargetParallelForDirective(const OMPTargetParallelForDirective * D)301606f32e7eSjoerg void EnqueueVisitor::VisitOMPTargetParallelForDirective(
301706f32e7eSjoerg const OMPTargetParallelForDirective *D) {
301806f32e7eSjoerg VisitOMPLoopDirective(D);
301906f32e7eSjoerg }
302006f32e7eSjoerg
VisitOMPTeamsDirective(const OMPTeamsDirective * D)302106f32e7eSjoerg void EnqueueVisitor::VisitOMPTeamsDirective(const OMPTeamsDirective *D) {
302206f32e7eSjoerg VisitOMPExecutableDirective(D);
302306f32e7eSjoerg }
302406f32e7eSjoerg
VisitOMPCancellationPointDirective(const OMPCancellationPointDirective * D)302506f32e7eSjoerg void EnqueueVisitor::VisitOMPCancellationPointDirective(
302606f32e7eSjoerg const OMPCancellationPointDirective *D) {
302706f32e7eSjoerg VisitOMPExecutableDirective(D);
302806f32e7eSjoerg }
302906f32e7eSjoerg
VisitOMPCancelDirective(const OMPCancelDirective * D)303006f32e7eSjoerg void EnqueueVisitor::VisitOMPCancelDirective(const OMPCancelDirective *D) {
303106f32e7eSjoerg VisitOMPExecutableDirective(D);
303206f32e7eSjoerg }
303306f32e7eSjoerg
VisitOMPTaskLoopDirective(const OMPTaskLoopDirective * D)303406f32e7eSjoerg void EnqueueVisitor::VisitOMPTaskLoopDirective(const OMPTaskLoopDirective *D) {
303506f32e7eSjoerg VisitOMPLoopDirective(D);
303606f32e7eSjoerg }
303706f32e7eSjoerg
VisitOMPTaskLoopSimdDirective(const OMPTaskLoopSimdDirective * D)303806f32e7eSjoerg void EnqueueVisitor::VisitOMPTaskLoopSimdDirective(
303906f32e7eSjoerg const OMPTaskLoopSimdDirective *D) {
304006f32e7eSjoerg VisitOMPLoopDirective(D);
304106f32e7eSjoerg }
304206f32e7eSjoerg
VisitOMPMasterTaskLoopDirective(const OMPMasterTaskLoopDirective * D)304306f32e7eSjoerg void EnqueueVisitor::VisitOMPMasterTaskLoopDirective(
304406f32e7eSjoerg const OMPMasterTaskLoopDirective *D) {
304506f32e7eSjoerg VisitOMPLoopDirective(D);
304606f32e7eSjoerg }
304706f32e7eSjoerg
VisitOMPMasterTaskLoopSimdDirective(const OMPMasterTaskLoopSimdDirective * D)304806f32e7eSjoerg void EnqueueVisitor::VisitOMPMasterTaskLoopSimdDirective(
304906f32e7eSjoerg const OMPMasterTaskLoopSimdDirective *D) {
305006f32e7eSjoerg VisitOMPLoopDirective(D);
305106f32e7eSjoerg }
305206f32e7eSjoerg
VisitOMPParallelMasterTaskLoopDirective(const OMPParallelMasterTaskLoopDirective * D)305306f32e7eSjoerg void EnqueueVisitor::VisitOMPParallelMasterTaskLoopDirective(
305406f32e7eSjoerg const OMPParallelMasterTaskLoopDirective *D) {
305506f32e7eSjoerg VisitOMPLoopDirective(D);
305606f32e7eSjoerg }
305706f32e7eSjoerg
VisitOMPParallelMasterTaskLoopSimdDirective(const OMPParallelMasterTaskLoopSimdDirective * D)3058*13fbcb42Sjoerg void EnqueueVisitor::VisitOMPParallelMasterTaskLoopSimdDirective(
3059*13fbcb42Sjoerg const OMPParallelMasterTaskLoopSimdDirective *D) {
3060*13fbcb42Sjoerg VisitOMPLoopDirective(D);
3061*13fbcb42Sjoerg }
3062*13fbcb42Sjoerg
VisitOMPDistributeDirective(const OMPDistributeDirective * D)306306f32e7eSjoerg void EnqueueVisitor::VisitOMPDistributeDirective(
306406f32e7eSjoerg const OMPDistributeDirective *D) {
306506f32e7eSjoerg VisitOMPLoopDirective(D);
306606f32e7eSjoerg }
306706f32e7eSjoerg
VisitOMPDistributeParallelForDirective(const OMPDistributeParallelForDirective * D)306806f32e7eSjoerg void EnqueueVisitor::VisitOMPDistributeParallelForDirective(
306906f32e7eSjoerg const OMPDistributeParallelForDirective *D) {
307006f32e7eSjoerg VisitOMPLoopDirective(D);
307106f32e7eSjoerg }
307206f32e7eSjoerg
VisitOMPDistributeParallelForSimdDirective(const OMPDistributeParallelForSimdDirective * D)307306f32e7eSjoerg void EnqueueVisitor::VisitOMPDistributeParallelForSimdDirective(
307406f32e7eSjoerg const OMPDistributeParallelForSimdDirective *D) {
307506f32e7eSjoerg VisitOMPLoopDirective(D);
307606f32e7eSjoerg }
307706f32e7eSjoerg
VisitOMPDistributeSimdDirective(const OMPDistributeSimdDirective * D)307806f32e7eSjoerg void EnqueueVisitor::VisitOMPDistributeSimdDirective(
307906f32e7eSjoerg const OMPDistributeSimdDirective *D) {
308006f32e7eSjoerg VisitOMPLoopDirective(D);
308106f32e7eSjoerg }
308206f32e7eSjoerg
VisitOMPTargetParallelForSimdDirective(const OMPTargetParallelForSimdDirective * D)308306f32e7eSjoerg void EnqueueVisitor::VisitOMPTargetParallelForSimdDirective(
308406f32e7eSjoerg const OMPTargetParallelForSimdDirective *D) {
308506f32e7eSjoerg VisitOMPLoopDirective(D);
308606f32e7eSjoerg }
308706f32e7eSjoerg
VisitOMPTargetSimdDirective(const OMPTargetSimdDirective * D)308806f32e7eSjoerg void EnqueueVisitor::VisitOMPTargetSimdDirective(
308906f32e7eSjoerg const OMPTargetSimdDirective *D) {
309006f32e7eSjoerg VisitOMPLoopDirective(D);
309106f32e7eSjoerg }
309206f32e7eSjoerg
VisitOMPTeamsDistributeDirective(const OMPTeamsDistributeDirective * D)309306f32e7eSjoerg void EnqueueVisitor::VisitOMPTeamsDistributeDirective(
309406f32e7eSjoerg const OMPTeamsDistributeDirective *D) {
309506f32e7eSjoerg VisitOMPLoopDirective(D);
309606f32e7eSjoerg }
309706f32e7eSjoerg
VisitOMPTeamsDistributeSimdDirective(const OMPTeamsDistributeSimdDirective * D)309806f32e7eSjoerg void EnqueueVisitor::VisitOMPTeamsDistributeSimdDirective(
309906f32e7eSjoerg const OMPTeamsDistributeSimdDirective *D) {
310006f32e7eSjoerg VisitOMPLoopDirective(D);
310106f32e7eSjoerg }
310206f32e7eSjoerg
VisitOMPTeamsDistributeParallelForSimdDirective(const OMPTeamsDistributeParallelForSimdDirective * D)310306f32e7eSjoerg void EnqueueVisitor::VisitOMPTeamsDistributeParallelForSimdDirective(
310406f32e7eSjoerg const OMPTeamsDistributeParallelForSimdDirective *D) {
310506f32e7eSjoerg VisitOMPLoopDirective(D);
310606f32e7eSjoerg }
310706f32e7eSjoerg
VisitOMPTeamsDistributeParallelForDirective(const OMPTeamsDistributeParallelForDirective * D)310806f32e7eSjoerg void EnqueueVisitor::VisitOMPTeamsDistributeParallelForDirective(
310906f32e7eSjoerg const OMPTeamsDistributeParallelForDirective *D) {
311006f32e7eSjoerg VisitOMPLoopDirective(D);
311106f32e7eSjoerg }
311206f32e7eSjoerg
VisitOMPTargetTeamsDirective(const OMPTargetTeamsDirective * D)311306f32e7eSjoerg void EnqueueVisitor::VisitOMPTargetTeamsDirective(
311406f32e7eSjoerg const OMPTargetTeamsDirective *D) {
311506f32e7eSjoerg VisitOMPExecutableDirective(D);
311606f32e7eSjoerg }
311706f32e7eSjoerg
VisitOMPTargetTeamsDistributeDirective(const OMPTargetTeamsDistributeDirective * D)311806f32e7eSjoerg void EnqueueVisitor::VisitOMPTargetTeamsDistributeDirective(
311906f32e7eSjoerg const OMPTargetTeamsDistributeDirective *D) {
312006f32e7eSjoerg VisitOMPLoopDirective(D);
312106f32e7eSjoerg }
312206f32e7eSjoerg
VisitOMPTargetTeamsDistributeParallelForDirective(const OMPTargetTeamsDistributeParallelForDirective * D)312306f32e7eSjoerg void EnqueueVisitor::VisitOMPTargetTeamsDistributeParallelForDirective(
312406f32e7eSjoerg const OMPTargetTeamsDistributeParallelForDirective *D) {
312506f32e7eSjoerg VisitOMPLoopDirective(D);
312606f32e7eSjoerg }
312706f32e7eSjoerg
VisitOMPTargetTeamsDistributeParallelForSimdDirective(const OMPTargetTeamsDistributeParallelForSimdDirective * D)312806f32e7eSjoerg void EnqueueVisitor::VisitOMPTargetTeamsDistributeParallelForSimdDirective(
312906f32e7eSjoerg const OMPTargetTeamsDistributeParallelForSimdDirective *D) {
313006f32e7eSjoerg VisitOMPLoopDirective(D);
313106f32e7eSjoerg }
313206f32e7eSjoerg
VisitOMPTargetTeamsDistributeSimdDirective(const OMPTargetTeamsDistributeSimdDirective * D)313306f32e7eSjoerg void EnqueueVisitor::VisitOMPTargetTeamsDistributeSimdDirective(
313406f32e7eSjoerg const OMPTargetTeamsDistributeSimdDirective *D) {
313506f32e7eSjoerg VisitOMPLoopDirective(D);
313606f32e7eSjoerg }
313706f32e7eSjoerg
EnqueueWorkList(VisitorWorkList & WL,const Stmt * S)313806f32e7eSjoerg void CursorVisitor::EnqueueWorkList(VisitorWorkList &WL, const Stmt *S) {
3139*13fbcb42Sjoerg EnqueueVisitor(WL, MakeCXCursor(S, StmtParent, TU, RegionOfInterest))
3140*13fbcb42Sjoerg .Visit(S);
314106f32e7eSjoerg }
314206f32e7eSjoerg
IsInRegionOfInterest(CXCursor C)314306f32e7eSjoerg bool CursorVisitor::IsInRegionOfInterest(CXCursor C) {
314406f32e7eSjoerg if (RegionOfInterest.isValid()) {
314506f32e7eSjoerg SourceRange Range = getRawCursorExtent(C);
314606f32e7eSjoerg if (Range.isInvalid() || CompareRegionOfInterest(Range))
314706f32e7eSjoerg return false;
314806f32e7eSjoerg }
314906f32e7eSjoerg return true;
315006f32e7eSjoerg }
315106f32e7eSjoerg
RunVisitorWorkList(VisitorWorkList & WL)315206f32e7eSjoerg bool CursorVisitor::RunVisitorWorkList(VisitorWorkList &WL) {
315306f32e7eSjoerg while (!WL.empty()) {
315406f32e7eSjoerg // Dequeue the worklist item.
315506f32e7eSjoerg VisitorJob LI = WL.pop_back_val();
315606f32e7eSjoerg
315706f32e7eSjoerg // Set the Parent field, then back to its old value once we're done.
315806f32e7eSjoerg SetParentRAII SetParent(Parent, StmtParent, LI.getParent());
315906f32e7eSjoerg
316006f32e7eSjoerg switch (LI.getKind()) {
316106f32e7eSjoerg case VisitorJob::DeclVisitKind: {
316206f32e7eSjoerg const Decl *D = cast<DeclVisit>(&LI)->get();
316306f32e7eSjoerg if (!D)
316406f32e7eSjoerg continue;
316506f32e7eSjoerg
316606f32e7eSjoerg // For now, perform default visitation for Decls.
316706f32e7eSjoerg if (Visit(MakeCXCursor(D, TU, RegionOfInterest,
316806f32e7eSjoerg cast<DeclVisit>(&LI)->isFirst())))
316906f32e7eSjoerg return true;
317006f32e7eSjoerg
317106f32e7eSjoerg continue;
317206f32e7eSjoerg }
317306f32e7eSjoerg case VisitorJob::ExplicitTemplateArgsVisitKind: {
317406f32e7eSjoerg for (const TemplateArgumentLoc &Arg :
317506f32e7eSjoerg *cast<ExplicitTemplateArgsVisit>(&LI)) {
317606f32e7eSjoerg if (VisitTemplateArgumentLoc(Arg))
317706f32e7eSjoerg return true;
317806f32e7eSjoerg }
317906f32e7eSjoerg continue;
318006f32e7eSjoerg }
318106f32e7eSjoerg case VisitorJob::TypeLocVisitKind: {
318206f32e7eSjoerg // Perform default visitation for TypeLocs.
318306f32e7eSjoerg if (Visit(cast<TypeLocVisit>(&LI)->get()))
318406f32e7eSjoerg return true;
318506f32e7eSjoerg continue;
318606f32e7eSjoerg }
318706f32e7eSjoerg case VisitorJob::LabelRefVisitKind: {
318806f32e7eSjoerg const LabelDecl *LS = cast<LabelRefVisit>(&LI)->get();
318906f32e7eSjoerg if (LabelStmt *stmt = LS->getStmt()) {
319006f32e7eSjoerg if (Visit(MakeCursorLabelRef(stmt, cast<LabelRefVisit>(&LI)->getLoc(),
319106f32e7eSjoerg TU))) {
319206f32e7eSjoerg return true;
319306f32e7eSjoerg }
319406f32e7eSjoerg }
319506f32e7eSjoerg continue;
319606f32e7eSjoerg }
319706f32e7eSjoerg
319806f32e7eSjoerg case VisitorJob::NestedNameSpecifierLocVisitKind: {
319906f32e7eSjoerg NestedNameSpecifierLocVisit *V = cast<NestedNameSpecifierLocVisit>(&LI);
320006f32e7eSjoerg if (VisitNestedNameSpecifierLoc(V->get()))
320106f32e7eSjoerg return true;
320206f32e7eSjoerg continue;
320306f32e7eSjoerg }
320406f32e7eSjoerg
320506f32e7eSjoerg case VisitorJob::DeclarationNameInfoVisitKind: {
3206*13fbcb42Sjoerg if (VisitDeclarationNameInfo(cast<DeclarationNameInfoVisit>(&LI)->get()))
320706f32e7eSjoerg return true;
320806f32e7eSjoerg continue;
320906f32e7eSjoerg }
321006f32e7eSjoerg case VisitorJob::MemberRefVisitKind: {
321106f32e7eSjoerg MemberRefVisit *V = cast<MemberRefVisit>(&LI);
321206f32e7eSjoerg if (Visit(MakeCursorMemberRef(V->get(), V->getLoc(), TU)))
321306f32e7eSjoerg return true;
321406f32e7eSjoerg continue;
321506f32e7eSjoerg }
321606f32e7eSjoerg case VisitorJob::StmtVisitKind: {
321706f32e7eSjoerg const Stmt *S = cast<StmtVisit>(&LI)->get();
321806f32e7eSjoerg if (!S)
321906f32e7eSjoerg continue;
322006f32e7eSjoerg
322106f32e7eSjoerg // Update the current cursor.
322206f32e7eSjoerg CXCursor Cursor = MakeCXCursor(S, StmtParent, TU, RegionOfInterest);
322306f32e7eSjoerg if (!IsInRegionOfInterest(Cursor))
322406f32e7eSjoerg continue;
322506f32e7eSjoerg switch (Visitor(Cursor, Parent, ClientData)) {
3226*13fbcb42Sjoerg case CXChildVisit_Break:
3227*13fbcb42Sjoerg return true;
3228*13fbcb42Sjoerg case CXChildVisit_Continue:
3229*13fbcb42Sjoerg break;
323006f32e7eSjoerg case CXChildVisit_Recurse:
323106f32e7eSjoerg if (PostChildrenVisitor)
323206f32e7eSjoerg WL.push_back(PostChildrenVisit(nullptr, Cursor));
323306f32e7eSjoerg EnqueueWorkList(WL, S);
323406f32e7eSjoerg break;
323506f32e7eSjoerg }
323606f32e7eSjoerg continue;
323706f32e7eSjoerg }
323806f32e7eSjoerg case VisitorJob::MemberExprPartsKind: {
323906f32e7eSjoerg // Handle the other pieces in the MemberExpr besides the base.
324006f32e7eSjoerg const MemberExpr *M = cast<MemberExprParts>(&LI)->get();
324106f32e7eSjoerg
324206f32e7eSjoerg // Visit the nested-name-specifier
324306f32e7eSjoerg if (NestedNameSpecifierLoc QualifierLoc = M->getQualifierLoc())
324406f32e7eSjoerg if (VisitNestedNameSpecifierLoc(QualifierLoc))
324506f32e7eSjoerg return true;
324606f32e7eSjoerg
324706f32e7eSjoerg // Visit the declaration name.
324806f32e7eSjoerg if (VisitDeclarationNameInfo(M->getMemberNameInfo()))
324906f32e7eSjoerg return true;
325006f32e7eSjoerg
325106f32e7eSjoerg // Visit the explicitly-specified template arguments, if any.
325206f32e7eSjoerg if (M->hasExplicitTemplateArgs()) {
325306f32e7eSjoerg for (const TemplateArgumentLoc *Arg = M->getTemplateArgs(),
325406f32e7eSjoerg *ArgEnd = Arg + M->getNumTemplateArgs();
325506f32e7eSjoerg Arg != ArgEnd; ++Arg) {
325606f32e7eSjoerg if (VisitTemplateArgumentLoc(*Arg))
325706f32e7eSjoerg return true;
325806f32e7eSjoerg }
325906f32e7eSjoerg }
326006f32e7eSjoerg continue;
326106f32e7eSjoerg }
326206f32e7eSjoerg case VisitorJob::DeclRefExprPartsKind: {
326306f32e7eSjoerg const DeclRefExpr *DR = cast<DeclRefExprParts>(&LI)->get();
326406f32e7eSjoerg // Visit nested-name-specifier, if present.
326506f32e7eSjoerg if (NestedNameSpecifierLoc QualifierLoc = DR->getQualifierLoc())
326606f32e7eSjoerg if (VisitNestedNameSpecifierLoc(QualifierLoc))
326706f32e7eSjoerg return true;
326806f32e7eSjoerg // Visit declaration name.
326906f32e7eSjoerg if (VisitDeclarationNameInfo(DR->getNameInfo()))
327006f32e7eSjoerg return true;
327106f32e7eSjoerg continue;
327206f32e7eSjoerg }
327306f32e7eSjoerg case VisitorJob::OverloadExprPartsKind: {
327406f32e7eSjoerg const OverloadExpr *O = cast<OverloadExprParts>(&LI)->get();
327506f32e7eSjoerg // Visit the nested-name-specifier.
327606f32e7eSjoerg if (NestedNameSpecifierLoc QualifierLoc = O->getQualifierLoc())
327706f32e7eSjoerg if (VisitNestedNameSpecifierLoc(QualifierLoc))
327806f32e7eSjoerg return true;
327906f32e7eSjoerg // Visit the declaration name.
328006f32e7eSjoerg if (VisitDeclarationNameInfo(O->getNameInfo()))
328106f32e7eSjoerg return true;
328206f32e7eSjoerg // Visit the overloaded declaration reference.
328306f32e7eSjoerg if (Visit(MakeCursorOverloadedDeclRef(O, TU)))
328406f32e7eSjoerg return true;
328506f32e7eSjoerg continue;
328606f32e7eSjoerg }
328706f32e7eSjoerg case VisitorJob::SizeOfPackExprPartsKind: {
328806f32e7eSjoerg const SizeOfPackExpr *E = cast<SizeOfPackExprParts>(&LI)->get();
328906f32e7eSjoerg NamedDecl *Pack = E->getPack();
329006f32e7eSjoerg if (isa<TemplateTypeParmDecl>(Pack)) {
329106f32e7eSjoerg if (Visit(MakeCursorTypeRef(cast<TemplateTypeParmDecl>(Pack),
329206f32e7eSjoerg E->getPackLoc(), TU)))
329306f32e7eSjoerg return true;
329406f32e7eSjoerg
329506f32e7eSjoerg continue;
329606f32e7eSjoerg }
329706f32e7eSjoerg
329806f32e7eSjoerg if (isa<TemplateTemplateParmDecl>(Pack)) {
329906f32e7eSjoerg if (Visit(MakeCursorTemplateRef(cast<TemplateTemplateParmDecl>(Pack),
330006f32e7eSjoerg E->getPackLoc(), TU)))
330106f32e7eSjoerg return true;
330206f32e7eSjoerg
330306f32e7eSjoerg continue;
330406f32e7eSjoerg }
330506f32e7eSjoerg
330606f32e7eSjoerg // Non-type template parameter packs and function parameter packs are
330706f32e7eSjoerg // treated like DeclRefExpr cursors.
330806f32e7eSjoerg continue;
330906f32e7eSjoerg }
331006f32e7eSjoerg
331106f32e7eSjoerg case VisitorJob::LambdaExprPartsKind: {
331206f32e7eSjoerg // Visit non-init captures.
331306f32e7eSjoerg const LambdaExpr *E = cast<LambdaExprParts>(&LI)->get();
331406f32e7eSjoerg for (LambdaExpr::capture_iterator C = E->explicit_capture_begin(),
331506f32e7eSjoerg CEnd = E->explicit_capture_end();
331606f32e7eSjoerg C != CEnd; ++C) {
331706f32e7eSjoerg if (!C->capturesVariable())
331806f32e7eSjoerg continue;
331906f32e7eSjoerg
3320*13fbcb42Sjoerg if (Visit(MakeCursorVariableRef(C->getCapturedVar(), C->getLocation(),
332106f32e7eSjoerg TU)))
332206f32e7eSjoerg return true;
332306f32e7eSjoerg }
332406f32e7eSjoerg // Visit init captures
332506f32e7eSjoerg for (auto InitExpr : E->capture_inits()) {
3326*13fbcb42Sjoerg if (InitExpr && Visit(InitExpr))
332706f32e7eSjoerg return true;
332806f32e7eSjoerg }
332906f32e7eSjoerg
333006f32e7eSjoerg TypeLoc TL = E->getCallOperator()->getTypeSourceInfo()->getTypeLoc();
333106f32e7eSjoerg // Visit parameters and return type, if present.
333206f32e7eSjoerg if (FunctionTypeLoc Proto = TL.getAs<FunctionProtoTypeLoc>()) {
333306f32e7eSjoerg if (E->hasExplicitParameters()) {
333406f32e7eSjoerg // Visit parameters.
333506f32e7eSjoerg for (unsigned I = 0, N = Proto.getNumParams(); I != N; ++I)
333606f32e7eSjoerg if (Visit(MakeCXCursor(Proto.getParam(I), TU)))
333706f32e7eSjoerg return true;
333806f32e7eSjoerg }
333906f32e7eSjoerg if (E->hasExplicitResultType()) {
334006f32e7eSjoerg // Visit result type.
334106f32e7eSjoerg if (Visit(Proto.getReturnLoc()))
334206f32e7eSjoerg return true;
334306f32e7eSjoerg }
334406f32e7eSjoerg }
334506f32e7eSjoerg break;
334606f32e7eSjoerg }
334706f32e7eSjoerg
334806f32e7eSjoerg case VisitorJob::PostChildrenVisitKind:
334906f32e7eSjoerg if (PostChildrenVisitor(Parent, ClientData))
335006f32e7eSjoerg return true;
335106f32e7eSjoerg break;
335206f32e7eSjoerg }
335306f32e7eSjoerg }
335406f32e7eSjoerg return false;
335506f32e7eSjoerg }
335606f32e7eSjoerg
Visit(const Stmt * S)335706f32e7eSjoerg bool CursorVisitor::Visit(const Stmt *S) {
335806f32e7eSjoerg VisitorWorkList *WL = nullptr;
335906f32e7eSjoerg if (!WorkListFreeList.empty()) {
336006f32e7eSjoerg WL = WorkListFreeList.back();
336106f32e7eSjoerg WL->clear();
336206f32e7eSjoerg WorkListFreeList.pop_back();
3363*13fbcb42Sjoerg } else {
336406f32e7eSjoerg WL = new VisitorWorkList();
336506f32e7eSjoerg WorkListCache.push_back(WL);
336606f32e7eSjoerg }
336706f32e7eSjoerg EnqueueWorkList(*WL, S);
336806f32e7eSjoerg bool result = RunVisitorWorkList(*WL);
336906f32e7eSjoerg WorkListFreeList.push_back(WL);
337006f32e7eSjoerg return result;
337106f32e7eSjoerg }
337206f32e7eSjoerg
337306f32e7eSjoerg namespace {
337406f32e7eSjoerg typedef SmallVector<SourceRange, 4> RefNamePieces;
buildPieces(unsigned NameFlags,bool IsMemberRefExpr,const DeclarationNameInfo & NI,SourceRange QLoc,const SourceRange * TemplateArgsLoc=nullptr)337506f32e7eSjoerg RefNamePieces buildPieces(unsigned NameFlags, bool IsMemberRefExpr,
337606f32e7eSjoerg const DeclarationNameInfo &NI, SourceRange QLoc,
337706f32e7eSjoerg const SourceRange *TemplateArgsLoc = nullptr) {
337806f32e7eSjoerg const bool WantQualifier = NameFlags & CXNameRange_WantQualifier;
337906f32e7eSjoerg const bool WantTemplateArgs = NameFlags & CXNameRange_WantTemplateArgs;
338006f32e7eSjoerg const bool WantSinglePiece = NameFlags & CXNameRange_WantSinglePiece;
338106f32e7eSjoerg
338206f32e7eSjoerg const DeclarationName::NameKind Kind = NI.getName().getNameKind();
338306f32e7eSjoerg
338406f32e7eSjoerg RefNamePieces Pieces;
338506f32e7eSjoerg
338606f32e7eSjoerg if (WantQualifier && QLoc.isValid())
338706f32e7eSjoerg Pieces.push_back(QLoc);
338806f32e7eSjoerg
338906f32e7eSjoerg if (Kind != DeclarationName::CXXOperatorName || IsMemberRefExpr)
339006f32e7eSjoerg Pieces.push_back(NI.getLoc());
339106f32e7eSjoerg
339206f32e7eSjoerg if (WantTemplateArgs && TemplateArgsLoc && TemplateArgsLoc->isValid())
339306f32e7eSjoerg Pieces.push_back(*TemplateArgsLoc);
339406f32e7eSjoerg
339506f32e7eSjoerg if (Kind == DeclarationName::CXXOperatorName) {
3396*13fbcb42Sjoerg Pieces.push_back(NI.getInfo().getCXXOperatorNameBeginLoc());
3397*13fbcb42Sjoerg Pieces.push_back(NI.getInfo().getCXXOperatorNameEndLoc());
339806f32e7eSjoerg }
339906f32e7eSjoerg
340006f32e7eSjoerg if (WantSinglePiece) {
340106f32e7eSjoerg SourceRange R(Pieces.front().getBegin(), Pieces.back().getEnd());
340206f32e7eSjoerg Pieces.clear();
340306f32e7eSjoerg Pieces.push_back(R);
340406f32e7eSjoerg }
340506f32e7eSjoerg
340606f32e7eSjoerg return Pieces;
340706f32e7eSjoerg }
3408*13fbcb42Sjoerg } // namespace
340906f32e7eSjoerg
341006f32e7eSjoerg //===----------------------------------------------------------------------===//
341106f32e7eSjoerg // Misc. API hooks.
341206f32e7eSjoerg //===----------------------------------------------------------------------===//
341306f32e7eSjoerg
341406f32e7eSjoerg namespace {
341506f32e7eSjoerg struct RegisterFatalErrorHandler {
RegisterFatalErrorHandler__anondcfcb7bb0511::RegisterFatalErrorHandler341606f32e7eSjoerg RegisterFatalErrorHandler() {
341706f32e7eSjoerg clang_install_aborting_llvm_fatal_error_handler();
341806f32e7eSjoerg }
341906f32e7eSjoerg };
3420*13fbcb42Sjoerg } // namespace
342106f32e7eSjoerg
3422*13fbcb42Sjoerg static llvm::ManagedStatic<RegisterFatalErrorHandler>
3423*13fbcb42Sjoerg RegisterFatalErrorHandlerOnce;
342406f32e7eSjoerg
clang_createIndex(int excludeDeclarationsFromPCH,int displayDiagnostics)342506f32e7eSjoerg CXIndex clang_createIndex(int excludeDeclarationsFromPCH,
342606f32e7eSjoerg int displayDiagnostics) {
342706f32e7eSjoerg // We use crash recovery to make some of our APIs more reliable, implicitly
342806f32e7eSjoerg // enable it.
342906f32e7eSjoerg if (!getenv("LIBCLANG_DISABLE_CRASH_RECOVERY"))
343006f32e7eSjoerg llvm::CrashRecoveryContext::Enable();
343106f32e7eSjoerg
343206f32e7eSjoerg // Look through the managed static to trigger construction of the managed
343306f32e7eSjoerg // static which registers our fatal error handler. This ensures it is only
343406f32e7eSjoerg // registered once.
343506f32e7eSjoerg (void)*RegisterFatalErrorHandlerOnce;
343606f32e7eSjoerg
343706f32e7eSjoerg // Initialize targets for clang module support.
343806f32e7eSjoerg llvm::InitializeAllTargets();
343906f32e7eSjoerg llvm::InitializeAllTargetMCs();
344006f32e7eSjoerg llvm::InitializeAllAsmPrinters();
344106f32e7eSjoerg llvm::InitializeAllAsmParsers();
344206f32e7eSjoerg
344306f32e7eSjoerg CIndexer *CIdxr = new CIndexer();
344406f32e7eSjoerg
344506f32e7eSjoerg if (excludeDeclarationsFromPCH)
344606f32e7eSjoerg CIdxr->setOnlyLocalDecls();
344706f32e7eSjoerg if (displayDiagnostics)
344806f32e7eSjoerg CIdxr->setDisplayDiagnostics();
344906f32e7eSjoerg
345006f32e7eSjoerg if (getenv("LIBCLANG_BGPRIO_INDEX"))
345106f32e7eSjoerg CIdxr->setCXGlobalOptFlags(CIdxr->getCXGlobalOptFlags() |
345206f32e7eSjoerg CXGlobalOpt_ThreadBackgroundPriorityForIndexing);
345306f32e7eSjoerg if (getenv("LIBCLANG_BGPRIO_EDIT"))
345406f32e7eSjoerg CIdxr->setCXGlobalOptFlags(CIdxr->getCXGlobalOptFlags() |
345506f32e7eSjoerg CXGlobalOpt_ThreadBackgroundPriorityForEditing);
345606f32e7eSjoerg
345706f32e7eSjoerg return CIdxr;
345806f32e7eSjoerg }
345906f32e7eSjoerg
clang_disposeIndex(CXIndex CIdx)346006f32e7eSjoerg void clang_disposeIndex(CXIndex CIdx) {
346106f32e7eSjoerg if (CIdx)
346206f32e7eSjoerg delete static_cast<CIndexer *>(CIdx);
346306f32e7eSjoerg }
346406f32e7eSjoerg
clang_CXIndex_setGlobalOptions(CXIndex CIdx,unsigned options)346506f32e7eSjoerg void clang_CXIndex_setGlobalOptions(CXIndex CIdx, unsigned options) {
346606f32e7eSjoerg if (CIdx)
346706f32e7eSjoerg static_cast<CIndexer *>(CIdx)->setCXGlobalOptFlags(options);
346806f32e7eSjoerg }
346906f32e7eSjoerg
clang_CXIndex_getGlobalOptions(CXIndex CIdx)347006f32e7eSjoerg unsigned clang_CXIndex_getGlobalOptions(CXIndex CIdx) {
347106f32e7eSjoerg if (CIdx)
347206f32e7eSjoerg return static_cast<CIndexer *>(CIdx)->getCXGlobalOptFlags();
347306f32e7eSjoerg return 0;
347406f32e7eSjoerg }
347506f32e7eSjoerg
clang_CXIndex_setInvocationEmissionPathOption(CXIndex CIdx,const char * Path)347606f32e7eSjoerg void clang_CXIndex_setInvocationEmissionPathOption(CXIndex CIdx,
347706f32e7eSjoerg const char *Path) {
347806f32e7eSjoerg if (CIdx)
347906f32e7eSjoerg static_cast<CIndexer *>(CIdx)->setInvocationEmissionPath(Path ? Path : "");
348006f32e7eSjoerg }
348106f32e7eSjoerg
clang_toggleCrashRecovery(unsigned isEnabled)348206f32e7eSjoerg void clang_toggleCrashRecovery(unsigned isEnabled) {
348306f32e7eSjoerg if (isEnabled)
348406f32e7eSjoerg llvm::CrashRecoveryContext::Enable();
348506f32e7eSjoerg else
348606f32e7eSjoerg llvm::CrashRecoveryContext::Disable();
348706f32e7eSjoerg }
348806f32e7eSjoerg
clang_createTranslationUnit(CXIndex CIdx,const char * ast_filename)348906f32e7eSjoerg CXTranslationUnit clang_createTranslationUnit(CXIndex CIdx,
349006f32e7eSjoerg const char *ast_filename) {
349106f32e7eSjoerg CXTranslationUnit TU;
349206f32e7eSjoerg enum CXErrorCode Result =
349306f32e7eSjoerg clang_createTranslationUnit2(CIdx, ast_filename, &TU);
349406f32e7eSjoerg (void)Result;
349506f32e7eSjoerg assert((TU && Result == CXError_Success) ||
349606f32e7eSjoerg (!TU && Result != CXError_Success));
349706f32e7eSjoerg return TU;
349806f32e7eSjoerg }
349906f32e7eSjoerg
clang_createTranslationUnit2(CXIndex CIdx,const char * ast_filename,CXTranslationUnit * out_TU)350006f32e7eSjoerg enum CXErrorCode clang_createTranslationUnit2(CXIndex CIdx,
350106f32e7eSjoerg const char *ast_filename,
350206f32e7eSjoerg CXTranslationUnit *out_TU) {
350306f32e7eSjoerg if (out_TU)
350406f32e7eSjoerg *out_TU = nullptr;
350506f32e7eSjoerg
350606f32e7eSjoerg if (!CIdx || !ast_filename || !out_TU)
350706f32e7eSjoerg return CXError_InvalidArguments;
350806f32e7eSjoerg
3509*13fbcb42Sjoerg LOG_FUNC_SECTION { *Log << ast_filename; }
351006f32e7eSjoerg
351106f32e7eSjoerg CIndexer *CXXIdx = static_cast<CIndexer *>(CIdx);
351206f32e7eSjoerg FileSystemOptions FileSystemOpts;
351306f32e7eSjoerg
351406f32e7eSjoerg IntrusiveRefCntPtr<DiagnosticsEngine> Diags =
351506f32e7eSjoerg CompilerInstance::createDiagnostics(new DiagnosticOptions());
351606f32e7eSjoerg std::unique_ptr<ASTUnit> AU = ASTUnit::LoadFromASTFile(
351706f32e7eSjoerg ast_filename, CXXIdx->getPCHContainerOperations()->getRawReader(),
3518*13fbcb42Sjoerg ASTUnit::LoadEverything, Diags, FileSystemOpts, /*UseDebugInfo=*/false,
3519*13fbcb42Sjoerg CXXIdx->getOnlyLocalDecls(), CaptureDiagsKind::All,
3520*13fbcb42Sjoerg /*AllowASTWithCompilerErrors=*/true,
352106f32e7eSjoerg /*UserFilesAreVolatile=*/true);
352206f32e7eSjoerg *out_TU = MakeCXTranslationUnit(CXXIdx, std::move(AU));
352306f32e7eSjoerg return *out_TU ? CXError_Success : CXError_Failure;
352406f32e7eSjoerg }
352506f32e7eSjoerg
clang_defaultEditingTranslationUnitOptions()352606f32e7eSjoerg unsigned clang_defaultEditingTranslationUnitOptions() {
352706f32e7eSjoerg return CXTranslationUnit_PrecompiledPreamble |
352806f32e7eSjoerg CXTranslationUnit_CacheCompletionResults;
352906f32e7eSjoerg }
353006f32e7eSjoerg
clang_createTranslationUnitFromSourceFile(CXIndex CIdx,const char * source_filename,int num_command_line_args,const char * const * command_line_args,unsigned num_unsaved_files,struct CXUnsavedFile * unsaved_files)3531*13fbcb42Sjoerg CXTranslationUnit clang_createTranslationUnitFromSourceFile(
3532*13fbcb42Sjoerg CXIndex CIdx, const char *source_filename, int num_command_line_args,
3533*13fbcb42Sjoerg const char *const *command_line_args, unsigned num_unsaved_files,
353406f32e7eSjoerg struct CXUnsavedFile *unsaved_files) {
353506f32e7eSjoerg unsigned Options = CXTranslationUnit_DetailedPreprocessingRecord;
3536*13fbcb42Sjoerg return clang_parseTranslationUnit(CIdx, source_filename, command_line_args,
3537*13fbcb42Sjoerg num_command_line_args, unsaved_files,
3538*13fbcb42Sjoerg num_unsaved_files, Options);
353906f32e7eSjoerg }
354006f32e7eSjoerg
354106f32e7eSjoerg static CXErrorCode
clang_parseTranslationUnit_Impl(CXIndex CIdx,const char * source_filename,const char * const * command_line_args,int num_command_line_args,ArrayRef<CXUnsavedFile> unsaved_files,unsigned options,CXTranslationUnit * out_TU)354206f32e7eSjoerg clang_parseTranslationUnit_Impl(CXIndex CIdx, const char *source_filename,
354306f32e7eSjoerg const char *const *command_line_args,
354406f32e7eSjoerg int num_command_line_args,
354506f32e7eSjoerg ArrayRef<CXUnsavedFile> unsaved_files,
354606f32e7eSjoerg unsigned options, CXTranslationUnit *out_TU) {
354706f32e7eSjoerg // Set up the initial return values.
354806f32e7eSjoerg if (out_TU)
354906f32e7eSjoerg *out_TU = nullptr;
355006f32e7eSjoerg
355106f32e7eSjoerg // Check arguments.
355206f32e7eSjoerg if (!CIdx || !out_TU)
355306f32e7eSjoerg return CXError_InvalidArguments;
355406f32e7eSjoerg
355506f32e7eSjoerg CIndexer *CXXIdx = static_cast<CIndexer *>(CIdx);
355606f32e7eSjoerg
355706f32e7eSjoerg if (CXXIdx->isOptEnabled(CXGlobalOpt_ThreadBackgroundPriorityForIndexing))
355806f32e7eSjoerg setThreadBackgroundPriority();
355906f32e7eSjoerg
356006f32e7eSjoerg bool PrecompilePreamble = options & CXTranslationUnit_PrecompiledPreamble;
356106f32e7eSjoerg bool CreatePreambleOnFirstParse =
356206f32e7eSjoerg options & CXTranslationUnit_CreatePreambleOnFirstParse;
356306f32e7eSjoerg // FIXME: Add a flag for modules.
3564*13fbcb42Sjoerg TranslationUnitKind TUKind = (options & (CXTranslationUnit_Incomplete |
3565*13fbcb42Sjoerg CXTranslationUnit_SingleFileParse))
3566*13fbcb42Sjoerg ? TU_Prefix
3567*13fbcb42Sjoerg : TU_Complete;
3568*13fbcb42Sjoerg bool CacheCodeCompletionResults =
3569*13fbcb42Sjoerg options & CXTranslationUnit_CacheCompletionResults;
3570*13fbcb42Sjoerg bool IncludeBriefCommentsInCodeCompletion =
3571*13fbcb42Sjoerg options & CXTranslationUnit_IncludeBriefCommentsInCodeCompletion;
357206f32e7eSjoerg bool SingleFileParse = options & CXTranslationUnit_SingleFileParse;
357306f32e7eSjoerg bool ForSerialization = options & CXTranslationUnit_ForSerialization;
3574*13fbcb42Sjoerg bool RetainExcludedCB =
3575*13fbcb42Sjoerg options & CXTranslationUnit_RetainExcludedConditionalBlocks;
357606f32e7eSjoerg SkipFunctionBodiesScope SkipFunctionBodies = SkipFunctionBodiesScope::None;
357706f32e7eSjoerg if (options & CXTranslationUnit_SkipFunctionBodies) {
357806f32e7eSjoerg SkipFunctionBodies =
357906f32e7eSjoerg (options & CXTranslationUnit_LimitSkipFunctionBodiesToPreamble)
358006f32e7eSjoerg ? SkipFunctionBodiesScope::Preamble
358106f32e7eSjoerg : SkipFunctionBodiesScope::PreambleAndMainFile;
358206f32e7eSjoerg }
358306f32e7eSjoerg
358406f32e7eSjoerg // Configure the diagnostics.
3585*13fbcb42Sjoerg IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
3586*13fbcb42Sjoerg CompilerInstance::createDiagnostics(new DiagnosticOptions));
358706f32e7eSjoerg
358806f32e7eSjoerg if (options & CXTranslationUnit_KeepGoing)
358906f32e7eSjoerg Diags->setFatalsAsError(true);
359006f32e7eSjoerg
359106f32e7eSjoerg CaptureDiagsKind CaptureDiagnostics = CaptureDiagsKind::All;
359206f32e7eSjoerg if (options & CXTranslationUnit_IgnoreNonErrorsFromIncludedFiles)
359306f32e7eSjoerg CaptureDiagnostics = CaptureDiagsKind::AllWithoutNonErrorsFromIncludes;
359406f32e7eSjoerg
359506f32e7eSjoerg // Recover resources if we crash before exiting this function.
3596*13fbcb42Sjoerg llvm::CrashRecoveryContextCleanupRegistrar<
3597*13fbcb42Sjoerg DiagnosticsEngine,
359806f32e7eSjoerg llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine>>
359906f32e7eSjoerg DiagCleanup(Diags.get());
360006f32e7eSjoerg
360106f32e7eSjoerg std::unique_ptr<std::vector<ASTUnit::RemappedFile>> RemappedFiles(
360206f32e7eSjoerg new std::vector<ASTUnit::RemappedFile>());
360306f32e7eSjoerg
360406f32e7eSjoerg // Recover resources if we crash before exiting this function.
3605*13fbcb42Sjoerg llvm::CrashRecoveryContextCleanupRegistrar<std::vector<ASTUnit::RemappedFile>>
3606*13fbcb42Sjoerg RemappedCleanup(RemappedFiles.get());
360706f32e7eSjoerg
360806f32e7eSjoerg for (auto &UF : unsaved_files) {
360906f32e7eSjoerg std::unique_ptr<llvm::MemoryBuffer> MB =
361006f32e7eSjoerg llvm::MemoryBuffer::getMemBufferCopy(getContents(UF), UF.Filename);
361106f32e7eSjoerg RemappedFiles->push_back(std::make_pair(UF.Filename, MB.release()));
361206f32e7eSjoerg }
361306f32e7eSjoerg
361406f32e7eSjoerg std::unique_ptr<std::vector<const char *>> Args(
361506f32e7eSjoerg new std::vector<const char *>());
361606f32e7eSjoerg
361706f32e7eSjoerg // Recover resources if we crash before exiting this method.
361806f32e7eSjoerg llvm::CrashRecoveryContextCleanupRegistrar<std::vector<const char *>>
361906f32e7eSjoerg ArgsCleanup(Args.get());
362006f32e7eSjoerg
362106f32e7eSjoerg // Since the Clang C library is primarily used by batch tools dealing with
362206f32e7eSjoerg // (often very broken) source code, where spell-checking can have a
362306f32e7eSjoerg // significant negative impact on performance (particularly when
362406f32e7eSjoerg // precompiled headers are involved), we disable it by default.
362506f32e7eSjoerg // Only do this if we haven't found a spell-checking-related argument.
362606f32e7eSjoerg bool FoundSpellCheckingArgument = false;
362706f32e7eSjoerg for (int I = 0; I != num_command_line_args; ++I) {
362806f32e7eSjoerg if (strcmp(command_line_args[I], "-fno-spell-checking") == 0 ||
362906f32e7eSjoerg strcmp(command_line_args[I], "-fspell-checking") == 0) {
363006f32e7eSjoerg FoundSpellCheckingArgument = true;
363106f32e7eSjoerg break;
363206f32e7eSjoerg }
363306f32e7eSjoerg }
363406f32e7eSjoerg Args->insert(Args->end(), command_line_args,
363506f32e7eSjoerg command_line_args + num_command_line_args);
363606f32e7eSjoerg
363706f32e7eSjoerg if (!FoundSpellCheckingArgument)
363806f32e7eSjoerg Args->insert(Args->begin() + 1, "-fno-spell-checking");
363906f32e7eSjoerg
364006f32e7eSjoerg // The 'source_filename' argument is optional. If the caller does not
364106f32e7eSjoerg // specify it then it is assumed that the source file is specified
364206f32e7eSjoerg // in the actual argument list.
364306f32e7eSjoerg // Put the source file after command_line_args otherwise if '-x' flag is
364406f32e7eSjoerg // present it will be unused.
364506f32e7eSjoerg if (source_filename)
364606f32e7eSjoerg Args->push_back(source_filename);
364706f32e7eSjoerg
364806f32e7eSjoerg // Do we need the detailed preprocessing record?
364906f32e7eSjoerg if (options & CXTranslationUnit_DetailedPreprocessingRecord) {
365006f32e7eSjoerg Args->push_back("-Xclang");
365106f32e7eSjoerg Args->push_back("-detailed-preprocessing-record");
365206f32e7eSjoerg }
365306f32e7eSjoerg
365406f32e7eSjoerg // Suppress any editor placeholder diagnostics.
365506f32e7eSjoerg Args->push_back("-fallow-editor-placeholders");
365606f32e7eSjoerg
365706f32e7eSjoerg unsigned NumErrors = Diags->getClient()->getNumErrors();
365806f32e7eSjoerg std::unique_ptr<ASTUnit> ErrUnit;
365906f32e7eSjoerg // Unless the user specified that they want the preamble on the first parse
366006f32e7eSjoerg // set it up to be created on the first reparse. This makes the first parse
366106f32e7eSjoerg // faster, trading for a slower (first) reparse.
366206f32e7eSjoerg unsigned PrecompilePreambleAfterNParses =
366306f32e7eSjoerg !PrecompilePreamble ? 0 : 2 - CreatePreambleOnFirstParse;
366406f32e7eSjoerg
366506f32e7eSjoerg LibclangInvocationReporter InvocationReporter(
366606f32e7eSjoerg *CXXIdx, LibclangInvocationReporter::OperationKind::ParseOperation,
366706f32e7eSjoerg options, llvm::makeArrayRef(*Args), /*InvocationArgs=*/None,
366806f32e7eSjoerg unsaved_files);
366906f32e7eSjoerg std::unique_ptr<ASTUnit> Unit(ASTUnit::LoadFromCommandLine(
367006f32e7eSjoerg Args->data(), Args->data() + Args->size(),
367106f32e7eSjoerg CXXIdx->getPCHContainerOperations(), Diags,
367206f32e7eSjoerg CXXIdx->getClangResourcesPath(), CXXIdx->getOnlyLocalDecls(),
367306f32e7eSjoerg CaptureDiagnostics, *RemappedFiles.get(),
367406f32e7eSjoerg /*RemappedFilesKeepOriginalName=*/true, PrecompilePreambleAfterNParses,
367506f32e7eSjoerg TUKind, CacheCodeCompletionResults, IncludeBriefCommentsInCodeCompletion,
367606f32e7eSjoerg /*AllowPCHWithCompilerErrors=*/true, SkipFunctionBodies, SingleFileParse,
367706f32e7eSjoerg /*UserFilesAreVolatile=*/true, ForSerialization, RetainExcludedCB,
367806f32e7eSjoerg CXXIdx->getPCHContainerOperations()->getRawReader().getFormat(),
367906f32e7eSjoerg &ErrUnit));
368006f32e7eSjoerg
368106f32e7eSjoerg // Early failures in LoadFromCommandLine may return with ErrUnit unset.
368206f32e7eSjoerg if (!Unit && !ErrUnit)
368306f32e7eSjoerg return CXError_ASTReadError;
368406f32e7eSjoerg
368506f32e7eSjoerg if (NumErrors != Diags->getClient()->getNumErrors()) {
368606f32e7eSjoerg // Make sure to check that 'Unit' is non-NULL.
368706f32e7eSjoerg if (CXXIdx->getDisplayDiagnostics())
368806f32e7eSjoerg printDiagsToStderr(Unit ? Unit.get() : ErrUnit.get());
368906f32e7eSjoerg }
369006f32e7eSjoerg
369106f32e7eSjoerg if (isASTReadError(Unit ? Unit.get() : ErrUnit.get()))
369206f32e7eSjoerg return CXError_ASTReadError;
369306f32e7eSjoerg
369406f32e7eSjoerg *out_TU = MakeCXTranslationUnit(CXXIdx, std::move(Unit));
369506f32e7eSjoerg if (CXTranslationUnitImpl *TU = *out_TU) {
369606f32e7eSjoerg TU->ParsingOptions = options;
369706f32e7eSjoerg TU->Arguments.reserve(Args->size());
369806f32e7eSjoerg for (const char *Arg : *Args)
369906f32e7eSjoerg TU->Arguments.push_back(Arg);
370006f32e7eSjoerg return CXError_Success;
370106f32e7eSjoerg }
370206f32e7eSjoerg return CXError_Failure;
370306f32e7eSjoerg }
370406f32e7eSjoerg
370506f32e7eSjoerg CXTranslationUnit
clang_parseTranslationUnit(CXIndex CIdx,const char * source_filename,const char * const * command_line_args,int num_command_line_args,struct CXUnsavedFile * unsaved_files,unsigned num_unsaved_files,unsigned options)3706*13fbcb42Sjoerg clang_parseTranslationUnit(CXIndex CIdx, const char *source_filename,
370706f32e7eSjoerg const char *const *command_line_args,
370806f32e7eSjoerg int num_command_line_args,
370906f32e7eSjoerg struct CXUnsavedFile *unsaved_files,
3710*13fbcb42Sjoerg unsigned num_unsaved_files, unsigned options) {
371106f32e7eSjoerg CXTranslationUnit TU;
371206f32e7eSjoerg enum CXErrorCode Result = clang_parseTranslationUnit2(
371306f32e7eSjoerg CIdx, source_filename, command_line_args, num_command_line_args,
371406f32e7eSjoerg unsaved_files, num_unsaved_files, options, &TU);
371506f32e7eSjoerg (void)Result;
371606f32e7eSjoerg assert((TU && Result == CXError_Success) ||
371706f32e7eSjoerg (!TU && Result != CXError_Success));
371806f32e7eSjoerg return TU;
371906f32e7eSjoerg }
372006f32e7eSjoerg
clang_parseTranslationUnit2(CXIndex CIdx,const char * source_filename,const char * const * command_line_args,int num_command_line_args,struct CXUnsavedFile * unsaved_files,unsigned num_unsaved_files,unsigned options,CXTranslationUnit * out_TU)372106f32e7eSjoerg enum CXErrorCode clang_parseTranslationUnit2(
372206f32e7eSjoerg CXIndex CIdx, const char *source_filename,
372306f32e7eSjoerg const char *const *command_line_args, int num_command_line_args,
372406f32e7eSjoerg struct CXUnsavedFile *unsaved_files, unsigned num_unsaved_files,
372506f32e7eSjoerg unsigned options, CXTranslationUnit *out_TU) {
3726*13fbcb42Sjoerg noteBottomOfStack();
372706f32e7eSjoerg SmallVector<const char *, 4> Args;
372806f32e7eSjoerg Args.push_back("clang");
372906f32e7eSjoerg Args.append(command_line_args, command_line_args + num_command_line_args);
373006f32e7eSjoerg return clang_parseTranslationUnit2FullArgv(
373106f32e7eSjoerg CIdx, source_filename, Args.data(), Args.size(), unsaved_files,
373206f32e7eSjoerg num_unsaved_files, options, out_TU);
373306f32e7eSjoerg }
373406f32e7eSjoerg
clang_parseTranslationUnit2FullArgv(CXIndex CIdx,const char * source_filename,const char * const * command_line_args,int num_command_line_args,struct CXUnsavedFile * unsaved_files,unsigned num_unsaved_files,unsigned options,CXTranslationUnit * out_TU)373506f32e7eSjoerg enum CXErrorCode clang_parseTranslationUnit2FullArgv(
373606f32e7eSjoerg CXIndex CIdx, const char *source_filename,
373706f32e7eSjoerg const char *const *command_line_args, int num_command_line_args,
373806f32e7eSjoerg struct CXUnsavedFile *unsaved_files, unsigned num_unsaved_files,
373906f32e7eSjoerg unsigned options, CXTranslationUnit *out_TU) {
374006f32e7eSjoerg LOG_FUNC_SECTION {
374106f32e7eSjoerg *Log << source_filename << ": ";
374206f32e7eSjoerg for (int i = 0; i != num_command_line_args; ++i)
374306f32e7eSjoerg *Log << command_line_args[i] << " ";
374406f32e7eSjoerg }
374506f32e7eSjoerg
374606f32e7eSjoerg if (num_unsaved_files && !unsaved_files)
374706f32e7eSjoerg return CXError_InvalidArguments;
374806f32e7eSjoerg
374906f32e7eSjoerg CXErrorCode result = CXError_Failure;
375006f32e7eSjoerg auto ParseTranslationUnitImpl = [=, &result] {
3751*13fbcb42Sjoerg noteBottomOfStack();
375206f32e7eSjoerg result = clang_parseTranslationUnit_Impl(
375306f32e7eSjoerg CIdx, source_filename, command_line_args, num_command_line_args,
375406f32e7eSjoerg llvm::makeArrayRef(unsaved_files, num_unsaved_files), options, out_TU);
375506f32e7eSjoerg };
375606f32e7eSjoerg
375706f32e7eSjoerg llvm::CrashRecoveryContext CRC;
375806f32e7eSjoerg
375906f32e7eSjoerg if (!RunSafely(CRC, ParseTranslationUnitImpl)) {
376006f32e7eSjoerg fprintf(stderr, "libclang: crash detected during parsing: {\n");
376106f32e7eSjoerg fprintf(stderr, " 'source_filename' : '%s'\n", source_filename);
376206f32e7eSjoerg fprintf(stderr, " 'command_line_args' : [");
376306f32e7eSjoerg for (int i = 0; i != num_command_line_args; ++i) {
376406f32e7eSjoerg if (i)
376506f32e7eSjoerg fprintf(stderr, ", ");
376606f32e7eSjoerg fprintf(stderr, "'%s'", command_line_args[i]);
376706f32e7eSjoerg }
376806f32e7eSjoerg fprintf(stderr, "],\n");
376906f32e7eSjoerg fprintf(stderr, " 'unsaved_files' : [");
377006f32e7eSjoerg for (unsigned i = 0; i != num_unsaved_files; ++i) {
377106f32e7eSjoerg if (i)
377206f32e7eSjoerg fprintf(stderr, ", ");
377306f32e7eSjoerg fprintf(stderr, "('%s', '...', %ld)", unsaved_files[i].Filename,
377406f32e7eSjoerg unsaved_files[i].Length);
377506f32e7eSjoerg }
377606f32e7eSjoerg fprintf(stderr, "],\n");
377706f32e7eSjoerg fprintf(stderr, " 'options' : %d,\n", options);
377806f32e7eSjoerg fprintf(stderr, "}\n");
377906f32e7eSjoerg
378006f32e7eSjoerg return CXError_Crashed;
378106f32e7eSjoerg } else if (getenv("LIBCLANG_RESOURCE_USAGE")) {
378206f32e7eSjoerg if (CXTranslationUnit *TU = out_TU)
378306f32e7eSjoerg PrintLibclangResourceUsage(*TU);
378406f32e7eSjoerg }
378506f32e7eSjoerg
378606f32e7eSjoerg return result;
378706f32e7eSjoerg }
378806f32e7eSjoerg
clang_Type_getObjCEncoding(CXType CT)378906f32e7eSjoerg CXString clang_Type_getObjCEncoding(CXType CT) {
379006f32e7eSjoerg CXTranslationUnit tu = static_cast<CXTranslationUnit>(CT.data[1]);
379106f32e7eSjoerg ASTContext &Ctx = getASTUnit(tu)->getASTContext();
379206f32e7eSjoerg std::string encoding;
3793*13fbcb42Sjoerg Ctx.getObjCEncodingForType(QualType::getFromOpaquePtr(CT.data[0]), encoding);
379406f32e7eSjoerg
379506f32e7eSjoerg return cxstring::createDup(encoding);
379606f32e7eSjoerg }
379706f32e7eSjoerg
getMacroIdentifier(CXCursor C)379806f32e7eSjoerg static const IdentifierInfo *getMacroIdentifier(CXCursor C) {
379906f32e7eSjoerg if (C.kind == CXCursor_MacroDefinition) {
380006f32e7eSjoerg if (const MacroDefinitionRecord *MDR = getCursorMacroDefinition(C))
380106f32e7eSjoerg return MDR->getName();
380206f32e7eSjoerg } else if (C.kind == CXCursor_MacroExpansion) {
380306f32e7eSjoerg MacroExpansionCursor ME = getCursorMacroExpansion(C);
380406f32e7eSjoerg return ME.getName();
380506f32e7eSjoerg }
380606f32e7eSjoerg return nullptr;
380706f32e7eSjoerg }
380806f32e7eSjoerg
clang_Cursor_isMacroFunctionLike(CXCursor C)380906f32e7eSjoerg unsigned clang_Cursor_isMacroFunctionLike(CXCursor C) {
381006f32e7eSjoerg const IdentifierInfo *II = getMacroIdentifier(C);
381106f32e7eSjoerg if (!II) {
381206f32e7eSjoerg return false;
381306f32e7eSjoerg }
381406f32e7eSjoerg ASTUnit *ASTU = getCursorASTUnit(C);
381506f32e7eSjoerg Preprocessor &PP = ASTU->getPreprocessor();
381606f32e7eSjoerg if (const MacroInfo *MI = PP.getMacroInfo(II))
381706f32e7eSjoerg return MI->isFunctionLike();
381806f32e7eSjoerg return false;
381906f32e7eSjoerg }
382006f32e7eSjoerg
clang_Cursor_isMacroBuiltin(CXCursor C)382106f32e7eSjoerg unsigned clang_Cursor_isMacroBuiltin(CXCursor C) {
382206f32e7eSjoerg const IdentifierInfo *II = getMacroIdentifier(C);
382306f32e7eSjoerg if (!II) {
382406f32e7eSjoerg return false;
382506f32e7eSjoerg }
382606f32e7eSjoerg ASTUnit *ASTU = getCursorASTUnit(C);
382706f32e7eSjoerg Preprocessor &PP = ASTU->getPreprocessor();
382806f32e7eSjoerg if (const MacroInfo *MI = PP.getMacroInfo(II))
382906f32e7eSjoerg return MI->isBuiltinMacro();
383006f32e7eSjoerg return false;
383106f32e7eSjoerg }
383206f32e7eSjoerg
clang_Cursor_isFunctionInlined(CXCursor C)383306f32e7eSjoerg unsigned clang_Cursor_isFunctionInlined(CXCursor C) {
383406f32e7eSjoerg const Decl *D = getCursorDecl(C);
383506f32e7eSjoerg const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D);
383606f32e7eSjoerg if (!FD) {
383706f32e7eSjoerg return false;
383806f32e7eSjoerg }
383906f32e7eSjoerg return FD->isInlined();
384006f32e7eSjoerg }
384106f32e7eSjoerg
getCFSTR_value(CallExpr * callExpr)384206f32e7eSjoerg static StringLiteral *getCFSTR_value(CallExpr *callExpr) {
384306f32e7eSjoerg if (callExpr->getNumArgs() != 1) {
384406f32e7eSjoerg return nullptr;
384506f32e7eSjoerg }
384606f32e7eSjoerg
384706f32e7eSjoerg StringLiteral *S = nullptr;
384806f32e7eSjoerg auto *arg = callExpr->getArg(0);
384906f32e7eSjoerg if (arg->getStmtClass() == Stmt::ImplicitCastExprClass) {
385006f32e7eSjoerg ImplicitCastExpr *I = static_cast<ImplicitCastExpr *>(arg);
385106f32e7eSjoerg auto *subExpr = I->getSubExprAsWritten();
385206f32e7eSjoerg
385306f32e7eSjoerg if (subExpr->getStmtClass() != Stmt::StringLiteralClass) {
385406f32e7eSjoerg return nullptr;
385506f32e7eSjoerg }
385606f32e7eSjoerg
385706f32e7eSjoerg S = static_cast<StringLiteral *>(I->getSubExprAsWritten());
385806f32e7eSjoerg } else if (arg->getStmtClass() == Stmt::StringLiteralClass) {
385906f32e7eSjoerg S = static_cast<StringLiteral *>(callExpr->getArg(0));
386006f32e7eSjoerg } else {
386106f32e7eSjoerg return nullptr;
386206f32e7eSjoerg }
386306f32e7eSjoerg return S;
386406f32e7eSjoerg }
386506f32e7eSjoerg
386606f32e7eSjoerg struct ExprEvalResult {
386706f32e7eSjoerg CXEvalResultKind EvalType;
386806f32e7eSjoerg union {
386906f32e7eSjoerg unsigned long long unsignedVal;
387006f32e7eSjoerg long long intVal;
387106f32e7eSjoerg double floatVal;
387206f32e7eSjoerg char *stringVal;
387306f32e7eSjoerg } EvalData;
387406f32e7eSjoerg bool IsUnsignedInt;
~ExprEvalResultExprEvalResult387506f32e7eSjoerg ~ExprEvalResult() {
387606f32e7eSjoerg if (EvalType != CXEval_UnExposed && EvalType != CXEval_Float &&
387706f32e7eSjoerg EvalType != CXEval_Int) {
387806f32e7eSjoerg delete[] EvalData.stringVal;
387906f32e7eSjoerg }
388006f32e7eSjoerg }
388106f32e7eSjoerg };
388206f32e7eSjoerg
clang_EvalResult_dispose(CXEvalResult E)388306f32e7eSjoerg void clang_EvalResult_dispose(CXEvalResult E) {
388406f32e7eSjoerg delete static_cast<ExprEvalResult *>(E);
388506f32e7eSjoerg }
388606f32e7eSjoerg
clang_EvalResult_getKind(CXEvalResult E)388706f32e7eSjoerg CXEvalResultKind clang_EvalResult_getKind(CXEvalResult E) {
388806f32e7eSjoerg if (!E) {
388906f32e7eSjoerg return CXEval_UnExposed;
389006f32e7eSjoerg }
389106f32e7eSjoerg return ((ExprEvalResult *)E)->EvalType;
389206f32e7eSjoerg }
389306f32e7eSjoerg
clang_EvalResult_getAsInt(CXEvalResult E)389406f32e7eSjoerg int clang_EvalResult_getAsInt(CXEvalResult E) {
389506f32e7eSjoerg return clang_EvalResult_getAsLongLong(E);
389606f32e7eSjoerg }
389706f32e7eSjoerg
clang_EvalResult_getAsLongLong(CXEvalResult E)389806f32e7eSjoerg long long clang_EvalResult_getAsLongLong(CXEvalResult E) {
389906f32e7eSjoerg if (!E) {
390006f32e7eSjoerg return 0;
390106f32e7eSjoerg }
390206f32e7eSjoerg ExprEvalResult *Result = (ExprEvalResult *)E;
390306f32e7eSjoerg if (Result->IsUnsignedInt)
390406f32e7eSjoerg return Result->EvalData.unsignedVal;
390506f32e7eSjoerg return Result->EvalData.intVal;
390606f32e7eSjoerg }
390706f32e7eSjoerg
clang_EvalResult_isUnsignedInt(CXEvalResult E)390806f32e7eSjoerg unsigned clang_EvalResult_isUnsignedInt(CXEvalResult E) {
390906f32e7eSjoerg return ((ExprEvalResult *)E)->IsUnsignedInt;
391006f32e7eSjoerg }
391106f32e7eSjoerg
clang_EvalResult_getAsUnsigned(CXEvalResult E)391206f32e7eSjoerg unsigned long long clang_EvalResult_getAsUnsigned(CXEvalResult E) {
391306f32e7eSjoerg if (!E) {
391406f32e7eSjoerg return 0;
391506f32e7eSjoerg }
391606f32e7eSjoerg
391706f32e7eSjoerg ExprEvalResult *Result = (ExprEvalResult *)E;
391806f32e7eSjoerg if (Result->IsUnsignedInt)
391906f32e7eSjoerg return Result->EvalData.unsignedVal;
392006f32e7eSjoerg return Result->EvalData.intVal;
392106f32e7eSjoerg }
392206f32e7eSjoerg
clang_EvalResult_getAsDouble(CXEvalResult E)392306f32e7eSjoerg double clang_EvalResult_getAsDouble(CXEvalResult E) {
392406f32e7eSjoerg if (!E) {
392506f32e7eSjoerg return 0;
392606f32e7eSjoerg }
392706f32e7eSjoerg return ((ExprEvalResult *)E)->EvalData.floatVal;
392806f32e7eSjoerg }
392906f32e7eSjoerg
clang_EvalResult_getAsStr(CXEvalResult E)393006f32e7eSjoerg const char *clang_EvalResult_getAsStr(CXEvalResult E) {
393106f32e7eSjoerg if (!E) {
393206f32e7eSjoerg return nullptr;
393306f32e7eSjoerg }
393406f32e7eSjoerg return ((ExprEvalResult *)E)->EvalData.stringVal;
393506f32e7eSjoerg }
393606f32e7eSjoerg
evaluateExpr(Expr * expr,CXCursor C)393706f32e7eSjoerg static const ExprEvalResult *evaluateExpr(Expr *expr, CXCursor C) {
393806f32e7eSjoerg Expr::EvalResult ER;
393906f32e7eSjoerg ASTContext &ctx = getCursorContext(C);
394006f32e7eSjoerg if (!expr)
394106f32e7eSjoerg return nullptr;
394206f32e7eSjoerg
394306f32e7eSjoerg expr = expr->IgnoreParens();
394406f32e7eSjoerg if (expr->isValueDependent())
394506f32e7eSjoerg return nullptr;
394606f32e7eSjoerg if (!expr->EvaluateAsRValue(ER, ctx))
394706f32e7eSjoerg return nullptr;
394806f32e7eSjoerg
394906f32e7eSjoerg QualType rettype;
395006f32e7eSjoerg CallExpr *callExpr;
395106f32e7eSjoerg auto result = std::make_unique<ExprEvalResult>();
395206f32e7eSjoerg result->EvalType = CXEval_UnExposed;
395306f32e7eSjoerg result->IsUnsignedInt = false;
395406f32e7eSjoerg
395506f32e7eSjoerg if (ER.Val.isInt()) {
395606f32e7eSjoerg result->EvalType = CXEval_Int;
395706f32e7eSjoerg
395806f32e7eSjoerg auto &val = ER.Val.getInt();
395906f32e7eSjoerg if (val.isUnsigned()) {
396006f32e7eSjoerg result->IsUnsignedInt = true;
396106f32e7eSjoerg result->EvalData.unsignedVal = val.getZExtValue();
396206f32e7eSjoerg } else {
396306f32e7eSjoerg result->EvalData.intVal = val.getExtValue();
396406f32e7eSjoerg }
396506f32e7eSjoerg
396606f32e7eSjoerg return result.release();
396706f32e7eSjoerg }
396806f32e7eSjoerg
396906f32e7eSjoerg if (ER.Val.isFloat()) {
397006f32e7eSjoerg llvm::SmallVector<char, 100> Buffer;
397106f32e7eSjoerg ER.Val.getFloat().toString(Buffer);
397206f32e7eSjoerg std::string floatStr(Buffer.data(), Buffer.size());
397306f32e7eSjoerg result->EvalType = CXEval_Float;
397406f32e7eSjoerg bool ignored;
397506f32e7eSjoerg llvm::APFloat apFloat = ER.Val.getFloat();
397606f32e7eSjoerg apFloat.convert(llvm::APFloat::IEEEdouble(),
397706f32e7eSjoerg llvm::APFloat::rmNearestTiesToEven, &ignored);
397806f32e7eSjoerg result->EvalData.floatVal = apFloat.convertToDouble();
397906f32e7eSjoerg return result.release();
398006f32e7eSjoerg }
398106f32e7eSjoerg
398206f32e7eSjoerg if (expr->getStmtClass() == Stmt::ImplicitCastExprClass) {
398306f32e7eSjoerg const ImplicitCastExpr *I = dyn_cast<ImplicitCastExpr>(expr);
398406f32e7eSjoerg auto *subExpr = I->getSubExprAsWritten();
398506f32e7eSjoerg if (subExpr->getStmtClass() == Stmt::StringLiteralClass ||
398606f32e7eSjoerg subExpr->getStmtClass() == Stmt::ObjCStringLiteralClass) {
398706f32e7eSjoerg const StringLiteral *StrE = nullptr;
398806f32e7eSjoerg const ObjCStringLiteral *ObjCExpr;
398906f32e7eSjoerg ObjCExpr = dyn_cast<ObjCStringLiteral>(subExpr);
399006f32e7eSjoerg
399106f32e7eSjoerg if (ObjCExpr) {
399206f32e7eSjoerg StrE = ObjCExpr->getString();
399306f32e7eSjoerg result->EvalType = CXEval_ObjCStrLiteral;
399406f32e7eSjoerg } else {
399506f32e7eSjoerg StrE = cast<StringLiteral>(I->getSubExprAsWritten());
399606f32e7eSjoerg result->EvalType = CXEval_StrLiteral;
399706f32e7eSjoerg }
399806f32e7eSjoerg
399906f32e7eSjoerg std::string strRef(StrE->getString().str());
400006f32e7eSjoerg result->EvalData.stringVal = new char[strRef.size() + 1];
400106f32e7eSjoerg strncpy((char *)result->EvalData.stringVal, strRef.c_str(),
400206f32e7eSjoerg strRef.size());
400306f32e7eSjoerg result->EvalData.stringVal[strRef.size()] = '\0';
400406f32e7eSjoerg return result.release();
400506f32e7eSjoerg }
400606f32e7eSjoerg } else if (expr->getStmtClass() == Stmt::ObjCStringLiteralClass ||
400706f32e7eSjoerg expr->getStmtClass() == Stmt::StringLiteralClass) {
400806f32e7eSjoerg const StringLiteral *StrE = nullptr;
400906f32e7eSjoerg const ObjCStringLiteral *ObjCExpr;
401006f32e7eSjoerg ObjCExpr = dyn_cast<ObjCStringLiteral>(expr);
401106f32e7eSjoerg
401206f32e7eSjoerg if (ObjCExpr) {
401306f32e7eSjoerg StrE = ObjCExpr->getString();
401406f32e7eSjoerg result->EvalType = CXEval_ObjCStrLiteral;
401506f32e7eSjoerg } else {
401606f32e7eSjoerg StrE = cast<StringLiteral>(expr);
401706f32e7eSjoerg result->EvalType = CXEval_StrLiteral;
401806f32e7eSjoerg }
401906f32e7eSjoerg
402006f32e7eSjoerg std::string strRef(StrE->getString().str());
402106f32e7eSjoerg result->EvalData.stringVal = new char[strRef.size() + 1];
402206f32e7eSjoerg strncpy((char *)result->EvalData.stringVal, strRef.c_str(), strRef.size());
402306f32e7eSjoerg result->EvalData.stringVal[strRef.size()] = '\0';
402406f32e7eSjoerg return result.release();
402506f32e7eSjoerg }
402606f32e7eSjoerg
402706f32e7eSjoerg if (expr->getStmtClass() == Stmt::CStyleCastExprClass) {
402806f32e7eSjoerg CStyleCastExpr *CC = static_cast<CStyleCastExpr *>(expr);
402906f32e7eSjoerg
403006f32e7eSjoerg rettype = CC->getType();
403106f32e7eSjoerg if (rettype.getAsString() == "CFStringRef" &&
403206f32e7eSjoerg CC->getSubExpr()->getStmtClass() == Stmt::CallExprClass) {
403306f32e7eSjoerg
403406f32e7eSjoerg callExpr = static_cast<CallExpr *>(CC->getSubExpr());
403506f32e7eSjoerg StringLiteral *S = getCFSTR_value(callExpr);
403606f32e7eSjoerg if (S) {
403706f32e7eSjoerg std::string strLiteral(S->getString().str());
403806f32e7eSjoerg result->EvalType = CXEval_CFStr;
403906f32e7eSjoerg
404006f32e7eSjoerg result->EvalData.stringVal = new char[strLiteral.size() + 1];
404106f32e7eSjoerg strncpy((char *)result->EvalData.stringVal, strLiteral.c_str(),
404206f32e7eSjoerg strLiteral.size());
404306f32e7eSjoerg result->EvalData.stringVal[strLiteral.size()] = '\0';
404406f32e7eSjoerg return result.release();
404506f32e7eSjoerg }
404606f32e7eSjoerg }
404706f32e7eSjoerg
404806f32e7eSjoerg } else if (expr->getStmtClass() == Stmt::CallExprClass) {
404906f32e7eSjoerg callExpr = static_cast<CallExpr *>(expr);
405006f32e7eSjoerg rettype = callExpr->getCallReturnType(ctx);
405106f32e7eSjoerg
405206f32e7eSjoerg if (rettype->isVectorType() || callExpr->getNumArgs() > 1)
405306f32e7eSjoerg return nullptr;
405406f32e7eSjoerg
405506f32e7eSjoerg if (rettype->isIntegralType(ctx) || rettype->isRealFloatingType()) {
405606f32e7eSjoerg if (callExpr->getNumArgs() == 1 &&
405706f32e7eSjoerg !callExpr->getArg(0)->getType()->isIntegralType(ctx))
405806f32e7eSjoerg return nullptr;
405906f32e7eSjoerg } else if (rettype.getAsString() == "CFStringRef") {
406006f32e7eSjoerg
406106f32e7eSjoerg StringLiteral *S = getCFSTR_value(callExpr);
406206f32e7eSjoerg if (S) {
406306f32e7eSjoerg std::string strLiteral(S->getString().str());
406406f32e7eSjoerg result->EvalType = CXEval_CFStr;
406506f32e7eSjoerg result->EvalData.stringVal = new char[strLiteral.size() + 1];
406606f32e7eSjoerg strncpy((char *)result->EvalData.stringVal, strLiteral.c_str(),
406706f32e7eSjoerg strLiteral.size());
406806f32e7eSjoerg result->EvalData.stringVal[strLiteral.size()] = '\0';
406906f32e7eSjoerg return result.release();
407006f32e7eSjoerg }
407106f32e7eSjoerg }
407206f32e7eSjoerg } else if (expr->getStmtClass() == Stmt::DeclRefExprClass) {
407306f32e7eSjoerg DeclRefExpr *D = static_cast<DeclRefExpr *>(expr);
407406f32e7eSjoerg ValueDecl *V = D->getDecl();
407506f32e7eSjoerg if (V->getKind() == Decl::Function) {
407606f32e7eSjoerg std::string strName = V->getNameAsString();
407706f32e7eSjoerg result->EvalType = CXEval_Other;
407806f32e7eSjoerg result->EvalData.stringVal = new char[strName.size() + 1];
407906f32e7eSjoerg strncpy(result->EvalData.stringVal, strName.c_str(), strName.size());
408006f32e7eSjoerg result->EvalData.stringVal[strName.size()] = '\0';
408106f32e7eSjoerg return result.release();
408206f32e7eSjoerg }
408306f32e7eSjoerg }
408406f32e7eSjoerg
408506f32e7eSjoerg return nullptr;
408606f32e7eSjoerg }
408706f32e7eSjoerg
evaluateDeclExpr(const Decl * D)408806f32e7eSjoerg static const Expr *evaluateDeclExpr(const Decl *D) {
408906f32e7eSjoerg if (!D)
409006f32e7eSjoerg return nullptr;
409106f32e7eSjoerg if (auto *Var = dyn_cast<VarDecl>(D))
409206f32e7eSjoerg return Var->getInit();
409306f32e7eSjoerg else if (auto *Field = dyn_cast<FieldDecl>(D))
409406f32e7eSjoerg return Field->getInClassInitializer();
409506f32e7eSjoerg return nullptr;
409606f32e7eSjoerg }
409706f32e7eSjoerg
evaluateCompoundStmtExpr(const CompoundStmt * CS)409806f32e7eSjoerg static const Expr *evaluateCompoundStmtExpr(const CompoundStmt *CS) {
409906f32e7eSjoerg assert(CS && "invalid compound statement");
410006f32e7eSjoerg for (auto *bodyIterator : CS->body()) {
410106f32e7eSjoerg if (const auto *E = dyn_cast<Expr>(bodyIterator))
410206f32e7eSjoerg return E;
410306f32e7eSjoerg }
410406f32e7eSjoerg return nullptr;
410506f32e7eSjoerg }
410606f32e7eSjoerg
clang_Cursor_Evaluate(CXCursor C)410706f32e7eSjoerg CXEvalResult clang_Cursor_Evaluate(CXCursor C) {
4108*13fbcb42Sjoerg const Expr *E = nullptr;
4109*13fbcb42Sjoerg if (clang_getCursorKind(C) == CXCursor_CompoundStmt)
4110*13fbcb42Sjoerg E = evaluateCompoundStmtExpr(cast<CompoundStmt>(getCursorStmt(C)));
4111*13fbcb42Sjoerg else if (clang_isDeclaration(C.kind))
4112*13fbcb42Sjoerg E = evaluateDeclExpr(getCursorDecl(C));
4113*13fbcb42Sjoerg else if (clang_isExpression(C.kind))
4114*13fbcb42Sjoerg E = getCursorExpr(C);
4115*13fbcb42Sjoerg if (E)
411606f32e7eSjoerg return const_cast<CXEvalResult>(
411706f32e7eSjoerg reinterpret_cast<const void *>(evaluateExpr(const_cast<Expr *>(E), C)));
411806f32e7eSjoerg return nullptr;
411906f32e7eSjoerg }
412006f32e7eSjoerg
clang_Cursor_hasAttrs(CXCursor C)412106f32e7eSjoerg unsigned clang_Cursor_hasAttrs(CXCursor C) {
412206f32e7eSjoerg const Decl *D = getCursorDecl(C);
412306f32e7eSjoerg if (!D) {
412406f32e7eSjoerg return 0;
412506f32e7eSjoerg }
412606f32e7eSjoerg
412706f32e7eSjoerg if (D->hasAttrs()) {
412806f32e7eSjoerg return 1;
412906f32e7eSjoerg }
413006f32e7eSjoerg
413106f32e7eSjoerg return 0;
413206f32e7eSjoerg }
clang_defaultSaveOptions(CXTranslationUnit TU)413306f32e7eSjoerg unsigned clang_defaultSaveOptions(CXTranslationUnit TU) {
413406f32e7eSjoerg return CXSaveTranslationUnit_None;
413506f32e7eSjoerg }
413606f32e7eSjoerg
clang_saveTranslationUnit_Impl(CXTranslationUnit TU,const char * FileName,unsigned options)413706f32e7eSjoerg static CXSaveError clang_saveTranslationUnit_Impl(CXTranslationUnit TU,
413806f32e7eSjoerg const char *FileName,
413906f32e7eSjoerg unsigned options) {
414006f32e7eSjoerg CIndexer *CXXIdx = TU->CIdx;
414106f32e7eSjoerg if (CXXIdx->isOptEnabled(CXGlobalOpt_ThreadBackgroundPriorityForIndexing))
414206f32e7eSjoerg setThreadBackgroundPriority();
414306f32e7eSjoerg
414406f32e7eSjoerg bool hadError = cxtu::getASTUnit(TU)->Save(FileName);
414506f32e7eSjoerg return hadError ? CXSaveError_Unknown : CXSaveError_None;
414606f32e7eSjoerg }
414706f32e7eSjoerg
clang_saveTranslationUnit(CXTranslationUnit TU,const char * FileName,unsigned options)414806f32e7eSjoerg int clang_saveTranslationUnit(CXTranslationUnit TU, const char *FileName,
414906f32e7eSjoerg unsigned options) {
4150*13fbcb42Sjoerg LOG_FUNC_SECTION { *Log << TU << ' ' << FileName; }
415106f32e7eSjoerg
415206f32e7eSjoerg if (isNotUsableTU(TU)) {
415306f32e7eSjoerg LOG_BAD_TU(TU);
415406f32e7eSjoerg return CXSaveError_InvalidTU;
415506f32e7eSjoerg }
415606f32e7eSjoerg
415706f32e7eSjoerg ASTUnit *CXXUnit = cxtu::getASTUnit(TU);
415806f32e7eSjoerg ASTUnit::ConcurrencyCheck Check(*CXXUnit);
415906f32e7eSjoerg if (!CXXUnit->hasSema())
416006f32e7eSjoerg return CXSaveError_InvalidTU;
416106f32e7eSjoerg
416206f32e7eSjoerg CXSaveError result;
416306f32e7eSjoerg auto SaveTranslationUnitImpl = [=, &result]() {
416406f32e7eSjoerg result = clang_saveTranslationUnit_Impl(TU, FileName, options);
416506f32e7eSjoerg };
416606f32e7eSjoerg
416706f32e7eSjoerg if (!CXXUnit->getDiagnostics().hasUnrecoverableErrorOccurred()) {
416806f32e7eSjoerg SaveTranslationUnitImpl();
416906f32e7eSjoerg
417006f32e7eSjoerg if (getenv("LIBCLANG_RESOURCE_USAGE"))
417106f32e7eSjoerg PrintLibclangResourceUsage(TU);
417206f32e7eSjoerg
417306f32e7eSjoerg return result;
417406f32e7eSjoerg }
417506f32e7eSjoerg
417606f32e7eSjoerg // We have an AST that has invalid nodes due to compiler errors.
417706f32e7eSjoerg // Use a crash recovery thread for protection.
417806f32e7eSjoerg
417906f32e7eSjoerg llvm::CrashRecoveryContext CRC;
418006f32e7eSjoerg
418106f32e7eSjoerg if (!RunSafely(CRC, SaveTranslationUnitImpl)) {
418206f32e7eSjoerg fprintf(stderr, "libclang: crash detected during AST saving: {\n");
418306f32e7eSjoerg fprintf(stderr, " 'filename' : '%s'\n", FileName);
418406f32e7eSjoerg fprintf(stderr, " 'options' : %d,\n", options);
418506f32e7eSjoerg fprintf(stderr, "}\n");
418606f32e7eSjoerg
418706f32e7eSjoerg return CXSaveError_Unknown;
418806f32e7eSjoerg
418906f32e7eSjoerg } else if (getenv("LIBCLANG_RESOURCE_USAGE")) {
419006f32e7eSjoerg PrintLibclangResourceUsage(TU);
419106f32e7eSjoerg }
419206f32e7eSjoerg
419306f32e7eSjoerg return result;
419406f32e7eSjoerg }
419506f32e7eSjoerg
clang_disposeTranslationUnit(CXTranslationUnit CTUnit)419606f32e7eSjoerg void clang_disposeTranslationUnit(CXTranslationUnit CTUnit) {
419706f32e7eSjoerg if (CTUnit) {
419806f32e7eSjoerg // If the translation unit has been marked as unsafe to free, just discard
419906f32e7eSjoerg // it.
420006f32e7eSjoerg ASTUnit *Unit = cxtu::getASTUnit(CTUnit);
420106f32e7eSjoerg if (Unit && Unit->isUnsafeToFree())
420206f32e7eSjoerg return;
420306f32e7eSjoerg
420406f32e7eSjoerg delete cxtu::getASTUnit(CTUnit);
420506f32e7eSjoerg delete CTUnit->StringPool;
420606f32e7eSjoerg delete static_cast<CXDiagnosticSetImpl *>(CTUnit->Diagnostics);
420706f32e7eSjoerg disposeOverridenCXCursorsPool(CTUnit->OverridenCursorsPool);
420806f32e7eSjoerg delete CTUnit->CommentToXML;
420906f32e7eSjoerg delete CTUnit;
421006f32e7eSjoerg }
421106f32e7eSjoerg }
421206f32e7eSjoerg
clang_suspendTranslationUnit(CXTranslationUnit CTUnit)421306f32e7eSjoerg unsigned clang_suspendTranslationUnit(CXTranslationUnit CTUnit) {
421406f32e7eSjoerg if (CTUnit) {
421506f32e7eSjoerg ASTUnit *Unit = cxtu::getASTUnit(CTUnit);
421606f32e7eSjoerg
421706f32e7eSjoerg if (Unit && Unit->isUnsafeToFree())
421806f32e7eSjoerg return false;
421906f32e7eSjoerg
422006f32e7eSjoerg Unit->ResetForParse();
422106f32e7eSjoerg return true;
422206f32e7eSjoerg }
422306f32e7eSjoerg
422406f32e7eSjoerg return false;
422506f32e7eSjoerg }
422606f32e7eSjoerg
clang_defaultReparseOptions(CXTranslationUnit TU)422706f32e7eSjoerg unsigned clang_defaultReparseOptions(CXTranslationUnit TU) {
422806f32e7eSjoerg return CXReparse_None;
422906f32e7eSjoerg }
423006f32e7eSjoerg
423106f32e7eSjoerg static CXErrorCode
clang_reparseTranslationUnit_Impl(CXTranslationUnit TU,ArrayRef<CXUnsavedFile> unsaved_files,unsigned options)423206f32e7eSjoerg clang_reparseTranslationUnit_Impl(CXTranslationUnit TU,
423306f32e7eSjoerg ArrayRef<CXUnsavedFile> unsaved_files,
423406f32e7eSjoerg unsigned options) {
423506f32e7eSjoerg // Check arguments.
423606f32e7eSjoerg if (isNotUsableTU(TU)) {
423706f32e7eSjoerg LOG_BAD_TU(TU);
423806f32e7eSjoerg return CXError_InvalidArguments;
423906f32e7eSjoerg }
424006f32e7eSjoerg
424106f32e7eSjoerg // Reset the associated diagnostics.
424206f32e7eSjoerg delete static_cast<CXDiagnosticSetImpl *>(TU->Diagnostics);
424306f32e7eSjoerg TU->Diagnostics = nullptr;
424406f32e7eSjoerg
424506f32e7eSjoerg CIndexer *CXXIdx = TU->CIdx;
424606f32e7eSjoerg if (CXXIdx->isOptEnabled(CXGlobalOpt_ThreadBackgroundPriorityForEditing))
424706f32e7eSjoerg setThreadBackgroundPriority();
424806f32e7eSjoerg
424906f32e7eSjoerg ASTUnit *CXXUnit = cxtu::getASTUnit(TU);
425006f32e7eSjoerg ASTUnit::ConcurrencyCheck Check(*CXXUnit);
425106f32e7eSjoerg
425206f32e7eSjoerg std::unique_ptr<std::vector<ASTUnit::RemappedFile>> RemappedFiles(
425306f32e7eSjoerg new std::vector<ASTUnit::RemappedFile>());
425406f32e7eSjoerg
425506f32e7eSjoerg // Recover resources if we crash before exiting this function.
4256*13fbcb42Sjoerg llvm::CrashRecoveryContextCleanupRegistrar<std::vector<ASTUnit::RemappedFile>>
4257*13fbcb42Sjoerg RemappedCleanup(RemappedFiles.get());
425806f32e7eSjoerg
425906f32e7eSjoerg for (auto &UF : unsaved_files) {
426006f32e7eSjoerg std::unique_ptr<llvm::MemoryBuffer> MB =
426106f32e7eSjoerg llvm::MemoryBuffer::getMemBufferCopy(getContents(UF), UF.Filename);
426206f32e7eSjoerg RemappedFiles->push_back(std::make_pair(UF.Filename, MB.release()));
426306f32e7eSjoerg }
426406f32e7eSjoerg
426506f32e7eSjoerg if (!CXXUnit->Reparse(CXXIdx->getPCHContainerOperations(),
426606f32e7eSjoerg *RemappedFiles.get()))
426706f32e7eSjoerg return CXError_Success;
426806f32e7eSjoerg if (isASTReadError(CXXUnit))
426906f32e7eSjoerg return CXError_ASTReadError;
427006f32e7eSjoerg return CXError_Failure;
427106f32e7eSjoerg }
427206f32e7eSjoerg
clang_reparseTranslationUnit(CXTranslationUnit TU,unsigned num_unsaved_files,struct CXUnsavedFile * unsaved_files,unsigned options)427306f32e7eSjoerg int clang_reparseTranslationUnit(CXTranslationUnit TU,
427406f32e7eSjoerg unsigned num_unsaved_files,
427506f32e7eSjoerg struct CXUnsavedFile *unsaved_files,
427606f32e7eSjoerg unsigned options) {
4277*13fbcb42Sjoerg LOG_FUNC_SECTION { *Log << TU; }
427806f32e7eSjoerg
427906f32e7eSjoerg if (num_unsaved_files && !unsaved_files)
428006f32e7eSjoerg return CXError_InvalidArguments;
428106f32e7eSjoerg
428206f32e7eSjoerg CXErrorCode result;
428306f32e7eSjoerg auto ReparseTranslationUnitImpl = [=, &result]() {
428406f32e7eSjoerg result = clang_reparseTranslationUnit_Impl(
428506f32e7eSjoerg TU, llvm::makeArrayRef(unsaved_files, num_unsaved_files), options);
428606f32e7eSjoerg };
428706f32e7eSjoerg
428806f32e7eSjoerg llvm::CrashRecoveryContext CRC;
428906f32e7eSjoerg
429006f32e7eSjoerg if (!RunSafely(CRC, ReparseTranslationUnitImpl)) {
429106f32e7eSjoerg fprintf(stderr, "libclang: crash detected during reparsing\n");
429206f32e7eSjoerg cxtu::getASTUnit(TU)->setUnsafeToFree(true);
429306f32e7eSjoerg return CXError_Crashed;
429406f32e7eSjoerg } else if (getenv("LIBCLANG_RESOURCE_USAGE"))
429506f32e7eSjoerg PrintLibclangResourceUsage(TU);
429606f32e7eSjoerg
429706f32e7eSjoerg return result;
429806f32e7eSjoerg }
429906f32e7eSjoerg
clang_getTranslationUnitSpelling(CXTranslationUnit CTUnit)430006f32e7eSjoerg CXString clang_getTranslationUnitSpelling(CXTranslationUnit CTUnit) {
430106f32e7eSjoerg if (isNotUsableTU(CTUnit)) {
430206f32e7eSjoerg LOG_BAD_TU(CTUnit);
430306f32e7eSjoerg return cxstring::createEmpty();
430406f32e7eSjoerg }
430506f32e7eSjoerg
430606f32e7eSjoerg ASTUnit *CXXUnit = cxtu::getASTUnit(CTUnit);
430706f32e7eSjoerg return cxstring::createDup(CXXUnit->getOriginalSourceFileName());
430806f32e7eSjoerg }
430906f32e7eSjoerg
clang_getTranslationUnitCursor(CXTranslationUnit TU)431006f32e7eSjoerg CXCursor clang_getTranslationUnitCursor(CXTranslationUnit TU) {
431106f32e7eSjoerg if (isNotUsableTU(TU)) {
431206f32e7eSjoerg LOG_BAD_TU(TU);
431306f32e7eSjoerg return clang_getNullCursor();
431406f32e7eSjoerg }
431506f32e7eSjoerg
431606f32e7eSjoerg ASTUnit *CXXUnit = cxtu::getASTUnit(TU);
431706f32e7eSjoerg return MakeCXCursor(CXXUnit->getASTContext().getTranslationUnitDecl(), TU);
431806f32e7eSjoerg }
431906f32e7eSjoerg
clang_getTranslationUnitTargetInfo(CXTranslationUnit CTUnit)432006f32e7eSjoerg CXTargetInfo clang_getTranslationUnitTargetInfo(CXTranslationUnit CTUnit) {
432106f32e7eSjoerg if (isNotUsableTU(CTUnit)) {
432206f32e7eSjoerg LOG_BAD_TU(CTUnit);
432306f32e7eSjoerg return nullptr;
432406f32e7eSjoerg }
432506f32e7eSjoerg
432606f32e7eSjoerg CXTargetInfoImpl *impl = new CXTargetInfoImpl();
432706f32e7eSjoerg impl->TranslationUnit = CTUnit;
432806f32e7eSjoerg return impl;
432906f32e7eSjoerg }
433006f32e7eSjoerg
clang_TargetInfo_getTriple(CXTargetInfo TargetInfo)433106f32e7eSjoerg CXString clang_TargetInfo_getTriple(CXTargetInfo TargetInfo) {
433206f32e7eSjoerg if (!TargetInfo)
433306f32e7eSjoerg return cxstring::createEmpty();
433406f32e7eSjoerg
433506f32e7eSjoerg CXTranslationUnit CTUnit = TargetInfo->TranslationUnit;
433606f32e7eSjoerg assert(!isNotUsableTU(CTUnit) &&
433706f32e7eSjoerg "Unexpected unusable translation unit in TargetInfo");
433806f32e7eSjoerg
433906f32e7eSjoerg ASTUnit *CXXUnit = cxtu::getASTUnit(CTUnit);
434006f32e7eSjoerg std::string Triple =
434106f32e7eSjoerg CXXUnit->getASTContext().getTargetInfo().getTriple().normalize();
434206f32e7eSjoerg return cxstring::createDup(Triple);
434306f32e7eSjoerg }
434406f32e7eSjoerg
clang_TargetInfo_getPointerWidth(CXTargetInfo TargetInfo)434506f32e7eSjoerg int clang_TargetInfo_getPointerWidth(CXTargetInfo TargetInfo) {
434606f32e7eSjoerg if (!TargetInfo)
434706f32e7eSjoerg return -1;
434806f32e7eSjoerg
434906f32e7eSjoerg CXTranslationUnit CTUnit = TargetInfo->TranslationUnit;
435006f32e7eSjoerg assert(!isNotUsableTU(CTUnit) &&
435106f32e7eSjoerg "Unexpected unusable translation unit in TargetInfo");
435206f32e7eSjoerg
435306f32e7eSjoerg ASTUnit *CXXUnit = cxtu::getASTUnit(CTUnit);
435406f32e7eSjoerg return CXXUnit->getASTContext().getTargetInfo().getMaxPointerWidth();
435506f32e7eSjoerg }
435606f32e7eSjoerg
clang_TargetInfo_dispose(CXTargetInfo TargetInfo)435706f32e7eSjoerg void clang_TargetInfo_dispose(CXTargetInfo TargetInfo) {
435806f32e7eSjoerg if (!TargetInfo)
435906f32e7eSjoerg return;
436006f32e7eSjoerg
436106f32e7eSjoerg delete TargetInfo;
436206f32e7eSjoerg }
436306f32e7eSjoerg
436406f32e7eSjoerg //===----------------------------------------------------------------------===//
436506f32e7eSjoerg // CXFile Operations.
436606f32e7eSjoerg //===----------------------------------------------------------------------===//
436706f32e7eSjoerg
clang_getFileName(CXFile SFile)436806f32e7eSjoerg CXString clang_getFileName(CXFile SFile) {
436906f32e7eSjoerg if (!SFile)
437006f32e7eSjoerg return cxstring::createNull();
437106f32e7eSjoerg
437206f32e7eSjoerg FileEntry *FEnt = static_cast<FileEntry *>(SFile);
437306f32e7eSjoerg return cxstring::createRef(FEnt->getName());
437406f32e7eSjoerg }
437506f32e7eSjoerg
clang_getFileTime(CXFile SFile)437606f32e7eSjoerg time_t clang_getFileTime(CXFile SFile) {
437706f32e7eSjoerg if (!SFile)
437806f32e7eSjoerg return 0;
437906f32e7eSjoerg
438006f32e7eSjoerg FileEntry *FEnt = static_cast<FileEntry *>(SFile);
438106f32e7eSjoerg return FEnt->getModificationTime();
438206f32e7eSjoerg }
438306f32e7eSjoerg
clang_getFile(CXTranslationUnit TU,const char * file_name)438406f32e7eSjoerg CXFile clang_getFile(CXTranslationUnit TU, const char *file_name) {
438506f32e7eSjoerg if (isNotUsableTU(TU)) {
438606f32e7eSjoerg LOG_BAD_TU(TU);
438706f32e7eSjoerg return nullptr;
438806f32e7eSjoerg }
438906f32e7eSjoerg
439006f32e7eSjoerg ASTUnit *CXXUnit = cxtu::getASTUnit(TU);
439106f32e7eSjoerg
439206f32e7eSjoerg FileManager &FMgr = CXXUnit->getFileManager();
439306f32e7eSjoerg auto File = FMgr.getFile(file_name);
439406f32e7eSjoerg if (!File)
439506f32e7eSjoerg return nullptr;
439606f32e7eSjoerg return const_cast<FileEntry *>(*File);
439706f32e7eSjoerg }
439806f32e7eSjoerg
clang_getFileContents(CXTranslationUnit TU,CXFile file,size_t * size)439906f32e7eSjoerg const char *clang_getFileContents(CXTranslationUnit TU, CXFile file,
440006f32e7eSjoerg size_t *size) {
440106f32e7eSjoerg if (isNotUsableTU(TU)) {
440206f32e7eSjoerg LOG_BAD_TU(TU);
440306f32e7eSjoerg return nullptr;
440406f32e7eSjoerg }
440506f32e7eSjoerg
440606f32e7eSjoerg const SourceManager &SM = cxtu::getASTUnit(TU)->getSourceManager();
440706f32e7eSjoerg FileID fid = SM.translateFile(static_cast<FileEntry *>(file));
4408*13fbcb42Sjoerg llvm::Optional<llvm::MemoryBufferRef> buf = SM.getBufferOrNone(fid);
4409*13fbcb42Sjoerg if (!buf) {
441006f32e7eSjoerg if (size)
441106f32e7eSjoerg *size = 0;
441206f32e7eSjoerg return nullptr;
441306f32e7eSjoerg }
441406f32e7eSjoerg if (size)
441506f32e7eSjoerg *size = buf->getBufferSize();
441606f32e7eSjoerg return buf->getBufferStart();
441706f32e7eSjoerg }
441806f32e7eSjoerg
clang_isFileMultipleIncludeGuarded(CXTranslationUnit TU,CXFile file)4419*13fbcb42Sjoerg unsigned clang_isFileMultipleIncludeGuarded(CXTranslationUnit TU, CXFile file) {
442006f32e7eSjoerg if (isNotUsableTU(TU)) {
442106f32e7eSjoerg LOG_BAD_TU(TU);
442206f32e7eSjoerg return 0;
442306f32e7eSjoerg }
442406f32e7eSjoerg
442506f32e7eSjoerg if (!file)
442606f32e7eSjoerg return 0;
442706f32e7eSjoerg
442806f32e7eSjoerg ASTUnit *CXXUnit = cxtu::getASTUnit(TU);
442906f32e7eSjoerg FileEntry *FEnt = static_cast<FileEntry *>(file);
4430*13fbcb42Sjoerg return CXXUnit->getPreprocessor()
4431*13fbcb42Sjoerg .getHeaderSearchInfo()
443206f32e7eSjoerg .isFileMultipleIncludeGuarded(FEnt);
443306f32e7eSjoerg }
443406f32e7eSjoerg
clang_getFileUniqueID(CXFile file,CXFileUniqueID * outID)443506f32e7eSjoerg int clang_getFileUniqueID(CXFile file, CXFileUniqueID *outID) {
443606f32e7eSjoerg if (!file || !outID)
443706f32e7eSjoerg return 1;
443806f32e7eSjoerg
443906f32e7eSjoerg FileEntry *FEnt = static_cast<FileEntry *>(file);
444006f32e7eSjoerg const llvm::sys::fs::UniqueID &ID = FEnt->getUniqueID();
444106f32e7eSjoerg outID->data[0] = ID.getDevice();
444206f32e7eSjoerg outID->data[1] = ID.getFile();
444306f32e7eSjoerg outID->data[2] = FEnt->getModificationTime();
444406f32e7eSjoerg return 0;
444506f32e7eSjoerg }
444606f32e7eSjoerg
clang_File_isEqual(CXFile file1,CXFile file2)444706f32e7eSjoerg int clang_File_isEqual(CXFile file1, CXFile file2) {
444806f32e7eSjoerg if (file1 == file2)
444906f32e7eSjoerg return true;
445006f32e7eSjoerg
445106f32e7eSjoerg if (!file1 || !file2)
445206f32e7eSjoerg return false;
445306f32e7eSjoerg
445406f32e7eSjoerg FileEntry *FEnt1 = static_cast<FileEntry *>(file1);
445506f32e7eSjoerg FileEntry *FEnt2 = static_cast<FileEntry *>(file2);
445606f32e7eSjoerg return FEnt1->getUniqueID() == FEnt2->getUniqueID();
445706f32e7eSjoerg }
445806f32e7eSjoerg
clang_File_tryGetRealPathName(CXFile SFile)445906f32e7eSjoerg CXString clang_File_tryGetRealPathName(CXFile SFile) {
446006f32e7eSjoerg if (!SFile)
446106f32e7eSjoerg return cxstring::createNull();
446206f32e7eSjoerg
446306f32e7eSjoerg FileEntry *FEnt = static_cast<FileEntry *>(SFile);
446406f32e7eSjoerg return cxstring::createRef(FEnt->tryGetRealPathName());
446506f32e7eSjoerg }
446606f32e7eSjoerg
446706f32e7eSjoerg //===----------------------------------------------------------------------===//
446806f32e7eSjoerg // CXCursor Operations.
446906f32e7eSjoerg //===----------------------------------------------------------------------===//
447006f32e7eSjoerg
getDeclFromExpr(const Stmt * E)447106f32e7eSjoerg static const Decl *getDeclFromExpr(const Stmt *E) {
447206f32e7eSjoerg if (const ImplicitCastExpr *CE = dyn_cast<ImplicitCastExpr>(E))
447306f32e7eSjoerg return getDeclFromExpr(CE->getSubExpr());
447406f32e7eSjoerg
447506f32e7eSjoerg if (const DeclRefExpr *RefExpr = dyn_cast<DeclRefExpr>(E))
447606f32e7eSjoerg return RefExpr->getDecl();
447706f32e7eSjoerg if (const MemberExpr *ME = dyn_cast<MemberExpr>(E))
447806f32e7eSjoerg return ME->getMemberDecl();
447906f32e7eSjoerg if (const ObjCIvarRefExpr *RE = dyn_cast<ObjCIvarRefExpr>(E))
448006f32e7eSjoerg return RE->getDecl();
448106f32e7eSjoerg if (const ObjCPropertyRefExpr *PRE = dyn_cast<ObjCPropertyRefExpr>(E)) {
448206f32e7eSjoerg if (PRE->isExplicitProperty())
448306f32e7eSjoerg return PRE->getExplicitProperty();
448406f32e7eSjoerg // It could be messaging both getter and setter as in:
448506f32e7eSjoerg // ++myobj.myprop;
448606f32e7eSjoerg // in which case prefer to associate the setter since it is less obvious
448706f32e7eSjoerg // from inspecting the source that the setter is going to get called.
448806f32e7eSjoerg if (PRE->isMessagingSetter())
448906f32e7eSjoerg return PRE->getImplicitPropertySetter();
449006f32e7eSjoerg return PRE->getImplicitPropertyGetter();
449106f32e7eSjoerg }
449206f32e7eSjoerg if (const PseudoObjectExpr *POE = dyn_cast<PseudoObjectExpr>(E))
449306f32e7eSjoerg return getDeclFromExpr(POE->getSyntacticForm());
449406f32e7eSjoerg if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(E))
449506f32e7eSjoerg if (Expr *Src = OVE->getSourceExpr())
449606f32e7eSjoerg return getDeclFromExpr(Src);
449706f32e7eSjoerg
449806f32e7eSjoerg if (const CallExpr *CE = dyn_cast<CallExpr>(E))
449906f32e7eSjoerg return getDeclFromExpr(CE->getCallee());
450006f32e7eSjoerg if (const CXXConstructExpr *CE = dyn_cast<CXXConstructExpr>(E))
450106f32e7eSjoerg if (!CE->isElidable())
450206f32e7eSjoerg return CE->getConstructor();
450306f32e7eSjoerg if (const CXXInheritedCtorInitExpr *CE =
450406f32e7eSjoerg dyn_cast<CXXInheritedCtorInitExpr>(E))
450506f32e7eSjoerg return CE->getConstructor();
450606f32e7eSjoerg if (const ObjCMessageExpr *OME = dyn_cast<ObjCMessageExpr>(E))
450706f32e7eSjoerg return OME->getMethodDecl();
450806f32e7eSjoerg
450906f32e7eSjoerg if (const ObjCProtocolExpr *PE = dyn_cast<ObjCProtocolExpr>(E))
451006f32e7eSjoerg return PE->getProtocol();
4511*13fbcb42Sjoerg if (const SubstNonTypeTemplateParmPackExpr *NTTP =
4512*13fbcb42Sjoerg dyn_cast<SubstNonTypeTemplateParmPackExpr>(E))
451306f32e7eSjoerg return NTTP->getParameterPack();
451406f32e7eSjoerg if (const SizeOfPackExpr *SizeOfPack = dyn_cast<SizeOfPackExpr>(E))
451506f32e7eSjoerg if (isa<NonTypeTemplateParmDecl>(SizeOfPack->getPack()) ||
451606f32e7eSjoerg isa<ParmVarDecl>(SizeOfPack->getPack()))
451706f32e7eSjoerg return SizeOfPack->getPack();
451806f32e7eSjoerg
451906f32e7eSjoerg return nullptr;
452006f32e7eSjoerg }
452106f32e7eSjoerg
getLocationFromExpr(const Expr * E)452206f32e7eSjoerg static SourceLocation getLocationFromExpr(const Expr *E) {
452306f32e7eSjoerg if (const ImplicitCastExpr *CE = dyn_cast<ImplicitCastExpr>(E))
452406f32e7eSjoerg return getLocationFromExpr(CE->getSubExpr());
452506f32e7eSjoerg
452606f32e7eSjoerg if (const ObjCMessageExpr *Msg = dyn_cast<ObjCMessageExpr>(E))
452706f32e7eSjoerg return /*FIXME:*/ Msg->getLeftLoc();
452806f32e7eSjoerg if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
452906f32e7eSjoerg return DRE->getLocation();
453006f32e7eSjoerg if (const MemberExpr *Member = dyn_cast<MemberExpr>(E))
453106f32e7eSjoerg return Member->getMemberLoc();
453206f32e7eSjoerg if (const ObjCIvarRefExpr *Ivar = dyn_cast<ObjCIvarRefExpr>(E))
453306f32e7eSjoerg return Ivar->getLocation();
453406f32e7eSjoerg if (const SizeOfPackExpr *SizeOfPack = dyn_cast<SizeOfPackExpr>(E))
453506f32e7eSjoerg return SizeOfPack->getPackLoc();
453606f32e7eSjoerg if (const ObjCPropertyRefExpr *PropRef = dyn_cast<ObjCPropertyRefExpr>(E))
453706f32e7eSjoerg return PropRef->getLocation();
453806f32e7eSjoerg
453906f32e7eSjoerg return E->getBeginLoc();
454006f32e7eSjoerg }
454106f32e7eSjoerg
454206f32e7eSjoerg extern "C" {
454306f32e7eSjoerg
clang_visitChildren(CXCursor parent,CXCursorVisitor visitor,CXClientData client_data)4544*13fbcb42Sjoerg unsigned clang_visitChildren(CXCursor parent, CXCursorVisitor visitor,
454506f32e7eSjoerg CXClientData client_data) {
454606f32e7eSjoerg CursorVisitor CursorVis(getCursorTU(parent), visitor, client_data,
454706f32e7eSjoerg /*VisitPreprocessorLast=*/false);
454806f32e7eSjoerg return CursorVis.VisitChildren(parent);
454906f32e7eSjoerg }
455006f32e7eSjoerg
455106f32e7eSjoerg #ifndef __has_feature
455206f32e7eSjoerg #define __has_feature(x) 0
455306f32e7eSjoerg #endif
455406f32e7eSjoerg #if __has_feature(blocks)
4555*13fbcb42Sjoerg typedef enum CXChildVisitResult (^CXCursorVisitorBlock)(CXCursor cursor,
4556*13fbcb42Sjoerg CXCursor parent);
455706f32e7eSjoerg
455806f32e7eSjoerg static enum CXChildVisitResult visitWithBlock(CXCursor cursor, CXCursor parent,
455906f32e7eSjoerg CXClientData client_data) {
456006f32e7eSjoerg CXCursorVisitorBlock block = (CXCursorVisitorBlock)client_data;
456106f32e7eSjoerg return block(cursor, parent);
456206f32e7eSjoerg }
456306f32e7eSjoerg #else
456406f32e7eSjoerg // If we are compiled with a compiler that doesn't have native blocks support,
456506f32e7eSjoerg // define and call the block manually, so the
4566*13fbcb42Sjoerg typedef struct _CXChildVisitResult {
456706f32e7eSjoerg void *isa;
456806f32e7eSjoerg int flags;
456906f32e7eSjoerg int reserved;
457006f32e7eSjoerg enum CXChildVisitResult (*invoke)(struct _CXChildVisitResult *, CXCursor,
457106f32e7eSjoerg CXCursor);
457206f32e7eSjoerg } * CXCursorVisitorBlock;
457306f32e7eSjoerg
457406f32e7eSjoerg static enum CXChildVisitResult visitWithBlock(CXCursor cursor, CXCursor parent,
457506f32e7eSjoerg CXClientData client_data) {
457606f32e7eSjoerg CXCursorVisitorBlock block = (CXCursorVisitorBlock)client_data;
457706f32e7eSjoerg return block->invoke(block, cursor, parent);
457806f32e7eSjoerg }
457906f32e7eSjoerg #endif
458006f32e7eSjoerg
458106f32e7eSjoerg unsigned clang_visitChildrenWithBlock(CXCursor parent,
458206f32e7eSjoerg CXCursorVisitorBlock block) {
458306f32e7eSjoerg return clang_visitChildren(parent, visitWithBlock, block);
458406f32e7eSjoerg }
458506f32e7eSjoerg
458606f32e7eSjoerg static CXString getDeclSpelling(const Decl *D) {
458706f32e7eSjoerg if (!D)
458806f32e7eSjoerg return cxstring::createEmpty();
458906f32e7eSjoerg
459006f32e7eSjoerg const NamedDecl *ND = dyn_cast<NamedDecl>(D);
459106f32e7eSjoerg if (!ND) {
459206f32e7eSjoerg if (const ObjCPropertyImplDecl *PropImpl =
459306f32e7eSjoerg dyn_cast<ObjCPropertyImplDecl>(D))
459406f32e7eSjoerg if (ObjCPropertyDecl *Property = PropImpl->getPropertyDecl())
459506f32e7eSjoerg return cxstring::createDup(Property->getIdentifier()->getName());
459606f32e7eSjoerg
459706f32e7eSjoerg if (const ImportDecl *ImportD = dyn_cast<ImportDecl>(D))
459806f32e7eSjoerg if (Module *Mod = ImportD->getImportedModule())
459906f32e7eSjoerg return cxstring::createDup(Mod->getFullModuleName());
460006f32e7eSjoerg
460106f32e7eSjoerg return cxstring::createEmpty();
460206f32e7eSjoerg }
460306f32e7eSjoerg
460406f32e7eSjoerg if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(ND))
460506f32e7eSjoerg return cxstring::createDup(OMD->getSelector().getAsString());
460606f32e7eSjoerg
460706f32e7eSjoerg if (const ObjCCategoryImplDecl *CIMP = dyn_cast<ObjCCategoryImplDecl>(ND))
460806f32e7eSjoerg // No, this isn't the same as the code below. getIdentifier() is non-virtual
460906f32e7eSjoerg // and returns different names. NamedDecl returns the class name and
461006f32e7eSjoerg // ObjCCategoryImplDecl returns the category name.
461106f32e7eSjoerg return cxstring::createRef(CIMP->getIdentifier()->getNameStart());
461206f32e7eSjoerg
461306f32e7eSjoerg if (isa<UsingDirectiveDecl>(D))
461406f32e7eSjoerg return cxstring::createEmpty();
461506f32e7eSjoerg
461606f32e7eSjoerg SmallString<1024> S;
461706f32e7eSjoerg llvm::raw_svector_ostream os(S);
461806f32e7eSjoerg ND->printName(os);
461906f32e7eSjoerg
462006f32e7eSjoerg return cxstring::createDup(os.str());
462106f32e7eSjoerg }
462206f32e7eSjoerg
462306f32e7eSjoerg CXString clang_getCursorSpelling(CXCursor C) {
462406f32e7eSjoerg if (clang_isTranslationUnit(C.kind))
462506f32e7eSjoerg return clang_getTranslationUnitSpelling(getCursorTU(C));
462606f32e7eSjoerg
462706f32e7eSjoerg if (clang_isReference(C.kind)) {
462806f32e7eSjoerg switch (C.kind) {
462906f32e7eSjoerg case CXCursor_ObjCSuperClassRef: {
463006f32e7eSjoerg const ObjCInterfaceDecl *Super = getCursorObjCSuperClassRef(C).first;
463106f32e7eSjoerg return cxstring::createRef(Super->getIdentifier()->getNameStart());
463206f32e7eSjoerg }
463306f32e7eSjoerg case CXCursor_ObjCClassRef: {
463406f32e7eSjoerg const ObjCInterfaceDecl *Class = getCursorObjCClassRef(C).first;
463506f32e7eSjoerg return cxstring::createRef(Class->getIdentifier()->getNameStart());
463606f32e7eSjoerg }
463706f32e7eSjoerg case CXCursor_ObjCProtocolRef: {
463806f32e7eSjoerg const ObjCProtocolDecl *OID = getCursorObjCProtocolRef(C).first;
463906f32e7eSjoerg assert(OID && "getCursorSpelling(): Missing protocol decl");
464006f32e7eSjoerg return cxstring::createRef(OID->getIdentifier()->getNameStart());
464106f32e7eSjoerg }
464206f32e7eSjoerg case CXCursor_CXXBaseSpecifier: {
464306f32e7eSjoerg const CXXBaseSpecifier *B = getCursorCXXBaseSpecifier(C);
464406f32e7eSjoerg return cxstring::createDup(B->getType().getAsString());
464506f32e7eSjoerg }
464606f32e7eSjoerg case CXCursor_TypeRef: {
464706f32e7eSjoerg const TypeDecl *Type = getCursorTypeRef(C).first;
464806f32e7eSjoerg assert(Type && "Missing type decl");
464906f32e7eSjoerg
4650*13fbcb42Sjoerg return cxstring::createDup(
4651*13fbcb42Sjoerg getCursorContext(C).getTypeDeclType(Type).getAsString());
465206f32e7eSjoerg }
465306f32e7eSjoerg case CXCursor_TemplateRef: {
465406f32e7eSjoerg const TemplateDecl *Template = getCursorTemplateRef(C).first;
465506f32e7eSjoerg assert(Template && "Missing template decl");
465606f32e7eSjoerg
465706f32e7eSjoerg return cxstring::createDup(Template->getNameAsString());
465806f32e7eSjoerg }
465906f32e7eSjoerg
466006f32e7eSjoerg case CXCursor_NamespaceRef: {
466106f32e7eSjoerg const NamedDecl *NS = getCursorNamespaceRef(C).first;
466206f32e7eSjoerg assert(NS && "Missing namespace decl");
466306f32e7eSjoerg
466406f32e7eSjoerg return cxstring::createDup(NS->getNameAsString());
466506f32e7eSjoerg }
466606f32e7eSjoerg
466706f32e7eSjoerg case CXCursor_MemberRef: {
466806f32e7eSjoerg const FieldDecl *Field = getCursorMemberRef(C).first;
466906f32e7eSjoerg assert(Field && "Missing member decl");
467006f32e7eSjoerg
467106f32e7eSjoerg return cxstring::createDup(Field->getNameAsString());
467206f32e7eSjoerg }
467306f32e7eSjoerg
467406f32e7eSjoerg case CXCursor_LabelRef: {
467506f32e7eSjoerg const LabelStmt *Label = getCursorLabelRef(C).first;
467606f32e7eSjoerg assert(Label && "Missing label");
467706f32e7eSjoerg
467806f32e7eSjoerg return cxstring::createRef(Label->getName());
467906f32e7eSjoerg }
468006f32e7eSjoerg
468106f32e7eSjoerg case CXCursor_OverloadedDeclRef: {
468206f32e7eSjoerg OverloadedDeclRefStorage Storage = getCursorOverloadedDeclRef(C).first;
468306f32e7eSjoerg if (const Decl *D = Storage.dyn_cast<const Decl *>()) {
468406f32e7eSjoerg if (const NamedDecl *ND = dyn_cast<NamedDecl>(D))
468506f32e7eSjoerg return cxstring::createDup(ND->getNameAsString());
468606f32e7eSjoerg return cxstring::createEmpty();
468706f32e7eSjoerg }
468806f32e7eSjoerg if (const OverloadExpr *E = Storage.dyn_cast<const OverloadExpr *>())
468906f32e7eSjoerg return cxstring::createDup(E->getName().getAsString());
4690*13fbcb42Sjoerg OverloadedTemplateStorage *Ovl =
4691*13fbcb42Sjoerg Storage.get<OverloadedTemplateStorage *>();
469206f32e7eSjoerg if (Ovl->size() == 0)
469306f32e7eSjoerg return cxstring::createEmpty();
469406f32e7eSjoerg return cxstring::createDup((*Ovl->begin())->getNameAsString());
469506f32e7eSjoerg }
469606f32e7eSjoerg
469706f32e7eSjoerg case CXCursor_VariableRef: {
469806f32e7eSjoerg const VarDecl *Var = getCursorVariableRef(C).first;
469906f32e7eSjoerg assert(Var && "Missing variable decl");
470006f32e7eSjoerg
470106f32e7eSjoerg return cxstring::createDup(Var->getNameAsString());
470206f32e7eSjoerg }
470306f32e7eSjoerg
470406f32e7eSjoerg default:
470506f32e7eSjoerg return cxstring::createRef("<not implemented>");
470606f32e7eSjoerg }
470706f32e7eSjoerg }
470806f32e7eSjoerg
470906f32e7eSjoerg if (clang_isExpression(C.kind)) {
471006f32e7eSjoerg const Expr *E = getCursorExpr(C);
471106f32e7eSjoerg
471206f32e7eSjoerg if (C.kind == CXCursor_ObjCStringLiteral ||
471306f32e7eSjoerg C.kind == CXCursor_StringLiteral) {
471406f32e7eSjoerg const StringLiteral *SLit;
471506f32e7eSjoerg if (const ObjCStringLiteral *OSL = dyn_cast<ObjCStringLiteral>(E)) {
471606f32e7eSjoerg SLit = OSL->getString();
471706f32e7eSjoerg } else {
471806f32e7eSjoerg SLit = cast<StringLiteral>(E);
471906f32e7eSjoerg }
472006f32e7eSjoerg SmallString<256> Buf;
472106f32e7eSjoerg llvm::raw_svector_ostream OS(Buf);
472206f32e7eSjoerg SLit->outputString(OS);
472306f32e7eSjoerg return cxstring::createDup(OS.str());
472406f32e7eSjoerg }
472506f32e7eSjoerg
472606f32e7eSjoerg const Decl *D = getDeclFromExpr(getCursorExpr(C));
472706f32e7eSjoerg if (D)
472806f32e7eSjoerg return getDeclSpelling(D);
472906f32e7eSjoerg return cxstring::createEmpty();
473006f32e7eSjoerg }
473106f32e7eSjoerg
473206f32e7eSjoerg if (clang_isStatement(C.kind)) {
473306f32e7eSjoerg const Stmt *S = getCursorStmt(C);
473406f32e7eSjoerg if (const LabelStmt *Label = dyn_cast_or_null<LabelStmt>(S))
473506f32e7eSjoerg return cxstring::createRef(Label->getName());
473606f32e7eSjoerg
473706f32e7eSjoerg return cxstring::createEmpty();
473806f32e7eSjoerg }
473906f32e7eSjoerg
474006f32e7eSjoerg if (C.kind == CXCursor_MacroExpansion)
4741*13fbcb42Sjoerg return cxstring::createRef(
4742*13fbcb42Sjoerg getCursorMacroExpansion(C).getName()->getNameStart());
474306f32e7eSjoerg
474406f32e7eSjoerg if (C.kind == CXCursor_MacroDefinition)
4745*13fbcb42Sjoerg return cxstring::createRef(
4746*13fbcb42Sjoerg getCursorMacroDefinition(C)->getName()->getNameStart());
474706f32e7eSjoerg
474806f32e7eSjoerg if (C.kind == CXCursor_InclusionDirective)
474906f32e7eSjoerg return cxstring::createDup(getCursorInclusionDirective(C)->getFileName());
475006f32e7eSjoerg
475106f32e7eSjoerg if (clang_isDeclaration(C.kind))
475206f32e7eSjoerg return getDeclSpelling(getCursorDecl(C));
475306f32e7eSjoerg
475406f32e7eSjoerg if (C.kind == CXCursor_AnnotateAttr) {
475506f32e7eSjoerg const AnnotateAttr *AA = cast<AnnotateAttr>(cxcursor::getCursorAttr(C));
475606f32e7eSjoerg return cxstring::createDup(AA->getAnnotation());
475706f32e7eSjoerg }
475806f32e7eSjoerg
475906f32e7eSjoerg if (C.kind == CXCursor_AsmLabelAttr) {
476006f32e7eSjoerg const AsmLabelAttr *AA = cast<AsmLabelAttr>(cxcursor::getCursorAttr(C));
476106f32e7eSjoerg return cxstring::createDup(AA->getLabel());
476206f32e7eSjoerg }
476306f32e7eSjoerg
476406f32e7eSjoerg if (C.kind == CXCursor_PackedAttr) {
476506f32e7eSjoerg return cxstring::createRef("packed");
476606f32e7eSjoerg }
476706f32e7eSjoerg
476806f32e7eSjoerg if (C.kind == CXCursor_VisibilityAttr) {
476906f32e7eSjoerg const VisibilityAttr *AA = cast<VisibilityAttr>(cxcursor::getCursorAttr(C));
477006f32e7eSjoerg switch (AA->getVisibility()) {
477106f32e7eSjoerg case VisibilityAttr::VisibilityType::Default:
477206f32e7eSjoerg return cxstring::createRef("default");
477306f32e7eSjoerg case VisibilityAttr::VisibilityType::Hidden:
477406f32e7eSjoerg return cxstring::createRef("hidden");
477506f32e7eSjoerg case VisibilityAttr::VisibilityType::Protected:
477606f32e7eSjoerg return cxstring::createRef("protected");
477706f32e7eSjoerg }
477806f32e7eSjoerg llvm_unreachable("unknown visibility type");
477906f32e7eSjoerg }
478006f32e7eSjoerg
478106f32e7eSjoerg return cxstring::createEmpty();
478206f32e7eSjoerg }
478306f32e7eSjoerg
4784*13fbcb42Sjoerg CXSourceRange clang_Cursor_getSpellingNameRange(CXCursor C, unsigned pieceIndex,
478506f32e7eSjoerg unsigned options) {
478606f32e7eSjoerg if (clang_Cursor_isNull(C))
478706f32e7eSjoerg return clang_getNullRange();
478806f32e7eSjoerg
478906f32e7eSjoerg ASTContext &Ctx = getCursorContext(C);
479006f32e7eSjoerg
479106f32e7eSjoerg if (clang_isStatement(C.kind)) {
479206f32e7eSjoerg const Stmt *S = getCursorStmt(C);
479306f32e7eSjoerg if (const LabelStmt *Label = dyn_cast_or_null<LabelStmt>(S)) {
479406f32e7eSjoerg if (pieceIndex > 0)
479506f32e7eSjoerg return clang_getNullRange();
479606f32e7eSjoerg return cxloc::translateSourceRange(Ctx, Label->getIdentLoc());
479706f32e7eSjoerg }
479806f32e7eSjoerg
479906f32e7eSjoerg return clang_getNullRange();
480006f32e7eSjoerg }
480106f32e7eSjoerg
480206f32e7eSjoerg if (C.kind == CXCursor_ObjCMessageExpr) {
4803*13fbcb42Sjoerg if (const ObjCMessageExpr *ME =
4804*13fbcb42Sjoerg dyn_cast_or_null<ObjCMessageExpr>(getCursorExpr(C))) {
480506f32e7eSjoerg if (pieceIndex >= ME->getNumSelectorLocs())
480606f32e7eSjoerg return clang_getNullRange();
480706f32e7eSjoerg return cxloc::translateSourceRange(Ctx, ME->getSelectorLoc(pieceIndex));
480806f32e7eSjoerg }
480906f32e7eSjoerg }
481006f32e7eSjoerg
481106f32e7eSjoerg if (C.kind == CXCursor_ObjCInstanceMethodDecl ||
481206f32e7eSjoerg C.kind == CXCursor_ObjCClassMethodDecl) {
4813*13fbcb42Sjoerg if (const ObjCMethodDecl *MD =
4814*13fbcb42Sjoerg dyn_cast_or_null<ObjCMethodDecl>(getCursorDecl(C))) {
481506f32e7eSjoerg if (pieceIndex >= MD->getNumSelectorLocs())
481606f32e7eSjoerg return clang_getNullRange();
481706f32e7eSjoerg return cxloc::translateSourceRange(Ctx, MD->getSelectorLoc(pieceIndex));
481806f32e7eSjoerg }
481906f32e7eSjoerg }
482006f32e7eSjoerg
482106f32e7eSjoerg if (C.kind == CXCursor_ObjCCategoryDecl ||
482206f32e7eSjoerg C.kind == CXCursor_ObjCCategoryImplDecl) {
482306f32e7eSjoerg if (pieceIndex > 0)
482406f32e7eSjoerg return clang_getNullRange();
4825*13fbcb42Sjoerg if (const ObjCCategoryDecl *CD =
4826*13fbcb42Sjoerg dyn_cast_or_null<ObjCCategoryDecl>(getCursorDecl(C)))
482706f32e7eSjoerg return cxloc::translateSourceRange(Ctx, CD->getCategoryNameLoc());
4828*13fbcb42Sjoerg if (const ObjCCategoryImplDecl *CID =
4829*13fbcb42Sjoerg dyn_cast_or_null<ObjCCategoryImplDecl>(getCursorDecl(C)))
483006f32e7eSjoerg return cxloc::translateSourceRange(Ctx, CID->getCategoryNameLoc());
483106f32e7eSjoerg }
483206f32e7eSjoerg
483306f32e7eSjoerg if (C.kind == CXCursor_ModuleImportDecl) {
483406f32e7eSjoerg if (pieceIndex > 0)
483506f32e7eSjoerg return clang_getNullRange();
483606f32e7eSjoerg if (const ImportDecl *ImportD =
483706f32e7eSjoerg dyn_cast_or_null<ImportDecl>(getCursorDecl(C))) {
483806f32e7eSjoerg ArrayRef<SourceLocation> Locs = ImportD->getIdentifierLocs();
483906f32e7eSjoerg if (!Locs.empty())
4840*13fbcb42Sjoerg return cxloc::translateSourceRange(
4841*13fbcb42Sjoerg Ctx, SourceRange(Locs.front(), Locs.back()));
484206f32e7eSjoerg }
484306f32e7eSjoerg return clang_getNullRange();
484406f32e7eSjoerg }
484506f32e7eSjoerg
484606f32e7eSjoerg if (C.kind == CXCursor_CXXMethod || C.kind == CXCursor_Destructor ||
484706f32e7eSjoerg C.kind == CXCursor_ConversionFunction ||
484806f32e7eSjoerg C.kind == CXCursor_FunctionDecl) {
484906f32e7eSjoerg if (pieceIndex > 0)
485006f32e7eSjoerg return clang_getNullRange();
485106f32e7eSjoerg if (const FunctionDecl *FD =
485206f32e7eSjoerg dyn_cast_or_null<FunctionDecl>(getCursorDecl(C))) {
485306f32e7eSjoerg DeclarationNameInfo FunctionName = FD->getNameInfo();
485406f32e7eSjoerg return cxloc::translateSourceRange(Ctx, FunctionName.getSourceRange());
485506f32e7eSjoerg }
485606f32e7eSjoerg return clang_getNullRange();
485706f32e7eSjoerg }
485806f32e7eSjoerg
485906f32e7eSjoerg // FIXME: A CXCursor_InclusionDirective should give the location of the
486006f32e7eSjoerg // filename, but we don't keep track of this.
486106f32e7eSjoerg
486206f32e7eSjoerg // FIXME: A CXCursor_AnnotateAttr should give the location of the annotation
486306f32e7eSjoerg // but we don't keep track of this.
486406f32e7eSjoerg
486506f32e7eSjoerg // FIXME: A CXCursor_AsmLabelAttr should give the location of the label
486606f32e7eSjoerg // but we don't keep track of this.
486706f32e7eSjoerg
486806f32e7eSjoerg // Default handling, give the location of the cursor.
486906f32e7eSjoerg
487006f32e7eSjoerg if (pieceIndex > 0)
487106f32e7eSjoerg return clang_getNullRange();
487206f32e7eSjoerg
487306f32e7eSjoerg CXSourceLocation CXLoc = clang_getCursorLocation(C);
487406f32e7eSjoerg SourceLocation Loc = cxloc::translateSourceLocation(CXLoc);
487506f32e7eSjoerg return cxloc::translateSourceRange(Ctx, Loc);
487606f32e7eSjoerg }
487706f32e7eSjoerg
487806f32e7eSjoerg CXString clang_Cursor_getMangling(CXCursor C) {
487906f32e7eSjoerg if (clang_isInvalid(C.kind) || !clang_isDeclaration(C.kind))
488006f32e7eSjoerg return cxstring::createEmpty();
488106f32e7eSjoerg
488206f32e7eSjoerg // Mangling only works for functions and variables.
488306f32e7eSjoerg const Decl *D = getCursorDecl(C);
488406f32e7eSjoerg if (!D || !(isa<FunctionDecl>(D) || isa<VarDecl>(D)))
488506f32e7eSjoerg return cxstring::createEmpty();
488606f32e7eSjoerg
488706f32e7eSjoerg ASTContext &Ctx = D->getASTContext();
488806f32e7eSjoerg ASTNameGenerator ASTNameGen(Ctx);
488906f32e7eSjoerg return cxstring::createDup(ASTNameGen.getName(D));
489006f32e7eSjoerg }
489106f32e7eSjoerg
489206f32e7eSjoerg CXStringSet *clang_Cursor_getCXXManglings(CXCursor C) {
489306f32e7eSjoerg if (clang_isInvalid(C.kind) || !clang_isDeclaration(C.kind))
489406f32e7eSjoerg return nullptr;
489506f32e7eSjoerg
489606f32e7eSjoerg const Decl *D = getCursorDecl(C);
489706f32e7eSjoerg if (!(isa<CXXRecordDecl>(D) || isa<CXXMethodDecl>(D)))
489806f32e7eSjoerg return nullptr;
489906f32e7eSjoerg
490006f32e7eSjoerg ASTContext &Ctx = D->getASTContext();
490106f32e7eSjoerg ASTNameGenerator ASTNameGen(Ctx);
490206f32e7eSjoerg std::vector<std::string> Manglings = ASTNameGen.getAllManglings(D);
490306f32e7eSjoerg return cxstring::createSet(Manglings);
490406f32e7eSjoerg }
490506f32e7eSjoerg
490606f32e7eSjoerg CXStringSet *clang_Cursor_getObjCManglings(CXCursor C) {
490706f32e7eSjoerg if (clang_isInvalid(C.kind) || !clang_isDeclaration(C.kind))
490806f32e7eSjoerg return nullptr;
490906f32e7eSjoerg
491006f32e7eSjoerg const Decl *D = getCursorDecl(C);
491106f32e7eSjoerg if (!(isa<ObjCInterfaceDecl>(D) || isa<ObjCImplementationDecl>(D)))
491206f32e7eSjoerg return nullptr;
491306f32e7eSjoerg
491406f32e7eSjoerg ASTContext &Ctx = D->getASTContext();
491506f32e7eSjoerg ASTNameGenerator ASTNameGen(Ctx);
491606f32e7eSjoerg std::vector<std::string> Manglings = ASTNameGen.getAllManglings(D);
491706f32e7eSjoerg return cxstring::createSet(Manglings);
491806f32e7eSjoerg }
491906f32e7eSjoerg
492006f32e7eSjoerg CXPrintingPolicy clang_getCursorPrintingPolicy(CXCursor C) {
492106f32e7eSjoerg if (clang_Cursor_isNull(C))
492206f32e7eSjoerg return 0;
492306f32e7eSjoerg return new PrintingPolicy(getCursorContext(C).getPrintingPolicy());
492406f32e7eSjoerg }
492506f32e7eSjoerg
492606f32e7eSjoerg void clang_PrintingPolicy_dispose(CXPrintingPolicy Policy) {
492706f32e7eSjoerg if (Policy)
492806f32e7eSjoerg delete static_cast<PrintingPolicy *>(Policy);
492906f32e7eSjoerg }
493006f32e7eSjoerg
493106f32e7eSjoerg unsigned
493206f32e7eSjoerg clang_PrintingPolicy_getProperty(CXPrintingPolicy Policy,
493306f32e7eSjoerg enum CXPrintingPolicyProperty Property) {
493406f32e7eSjoerg if (!Policy)
493506f32e7eSjoerg return 0;
493606f32e7eSjoerg
493706f32e7eSjoerg PrintingPolicy *P = static_cast<PrintingPolicy *>(Policy);
493806f32e7eSjoerg switch (Property) {
493906f32e7eSjoerg case CXPrintingPolicy_Indentation:
494006f32e7eSjoerg return P->Indentation;
494106f32e7eSjoerg case CXPrintingPolicy_SuppressSpecifiers:
494206f32e7eSjoerg return P->SuppressSpecifiers;
494306f32e7eSjoerg case CXPrintingPolicy_SuppressTagKeyword:
494406f32e7eSjoerg return P->SuppressTagKeyword;
494506f32e7eSjoerg case CXPrintingPolicy_IncludeTagDefinition:
494606f32e7eSjoerg return P->IncludeTagDefinition;
494706f32e7eSjoerg case CXPrintingPolicy_SuppressScope:
494806f32e7eSjoerg return P->SuppressScope;
494906f32e7eSjoerg case CXPrintingPolicy_SuppressUnwrittenScope:
495006f32e7eSjoerg return P->SuppressUnwrittenScope;
495106f32e7eSjoerg case CXPrintingPolicy_SuppressInitializers:
495206f32e7eSjoerg return P->SuppressInitializers;
495306f32e7eSjoerg case CXPrintingPolicy_ConstantArraySizeAsWritten:
495406f32e7eSjoerg return P->ConstantArraySizeAsWritten;
495506f32e7eSjoerg case CXPrintingPolicy_AnonymousTagLocations:
495606f32e7eSjoerg return P->AnonymousTagLocations;
495706f32e7eSjoerg case CXPrintingPolicy_SuppressStrongLifetime:
495806f32e7eSjoerg return P->SuppressStrongLifetime;
495906f32e7eSjoerg case CXPrintingPolicy_SuppressLifetimeQualifiers:
496006f32e7eSjoerg return P->SuppressLifetimeQualifiers;
496106f32e7eSjoerg case CXPrintingPolicy_SuppressTemplateArgsInCXXConstructors:
496206f32e7eSjoerg return P->SuppressTemplateArgsInCXXConstructors;
496306f32e7eSjoerg case CXPrintingPolicy_Bool:
496406f32e7eSjoerg return P->Bool;
496506f32e7eSjoerg case CXPrintingPolicy_Restrict:
496606f32e7eSjoerg return P->Restrict;
496706f32e7eSjoerg case CXPrintingPolicy_Alignof:
496806f32e7eSjoerg return P->Alignof;
496906f32e7eSjoerg case CXPrintingPolicy_UnderscoreAlignof:
497006f32e7eSjoerg return P->UnderscoreAlignof;
497106f32e7eSjoerg case CXPrintingPolicy_UseVoidForZeroParams:
497206f32e7eSjoerg return P->UseVoidForZeroParams;
497306f32e7eSjoerg case CXPrintingPolicy_TerseOutput:
497406f32e7eSjoerg return P->TerseOutput;
497506f32e7eSjoerg case CXPrintingPolicy_PolishForDeclaration:
497606f32e7eSjoerg return P->PolishForDeclaration;
497706f32e7eSjoerg case CXPrintingPolicy_Half:
497806f32e7eSjoerg return P->Half;
497906f32e7eSjoerg case CXPrintingPolicy_MSWChar:
498006f32e7eSjoerg return P->MSWChar;
498106f32e7eSjoerg case CXPrintingPolicy_IncludeNewlines:
498206f32e7eSjoerg return P->IncludeNewlines;
498306f32e7eSjoerg case CXPrintingPolicy_MSVCFormatting:
498406f32e7eSjoerg return P->MSVCFormatting;
498506f32e7eSjoerg case CXPrintingPolicy_ConstantsAsWritten:
498606f32e7eSjoerg return P->ConstantsAsWritten;
498706f32e7eSjoerg case CXPrintingPolicy_SuppressImplicitBase:
498806f32e7eSjoerg return P->SuppressImplicitBase;
498906f32e7eSjoerg case CXPrintingPolicy_FullyQualifiedName:
499006f32e7eSjoerg return P->FullyQualifiedName;
499106f32e7eSjoerg }
499206f32e7eSjoerg
499306f32e7eSjoerg assert(false && "Invalid CXPrintingPolicyProperty");
499406f32e7eSjoerg return 0;
499506f32e7eSjoerg }
499606f32e7eSjoerg
499706f32e7eSjoerg void clang_PrintingPolicy_setProperty(CXPrintingPolicy Policy,
499806f32e7eSjoerg enum CXPrintingPolicyProperty Property,
499906f32e7eSjoerg unsigned Value) {
500006f32e7eSjoerg if (!Policy)
500106f32e7eSjoerg return;
500206f32e7eSjoerg
500306f32e7eSjoerg PrintingPolicy *P = static_cast<PrintingPolicy *>(Policy);
500406f32e7eSjoerg switch (Property) {
500506f32e7eSjoerg case CXPrintingPolicy_Indentation:
500606f32e7eSjoerg P->Indentation = Value;
500706f32e7eSjoerg return;
500806f32e7eSjoerg case CXPrintingPolicy_SuppressSpecifiers:
500906f32e7eSjoerg P->SuppressSpecifiers = Value;
501006f32e7eSjoerg return;
501106f32e7eSjoerg case CXPrintingPolicy_SuppressTagKeyword:
501206f32e7eSjoerg P->SuppressTagKeyword = Value;
501306f32e7eSjoerg return;
501406f32e7eSjoerg case CXPrintingPolicy_IncludeTagDefinition:
501506f32e7eSjoerg P->IncludeTagDefinition = Value;
501606f32e7eSjoerg return;
501706f32e7eSjoerg case CXPrintingPolicy_SuppressScope:
501806f32e7eSjoerg P->SuppressScope = Value;
501906f32e7eSjoerg return;
502006f32e7eSjoerg case CXPrintingPolicy_SuppressUnwrittenScope:
502106f32e7eSjoerg P->SuppressUnwrittenScope = Value;
502206f32e7eSjoerg return;
502306f32e7eSjoerg case CXPrintingPolicy_SuppressInitializers:
502406f32e7eSjoerg P->SuppressInitializers = Value;
502506f32e7eSjoerg return;
502606f32e7eSjoerg case CXPrintingPolicy_ConstantArraySizeAsWritten:
502706f32e7eSjoerg P->ConstantArraySizeAsWritten = Value;
502806f32e7eSjoerg return;
502906f32e7eSjoerg case CXPrintingPolicy_AnonymousTagLocations:
503006f32e7eSjoerg P->AnonymousTagLocations = Value;
503106f32e7eSjoerg return;
503206f32e7eSjoerg case CXPrintingPolicy_SuppressStrongLifetime:
503306f32e7eSjoerg P->SuppressStrongLifetime = Value;
503406f32e7eSjoerg return;
503506f32e7eSjoerg case CXPrintingPolicy_SuppressLifetimeQualifiers:
503606f32e7eSjoerg P->SuppressLifetimeQualifiers = Value;
503706f32e7eSjoerg return;
503806f32e7eSjoerg case CXPrintingPolicy_SuppressTemplateArgsInCXXConstructors:
503906f32e7eSjoerg P->SuppressTemplateArgsInCXXConstructors = Value;
504006f32e7eSjoerg return;
504106f32e7eSjoerg case CXPrintingPolicy_Bool:
504206f32e7eSjoerg P->Bool = Value;
504306f32e7eSjoerg return;
504406f32e7eSjoerg case CXPrintingPolicy_Restrict:
504506f32e7eSjoerg P->Restrict = Value;
504606f32e7eSjoerg return;
504706f32e7eSjoerg case CXPrintingPolicy_Alignof:
504806f32e7eSjoerg P->Alignof = Value;
504906f32e7eSjoerg return;
505006f32e7eSjoerg case CXPrintingPolicy_UnderscoreAlignof:
505106f32e7eSjoerg P->UnderscoreAlignof = Value;
505206f32e7eSjoerg return;
505306f32e7eSjoerg case CXPrintingPolicy_UseVoidForZeroParams:
505406f32e7eSjoerg P->UseVoidForZeroParams = Value;
505506f32e7eSjoerg return;
505606f32e7eSjoerg case CXPrintingPolicy_TerseOutput:
505706f32e7eSjoerg P->TerseOutput = Value;
505806f32e7eSjoerg return;
505906f32e7eSjoerg case CXPrintingPolicy_PolishForDeclaration:
506006f32e7eSjoerg P->PolishForDeclaration = Value;
506106f32e7eSjoerg return;
506206f32e7eSjoerg case CXPrintingPolicy_Half:
506306f32e7eSjoerg P->Half = Value;
506406f32e7eSjoerg return;
506506f32e7eSjoerg case CXPrintingPolicy_MSWChar:
506606f32e7eSjoerg P->MSWChar = Value;
506706f32e7eSjoerg return;
506806f32e7eSjoerg case CXPrintingPolicy_IncludeNewlines:
506906f32e7eSjoerg P->IncludeNewlines = Value;
507006f32e7eSjoerg return;
507106f32e7eSjoerg case CXPrintingPolicy_MSVCFormatting:
507206f32e7eSjoerg P->MSVCFormatting = Value;
507306f32e7eSjoerg return;
507406f32e7eSjoerg case CXPrintingPolicy_ConstantsAsWritten:
507506f32e7eSjoerg P->ConstantsAsWritten = Value;
507606f32e7eSjoerg return;
507706f32e7eSjoerg case CXPrintingPolicy_SuppressImplicitBase:
507806f32e7eSjoerg P->SuppressImplicitBase = Value;
507906f32e7eSjoerg return;
508006f32e7eSjoerg case CXPrintingPolicy_FullyQualifiedName:
508106f32e7eSjoerg P->FullyQualifiedName = Value;
508206f32e7eSjoerg return;
508306f32e7eSjoerg }
508406f32e7eSjoerg
508506f32e7eSjoerg assert(false && "Invalid CXPrintingPolicyProperty");
508606f32e7eSjoerg }
508706f32e7eSjoerg
508806f32e7eSjoerg CXString clang_getCursorPrettyPrinted(CXCursor C, CXPrintingPolicy cxPolicy) {
508906f32e7eSjoerg if (clang_Cursor_isNull(C))
509006f32e7eSjoerg return cxstring::createEmpty();
509106f32e7eSjoerg
509206f32e7eSjoerg if (clang_isDeclaration(C.kind)) {
509306f32e7eSjoerg const Decl *D = getCursorDecl(C);
509406f32e7eSjoerg if (!D)
509506f32e7eSjoerg return cxstring::createEmpty();
509606f32e7eSjoerg
509706f32e7eSjoerg SmallString<128> Str;
509806f32e7eSjoerg llvm::raw_svector_ostream OS(Str);
509906f32e7eSjoerg PrintingPolicy *UserPolicy = static_cast<PrintingPolicy *>(cxPolicy);
510006f32e7eSjoerg D->print(OS, UserPolicy ? *UserPolicy
510106f32e7eSjoerg : getCursorContext(C).getPrintingPolicy());
510206f32e7eSjoerg
510306f32e7eSjoerg return cxstring::createDup(OS.str());
510406f32e7eSjoerg }
510506f32e7eSjoerg
510606f32e7eSjoerg return cxstring::createEmpty();
510706f32e7eSjoerg }
510806f32e7eSjoerg
510906f32e7eSjoerg CXString clang_getCursorDisplayName(CXCursor C) {
511006f32e7eSjoerg if (!clang_isDeclaration(C.kind))
511106f32e7eSjoerg return clang_getCursorSpelling(C);
511206f32e7eSjoerg
511306f32e7eSjoerg const Decl *D = getCursorDecl(C);
511406f32e7eSjoerg if (!D)
511506f32e7eSjoerg return cxstring::createEmpty();
511606f32e7eSjoerg
511706f32e7eSjoerg PrintingPolicy Policy = getCursorContext(C).getPrintingPolicy();
511806f32e7eSjoerg if (const FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(D))
511906f32e7eSjoerg D = FunTmpl->getTemplatedDecl();
512006f32e7eSjoerg
512106f32e7eSjoerg if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
512206f32e7eSjoerg SmallString<64> Str;
512306f32e7eSjoerg llvm::raw_svector_ostream OS(Str);
512406f32e7eSjoerg OS << *Function;
512506f32e7eSjoerg if (Function->getPrimaryTemplate())
512606f32e7eSjoerg OS << "<>";
512706f32e7eSjoerg OS << "(";
512806f32e7eSjoerg for (unsigned I = 0, N = Function->getNumParams(); I != N; ++I) {
512906f32e7eSjoerg if (I)
513006f32e7eSjoerg OS << ", ";
513106f32e7eSjoerg OS << Function->getParamDecl(I)->getType().getAsString(Policy);
513206f32e7eSjoerg }
513306f32e7eSjoerg
513406f32e7eSjoerg if (Function->isVariadic()) {
513506f32e7eSjoerg if (Function->getNumParams())
513606f32e7eSjoerg OS << ", ";
513706f32e7eSjoerg OS << "...";
513806f32e7eSjoerg }
513906f32e7eSjoerg OS << ")";
514006f32e7eSjoerg return cxstring::createDup(OS.str());
514106f32e7eSjoerg }
514206f32e7eSjoerg
514306f32e7eSjoerg if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(D)) {
514406f32e7eSjoerg SmallString<64> Str;
514506f32e7eSjoerg llvm::raw_svector_ostream OS(Str);
514606f32e7eSjoerg OS << *ClassTemplate;
514706f32e7eSjoerg OS << "<";
514806f32e7eSjoerg TemplateParameterList *Params = ClassTemplate->getTemplateParameters();
514906f32e7eSjoerg for (unsigned I = 0, N = Params->size(); I != N; ++I) {
515006f32e7eSjoerg if (I)
515106f32e7eSjoerg OS << ", ";
515206f32e7eSjoerg
515306f32e7eSjoerg NamedDecl *Param = Params->getParam(I);
515406f32e7eSjoerg if (Param->getIdentifier()) {
515506f32e7eSjoerg OS << Param->getIdentifier()->getName();
515606f32e7eSjoerg continue;
515706f32e7eSjoerg }
515806f32e7eSjoerg
515906f32e7eSjoerg // There is no parameter name, which makes this tricky. Try to come up
516006f32e7eSjoerg // with something useful that isn't too long.
516106f32e7eSjoerg if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
5162*13fbcb42Sjoerg if (const auto *TC = TTP->getTypeConstraint()) {
5163*13fbcb42Sjoerg TC->getConceptNameInfo().printName(OS, Policy);
5164*13fbcb42Sjoerg if (TC->hasExplicitTemplateArgs())
5165*13fbcb42Sjoerg OS << "<...>";
5166*13fbcb42Sjoerg } else
516706f32e7eSjoerg OS << (TTP->wasDeclaredWithTypename() ? "typename" : "class");
5168*13fbcb42Sjoerg else if (NonTypeTemplateParmDecl *NTTP =
5169*13fbcb42Sjoerg dyn_cast<NonTypeTemplateParmDecl>(Param))
517006f32e7eSjoerg OS << NTTP->getType().getAsString(Policy);
517106f32e7eSjoerg else
517206f32e7eSjoerg OS << "template<...> class";
517306f32e7eSjoerg }
517406f32e7eSjoerg
517506f32e7eSjoerg OS << ">";
517606f32e7eSjoerg return cxstring::createDup(OS.str());
517706f32e7eSjoerg }
517806f32e7eSjoerg
5179*13fbcb42Sjoerg if (const ClassTemplateSpecializationDecl *ClassSpec =
5180*13fbcb42Sjoerg dyn_cast<ClassTemplateSpecializationDecl>(D)) {
518106f32e7eSjoerg // If the type was explicitly written, use that.
518206f32e7eSjoerg if (TypeSourceInfo *TSInfo = ClassSpec->getTypeAsWritten())
518306f32e7eSjoerg return cxstring::createDup(TSInfo->getType().getAsString(Policy));
518406f32e7eSjoerg
518506f32e7eSjoerg SmallString<128> Str;
518606f32e7eSjoerg llvm::raw_svector_ostream OS(Str);
518706f32e7eSjoerg OS << *ClassSpec;
5188*13fbcb42Sjoerg printTemplateArgumentList(
5189*13fbcb42Sjoerg OS, ClassSpec->getTemplateArgs().asArray(), Policy,
5190*13fbcb42Sjoerg ClassSpec->getSpecializedTemplate()->getTemplateParameters());
519106f32e7eSjoerg return cxstring::createDup(OS.str());
519206f32e7eSjoerg }
519306f32e7eSjoerg
519406f32e7eSjoerg return clang_getCursorSpelling(C);
519506f32e7eSjoerg }
519606f32e7eSjoerg
519706f32e7eSjoerg CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) {
519806f32e7eSjoerg switch (Kind) {
519906f32e7eSjoerg case CXCursor_FunctionDecl:
520006f32e7eSjoerg return cxstring::createRef("FunctionDecl");
520106f32e7eSjoerg case CXCursor_TypedefDecl:
520206f32e7eSjoerg return cxstring::createRef("TypedefDecl");
520306f32e7eSjoerg case CXCursor_EnumDecl:
520406f32e7eSjoerg return cxstring::createRef("EnumDecl");
520506f32e7eSjoerg case CXCursor_EnumConstantDecl:
520606f32e7eSjoerg return cxstring::createRef("EnumConstantDecl");
520706f32e7eSjoerg case CXCursor_StructDecl:
520806f32e7eSjoerg return cxstring::createRef("StructDecl");
520906f32e7eSjoerg case CXCursor_UnionDecl:
521006f32e7eSjoerg return cxstring::createRef("UnionDecl");
521106f32e7eSjoerg case CXCursor_ClassDecl:
521206f32e7eSjoerg return cxstring::createRef("ClassDecl");
521306f32e7eSjoerg case CXCursor_FieldDecl:
521406f32e7eSjoerg return cxstring::createRef("FieldDecl");
521506f32e7eSjoerg case CXCursor_VarDecl:
521606f32e7eSjoerg return cxstring::createRef("VarDecl");
521706f32e7eSjoerg case CXCursor_ParmDecl:
521806f32e7eSjoerg return cxstring::createRef("ParmDecl");
521906f32e7eSjoerg case CXCursor_ObjCInterfaceDecl:
522006f32e7eSjoerg return cxstring::createRef("ObjCInterfaceDecl");
522106f32e7eSjoerg case CXCursor_ObjCCategoryDecl:
522206f32e7eSjoerg return cxstring::createRef("ObjCCategoryDecl");
522306f32e7eSjoerg case CXCursor_ObjCProtocolDecl:
522406f32e7eSjoerg return cxstring::createRef("ObjCProtocolDecl");
522506f32e7eSjoerg case CXCursor_ObjCPropertyDecl:
522606f32e7eSjoerg return cxstring::createRef("ObjCPropertyDecl");
522706f32e7eSjoerg case CXCursor_ObjCIvarDecl:
522806f32e7eSjoerg return cxstring::createRef("ObjCIvarDecl");
522906f32e7eSjoerg case CXCursor_ObjCInstanceMethodDecl:
523006f32e7eSjoerg return cxstring::createRef("ObjCInstanceMethodDecl");
523106f32e7eSjoerg case CXCursor_ObjCClassMethodDecl:
523206f32e7eSjoerg return cxstring::createRef("ObjCClassMethodDecl");
523306f32e7eSjoerg case CXCursor_ObjCImplementationDecl:
523406f32e7eSjoerg return cxstring::createRef("ObjCImplementationDecl");
523506f32e7eSjoerg case CXCursor_ObjCCategoryImplDecl:
523606f32e7eSjoerg return cxstring::createRef("ObjCCategoryImplDecl");
523706f32e7eSjoerg case CXCursor_CXXMethod:
523806f32e7eSjoerg return cxstring::createRef("CXXMethod");
523906f32e7eSjoerg case CXCursor_UnexposedDecl:
524006f32e7eSjoerg return cxstring::createRef("UnexposedDecl");
524106f32e7eSjoerg case CXCursor_ObjCSuperClassRef:
524206f32e7eSjoerg return cxstring::createRef("ObjCSuperClassRef");
524306f32e7eSjoerg case CXCursor_ObjCProtocolRef:
524406f32e7eSjoerg return cxstring::createRef("ObjCProtocolRef");
524506f32e7eSjoerg case CXCursor_ObjCClassRef:
524606f32e7eSjoerg return cxstring::createRef("ObjCClassRef");
524706f32e7eSjoerg case CXCursor_TypeRef:
524806f32e7eSjoerg return cxstring::createRef("TypeRef");
524906f32e7eSjoerg case CXCursor_TemplateRef:
525006f32e7eSjoerg return cxstring::createRef("TemplateRef");
525106f32e7eSjoerg case CXCursor_NamespaceRef:
525206f32e7eSjoerg return cxstring::createRef("NamespaceRef");
525306f32e7eSjoerg case CXCursor_MemberRef:
525406f32e7eSjoerg return cxstring::createRef("MemberRef");
525506f32e7eSjoerg case CXCursor_LabelRef:
525606f32e7eSjoerg return cxstring::createRef("LabelRef");
525706f32e7eSjoerg case CXCursor_OverloadedDeclRef:
525806f32e7eSjoerg return cxstring::createRef("OverloadedDeclRef");
525906f32e7eSjoerg case CXCursor_VariableRef:
526006f32e7eSjoerg return cxstring::createRef("VariableRef");
526106f32e7eSjoerg case CXCursor_IntegerLiteral:
526206f32e7eSjoerg return cxstring::createRef("IntegerLiteral");
526306f32e7eSjoerg case CXCursor_FixedPointLiteral:
526406f32e7eSjoerg return cxstring::createRef("FixedPointLiteral");
526506f32e7eSjoerg case CXCursor_FloatingLiteral:
526606f32e7eSjoerg return cxstring::createRef("FloatingLiteral");
526706f32e7eSjoerg case CXCursor_ImaginaryLiteral:
526806f32e7eSjoerg return cxstring::createRef("ImaginaryLiteral");
526906f32e7eSjoerg case CXCursor_StringLiteral:
527006f32e7eSjoerg return cxstring::createRef("StringLiteral");
527106f32e7eSjoerg case CXCursor_CharacterLiteral:
527206f32e7eSjoerg return cxstring::createRef("CharacterLiteral");
527306f32e7eSjoerg case CXCursor_ParenExpr:
527406f32e7eSjoerg return cxstring::createRef("ParenExpr");
527506f32e7eSjoerg case CXCursor_UnaryOperator:
527606f32e7eSjoerg return cxstring::createRef("UnaryOperator");
527706f32e7eSjoerg case CXCursor_ArraySubscriptExpr:
527806f32e7eSjoerg return cxstring::createRef("ArraySubscriptExpr");
527906f32e7eSjoerg case CXCursor_OMPArraySectionExpr:
528006f32e7eSjoerg return cxstring::createRef("OMPArraySectionExpr");
5281*13fbcb42Sjoerg case CXCursor_OMPArrayShapingExpr:
5282*13fbcb42Sjoerg return cxstring::createRef("OMPArrayShapingExpr");
5283*13fbcb42Sjoerg case CXCursor_OMPIteratorExpr:
5284*13fbcb42Sjoerg return cxstring::createRef("OMPIteratorExpr");
528506f32e7eSjoerg case CXCursor_BinaryOperator:
528606f32e7eSjoerg return cxstring::createRef("BinaryOperator");
528706f32e7eSjoerg case CXCursor_CompoundAssignOperator:
528806f32e7eSjoerg return cxstring::createRef("CompoundAssignOperator");
528906f32e7eSjoerg case CXCursor_ConditionalOperator:
529006f32e7eSjoerg return cxstring::createRef("ConditionalOperator");
529106f32e7eSjoerg case CXCursor_CStyleCastExpr:
529206f32e7eSjoerg return cxstring::createRef("CStyleCastExpr");
529306f32e7eSjoerg case CXCursor_CompoundLiteralExpr:
529406f32e7eSjoerg return cxstring::createRef("CompoundLiteralExpr");
529506f32e7eSjoerg case CXCursor_InitListExpr:
529606f32e7eSjoerg return cxstring::createRef("InitListExpr");
529706f32e7eSjoerg case CXCursor_AddrLabelExpr:
529806f32e7eSjoerg return cxstring::createRef("AddrLabelExpr");
529906f32e7eSjoerg case CXCursor_StmtExpr:
530006f32e7eSjoerg return cxstring::createRef("StmtExpr");
530106f32e7eSjoerg case CXCursor_GenericSelectionExpr:
530206f32e7eSjoerg return cxstring::createRef("GenericSelectionExpr");
530306f32e7eSjoerg case CXCursor_GNUNullExpr:
530406f32e7eSjoerg return cxstring::createRef("GNUNullExpr");
530506f32e7eSjoerg case CXCursor_CXXStaticCastExpr:
530606f32e7eSjoerg return cxstring::createRef("CXXStaticCastExpr");
530706f32e7eSjoerg case CXCursor_CXXDynamicCastExpr:
530806f32e7eSjoerg return cxstring::createRef("CXXDynamicCastExpr");
530906f32e7eSjoerg case CXCursor_CXXReinterpretCastExpr:
531006f32e7eSjoerg return cxstring::createRef("CXXReinterpretCastExpr");
531106f32e7eSjoerg case CXCursor_CXXConstCastExpr:
531206f32e7eSjoerg return cxstring::createRef("CXXConstCastExpr");
531306f32e7eSjoerg case CXCursor_CXXFunctionalCastExpr:
531406f32e7eSjoerg return cxstring::createRef("CXXFunctionalCastExpr");
5315*13fbcb42Sjoerg case CXCursor_CXXAddrspaceCastExpr:
5316*13fbcb42Sjoerg return cxstring::createRef("CXXAddrspaceCastExpr");
531706f32e7eSjoerg case CXCursor_CXXTypeidExpr:
531806f32e7eSjoerg return cxstring::createRef("CXXTypeidExpr");
531906f32e7eSjoerg case CXCursor_CXXBoolLiteralExpr:
532006f32e7eSjoerg return cxstring::createRef("CXXBoolLiteralExpr");
532106f32e7eSjoerg case CXCursor_CXXNullPtrLiteralExpr:
532206f32e7eSjoerg return cxstring::createRef("CXXNullPtrLiteralExpr");
532306f32e7eSjoerg case CXCursor_CXXThisExpr:
532406f32e7eSjoerg return cxstring::createRef("CXXThisExpr");
532506f32e7eSjoerg case CXCursor_CXXThrowExpr:
532606f32e7eSjoerg return cxstring::createRef("CXXThrowExpr");
532706f32e7eSjoerg case CXCursor_CXXNewExpr:
532806f32e7eSjoerg return cxstring::createRef("CXXNewExpr");
532906f32e7eSjoerg case CXCursor_CXXDeleteExpr:
533006f32e7eSjoerg return cxstring::createRef("CXXDeleteExpr");
533106f32e7eSjoerg case CXCursor_UnaryExpr:
533206f32e7eSjoerg return cxstring::createRef("UnaryExpr");
533306f32e7eSjoerg case CXCursor_ObjCStringLiteral:
533406f32e7eSjoerg return cxstring::createRef("ObjCStringLiteral");
533506f32e7eSjoerg case CXCursor_ObjCBoolLiteralExpr:
533606f32e7eSjoerg return cxstring::createRef("ObjCBoolLiteralExpr");
533706f32e7eSjoerg case CXCursor_ObjCAvailabilityCheckExpr:
533806f32e7eSjoerg return cxstring::createRef("ObjCAvailabilityCheckExpr");
533906f32e7eSjoerg case CXCursor_ObjCSelfExpr:
534006f32e7eSjoerg return cxstring::createRef("ObjCSelfExpr");
534106f32e7eSjoerg case CXCursor_ObjCEncodeExpr:
534206f32e7eSjoerg return cxstring::createRef("ObjCEncodeExpr");
534306f32e7eSjoerg case CXCursor_ObjCSelectorExpr:
534406f32e7eSjoerg return cxstring::createRef("ObjCSelectorExpr");
534506f32e7eSjoerg case CXCursor_ObjCProtocolExpr:
534606f32e7eSjoerg return cxstring::createRef("ObjCProtocolExpr");
534706f32e7eSjoerg case CXCursor_ObjCBridgedCastExpr:
534806f32e7eSjoerg return cxstring::createRef("ObjCBridgedCastExpr");
534906f32e7eSjoerg case CXCursor_BlockExpr:
535006f32e7eSjoerg return cxstring::createRef("BlockExpr");
535106f32e7eSjoerg case CXCursor_PackExpansionExpr:
535206f32e7eSjoerg return cxstring::createRef("PackExpansionExpr");
535306f32e7eSjoerg case CXCursor_SizeOfPackExpr:
535406f32e7eSjoerg return cxstring::createRef("SizeOfPackExpr");
535506f32e7eSjoerg case CXCursor_LambdaExpr:
535606f32e7eSjoerg return cxstring::createRef("LambdaExpr");
535706f32e7eSjoerg case CXCursor_UnexposedExpr:
535806f32e7eSjoerg return cxstring::createRef("UnexposedExpr");
535906f32e7eSjoerg case CXCursor_DeclRefExpr:
536006f32e7eSjoerg return cxstring::createRef("DeclRefExpr");
536106f32e7eSjoerg case CXCursor_MemberRefExpr:
536206f32e7eSjoerg return cxstring::createRef("MemberRefExpr");
536306f32e7eSjoerg case CXCursor_CallExpr:
536406f32e7eSjoerg return cxstring::createRef("CallExpr");
536506f32e7eSjoerg case CXCursor_ObjCMessageExpr:
536606f32e7eSjoerg return cxstring::createRef("ObjCMessageExpr");
536706f32e7eSjoerg case CXCursor_BuiltinBitCastExpr:
536806f32e7eSjoerg return cxstring::createRef("BuiltinBitCastExpr");
536906f32e7eSjoerg case CXCursor_UnexposedStmt:
537006f32e7eSjoerg return cxstring::createRef("UnexposedStmt");
537106f32e7eSjoerg case CXCursor_DeclStmt:
537206f32e7eSjoerg return cxstring::createRef("DeclStmt");
537306f32e7eSjoerg case CXCursor_LabelStmt:
537406f32e7eSjoerg return cxstring::createRef("LabelStmt");
537506f32e7eSjoerg case CXCursor_CompoundStmt:
537606f32e7eSjoerg return cxstring::createRef("CompoundStmt");
537706f32e7eSjoerg case CXCursor_CaseStmt:
537806f32e7eSjoerg return cxstring::createRef("CaseStmt");
537906f32e7eSjoerg case CXCursor_DefaultStmt:
538006f32e7eSjoerg return cxstring::createRef("DefaultStmt");
538106f32e7eSjoerg case CXCursor_IfStmt:
538206f32e7eSjoerg return cxstring::createRef("IfStmt");
538306f32e7eSjoerg case CXCursor_SwitchStmt:
538406f32e7eSjoerg return cxstring::createRef("SwitchStmt");
538506f32e7eSjoerg case CXCursor_WhileStmt:
538606f32e7eSjoerg return cxstring::createRef("WhileStmt");
538706f32e7eSjoerg case CXCursor_DoStmt:
538806f32e7eSjoerg return cxstring::createRef("DoStmt");
538906f32e7eSjoerg case CXCursor_ForStmt:
539006f32e7eSjoerg return cxstring::createRef("ForStmt");
539106f32e7eSjoerg case CXCursor_GotoStmt:
539206f32e7eSjoerg return cxstring::createRef("GotoStmt");
539306f32e7eSjoerg case CXCursor_IndirectGotoStmt:
539406f32e7eSjoerg return cxstring::createRef("IndirectGotoStmt");
539506f32e7eSjoerg case CXCursor_ContinueStmt:
539606f32e7eSjoerg return cxstring::createRef("ContinueStmt");
539706f32e7eSjoerg case CXCursor_BreakStmt:
539806f32e7eSjoerg return cxstring::createRef("BreakStmt");
539906f32e7eSjoerg case CXCursor_ReturnStmt:
540006f32e7eSjoerg return cxstring::createRef("ReturnStmt");
540106f32e7eSjoerg case CXCursor_GCCAsmStmt:
540206f32e7eSjoerg return cxstring::createRef("GCCAsmStmt");
540306f32e7eSjoerg case CXCursor_MSAsmStmt:
540406f32e7eSjoerg return cxstring::createRef("MSAsmStmt");
540506f32e7eSjoerg case CXCursor_ObjCAtTryStmt:
540606f32e7eSjoerg return cxstring::createRef("ObjCAtTryStmt");
540706f32e7eSjoerg case CXCursor_ObjCAtCatchStmt:
540806f32e7eSjoerg return cxstring::createRef("ObjCAtCatchStmt");
540906f32e7eSjoerg case CXCursor_ObjCAtFinallyStmt:
541006f32e7eSjoerg return cxstring::createRef("ObjCAtFinallyStmt");
541106f32e7eSjoerg case CXCursor_ObjCAtThrowStmt:
541206f32e7eSjoerg return cxstring::createRef("ObjCAtThrowStmt");
541306f32e7eSjoerg case CXCursor_ObjCAtSynchronizedStmt:
541406f32e7eSjoerg return cxstring::createRef("ObjCAtSynchronizedStmt");
541506f32e7eSjoerg case CXCursor_ObjCAutoreleasePoolStmt:
541606f32e7eSjoerg return cxstring::createRef("ObjCAutoreleasePoolStmt");
541706f32e7eSjoerg case CXCursor_ObjCForCollectionStmt:
541806f32e7eSjoerg return cxstring::createRef("ObjCForCollectionStmt");
541906f32e7eSjoerg case CXCursor_CXXCatchStmt:
542006f32e7eSjoerg return cxstring::createRef("CXXCatchStmt");
542106f32e7eSjoerg case CXCursor_CXXTryStmt:
542206f32e7eSjoerg return cxstring::createRef("CXXTryStmt");
542306f32e7eSjoerg case CXCursor_CXXForRangeStmt:
542406f32e7eSjoerg return cxstring::createRef("CXXForRangeStmt");
542506f32e7eSjoerg case CXCursor_SEHTryStmt:
542606f32e7eSjoerg return cxstring::createRef("SEHTryStmt");
542706f32e7eSjoerg case CXCursor_SEHExceptStmt:
542806f32e7eSjoerg return cxstring::createRef("SEHExceptStmt");
542906f32e7eSjoerg case CXCursor_SEHFinallyStmt:
543006f32e7eSjoerg return cxstring::createRef("SEHFinallyStmt");
543106f32e7eSjoerg case CXCursor_SEHLeaveStmt:
543206f32e7eSjoerg return cxstring::createRef("SEHLeaveStmt");
543306f32e7eSjoerg case CXCursor_NullStmt:
543406f32e7eSjoerg return cxstring::createRef("NullStmt");
543506f32e7eSjoerg case CXCursor_InvalidFile:
543606f32e7eSjoerg return cxstring::createRef("InvalidFile");
543706f32e7eSjoerg case CXCursor_InvalidCode:
543806f32e7eSjoerg return cxstring::createRef("InvalidCode");
543906f32e7eSjoerg case CXCursor_NoDeclFound:
544006f32e7eSjoerg return cxstring::createRef("NoDeclFound");
544106f32e7eSjoerg case CXCursor_NotImplemented:
544206f32e7eSjoerg return cxstring::createRef("NotImplemented");
544306f32e7eSjoerg case CXCursor_TranslationUnit:
544406f32e7eSjoerg return cxstring::createRef("TranslationUnit");
544506f32e7eSjoerg case CXCursor_UnexposedAttr:
544606f32e7eSjoerg return cxstring::createRef("UnexposedAttr");
544706f32e7eSjoerg case CXCursor_IBActionAttr:
544806f32e7eSjoerg return cxstring::createRef("attribute(ibaction)");
544906f32e7eSjoerg case CXCursor_IBOutletAttr:
545006f32e7eSjoerg return cxstring::createRef("attribute(iboutlet)");
545106f32e7eSjoerg case CXCursor_IBOutletCollectionAttr:
545206f32e7eSjoerg return cxstring::createRef("attribute(iboutletcollection)");
545306f32e7eSjoerg case CXCursor_CXXFinalAttr:
545406f32e7eSjoerg return cxstring::createRef("attribute(final)");
545506f32e7eSjoerg case CXCursor_CXXOverrideAttr:
545606f32e7eSjoerg return cxstring::createRef("attribute(override)");
545706f32e7eSjoerg case CXCursor_AnnotateAttr:
545806f32e7eSjoerg return cxstring::createRef("attribute(annotate)");
545906f32e7eSjoerg case CXCursor_AsmLabelAttr:
546006f32e7eSjoerg return cxstring::createRef("asm label");
546106f32e7eSjoerg case CXCursor_PackedAttr:
546206f32e7eSjoerg return cxstring::createRef("attribute(packed)");
546306f32e7eSjoerg case CXCursor_PureAttr:
546406f32e7eSjoerg return cxstring::createRef("attribute(pure)");
546506f32e7eSjoerg case CXCursor_ConstAttr:
546606f32e7eSjoerg return cxstring::createRef("attribute(const)");
546706f32e7eSjoerg case CXCursor_NoDuplicateAttr:
546806f32e7eSjoerg return cxstring::createRef("attribute(noduplicate)");
546906f32e7eSjoerg case CXCursor_CUDAConstantAttr:
547006f32e7eSjoerg return cxstring::createRef("attribute(constant)");
547106f32e7eSjoerg case CXCursor_CUDADeviceAttr:
547206f32e7eSjoerg return cxstring::createRef("attribute(device)");
547306f32e7eSjoerg case CXCursor_CUDAGlobalAttr:
547406f32e7eSjoerg return cxstring::createRef("attribute(global)");
547506f32e7eSjoerg case CXCursor_CUDAHostAttr:
547606f32e7eSjoerg return cxstring::createRef("attribute(host)");
547706f32e7eSjoerg case CXCursor_CUDASharedAttr:
547806f32e7eSjoerg return cxstring::createRef("attribute(shared)");
547906f32e7eSjoerg case CXCursor_VisibilityAttr:
548006f32e7eSjoerg return cxstring::createRef("attribute(visibility)");
548106f32e7eSjoerg case CXCursor_DLLExport:
548206f32e7eSjoerg return cxstring::createRef("attribute(dllexport)");
548306f32e7eSjoerg case CXCursor_DLLImport:
548406f32e7eSjoerg return cxstring::createRef("attribute(dllimport)");
548506f32e7eSjoerg case CXCursor_NSReturnsRetained:
548606f32e7eSjoerg return cxstring::createRef("attribute(ns_returns_retained)");
548706f32e7eSjoerg case CXCursor_NSReturnsNotRetained:
548806f32e7eSjoerg return cxstring::createRef("attribute(ns_returns_not_retained)");
548906f32e7eSjoerg case CXCursor_NSReturnsAutoreleased:
549006f32e7eSjoerg return cxstring::createRef("attribute(ns_returns_autoreleased)");
549106f32e7eSjoerg case CXCursor_NSConsumesSelf:
549206f32e7eSjoerg return cxstring::createRef("attribute(ns_consumes_self)");
549306f32e7eSjoerg case CXCursor_NSConsumed:
549406f32e7eSjoerg return cxstring::createRef("attribute(ns_consumed)");
549506f32e7eSjoerg case CXCursor_ObjCException:
549606f32e7eSjoerg return cxstring::createRef("attribute(objc_exception)");
549706f32e7eSjoerg case CXCursor_ObjCNSObject:
549806f32e7eSjoerg return cxstring::createRef("attribute(NSObject)");
549906f32e7eSjoerg case CXCursor_ObjCIndependentClass:
550006f32e7eSjoerg return cxstring::createRef("attribute(objc_independent_class)");
550106f32e7eSjoerg case CXCursor_ObjCPreciseLifetime:
550206f32e7eSjoerg return cxstring::createRef("attribute(objc_precise_lifetime)");
550306f32e7eSjoerg case CXCursor_ObjCReturnsInnerPointer:
550406f32e7eSjoerg return cxstring::createRef("attribute(objc_returns_inner_pointer)");
550506f32e7eSjoerg case CXCursor_ObjCRequiresSuper:
550606f32e7eSjoerg return cxstring::createRef("attribute(objc_requires_super)");
550706f32e7eSjoerg case CXCursor_ObjCRootClass:
550806f32e7eSjoerg return cxstring::createRef("attribute(objc_root_class)");
550906f32e7eSjoerg case CXCursor_ObjCSubclassingRestricted:
551006f32e7eSjoerg return cxstring::createRef("attribute(objc_subclassing_restricted)");
551106f32e7eSjoerg case CXCursor_ObjCExplicitProtocolImpl:
5512*13fbcb42Sjoerg return cxstring::createRef(
5513*13fbcb42Sjoerg "attribute(objc_protocol_requires_explicit_implementation)");
551406f32e7eSjoerg case CXCursor_ObjCDesignatedInitializer:
551506f32e7eSjoerg return cxstring::createRef("attribute(objc_designated_initializer)");
551606f32e7eSjoerg case CXCursor_ObjCRuntimeVisible:
551706f32e7eSjoerg return cxstring::createRef("attribute(objc_runtime_visible)");
551806f32e7eSjoerg case CXCursor_ObjCBoxable:
551906f32e7eSjoerg return cxstring::createRef("attribute(objc_boxable)");
552006f32e7eSjoerg case CXCursor_FlagEnum:
552106f32e7eSjoerg return cxstring::createRef("attribute(flag_enum)");
552206f32e7eSjoerg case CXCursor_PreprocessingDirective:
552306f32e7eSjoerg return cxstring::createRef("preprocessing directive");
552406f32e7eSjoerg case CXCursor_MacroDefinition:
552506f32e7eSjoerg return cxstring::createRef("macro definition");
552606f32e7eSjoerg case CXCursor_MacroExpansion:
552706f32e7eSjoerg return cxstring::createRef("macro expansion");
552806f32e7eSjoerg case CXCursor_InclusionDirective:
552906f32e7eSjoerg return cxstring::createRef("inclusion directive");
553006f32e7eSjoerg case CXCursor_Namespace:
553106f32e7eSjoerg return cxstring::createRef("Namespace");
553206f32e7eSjoerg case CXCursor_LinkageSpec:
553306f32e7eSjoerg return cxstring::createRef("LinkageSpec");
553406f32e7eSjoerg case CXCursor_CXXBaseSpecifier:
553506f32e7eSjoerg return cxstring::createRef("C++ base class specifier");
553606f32e7eSjoerg case CXCursor_Constructor:
553706f32e7eSjoerg return cxstring::createRef("CXXConstructor");
553806f32e7eSjoerg case CXCursor_Destructor:
553906f32e7eSjoerg return cxstring::createRef("CXXDestructor");
554006f32e7eSjoerg case CXCursor_ConversionFunction:
554106f32e7eSjoerg return cxstring::createRef("CXXConversion");
554206f32e7eSjoerg case CXCursor_TemplateTypeParameter:
554306f32e7eSjoerg return cxstring::createRef("TemplateTypeParameter");
554406f32e7eSjoerg case CXCursor_NonTypeTemplateParameter:
554506f32e7eSjoerg return cxstring::createRef("NonTypeTemplateParameter");
554606f32e7eSjoerg case CXCursor_TemplateTemplateParameter:
554706f32e7eSjoerg return cxstring::createRef("TemplateTemplateParameter");
554806f32e7eSjoerg case CXCursor_FunctionTemplate:
554906f32e7eSjoerg return cxstring::createRef("FunctionTemplate");
555006f32e7eSjoerg case CXCursor_ClassTemplate:
555106f32e7eSjoerg return cxstring::createRef("ClassTemplate");
555206f32e7eSjoerg case CXCursor_ClassTemplatePartialSpecialization:
555306f32e7eSjoerg return cxstring::createRef("ClassTemplatePartialSpecialization");
555406f32e7eSjoerg case CXCursor_NamespaceAlias:
555506f32e7eSjoerg return cxstring::createRef("NamespaceAlias");
555606f32e7eSjoerg case CXCursor_UsingDirective:
555706f32e7eSjoerg return cxstring::createRef("UsingDirective");
555806f32e7eSjoerg case CXCursor_UsingDeclaration:
555906f32e7eSjoerg return cxstring::createRef("UsingDeclaration");
556006f32e7eSjoerg case CXCursor_TypeAliasDecl:
556106f32e7eSjoerg return cxstring::createRef("TypeAliasDecl");
556206f32e7eSjoerg case CXCursor_ObjCSynthesizeDecl:
556306f32e7eSjoerg return cxstring::createRef("ObjCSynthesizeDecl");
556406f32e7eSjoerg case CXCursor_ObjCDynamicDecl:
556506f32e7eSjoerg return cxstring::createRef("ObjCDynamicDecl");
556606f32e7eSjoerg case CXCursor_CXXAccessSpecifier:
556706f32e7eSjoerg return cxstring::createRef("CXXAccessSpecifier");
556806f32e7eSjoerg case CXCursor_ModuleImportDecl:
556906f32e7eSjoerg return cxstring::createRef("ModuleImport");
5570*13fbcb42Sjoerg case CXCursor_OMPCanonicalLoop:
5571*13fbcb42Sjoerg return cxstring::createRef("OMPCanonicalLoop");
557206f32e7eSjoerg case CXCursor_OMPParallelDirective:
557306f32e7eSjoerg return cxstring::createRef("OMPParallelDirective");
557406f32e7eSjoerg case CXCursor_OMPSimdDirective:
557506f32e7eSjoerg return cxstring::createRef("OMPSimdDirective");
5576*13fbcb42Sjoerg case CXCursor_OMPTileDirective:
5577*13fbcb42Sjoerg return cxstring::createRef("OMPTileDirective");
557806f32e7eSjoerg case CXCursor_OMPForDirective:
557906f32e7eSjoerg return cxstring::createRef("OMPForDirective");
558006f32e7eSjoerg case CXCursor_OMPForSimdDirective:
558106f32e7eSjoerg return cxstring::createRef("OMPForSimdDirective");
558206f32e7eSjoerg case CXCursor_OMPSectionsDirective:
558306f32e7eSjoerg return cxstring::createRef("OMPSectionsDirective");
558406f32e7eSjoerg case CXCursor_OMPSectionDirective:
558506f32e7eSjoerg return cxstring::createRef("OMPSectionDirective");
558606f32e7eSjoerg case CXCursor_OMPSingleDirective:
558706f32e7eSjoerg return cxstring::createRef("OMPSingleDirective");
558806f32e7eSjoerg case CXCursor_OMPMasterDirective:
558906f32e7eSjoerg return cxstring::createRef("OMPMasterDirective");
559006f32e7eSjoerg case CXCursor_OMPCriticalDirective:
559106f32e7eSjoerg return cxstring::createRef("OMPCriticalDirective");
559206f32e7eSjoerg case CXCursor_OMPParallelForDirective:
559306f32e7eSjoerg return cxstring::createRef("OMPParallelForDirective");
559406f32e7eSjoerg case CXCursor_OMPParallelForSimdDirective:
559506f32e7eSjoerg return cxstring::createRef("OMPParallelForSimdDirective");
5596*13fbcb42Sjoerg case CXCursor_OMPParallelMasterDirective:
5597*13fbcb42Sjoerg return cxstring::createRef("OMPParallelMasterDirective");
559806f32e7eSjoerg case CXCursor_OMPParallelSectionsDirective:
559906f32e7eSjoerg return cxstring::createRef("OMPParallelSectionsDirective");
560006f32e7eSjoerg case CXCursor_OMPTaskDirective:
560106f32e7eSjoerg return cxstring::createRef("OMPTaskDirective");
560206f32e7eSjoerg case CXCursor_OMPTaskyieldDirective:
560306f32e7eSjoerg return cxstring::createRef("OMPTaskyieldDirective");
560406f32e7eSjoerg case CXCursor_OMPBarrierDirective:
560506f32e7eSjoerg return cxstring::createRef("OMPBarrierDirective");
560606f32e7eSjoerg case CXCursor_OMPTaskwaitDirective:
560706f32e7eSjoerg return cxstring::createRef("OMPTaskwaitDirective");
560806f32e7eSjoerg case CXCursor_OMPTaskgroupDirective:
560906f32e7eSjoerg return cxstring::createRef("OMPTaskgroupDirective");
561006f32e7eSjoerg case CXCursor_OMPFlushDirective:
561106f32e7eSjoerg return cxstring::createRef("OMPFlushDirective");
5612*13fbcb42Sjoerg case CXCursor_OMPDepobjDirective:
5613*13fbcb42Sjoerg return cxstring::createRef("OMPDepobjDirective");
5614*13fbcb42Sjoerg case CXCursor_OMPScanDirective:
5615*13fbcb42Sjoerg return cxstring::createRef("OMPScanDirective");
561606f32e7eSjoerg case CXCursor_OMPOrderedDirective:
561706f32e7eSjoerg return cxstring::createRef("OMPOrderedDirective");
561806f32e7eSjoerg case CXCursor_OMPAtomicDirective:
561906f32e7eSjoerg return cxstring::createRef("OMPAtomicDirective");
562006f32e7eSjoerg case CXCursor_OMPTargetDirective:
562106f32e7eSjoerg return cxstring::createRef("OMPTargetDirective");
562206f32e7eSjoerg case CXCursor_OMPTargetDataDirective:
562306f32e7eSjoerg return cxstring::createRef("OMPTargetDataDirective");
562406f32e7eSjoerg case CXCursor_OMPTargetEnterDataDirective:
562506f32e7eSjoerg return cxstring::createRef("OMPTargetEnterDataDirective");
562606f32e7eSjoerg case CXCursor_OMPTargetExitDataDirective:
562706f32e7eSjoerg return cxstring::createRef("OMPTargetExitDataDirective");
562806f32e7eSjoerg case CXCursor_OMPTargetParallelDirective:
562906f32e7eSjoerg return cxstring::createRef("OMPTargetParallelDirective");
563006f32e7eSjoerg case CXCursor_OMPTargetParallelForDirective:
563106f32e7eSjoerg return cxstring::createRef("OMPTargetParallelForDirective");
563206f32e7eSjoerg case CXCursor_OMPTargetUpdateDirective:
563306f32e7eSjoerg return cxstring::createRef("OMPTargetUpdateDirective");
563406f32e7eSjoerg case CXCursor_OMPTeamsDirective:
563506f32e7eSjoerg return cxstring::createRef("OMPTeamsDirective");
563606f32e7eSjoerg case CXCursor_OMPCancellationPointDirective:
563706f32e7eSjoerg return cxstring::createRef("OMPCancellationPointDirective");
563806f32e7eSjoerg case CXCursor_OMPCancelDirective:
563906f32e7eSjoerg return cxstring::createRef("OMPCancelDirective");
564006f32e7eSjoerg case CXCursor_OMPTaskLoopDirective:
564106f32e7eSjoerg return cxstring::createRef("OMPTaskLoopDirective");
564206f32e7eSjoerg case CXCursor_OMPTaskLoopSimdDirective:
564306f32e7eSjoerg return cxstring::createRef("OMPTaskLoopSimdDirective");
564406f32e7eSjoerg case CXCursor_OMPMasterTaskLoopDirective:
564506f32e7eSjoerg return cxstring::createRef("OMPMasterTaskLoopDirective");
564606f32e7eSjoerg case CXCursor_OMPMasterTaskLoopSimdDirective:
564706f32e7eSjoerg return cxstring::createRef("OMPMasterTaskLoopSimdDirective");
564806f32e7eSjoerg case CXCursor_OMPParallelMasterTaskLoopDirective:
564906f32e7eSjoerg return cxstring::createRef("OMPParallelMasterTaskLoopDirective");
5650*13fbcb42Sjoerg case CXCursor_OMPParallelMasterTaskLoopSimdDirective:
5651*13fbcb42Sjoerg return cxstring::createRef("OMPParallelMasterTaskLoopSimdDirective");
565206f32e7eSjoerg case CXCursor_OMPDistributeDirective:
565306f32e7eSjoerg return cxstring::createRef("OMPDistributeDirective");
565406f32e7eSjoerg case CXCursor_OMPDistributeParallelForDirective:
565506f32e7eSjoerg return cxstring::createRef("OMPDistributeParallelForDirective");
565606f32e7eSjoerg case CXCursor_OMPDistributeParallelForSimdDirective:
565706f32e7eSjoerg return cxstring::createRef("OMPDistributeParallelForSimdDirective");
565806f32e7eSjoerg case CXCursor_OMPDistributeSimdDirective:
565906f32e7eSjoerg return cxstring::createRef("OMPDistributeSimdDirective");
566006f32e7eSjoerg case CXCursor_OMPTargetParallelForSimdDirective:
566106f32e7eSjoerg return cxstring::createRef("OMPTargetParallelForSimdDirective");
566206f32e7eSjoerg case CXCursor_OMPTargetSimdDirective:
566306f32e7eSjoerg return cxstring::createRef("OMPTargetSimdDirective");
566406f32e7eSjoerg case CXCursor_OMPTeamsDistributeDirective:
566506f32e7eSjoerg return cxstring::createRef("OMPTeamsDistributeDirective");
566606f32e7eSjoerg case CXCursor_OMPTeamsDistributeSimdDirective:
566706f32e7eSjoerg return cxstring::createRef("OMPTeamsDistributeSimdDirective");
566806f32e7eSjoerg case CXCursor_OMPTeamsDistributeParallelForSimdDirective:
566906f32e7eSjoerg return cxstring::createRef("OMPTeamsDistributeParallelForSimdDirective");
567006f32e7eSjoerg case CXCursor_OMPTeamsDistributeParallelForDirective:
567106f32e7eSjoerg return cxstring::createRef("OMPTeamsDistributeParallelForDirective");
567206f32e7eSjoerg case CXCursor_OMPTargetTeamsDirective:
567306f32e7eSjoerg return cxstring::createRef("OMPTargetTeamsDirective");
567406f32e7eSjoerg case CXCursor_OMPTargetTeamsDistributeDirective:
567506f32e7eSjoerg return cxstring::createRef("OMPTargetTeamsDistributeDirective");
567606f32e7eSjoerg case CXCursor_OMPTargetTeamsDistributeParallelForDirective:
567706f32e7eSjoerg return cxstring::createRef("OMPTargetTeamsDistributeParallelForDirective");
567806f32e7eSjoerg case CXCursor_OMPTargetTeamsDistributeParallelForSimdDirective:
567906f32e7eSjoerg return cxstring::createRef(
568006f32e7eSjoerg "OMPTargetTeamsDistributeParallelForSimdDirective");
568106f32e7eSjoerg case CXCursor_OMPTargetTeamsDistributeSimdDirective:
568206f32e7eSjoerg return cxstring::createRef("OMPTargetTeamsDistributeSimdDirective");
5683*13fbcb42Sjoerg case CXCursor_OMPInteropDirective:
5684*13fbcb42Sjoerg return cxstring::createRef("OMPInteropDirective");
5685*13fbcb42Sjoerg case CXCursor_OMPDispatchDirective:
5686*13fbcb42Sjoerg return cxstring::createRef("OMPDispatchDirective");
5687*13fbcb42Sjoerg case CXCursor_OMPMaskedDirective:
5688*13fbcb42Sjoerg return cxstring::createRef("OMPMaskedDirective");
568906f32e7eSjoerg case CXCursor_OverloadCandidate:
569006f32e7eSjoerg return cxstring::createRef("OverloadCandidate");
569106f32e7eSjoerg case CXCursor_TypeAliasTemplateDecl:
569206f32e7eSjoerg return cxstring::createRef("TypeAliasTemplateDecl");
569306f32e7eSjoerg case CXCursor_StaticAssert:
569406f32e7eSjoerg return cxstring::createRef("StaticAssert");
569506f32e7eSjoerg case CXCursor_FriendDecl:
569606f32e7eSjoerg return cxstring::createRef("FriendDecl");
569706f32e7eSjoerg case CXCursor_ConvergentAttr:
569806f32e7eSjoerg return cxstring::createRef("attribute(convergent)");
569906f32e7eSjoerg case CXCursor_WarnUnusedAttr:
570006f32e7eSjoerg return cxstring::createRef("attribute(warn_unused)");
570106f32e7eSjoerg case CXCursor_WarnUnusedResultAttr:
570206f32e7eSjoerg return cxstring::createRef("attribute(warn_unused_result)");
570306f32e7eSjoerg case CXCursor_AlignedAttr:
570406f32e7eSjoerg return cxstring::createRef("attribute(aligned)");
570506f32e7eSjoerg }
570606f32e7eSjoerg
570706f32e7eSjoerg llvm_unreachable("Unhandled CXCursorKind");
570806f32e7eSjoerg }
570906f32e7eSjoerg
571006f32e7eSjoerg struct GetCursorData {
571106f32e7eSjoerg SourceLocation TokenBeginLoc;
571206f32e7eSjoerg bool PointsAtMacroArgExpansion;
571306f32e7eSjoerg bool VisitedObjCPropertyImplDecl;
571406f32e7eSjoerg SourceLocation VisitedDeclaratorDeclStartLoc;
571506f32e7eSjoerg CXCursor &BestCursor;
571606f32e7eSjoerg
5717*13fbcb42Sjoerg GetCursorData(SourceManager &SM, SourceLocation tokenBegin,
5718*13fbcb42Sjoerg CXCursor &outputCursor)
571906f32e7eSjoerg : TokenBeginLoc(tokenBegin), BestCursor(outputCursor) {
572006f32e7eSjoerg PointsAtMacroArgExpansion = SM.isMacroArgExpansion(tokenBegin);
572106f32e7eSjoerg VisitedObjCPropertyImplDecl = false;
572206f32e7eSjoerg }
572306f32e7eSjoerg };
572406f32e7eSjoerg
5725*13fbcb42Sjoerg static enum CXChildVisitResult
GetCursorVisitor(CXCursor cursor,CXCursor parent,CXClientData client_data)5726*13fbcb42Sjoerg GetCursorVisitor(CXCursor cursor, CXCursor parent, CXClientData client_data) {
572706f32e7eSjoerg GetCursorData *Data = static_cast<GetCursorData *>(client_data);
572806f32e7eSjoerg CXCursor *BestCursor = &Data->BestCursor;
572906f32e7eSjoerg
573006f32e7eSjoerg // If we point inside a macro argument we should provide info of what the
573106f32e7eSjoerg // token is so use the actual cursor, don't replace it with a macro expansion
573206f32e7eSjoerg // cursor.
573306f32e7eSjoerg if (cursor.kind == CXCursor_MacroExpansion && Data->PointsAtMacroArgExpansion)
573406f32e7eSjoerg return CXChildVisit_Recurse;
573506f32e7eSjoerg
573606f32e7eSjoerg if (clang_isDeclaration(cursor.kind)) {
573706f32e7eSjoerg // Avoid having the implicit methods override the property decls.
5738*13fbcb42Sjoerg if (const ObjCMethodDecl *MD =
5739*13fbcb42Sjoerg dyn_cast_or_null<ObjCMethodDecl>(getCursorDecl(cursor))) {
574006f32e7eSjoerg if (MD->isImplicit())
574106f32e7eSjoerg return CXChildVisit_Break;
574206f32e7eSjoerg
5743*13fbcb42Sjoerg } else if (const ObjCInterfaceDecl *ID =
5744*13fbcb42Sjoerg dyn_cast_or_null<ObjCInterfaceDecl>(getCursorDecl(cursor))) {
574506f32e7eSjoerg // Check that when we have multiple @class references in the same line,
574606f32e7eSjoerg // that later ones do not override the previous ones.
574706f32e7eSjoerg // If we have:
574806f32e7eSjoerg // @class Foo, Bar;
574906f32e7eSjoerg // source ranges for both start at '@', so 'Bar' will end up overriding
575006f32e7eSjoerg // 'Foo' even though the cursor location was at 'Foo'.
575106f32e7eSjoerg if (BestCursor->kind == CXCursor_ObjCInterfaceDecl ||
575206f32e7eSjoerg BestCursor->kind == CXCursor_ObjCClassRef)
5753*13fbcb42Sjoerg if (const ObjCInterfaceDecl *PrevID =
5754*13fbcb42Sjoerg dyn_cast_or_null<ObjCInterfaceDecl>(
5755*13fbcb42Sjoerg getCursorDecl(*BestCursor))) {
5756*13fbcb42Sjoerg if (PrevID != ID && !PrevID->isThisDeclarationADefinition() &&
575706f32e7eSjoerg !ID->isThisDeclarationADefinition())
575806f32e7eSjoerg return CXChildVisit_Break;
575906f32e7eSjoerg }
576006f32e7eSjoerg
5761*13fbcb42Sjoerg } else if (const DeclaratorDecl *DD =
5762*13fbcb42Sjoerg dyn_cast_or_null<DeclaratorDecl>(getCursorDecl(cursor))) {
576306f32e7eSjoerg SourceLocation StartLoc = DD->getSourceRange().getBegin();
576406f32e7eSjoerg // Check that when we have multiple declarators in the same line,
576506f32e7eSjoerg // that later ones do not override the previous ones.
576606f32e7eSjoerg // If we have:
576706f32e7eSjoerg // int Foo, Bar;
576806f32e7eSjoerg // source ranges for both start at 'int', so 'Bar' will end up overriding
576906f32e7eSjoerg // 'Foo' even though the cursor location was at 'Foo'.
577006f32e7eSjoerg if (Data->VisitedDeclaratorDeclStartLoc == StartLoc)
577106f32e7eSjoerg return CXChildVisit_Break;
577206f32e7eSjoerg Data->VisitedDeclaratorDeclStartLoc = StartLoc;
577306f32e7eSjoerg
5774*13fbcb42Sjoerg } else if (const ObjCPropertyImplDecl *PropImp =
5775*13fbcb42Sjoerg dyn_cast_or_null<ObjCPropertyImplDecl>(
5776*13fbcb42Sjoerg getCursorDecl(cursor))) {
577706f32e7eSjoerg (void)PropImp;
577806f32e7eSjoerg // Check that when we have multiple @synthesize in the same line,
577906f32e7eSjoerg // that later ones do not override the previous ones.
578006f32e7eSjoerg // If we have:
578106f32e7eSjoerg // @synthesize Foo, Bar;
578206f32e7eSjoerg // source ranges for both start at '@', so 'Bar' will end up overriding
578306f32e7eSjoerg // 'Foo' even though the cursor location was at 'Foo'.
578406f32e7eSjoerg if (Data->VisitedObjCPropertyImplDecl)
578506f32e7eSjoerg return CXChildVisit_Break;
578606f32e7eSjoerg Data->VisitedObjCPropertyImplDecl = true;
578706f32e7eSjoerg }
578806f32e7eSjoerg }
578906f32e7eSjoerg
579006f32e7eSjoerg if (clang_isExpression(cursor.kind) &&
579106f32e7eSjoerg clang_isDeclaration(BestCursor->kind)) {
579206f32e7eSjoerg if (const Decl *D = getCursorDecl(*BestCursor)) {
579306f32e7eSjoerg // Avoid having the cursor of an expression replace the declaration cursor
579406f32e7eSjoerg // when the expression source range overlaps the declaration range.
579506f32e7eSjoerg // This can happen for C++ constructor expressions whose range generally
579606f32e7eSjoerg // include the variable declaration, e.g.:
5797*13fbcb42Sjoerg // MyCXXClass foo; // Make sure pointing at 'foo' returns a VarDecl
5798*13fbcb42Sjoerg // cursor.
579906f32e7eSjoerg if (D->getLocation().isValid() && Data->TokenBeginLoc.isValid() &&
580006f32e7eSjoerg D->getLocation() == Data->TokenBeginLoc)
580106f32e7eSjoerg return CXChildVisit_Break;
580206f32e7eSjoerg }
580306f32e7eSjoerg }
580406f32e7eSjoerg
580506f32e7eSjoerg // If our current best cursor is the construction of a temporary object,
580606f32e7eSjoerg // don't replace that cursor with a type reference, because we want
580706f32e7eSjoerg // clang_getCursor() to point at the constructor.
580806f32e7eSjoerg if (clang_isExpression(BestCursor->kind) &&
580906f32e7eSjoerg isa<CXXTemporaryObjectExpr>(getCursorExpr(*BestCursor)) &&
581006f32e7eSjoerg cursor.kind == CXCursor_TypeRef) {
581106f32e7eSjoerg // Keep the cursor pointing at CXXTemporaryObjectExpr but also mark it
581206f32e7eSjoerg // as having the actual point on the type reference.
581306f32e7eSjoerg *BestCursor = getTypeRefedCallExprCursor(*BestCursor);
581406f32e7eSjoerg return CXChildVisit_Recurse;
581506f32e7eSjoerg }
581606f32e7eSjoerg
581706f32e7eSjoerg // If we already have an Objective-C superclass reference, don't
581806f32e7eSjoerg // update it further.
581906f32e7eSjoerg if (BestCursor->kind == CXCursor_ObjCSuperClassRef)
582006f32e7eSjoerg return CXChildVisit_Break;
582106f32e7eSjoerg
582206f32e7eSjoerg *BestCursor = cursor;
582306f32e7eSjoerg return CXChildVisit_Recurse;
582406f32e7eSjoerg }
582506f32e7eSjoerg
clang_getCursor(CXTranslationUnit TU,CXSourceLocation Loc)582606f32e7eSjoerg CXCursor clang_getCursor(CXTranslationUnit TU, CXSourceLocation Loc) {
582706f32e7eSjoerg if (isNotUsableTU(TU)) {
582806f32e7eSjoerg LOG_BAD_TU(TU);
582906f32e7eSjoerg return clang_getNullCursor();
583006f32e7eSjoerg }
583106f32e7eSjoerg
583206f32e7eSjoerg ASTUnit *CXXUnit = cxtu::getASTUnit(TU);
583306f32e7eSjoerg ASTUnit::ConcurrencyCheck Check(*CXXUnit);
583406f32e7eSjoerg
583506f32e7eSjoerg SourceLocation SLoc = cxloc::translateSourceLocation(Loc);
583606f32e7eSjoerg CXCursor Result = cxcursor::getCursor(TU, SLoc);
583706f32e7eSjoerg
583806f32e7eSjoerg LOG_FUNC_SECTION {
583906f32e7eSjoerg CXFile SearchFile;
584006f32e7eSjoerg unsigned SearchLine, SearchColumn;
584106f32e7eSjoerg CXFile ResultFile;
584206f32e7eSjoerg unsigned ResultLine, ResultColumn;
584306f32e7eSjoerg CXString SearchFileName, ResultFileName, KindSpelling, USR;
584406f32e7eSjoerg const char *IsDef = clang_isCursorDefinition(Result) ? " (Definition)" : "";
584506f32e7eSjoerg CXSourceLocation ResultLoc = clang_getCursorLocation(Result);
584606f32e7eSjoerg
584706f32e7eSjoerg clang_getFileLocation(Loc, &SearchFile, &SearchLine, &SearchColumn,
584806f32e7eSjoerg nullptr);
5849*13fbcb42Sjoerg clang_getFileLocation(ResultLoc, &ResultFile, &ResultLine, &ResultColumn,
5850*13fbcb42Sjoerg nullptr);
585106f32e7eSjoerg SearchFileName = clang_getFileName(SearchFile);
585206f32e7eSjoerg ResultFileName = clang_getFileName(ResultFile);
585306f32e7eSjoerg KindSpelling = clang_getCursorKindSpelling(Result.kind);
585406f32e7eSjoerg USR = clang_getCursorUSR(Result);
5855*13fbcb42Sjoerg *Log << llvm::format("(%s:%d:%d) = %s", clang_getCString(SearchFileName),
5856*13fbcb42Sjoerg SearchLine, SearchColumn,
585706f32e7eSjoerg clang_getCString(KindSpelling))
5858*13fbcb42Sjoerg << llvm::format("(%s:%d:%d):%s%s", clang_getCString(ResultFileName),
5859*13fbcb42Sjoerg ResultLine, ResultColumn, clang_getCString(USR),
5860*13fbcb42Sjoerg IsDef);
586106f32e7eSjoerg clang_disposeString(SearchFileName);
586206f32e7eSjoerg clang_disposeString(ResultFileName);
586306f32e7eSjoerg clang_disposeString(KindSpelling);
586406f32e7eSjoerg clang_disposeString(USR);
586506f32e7eSjoerg
586606f32e7eSjoerg CXCursor Definition = clang_getCursorDefinition(Result);
586706f32e7eSjoerg if (!clang_equalCursors(Definition, clang_getNullCursor())) {
586806f32e7eSjoerg CXSourceLocation DefinitionLoc = clang_getCursorLocation(Definition);
5869*13fbcb42Sjoerg CXString DefinitionKindSpelling =
5870*13fbcb42Sjoerg clang_getCursorKindSpelling(Definition.kind);
587106f32e7eSjoerg CXFile DefinitionFile;
587206f32e7eSjoerg unsigned DefinitionLine, DefinitionColumn;
5873*13fbcb42Sjoerg clang_getFileLocation(DefinitionLoc, &DefinitionFile, &DefinitionLine,
5874*13fbcb42Sjoerg &DefinitionColumn, nullptr);
587506f32e7eSjoerg CXString DefinitionFileName = clang_getFileName(DefinitionFile);
587606f32e7eSjoerg *Log << llvm::format(" -> %s(%s:%d:%d)",
587706f32e7eSjoerg clang_getCString(DefinitionKindSpelling),
5878*13fbcb42Sjoerg clang_getCString(DefinitionFileName), DefinitionLine,
5879*13fbcb42Sjoerg DefinitionColumn);
588006f32e7eSjoerg clang_disposeString(DefinitionFileName);
588106f32e7eSjoerg clang_disposeString(DefinitionKindSpelling);
588206f32e7eSjoerg }
588306f32e7eSjoerg }
588406f32e7eSjoerg
588506f32e7eSjoerg return Result;
588606f32e7eSjoerg }
588706f32e7eSjoerg
clang_getNullCursor(void)588806f32e7eSjoerg CXCursor clang_getNullCursor(void) {
588906f32e7eSjoerg return MakeCXCursorInvalid(CXCursor_InvalidFile);
589006f32e7eSjoerg }
589106f32e7eSjoerg
clang_equalCursors(CXCursor X,CXCursor Y)589206f32e7eSjoerg unsigned clang_equalCursors(CXCursor X, CXCursor Y) {
589306f32e7eSjoerg // Clear out the "FirstInDeclGroup" part in a declaration cursor, since we
589406f32e7eSjoerg // can't set consistently. For example, when visiting a DeclStmt we will set
589506f32e7eSjoerg // it but we don't set it on the result of clang_getCursorDefinition for
589606f32e7eSjoerg // a reference of the same declaration.
589706f32e7eSjoerg // FIXME: Setting "FirstInDeclGroup" in CXCursors is a hack that only works
589806f32e7eSjoerg // when visiting a DeclStmt currently, the AST should be enhanced to be able
589906f32e7eSjoerg // to provide that kind of info.
590006f32e7eSjoerg if (clang_isDeclaration(X.kind))
590106f32e7eSjoerg X.data[1] = nullptr;
590206f32e7eSjoerg if (clang_isDeclaration(Y.kind))
590306f32e7eSjoerg Y.data[1] = nullptr;
590406f32e7eSjoerg
590506f32e7eSjoerg return X == Y;
590606f32e7eSjoerg }
590706f32e7eSjoerg
clang_hashCursor(CXCursor C)590806f32e7eSjoerg unsigned clang_hashCursor(CXCursor C) {
590906f32e7eSjoerg unsigned Index = 0;
591006f32e7eSjoerg if (clang_isExpression(C.kind) || clang_isStatement(C.kind))
591106f32e7eSjoerg Index = 1;
591206f32e7eSjoerg
591306f32e7eSjoerg return llvm::DenseMapInfo<std::pair<unsigned, const void *>>::getHashValue(
591406f32e7eSjoerg std::make_pair(C.kind, C.data[Index]));
591506f32e7eSjoerg }
591606f32e7eSjoerg
clang_isInvalid(enum CXCursorKind K)591706f32e7eSjoerg unsigned clang_isInvalid(enum CXCursorKind K) {
591806f32e7eSjoerg return K >= CXCursor_FirstInvalid && K <= CXCursor_LastInvalid;
591906f32e7eSjoerg }
592006f32e7eSjoerg
clang_isDeclaration(enum CXCursorKind K)592106f32e7eSjoerg unsigned clang_isDeclaration(enum CXCursorKind K) {
592206f32e7eSjoerg return (K >= CXCursor_FirstDecl && K <= CXCursor_LastDecl) ||
592306f32e7eSjoerg (K >= CXCursor_FirstExtraDecl && K <= CXCursor_LastExtraDecl);
592406f32e7eSjoerg }
592506f32e7eSjoerg
clang_isInvalidDeclaration(CXCursor C)592606f32e7eSjoerg unsigned clang_isInvalidDeclaration(CXCursor C) {
592706f32e7eSjoerg if (clang_isDeclaration(C.kind)) {
592806f32e7eSjoerg if (const Decl *D = getCursorDecl(C))
592906f32e7eSjoerg return D->isInvalidDecl();
593006f32e7eSjoerg }
593106f32e7eSjoerg
593206f32e7eSjoerg return 0;
593306f32e7eSjoerg }
593406f32e7eSjoerg
clang_isReference(enum CXCursorKind K)593506f32e7eSjoerg unsigned clang_isReference(enum CXCursorKind K) {
593606f32e7eSjoerg return K >= CXCursor_FirstRef && K <= CXCursor_LastRef;
593706f32e7eSjoerg }
593806f32e7eSjoerg
clang_isExpression(enum CXCursorKind K)593906f32e7eSjoerg unsigned clang_isExpression(enum CXCursorKind K) {
594006f32e7eSjoerg return K >= CXCursor_FirstExpr && K <= CXCursor_LastExpr;
594106f32e7eSjoerg }
594206f32e7eSjoerg
clang_isStatement(enum CXCursorKind K)594306f32e7eSjoerg unsigned clang_isStatement(enum CXCursorKind K) {
594406f32e7eSjoerg return K >= CXCursor_FirstStmt && K <= CXCursor_LastStmt;
594506f32e7eSjoerg }
594606f32e7eSjoerg
clang_isAttribute(enum CXCursorKind K)594706f32e7eSjoerg unsigned clang_isAttribute(enum CXCursorKind K) {
594806f32e7eSjoerg return K >= CXCursor_FirstAttr && K <= CXCursor_LastAttr;
594906f32e7eSjoerg }
595006f32e7eSjoerg
clang_isTranslationUnit(enum CXCursorKind K)595106f32e7eSjoerg unsigned clang_isTranslationUnit(enum CXCursorKind K) {
595206f32e7eSjoerg return K == CXCursor_TranslationUnit;
595306f32e7eSjoerg }
595406f32e7eSjoerg
clang_isPreprocessing(enum CXCursorKind K)595506f32e7eSjoerg unsigned clang_isPreprocessing(enum CXCursorKind K) {
595606f32e7eSjoerg return K >= CXCursor_FirstPreprocessing && K <= CXCursor_LastPreprocessing;
595706f32e7eSjoerg }
595806f32e7eSjoerg
clang_isUnexposed(enum CXCursorKind K)595906f32e7eSjoerg unsigned clang_isUnexposed(enum CXCursorKind K) {
596006f32e7eSjoerg switch (K) {
596106f32e7eSjoerg case CXCursor_UnexposedDecl:
596206f32e7eSjoerg case CXCursor_UnexposedExpr:
596306f32e7eSjoerg case CXCursor_UnexposedStmt:
596406f32e7eSjoerg case CXCursor_UnexposedAttr:
596506f32e7eSjoerg return true;
596606f32e7eSjoerg default:
596706f32e7eSjoerg return false;
596806f32e7eSjoerg }
596906f32e7eSjoerg }
597006f32e7eSjoerg
clang_getCursorKind(CXCursor C)5971*13fbcb42Sjoerg CXCursorKind clang_getCursorKind(CXCursor C) { return C.kind; }
597206f32e7eSjoerg
clang_getCursorLocation(CXCursor C)597306f32e7eSjoerg CXSourceLocation clang_getCursorLocation(CXCursor C) {
597406f32e7eSjoerg if (clang_isReference(C.kind)) {
597506f32e7eSjoerg switch (C.kind) {
597606f32e7eSjoerg case CXCursor_ObjCSuperClassRef: {
5977*13fbcb42Sjoerg std::pair<const ObjCInterfaceDecl *, SourceLocation> P =
5978*13fbcb42Sjoerg getCursorObjCSuperClassRef(C);
597906f32e7eSjoerg return cxloc::translateSourceLocation(P.first->getASTContext(), P.second);
598006f32e7eSjoerg }
598106f32e7eSjoerg
598206f32e7eSjoerg case CXCursor_ObjCProtocolRef: {
5983*13fbcb42Sjoerg std::pair<const ObjCProtocolDecl *, SourceLocation> P =
5984*13fbcb42Sjoerg getCursorObjCProtocolRef(C);
598506f32e7eSjoerg return cxloc::translateSourceLocation(P.first->getASTContext(), P.second);
598606f32e7eSjoerg }
598706f32e7eSjoerg
598806f32e7eSjoerg case CXCursor_ObjCClassRef: {
5989*13fbcb42Sjoerg std::pair<const ObjCInterfaceDecl *, SourceLocation> P =
5990*13fbcb42Sjoerg getCursorObjCClassRef(C);
599106f32e7eSjoerg return cxloc::translateSourceLocation(P.first->getASTContext(), P.second);
599206f32e7eSjoerg }
599306f32e7eSjoerg
599406f32e7eSjoerg case CXCursor_TypeRef: {
599506f32e7eSjoerg std::pair<const TypeDecl *, SourceLocation> P = getCursorTypeRef(C);
599606f32e7eSjoerg return cxloc::translateSourceLocation(P.first->getASTContext(), P.second);
599706f32e7eSjoerg }
599806f32e7eSjoerg
599906f32e7eSjoerg case CXCursor_TemplateRef: {
600006f32e7eSjoerg std::pair<const TemplateDecl *, SourceLocation> P =
600106f32e7eSjoerg getCursorTemplateRef(C);
600206f32e7eSjoerg return cxloc::translateSourceLocation(P.first->getASTContext(), P.second);
600306f32e7eSjoerg }
600406f32e7eSjoerg
600506f32e7eSjoerg case CXCursor_NamespaceRef: {
600606f32e7eSjoerg std::pair<const NamedDecl *, SourceLocation> P = getCursorNamespaceRef(C);
600706f32e7eSjoerg return cxloc::translateSourceLocation(P.first->getASTContext(), P.second);
600806f32e7eSjoerg }
600906f32e7eSjoerg
601006f32e7eSjoerg case CXCursor_MemberRef: {
601106f32e7eSjoerg std::pair<const FieldDecl *, SourceLocation> P = getCursorMemberRef(C);
601206f32e7eSjoerg return cxloc::translateSourceLocation(P.first->getASTContext(), P.second);
601306f32e7eSjoerg }
601406f32e7eSjoerg
601506f32e7eSjoerg case CXCursor_VariableRef: {
601606f32e7eSjoerg std::pair<const VarDecl *, SourceLocation> P = getCursorVariableRef(C);
601706f32e7eSjoerg return cxloc::translateSourceLocation(P.first->getASTContext(), P.second);
601806f32e7eSjoerg }
601906f32e7eSjoerg
602006f32e7eSjoerg case CXCursor_CXXBaseSpecifier: {
602106f32e7eSjoerg const CXXBaseSpecifier *BaseSpec = getCursorCXXBaseSpecifier(C);
602206f32e7eSjoerg if (!BaseSpec)
602306f32e7eSjoerg return clang_getNullLocation();
602406f32e7eSjoerg
602506f32e7eSjoerg if (TypeSourceInfo *TSInfo = BaseSpec->getTypeSourceInfo())
6026*13fbcb42Sjoerg return cxloc::translateSourceLocation(
6027*13fbcb42Sjoerg getCursorContext(C), TSInfo->getTypeLoc().getBeginLoc());
602806f32e7eSjoerg
602906f32e7eSjoerg return cxloc::translateSourceLocation(getCursorContext(C),
603006f32e7eSjoerg BaseSpec->getBeginLoc());
603106f32e7eSjoerg }
603206f32e7eSjoerg
603306f32e7eSjoerg case CXCursor_LabelRef: {
603406f32e7eSjoerg std::pair<const LabelStmt *, SourceLocation> P = getCursorLabelRef(C);
603506f32e7eSjoerg return cxloc::translateSourceLocation(getCursorContext(C), P.second);
603606f32e7eSjoerg }
603706f32e7eSjoerg
603806f32e7eSjoerg case CXCursor_OverloadedDeclRef:
6039*13fbcb42Sjoerg return cxloc::translateSourceLocation(
6040*13fbcb42Sjoerg getCursorContext(C), getCursorOverloadedDeclRef(C).second);
604106f32e7eSjoerg
604206f32e7eSjoerg default:
604306f32e7eSjoerg // FIXME: Need a way to enumerate all non-reference cases.
604406f32e7eSjoerg llvm_unreachable("Missed a reference kind");
604506f32e7eSjoerg }
604606f32e7eSjoerg }
604706f32e7eSjoerg
604806f32e7eSjoerg if (clang_isExpression(C.kind))
6049*13fbcb42Sjoerg return cxloc::translateSourceLocation(
6050*13fbcb42Sjoerg getCursorContext(C), getLocationFromExpr(getCursorExpr(C)));
605106f32e7eSjoerg
605206f32e7eSjoerg if (clang_isStatement(C.kind))
605306f32e7eSjoerg return cxloc::translateSourceLocation(getCursorContext(C),
605406f32e7eSjoerg getCursorStmt(C)->getBeginLoc());
605506f32e7eSjoerg
605606f32e7eSjoerg if (C.kind == CXCursor_PreprocessingDirective) {
605706f32e7eSjoerg SourceLocation L = cxcursor::getCursorPreprocessingDirective(C).getBegin();
605806f32e7eSjoerg return cxloc::translateSourceLocation(getCursorContext(C), L);
605906f32e7eSjoerg }
606006f32e7eSjoerg
606106f32e7eSjoerg if (C.kind == CXCursor_MacroExpansion) {
6062*13fbcb42Sjoerg SourceLocation L =
6063*13fbcb42Sjoerg cxcursor::getCursorMacroExpansion(C).getSourceRange().getBegin();
606406f32e7eSjoerg return cxloc::translateSourceLocation(getCursorContext(C), L);
606506f32e7eSjoerg }
606606f32e7eSjoerg
606706f32e7eSjoerg if (C.kind == CXCursor_MacroDefinition) {
606806f32e7eSjoerg SourceLocation L = cxcursor::getCursorMacroDefinition(C)->getLocation();
606906f32e7eSjoerg return cxloc::translateSourceLocation(getCursorContext(C), L);
607006f32e7eSjoerg }
607106f32e7eSjoerg
607206f32e7eSjoerg if (C.kind == CXCursor_InclusionDirective) {
6073*13fbcb42Sjoerg SourceLocation L =
6074*13fbcb42Sjoerg cxcursor::getCursorInclusionDirective(C)->getSourceRange().getBegin();
607506f32e7eSjoerg return cxloc::translateSourceLocation(getCursorContext(C), L);
607606f32e7eSjoerg }
607706f32e7eSjoerg
607806f32e7eSjoerg if (clang_isAttribute(C.kind)) {
6079*13fbcb42Sjoerg SourceLocation L = cxcursor::getCursorAttr(C)->getLocation();
608006f32e7eSjoerg return cxloc::translateSourceLocation(getCursorContext(C), L);
608106f32e7eSjoerg }
608206f32e7eSjoerg
608306f32e7eSjoerg if (!clang_isDeclaration(C.kind))
608406f32e7eSjoerg return clang_getNullLocation();
608506f32e7eSjoerg
608606f32e7eSjoerg const Decl *D = getCursorDecl(C);
608706f32e7eSjoerg if (!D)
608806f32e7eSjoerg return clang_getNullLocation();
608906f32e7eSjoerg
609006f32e7eSjoerg SourceLocation Loc = D->getLocation();
609106f32e7eSjoerg // FIXME: Multiple variables declared in a single declaration
609206f32e7eSjoerg // currently lack the information needed to correctly determine their
609306f32e7eSjoerg // ranges when accounting for the type-specifier. We use context
609406f32e7eSjoerg // stored in the CXCursor to determine if the VarDecl is in a DeclGroup,
609506f32e7eSjoerg // and if so, whether it is the first decl.
609606f32e7eSjoerg if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
609706f32e7eSjoerg if (!cxcursor::isFirstInDeclGroup(C))
609806f32e7eSjoerg Loc = VD->getLocation();
609906f32e7eSjoerg }
610006f32e7eSjoerg
610106f32e7eSjoerg // For ObjC methods, give the start location of the method name.
610206f32e7eSjoerg if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
610306f32e7eSjoerg Loc = MD->getSelectorStartLoc();
610406f32e7eSjoerg
610506f32e7eSjoerg return cxloc::translateSourceLocation(getCursorContext(C), Loc);
610606f32e7eSjoerg }
610706f32e7eSjoerg
610806f32e7eSjoerg } // end extern "C"
610906f32e7eSjoerg
getCursor(CXTranslationUnit TU,SourceLocation SLoc)611006f32e7eSjoerg CXCursor cxcursor::getCursor(CXTranslationUnit TU, SourceLocation SLoc) {
611106f32e7eSjoerg assert(TU);
611206f32e7eSjoerg
611306f32e7eSjoerg // Guard against an invalid SourceLocation, or we may assert in one
611406f32e7eSjoerg // of the following calls.
611506f32e7eSjoerg if (SLoc.isInvalid())
611606f32e7eSjoerg return clang_getNullCursor();
611706f32e7eSjoerg
611806f32e7eSjoerg ASTUnit *CXXUnit = cxtu::getASTUnit(TU);
611906f32e7eSjoerg
612006f32e7eSjoerg // Translate the given source location to make it point at the beginning of
612106f32e7eSjoerg // the token under the cursor.
612206f32e7eSjoerg SLoc = Lexer::GetBeginningOfToken(SLoc, CXXUnit->getSourceManager(),
612306f32e7eSjoerg CXXUnit->getASTContext().getLangOpts());
612406f32e7eSjoerg
612506f32e7eSjoerg CXCursor Result = MakeCXCursorInvalid(CXCursor_NoDeclFound);
612606f32e7eSjoerg if (SLoc.isValid()) {
612706f32e7eSjoerg GetCursorData ResultData(CXXUnit->getSourceManager(), SLoc, Result);
612806f32e7eSjoerg CursorVisitor CursorVis(TU, GetCursorVisitor, &ResultData,
612906f32e7eSjoerg /*VisitPreprocessorLast=*/true,
613006f32e7eSjoerg /*VisitIncludedEntities=*/false,
613106f32e7eSjoerg SourceLocation(SLoc));
613206f32e7eSjoerg CursorVis.visitFileRegion();
613306f32e7eSjoerg }
613406f32e7eSjoerg
613506f32e7eSjoerg return Result;
613606f32e7eSjoerg }
613706f32e7eSjoerg
getRawCursorExtent(CXCursor C)613806f32e7eSjoerg static SourceRange getRawCursorExtent(CXCursor C) {
613906f32e7eSjoerg if (clang_isReference(C.kind)) {
614006f32e7eSjoerg switch (C.kind) {
614106f32e7eSjoerg case CXCursor_ObjCSuperClassRef:
614206f32e7eSjoerg return getCursorObjCSuperClassRef(C).second;
614306f32e7eSjoerg
614406f32e7eSjoerg case CXCursor_ObjCProtocolRef:
614506f32e7eSjoerg return getCursorObjCProtocolRef(C).second;
614606f32e7eSjoerg
614706f32e7eSjoerg case CXCursor_ObjCClassRef:
614806f32e7eSjoerg return getCursorObjCClassRef(C).second;
614906f32e7eSjoerg
615006f32e7eSjoerg case CXCursor_TypeRef:
615106f32e7eSjoerg return getCursorTypeRef(C).second;
615206f32e7eSjoerg
615306f32e7eSjoerg case CXCursor_TemplateRef:
615406f32e7eSjoerg return getCursorTemplateRef(C).second;
615506f32e7eSjoerg
615606f32e7eSjoerg case CXCursor_NamespaceRef:
615706f32e7eSjoerg return getCursorNamespaceRef(C).second;
615806f32e7eSjoerg
615906f32e7eSjoerg case CXCursor_MemberRef:
616006f32e7eSjoerg return getCursorMemberRef(C).second;
616106f32e7eSjoerg
616206f32e7eSjoerg case CXCursor_CXXBaseSpecifier:
616306f32e7eSjoerg return getCursorCXXBaseSpecifier(C)->getSourceRange();
616406f32e7eSjoerg
616506f32e7eSjoerg case CXCursor_LabelRef:
616606f32e7eSjoerg return getCursorLabelRef(C).second;
616706f32e7eSjoerg
616806f32e7eSjoerg case CXCursor_OverloadedDeclRef:
616906f32e7eSjoerg return getCursorOverloadedDeclRef(C).second;
617006f32e7eSjoerg
617106f32e7eSjoerg case CXCursor_VariableRef:
617206f32e7eSjoerg return getCursorVariableRef(C).second;
617306f32e7eSjoerg
617406f32e7eSjoerg default:
617506f32e7eSjoerg // FIXME: Need a way to enumerate all non-reference cases.
617606f32e7eSjoerg llvm_unreachable("Missed a reference kind");
617706f32e7eSjoerg }
617806f32e7eSjoerg }
617906f32e7eSjoerg
618006f32e7eSjoerg if (clang_isExpression(C.kind))
618106f32e7eSjoerg return getCursorExpr(C)->getSourceRange();
618206f32e7eSjoerg
618306f32e7eSjoerg if (clang_isStatement(C.kind))
618406f32e7eSjoerg return getCursorStmt(C)->getSourceRange();
618506f32e7eSjoerg
618606f32e7eSjoerg if (clang_isAttribute(C.kind))
618706f32e7eSjoerg return getCursorAttr(C)->getRange();
618806f32e7eSjoerg
618906f32e7eSjoerg if (C.kind == CXCursor_PreprocessingDirective)
619006f32e7eSjoerg return cxcursor::getCursorPreprocessingDirective(C);
619106f32e7eSjoerg
619206f32e7eSjoerg if (C.kind == CXCursor_MacroExpansion) {
619306f32e7eSjoerg ASTUnit *TU = getCursorASTUnit(C);
619406f32e7eSjoerg SourceRange Range = cxcursor::getCursorMacroExpansion(C).getSourceRange();
619506f32e7eSjoerg return TU->mapRangeFromPreamble(Range);
619606f32e7eSjoerg }
619706f32e7eSjoerg
619806f32e7eSjoerg if (C.kind == CXCursor_MacroDefinition) {
619906f32e7eSjoerg ASTUnit *TU = getCursorASTUnit(C);
620006f32e7eSjoerg SourceRange Range = cxcursor::getCursorMacroDefinition(C)->getSourceRange();
620106f32e7eSjoerg return TU->mapRangeFromPreamble(Range);
620206f32e7eSjoerg }
620306f32e7eSjoerg
620406f32e7eSjoerg if (C.kind == CXCursor_InclusionDirective) {
620506f32e7eSjoerg ASTUnit *TU = getCursorASTUnit(C);
6206*13fbcb42Sjoerg SourceRange Range =
6207*13fbcb42Sjoerg cxcursor::getCursorInclusionDirective(C)->getSourceRange();
620806f32e7eSjoerg return TU->mapRangeFromPreamble(Range);
620906f32e7eSjoerg }
621006f32e7eSjoerg
621106f32e7eSjoerg if (C.kind == CXCursor_TranslationUnit) {
621206f32e7eSjoerg ASTUnit *TU = getCursorASTUnit(C);
621306f32e7eSjoerg FileID MainID = TU->getSourceManager().getMainFileID();
621406f32e7eSjoerg SourceLocation Start = TU->getSourceManager().getLocForStartOfFile(MainID);
621506f32e7eSjoerg SourceLocation End = TU->getSourceManager().getLocForEndOfFile(MainID);
621606f32e7eSjoerg return SourceRange(Start, End);
621706f32e7eSjoerg }
621806f32e7eSjoerg
621906f32e7eSjoerg if (clang_isDeclaration(C.kind)) {
622006f32e7eSjoerg const Decl *D = cxcursor::getCursorDecl(C);
622106f32e7eSjoerg if (!D)
622206f32e7eSjoerg return SourceRange();
622306f32e7eSjoerg
622406f32e7eSjoerg SourceRange R = D->getSourceRange();
622506f32e7eSjoerg // FIXME: Multiple variables declared in a single declaration
622606f32e7eSjoerg // currently lack the information needed to correctly determine their
622706f32e7eSjoerg // ranges when accounting for the type-specifier. We use context
622806f32e7eSjoerg // stored in the CXCursor to determine if the VarDecl is in a DeclGroup,
622906f32e7eSjoerg // and if so, whether it is the first decl.
623006f32e7eSjoerg if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
623106f32e7eSjoerg if (!cxcursor::isFirstInDeclGroup(C))
623206f32e7eSjoerg R.setBegin(VD->getLocation());
623306f32e7eSjoerg }
623406f32e7eSjoerg return R;
623506f32e7eSjoerg }
623606f32e7eSjoerg return SourceRange();
623706f32e7eSjoerg }
623806f32e7eSjoerg
623906f32e7eSjoerg /// Retrieves the "raw" cursor extent, which is then extended to include
624006f32e7eSjoerg /// the decl-specifier-seq for declarations.
getFullCursorExtent(CXCursor C,SourceManager & SrcMgr)624106f32e7eSjoerg static SourceRange getFullCursorExtent(CXCursor C, SourceManager &SrcMgr) {
624206f32e7eSjoerg if (clang_isDeclaration(C.kind)) {
624306f32e7eSjoerg const Decl *D = cxcursor::getCursorDecl(C);
624406f32e7eSjoerg if (!D)
624506f32e7eSjoerg return SourceRange();
624606f32e7eSjoerg
624706f32e7eSjoerg SourceRange R = D->getSourceRange();
624806f32e7eSjoerg
624906f32e7eSjoerg // Adjust the start of the location for declarations preceded by
625006f32e7eSjoerg // declaration specifiers.
625106f32e7eSjoerg SourceLocation StartLoc;
625206f32e7eSjoerg if (const DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(D)) {
625306f32e7eSjoerg if (TypeSourceInfo *TI = DD->getTypeSourceInfo())
625406f32e7eSjoerg StartLoc = TI->getTypeLoc().getBeginLoc();
625506f32e7eSjoerg } else if (const TypedefDecl *Typedef = dyn_cast<TypedefDecl>(D)) {
625606f32e7eSjoerg if (TypeSourceInfo *TI = Typedef->getTypeSourceInfo())
625706f32e7eSjoerg StartLoc = TI->getTypeLoc().getBeginLoc();
625806f32e7eSjoerg }
625906f32e7eSjoerg
626006f32e7eSjoerg if (StartLoc.isValid() && R.getBegin().isValid() &&
626106f32e7eSjoerg SrcMgr.isBeforeInTranslationUnit(StartLoc, R.getBegin()))
626206f32e7eSjoerg R.setBegin(StartLoc);
626306f32e7eSjoerg
626406f32e7eSjoerg // FIXME: Multiple variables declared in a single declaration
626506f32e7eSjoerg // currently lack the information needed to correctly determine their
626606f32e7eSjoerg // ranges when accounting for the type-specifier. We use context
626706f32e7eSjoerg // stored in the CXCursor to determine if the VarDecl is in a DeclGroup,
626806f32e7eSjoerg // and if so, whether it is the first decl.
626906f32e7eSjoerg if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
627006f32e7eSjoerg if (!cxcursor::isFirstInDeclGroup(C))
627106f32e7eSjoerg R.setBegin(VD->getLocation());
627206f32e7eSjoerg }
627306f32e7eSjoerg
627406f32e7eSjoerg return R;
627506f32e7eSjoerg }
627606f32e7eSjoerg
627706f32e7eSjoerg return getRawCursorExtent(C);
627806f32e7eSjoerg }
627906f32e7eSjoerg
clang_getCursorExtent(CXCursor C)628006f32e7eSjoerg CXSourceRange clang_getCursorExtent(CXCursor C) {
628106f32e7eSjoerg SourceRange R = getRawCursorExtent(C);
628206f32e7eSjoerg if (R.isInvalid())
628306f32e7eSjoerg return clang_getNullRange();
628406f32e7eSjoerg
628506f32e7eSjoerg return cxloc::translateSourceRange(getCursorContext(C), R);
628606f32e7eSjoerg }
628706f32e7eSjoerg
clang_getCursorReferenced(CXCursor C)628806f32e7eSjoerg CXCursor clang_getCursorReferenced(CXCursor C) {
628906f32e7eSjoerg if (clang_isInvalid(C.kind))
629006f32e7eSjoerg return clang_getNullCursor();
629106f32e7eSjoerg
629206f32e7eSjoerg CXTranslationUnit tu = getCursorTU(C);
629306f32e7eSjoerg if (clang_isDeclaration(C.kind)) {
629406f32e7eSjoerg const Decl *D = getCursorDecl(C);
629506f32e7eSjoerg if (!D)
629606f32e7eSjoerg return clang_getNullCursor();
629706f32e7eSjoerg if (const UsingDecl *Using = dyn_cast<UsingDecl>(D))
629806f32e7eSjoerg return MakeCursorOverloadedDeclRef(Using, D->getLocation(), tu);
629906f32e7eSjoerg if (const ObjCPropertyImplDecl *PropImpl =
630006f32e7eSjoerg dyn_cast<ObjCPropertyImplDecl>(D))
630106f32e7eSjoerg if (ObjCPropertyDecl *Property = PropImpl->getPropertyDecl())
630206f32e7eSjoerg return MakeCXCursor(Property, tu);
630306f32e7eSjoerg
630406f32e7eSjoerg return C;
630506f32e7eSjoerg }
630606f32e7eSjoerg
630706f32e7eSjoerg if (clang_isExpression(C.kind)) {
630806f32e7eSjoerg const Expr *E = getCursorExpr(C);
630906f32e7eSjoerg const Decl *D = getDeclFromExpr(E);
631006f32e7eSjoerg if (D) {
631106f32e7eSjoerg CXCursor declCursor = MakeCXCursor(D, tu);
631206f32e7eSjoerg declCursor = getSelectorIdentifierCursor(getSelectorIdentifierIndex(C),
631306f32e7eSjoerg declCursor);
631406f32e7eSjoerg return declCursor;
631506f32e7eSjoerg }
631606f32e7eSjoerg
631706f32e7eSjoerg if (const OverloadExpr *Ovl = dyn_cast_or_null<OverloadExpr>(E))
631806f32e7eSjoerg return MakeCursorOverloadedDeclRef(Ovl, tu);
631906f32e7eSjoerg
632006f32e7eSjoerg return clang_getNullCursor();
632106f32e7eSjoerg }
632206f32e7eSjoerg
632306f32e7eSjoerg if (clang_isStatement(C.kind)) {
632406f32e7eSjoerg const Stmt *S = getCursorStmt(C);
632506f32e7eSjoerg if (const GotoStmt *Goto = dyn_cast_or_null<GotoStmt>(S))
632606f32e7eSjoerg if (LabelDecl *label = Goto->getLabel())
632706f32e7eSjoerg if (LabelStmt *labelS = label->getStmt())
632806f32e7eSjoerg return MakeCXCursor(labelS, getCursorDecl(C), tu);
632906f32e7eSjoerg
633006f32e7eSjoerg return clang_getNullCursor();
633106f32e7eSjoerg }
633206f32e7eSjoerg
633306f32e7eSjoerg if (C.kind == CXCursor_MacroExpansion) {
633406f32e7eSjoerg if (const MacroDefinitionRecord *Def =
633506f32e7eSjoerg getCursorMacroExpansion(C).getDefinition())
633606f32e7eSjoerg return MakeMacroDefinitionCursor(Def, tu);
633706f32e7eSjoerg }
633806f32e7eSjoerg
633906f32e7eSjoerg if (!clang_isReference(C.kind))
634006f32e7eSjoerg return clang_getNullCursor();
634106f32e7eSjoerg
634206f32e7eSjoerg switch (C.kind) {
634306f32e7eSjoerg case CXCursor_ObjCSuperClassRef:
634406f32e7eSjoerg return MakeCXCursor(getCursorObjCSuperClassRef(C).first, tu);
634506f32e7eSjoerg
634606f32e7eSjoerg case CXCursor_ObjCProtocolRef: {
634706f32e7eSjoerg const ObjCProtocolDecl *Prot = getCursorObjCProtocolRef(C).first;
634806f32e7eSjoerg if (const ObjCProtocolDecl *Def = Prot->getDefinition())
634906f32e7eSjoerg return MakeCXCursor(Def, tu);
635006f32e7eSjoerg
635106f32e7eSjoerg return MakeCXCursor(Prot, tu);
635206f32e7eSjoerg }
635306f32e7eSjoerg
635406f32e7eSjoerg case CXCursor_ObjCClassRef: {
635506f32e7eSjoerg const ObjCInterfaceDecl *Class = getCursorObjCClassRef(C).first;
635606f32e7eSjoerg if (const ObjCInterfaceDecl *Def = Class->getDefinition())
635706f32e7eSjoerg return MakeCXCursor(Def, tu);
635806f32e7eSjoerg
635906f32e7eSjoerg return MakeCXCursor(Class, tu);
636006f32e7eSjoerg }
636106f32e7eSjoerg
636206f32e7eSjoerg case CXCursor_TypeRef:
636306f32e7eSjoerg return MakeCXCursor(getCursorTypeRef(C).first, tu);
636406f32e7eSjoerg
636506f32e7eSjoerg case CXCursor_TemplateRef:
636606f32e7eSjoerg return MakeCXCursor(getCursorTemplateRef(C).first, tu);
636706f32e7eSjoerg
636806f32e7eSjoerg case CXCursor_NamespaceRef:
636906f32e7eSjoerg return MakeCXCursor(getCursorNamespaceRef(C).first, tu);
637006f32e7eSjoerg
637106f32e7eSjoerg case CXCursor_MemberRef:
637206f32e7eSjoerg return MakeCXCursor(getCursorMemberRef(C).first, tu);
637306f32e7eSjoerg
637406f32e7eSjoerg case CXCursor_CXXBaseSpecifier: {
637506f32e7eSjoerg const CXXBaseSpecifier *B = cxcursor::getCursorCXXBaseSpecifier(C);
6376*13fbcb42Sjoerg return clang_getTypeDeclaration(cxtype::MakeCXType(B->getType(), tu));
637706f32e7eSjoerg }
637806f32e7eSjoerg
637906f32e7eSjoerg case CXCursor_LabelRef:
638006f32e7eSjoerg // FIXME: We end up faking the "parent" declaration here because we
638106f32e7eSjoerg // don't want to make CXCursor larger.
6382*13fbcb42Sjoerg return MakeCXCursor(
6383*13fbcb42Sjoerg getCursorLabelRef(C).first,
6384*13fbcb42Sjoerg cxtu::getASTUnit(tu)->getASTContext().getTranslationUnitDecl(), tu);
638506f32e7eSjoerg
638606f32e7eSjoerg case CXCursor_OverloadedDeclRef:
638706f32e7eSjoerg return C;
638806f32e7eSjoerg
638906f32e7eSjoerg case CXCursor_VariableRef:
639006f32e7eSjoerg return MakeCXCursor(getCursorVariableRef(C).first, tu);
639106f32e7eSjoerg
639206f32e7eSjoerg default:
639306f32e7eSjoerg // We would prefer to enumerate all non-reference cursor kinds here.
639406f32e7eSjoerg llvm_unreachable("Unhandled reference cursor kind");
639506f32e7eSjoerg }
639606f32e7eSjoerg }
639706f32e7eSjoerg
clang_getCursorDefinition(CXCursor C)639806f32e7eSjoerg CXCursor clang_getCursorDefinition(CXCursor C) {
639906f32e7eSjoerg if (clang_isInvalid(C.kind))
640006f32e7eSjoerg return clang_getNullCursor();
640106f32e7eSjoerg
640206f32e7eSjoerg CXTranslationUnit TU = getCursorTU(C);
640306f32e7eSjoerg
640406f32e7eSjoerg bool WasReference = false;
640506f32e7eSjoerg if (clang_isReference(C.kind) || clang_isExpression(C.kind)) {
640606f32e7eSjoerg C = clang_getCursorReferenced(C);
640706f32e7eSjoerg WasReference = true;
640806f32e7eSjoerg }
640906f32e7eSjoerg
641006f32e7eSjoerg if (C.kind == CXCursor_MacroExpansion)
641106f32e7eSjoerg return clang_getCursorReferenced(C);
641206f32e7eSjoerg
641306f32e7eSjoerg if (!clang_isDeclaration(C.kind))
641406f32e7eSjoerg return clang_getNullCursor();
641506f32e7eSjoerg
641606f32e7eSjoerg const Decl *D = getCursorDecl(C);
641706f32e7eSjoerg if (!D)
641806f32e7eSjoerg return clang_getNullCursor();
641906f32e7eSjoerg
642006f32e7eSjoerg switch (D->getKind()) {
642106f32e7eSjoerg // Declaration kinds that don't really separate the notions of
642206f32e7eSjoerg // declaration and definition.
642306f32e7eSjoerg case Decl::Namespace:
642406f32e7eSjoerg case Decl::Typedef:
642506f32e7eSjoerg case Decl::TypeAlias:
642606f32e7eSjoerg case Decl::TypeAliasTemplate:
642706f32e7eSjoerg case Decl::TemplateTypeParm:
642806f32e7eSjoerg case Decl::EnumConstant:
642906f32e7eSjoerg case Decl::Field:
643006f32e7eSjoerg case Decl::Binding:
643106f32e7eSjoerg case Decl::MSProperty:
6432*13fbcb42Sjoerg case Decl::MSGuid:
6433*13fbcb42Sjoerg case Decl::TemplateParamObject:
643406f32e7eSjoerg case Decl::IndirectField:
643506f32e7eSjoerg case Decl::ObjCIvar:
643606f32e7eSjoerg case Decl::ObjCAtDefsField:
643706f32e7eSjoerg case Decl::ImplicitParam:
643806f32e7eSjoerg case Decl::ParmVar:
643906f32e7eSjoerg case Decl::NonTypeTemplateParm:
644006f32e7eSjoerg case Decl::TemplateTemplateParm:
644106f32e7eSjoerg case Decl::ObjCCategoryImpl:
644206f32e7eSjoerg case Decl::ObjCImplementation:
644306f32e7eSjoerg case Decl::AccessSpec:
644406f32e7eSjoerg case Decl::LinkageSpec:
644506f32e7eSjoerg case Decl::Export:
644606f32e7eSjoerg case Decl::ObjCPropertyImpl:
644706f32e7eSjoerg case Decl::FileScopeAsm:
644806f32e7eSjoerg case Decl::StaticAssert:
644906f32e7eSjoerg case Decl::Block:
645006f32e7eSjoerg case Decl::Captured:
645106f32e7eSjoerg case Decl::OMPCapturedExpr:
645206f32e7eSjoerg case Decl::Label: // FIXME: Is this right??
645306f32e7eSjoerg case Decl::ClassScopeFunctionSpecialization:
645406f32e7eSjoerg case Decl::CXXDeductionGuide:
645506f32e7eSjoerg case Decl::Import:
645606f32e7eSjoerg case Decl::OMPThreadPrivate:
645706f32e7eSjoerg case Decl::OMPAllocate:
645806f32e7eSjoerg case Decl::OMPDeclareReduction:
645906f32e7eSjoerg case Decl::OMPDeclareMapper:
646006f32e7eSjoerg case Decl::OMPRequires:
646106f32e7eSjoerg case Decl::ObjCTypeParam:
646206f32e7eSjoerg case Decl::BuiltinTemplate:
646306f32e7eSjoerg case Decl::PragmaComment:
646406f32e7eSjoerg case Decl::PragmaDetectMismatch:
646506f32e7eSjoerg case Decl::UsingPack:
646606f32e7eSjoerg case Decl::Concept:
6467*13fbcb42Sjoerg case Decl::LifetimeExtendedTemporary:
6468*13fbcb42Sjoerg case Decl::RequiresExprBody:
646906f32e7eSjoerg return C;
647006f32e7eSjoerg
647106f32e7eSjoerg // Declaration kinds that don't make any sense here, but are
647206f32e7eSjoerg // nonetheless harmless.
647306f32e7eSjoerg case Decl::Empty:
647406f32e7eSjoerg case Decl::TranslationUnit:
647506f32e7eSjoerg case Decl::ExternCContext:
647606f32e7eSjoerg break;
647706f32e7eSjoerg
647806f32e7eSjoerg // Declaration kinds for which the definition is not resolvable.
647906f32e7eSjoerg case Decl::UnresolvedUsingTypename:
648006f32e7eSjoerg case Decl::UnresolvedUsingValue:
648106f32e7eSjoerg break;
648206f32e7eSjoerg
648306f32e7eSjoerg case Decl::UsingDirective:
648406f32e7eSjoerg return MakeCXCursor(cast<UsingDirectiveDecl>(D)->getNominatedNamespace(),
648506f32e7eSjoerg TU);
648606f32e7eSjoerg
648706f32e7eSjoerg case Decl::NamespaceAlias:
648806f32e7eSjoerg return MakeCXCursor(cast<NamespaceAliasDecl>(D)->getNamespace(), TU);
648906f32e7eSjoerg
649006f32e7eSjoerg case Decl::Enum:
649106f32e7eSjoerg case Decl::Record:
649206f32e7eSjoerg case Decl::CXXRecord:
649306f32e7eSjoerg case Decl::ClassTemplateSpecialization:
649406f32e7eSjoerg case Decl::ClassTemplatePartialSpecialization:
649506f32e7eSjoerg if (TagDecl *Def = cast<TagDecl>(D)->getDefinition())
649606f32e7eSjoerg return MakeCXCursor(Def, TU);
649706f32e7eSjoerg return clang_getNullCursor();
649806f32e7eSjoerg
649906f32e7eSjoerg case Decl::Function:
650006f32e7eSjoerg case Decl::CXXMethod:
650106f32e7eSjoerg case Decl::CXXConstructor:
650206f32e7eSjoerg case Decl::CXXDestructor:
650306f32e7eSjoerg case Decl::CXXConversion: {
650406f32e7eSjoerg const FunctionDecl *Def = nullptr;
650506f32e7eSjoerg if (cast<FunctionDecl>(D)->getBody(Def))
650606f32e7eSjoerg return MakeCXCursor(Def, TU);
650706f32e7eSjoerg return clang_getNullCursor();
650806f32e7eSjoerg }
650906f32e7eSjoerg
651006f32e7eSjoerg case Decl::Var:
651106f32e7eSjoerg case Decl::VarTemplateSpecialization:
651206f32e7eSjoerg case Decl::VarTemplatePartialSpecialization:
651306f32e7eSjoerg case Decl::Decomposition: {
651406f32e7eSjoerg // Ask the variable if it has a definition.
651506f32e7eSjoerg if (const VarDecl *Def = cast<VarDecl>(D)->getDefinition())
651606f32e7eSjoerg return MakeCXCursor(Def, TU);
651706f32e7eSjoerg return clang_getNullCursor();
651806f32e7eSjoerg }
651906f32e7eSjoerg
652006f32e7eSjoerg case Decl::FunctionTemplate: {
652106f32e7eSjoerg const FunctionDecl *Def = nullptr;
652206f32e7eSjoerg if (cast<FunctionTemplateDecl>(D)->getTemplatedDecl()->getBody(Def))
652306f32e7eSjoerg return MakeCXCursor(Def->getDescribedFunctionTemplate(), TU);
652406f32e7eSjoerg return clang_getNullCursor();
652506f32e7eSjoerg }
652606f32e7eSjoerg
652706f32e7eSjoerg case Decl::ClassTemplate: {
6528*13fbcb42Sjoerg if (RecordDecl *Def =
6529*13fbcb42Sjoerg cast<ClassTemplateDecl>(D)->getTemplatedDecl()->getDefinition())
653006f32e7eSjoerg return MakeCXCursor(cast<CXXRecordDecl>(Def)->getDescribedClassTemplate(),
653106f32e7eSjoerg TU);
653206f32e7eSjoerg return clang_getNullCursor();
653306f32e7eSjoerg }
653406f32e7eSjoerg
653506f32e7eSjoerg case Decl::VarTemplate: {
653606f32e7eSjoerg if (VarDecl *Def =
653706f32e7eSjoerg cast<VarTemplateDecl>(D)->getTemplatedDecl()->getDefinition())
653806f32e7eSjoerg return MakeCXCursor(cast<VarDecl>(Def)->getDescribedVarTemplate(), TU);
653906f32e7eSjoerg return clang_getNullCursor();
654006f32e7eSjoerg }
654106f32e7eSjoerg
654206f32e7eSjoerg case Decl::Using:
6543*13fbcb42Sjoerg return MakeCursorOverloadedDeclRef(cast<UsingDecl>(D), D->getLocation(),
6544*13fbcb42Sjoerg TU);
654506f32e7eSjoerg
654606f32e7eSjoerg case Decl::UsingShadow:
654706f32e7eSjoerg case Decl::ConstructorUsingShadow:
654806f32e7eSjoerg return clang_getCursorDefinition(
6549*13fbcb42Sjoerg MakeCXCursor(cast<UsingShadowDecl>(D)->getTargetDecl(), TU));
655006f32e7eSjoerg
655106f32e7eSjoerg case Decl::ObjCMethod: {
655206f32e7eSjoerg const ObjCMethodDecl *Method = cast<ObjCMethodDecl>(D);
655306f32e7eSjoerg if (Method->isThisDeclarationADefinition())
655406f32e7eSjoerg return C;
655506f32e7eSjoerg
655606f32e7eSjoerg // Dig out the method definition in the associated
655706f32e7eSjoerg // @implementation, if we have it.
655806f32e7eSjoerg // FIXME: The ASTs should make finding the definition easier.
6559*13fbcb42Sjoerg if (const ObjCInterfaceDecl *Class =
6560*13fbcb42Sjoerg dyn_cast<ObjCInterfaceDecl>(Method->getDeclContext()))
656106f32e7eSjoerg if (ObjCImplementationDecl *ClassImpl = Class->getImplementation())
6562*13fbcb42Sjoerg if (ObjCMethodDecl *Def = ClassImpl->getMethod(
6563*13fbcb42Sjoerg Method->getSelector(), Method->isInstanceMethod()))
656406f32e7eSjoerg if (Def->isThisDeclarationADefinition())
656506f32e7eSjoerg return MakeCXCursor(Def, TU);
656606f32e7eSjoerg
656706f32e7eSjoerg return clang_getNullCursor();
656806f32e7eSjoerg }
656906f32e7eSjoerg
657006f32e7eSjoerg case Decl::ObjCCategory:
6571*13fbcb42Sjoerg if (ObjCCategoryImplDecl *Impl =
6572*13fbcb42Sjoerg cast<ObjCCategoryDecl>(D)->getImplementation())
657306f32e7eSjoerg return MakeCXCursor(Impl, TU);
657406f32e7eSjoerg return clang_getNullCursor();
657506f32e7eSjoerg
657606f32e7eSjoerg case Decl::ObjCProtocol:
6577*13fbcb42Sjoerg if (const ObjCProtocolDecl *Def =
6578*13fbcb42Sjoerg cast<ObjCProtocolDecl>(D)->getDefinition())
657906f32e7eSjoerg return MakeCXCursor(Def, TU);
658006f32e7eSjoerg return clang_getNullCursor();
658106f32e7eSjoerg
658206f32e7eSjoerg case Decl::ObjCInterface: {
658306f32e7eSjoerg // There are two notions of a "definition" for an Objective-C
658406f32e7eSjoerg // class: the interface and its implementation. When we resolved a
658506f32e7eSjoerg // reference to an Objective-C class, produce the @interface as
658606f32e7eSjoerg // the definition; when we were provided with the interface,
658706f32e7eSjoerg // produce the @implementation as the definition.
658806f32e7eSjoerg const ObjCInterfaceDecl *IFace = cast<ObjCInterfaceDecl>(D);
658906f32e7eSjoerg if (WasReference) {
659006f32e7eSjoerg if (const ObjCInterfaceDecl *Def = IFace->getDefinition())
659106f32e7eSjoerg return MakeCXCursor(Def, TU);
659206f32e7eSjoerg } else if (ObjCImplementationDecl *Impl = IFace->getImplementation())
659306f32e7eSjoerg return MakeCXCursor(Impl, TU);
659406f32e7eSjoerg return clang_getNullCursor();
659506f32e7eSjoerg }
659606f32e7eSjoerg
659706f32e7eSjoerg case Decl::ObjCProperty:
659806f32e7eSjoerg // FIXME: We don't really know where to find the
659906f32e7eSjoerg // ObjCPropertyImplDecls that implement this property.
660006f32e7eSjoerg return clang_getNullCursor();
660106f32e7eSjoerg
660206f32e7eSjoerg case Decl::ObjCCompatibleAlias:
6603*13fbcb42Sjoerg if (const ObjCInterfaceDecl *Class =
6604*13fbcb42Sjoerg cast<ObjCCompatibleAliasDecl>(D)->getClassInterface())
660506f32e7eSjoerg if (const ObjCInterfaceDecl *Def = Class->getDefinition())
660606f32e7eSjoerg return MakeCXCursor(Def, TU);
660706f32e7eSjoerg
660806f32e7eSjoerg return clang_getNullCursor();
660906f32e7eSjoerg
661006f32e7eSjoerg case Decl::Friend:
661106f32e7eSjoerg if (NamedDecl *Friend = cast<FriendDecl>(D)->getFriendDecl())
661206f32e7eSjoerg return clang_getCursorDefinition(MakeCXCursor(Friend, TU));
661306f32e7eSjoerg return clang_getNullCursor();
661406f32e7eSjoerg
661506f32e7eSjoerg case Decl::FriendTemplate:
661606f32e7eSjoerg if (NamedDecl *Friend = cast<FriendTemplateDecl>(D)->getFriendDecl())
661706f32e7eSjoerg return clang_getCursorDefinition(MakeCXCursor(Friend, TU));
661806f32e7eSjoerg return clang_getNullCursor();
661906f32e7eSjoerg }
662006f32e7eSjoerg
662106f32e7eSjoerg return clang_getNullCursor();
662206f32e7eSjoerg }
662306f32e7eSjoerg
clang_isCursorDefinition(CXCursor C)662406f32e7eSjoerg unsigned clang_isCursorDefinition(CXCursor C) {
662506f32e7eSjoerg if (!clang_isDeclaration(C.kind))
662606f32e7eSjoerg return 0;
662706f32e7eSjoerg
662806f32e7eSjoerg return clang_getCursorDefinition(C) == C;
662906f32e7eSjoerg }
663006f32e7eSjoerg
clang_getCanonicalCursor(CXCursor C)663106f32e7eSjoerg CXCursor clang_getCanonicalCursor(CXCursor C) {
663206f32e7eSjoerg if (!clang_isDeclaration(C.kind))
663306f32e7eSjoerg return C;
663406f32e7eSjoerg
663506f32e7eSjoerg if (const Decl *D = getCursorDecl(C)) {
6636*13fbcb42Sjoerg if (const ObjCCategoryImplDecl *CatImplD =
6637*13fbcb42Sjoerg dyn_cast<ObjCCategoryImplDecl>(D))
663806f32e7eSjoerg if (ObjCCategoryDecl *CatD = CatImplD->getCategoryDecl())
663906f32e7eSjoerg return MakeCXCursor(CatD, getCursorTU(C));
664006f32e7eSjoerg
664106f32e7eSjoerg if (const ObjCImplDecl *ImplD = dyn_cast<ObjCImplDecl>(D))
664206f32e7eSjoerg if (const ObjCInterfaceDecl *IFD = ImplD->getClassInterface())
664306f32e7eSjoerg return MakeCXCursor(IFD, getCursorTU(C));
664406f32e7eSjoerg
664506f32e7eSjoerg return MakeCXCursor(D->getCanonicalDecl(), getCursorTU(C));
664606f32e7eSjoerg }
664706f32e7eSjoerg
664806f32e7eSjoerg return C;
664906f32e7eSjoerg }
665006f32e7eSjoerg
clang_Cursor_getObjCSelectorIndex(CXCursor cursor)665106f32e7eSjoerg int clang_Cursor_getObjCSelectorIndex(CXCursor cursor) {
665206f32e7eSjoerg return cxcursor::getSelectorIdentifierIndexAndLoc(cursor).first;
665306f32e7eSjoerg }
665406f32e7eSjoerg
clang_getNumOverloadedDecls(CXCursor C)665506f32e7eSjoerg unsigned clang_getNumOverloadedDecls(CXCursor C) {
665606f32e7eSjoerg if (C.kind != CXCursor_OverloadedDeclRef)
665706f32e7eSjoerg return 0;
665806f32e7eSjoerg
665906f32e7eSjoerg OverloadedDeclRefStorage Storage = getCursorOverloadedDeclRef(C).first;
666006f32e7eSjoerg if (const OverloadExpr *E = Storage.dyn_cast<const OverloadExpr *>())
666106f32e7eSjoerg return E->getNumDecls();
666206f32e7eSjoerg
6663*13fbcb42Sjoerg if (OverloadedTemplateStorage *S =
6664*13fbcb42Sjoerg Storage.dyn_cast<OverloadedTemplateStorage *>())
666506f32e7eSjoerg return S->size();
666606f32e7eSjoerg
666706f32e7eSjoerg const Decl *D = Storage.get<const Decl *>();
666806f32e7eSjoerg if (const UsingDecl *Using = dyn_cast<UsingDecl>(D))
666906f32e7eSjoerg return Using->shadow_size();
667006f32e7eSjoerg
667106f32e7eSjoerg return 0;
667206f32e7eSjoerg }
667306f32e7eSjoerg
clang_getOverloadedDecl(CXCursor cursor,unsigned index)667406f32e7eSjoerg CXCursor clang_getOverloadedDecl(CXCursor cursor, unsigned index) {
667506f32e7eSjoerg if (cursor.kind != CXCursor_OverloadedDeclRef)
667606f32e7eSjoerg return clang_getNullCursor();
667706f32e7eSjoerg
667806f32e7eSjoerg if (index >= clang_getNumOverloadedDecls(cursor))
667906f32e7eSjoerg return clang_getNullCursor();
668006f32e7eSjoerg
668106f32e7eSjoerg CXTranslationUnit TU = getCursorTU(cursor);
668206f32e7eSjoerg OverloadedDeclRefStorage Storage = getCursorOverloadedDeclRef(cursor).first;
668306f32e7eSjoerg if (const OverloadExpr *E = Storage.dyn_cast<const OverloadExpr *>())
668406f32e7eSjoerg return MakeCXCursor(E->decls_begin()[index], TU);
668506f32e7eSjoerg
6686*13fbcb42Sjoerg if (OverloadedTemplateStorage *S =
6687*13fbcb42Sjoerg Storage.dyn_cast<OverloadedTemplateStorage *>())
668806f32e7eSjoerg return MakeCXCursor(S->begin()[index], TU);
668906f32e7eSjoerg
669006f32e7eSjoerg const Decl *D = Storage.get<const Decl *>();
669106f32e7eSjoerg if (const UsingDecl *Using = dyn_cast<UsingDecl>(D)) {
669206f32e7eSjoerg // FIXME: This is, unfortunately, linear time.
669306f32e7eSjoerg UsingDecl::shadow_iterator Pos = Using->shadow_begin();
669406f32e7eSjoerg std::advance(Pos, index);
669506f32e7eSjoerg return MakeCXCursor(cast<UsingShadowDecl>(*Pos)->getTargetDecl(), TU);
669606f32e7eSjoerg }
669706f32e7eSjoerg
669806f32e7eSjoerg return clang_getNullCursor();
669906f32e7eSjoerg }
670006f32e7eSjoerg
clang_getDefinitionSpellingAndExtent(CXCursor C,const char ** startBuf,const char ** endBuf,unsigned * startLine,unsigned * startColumn,unsigned * endLine,unsigned * endColumn)6701*13fbcb42Sjoerg void clang_getDefinitionSpellingAndExtent(
6702*13fbcb42Sjoerg CXCursor C, const char **startBuf, const char **endBuf, unsigned *startLine,
6703*13fbcb42Sjoerg unsigned *startColumn, unsigned *endLine, unsigned *endColumn) {
670406f32e7eSjoerg assert(getCursorDecl(C) && "CXCursor has null decl");
670506f32e7eSjoerg const FunctionDecl *FD = dyn_cast<FunctionDecl>(getCursorDecl(C));
670606f32e7eSjoerg CompoundStmt *Body = dyn_cast<CompoundStmt>(FD->getBody());
670706f32e7eSjoerg
670806f32e7eSjoerg SourceManager &SM = FD->getASTContext().getSourceManager();
670906f32e7eSjoerg *startBuf = SM.getCharacterData(Body->getLBracLoc());
671006f32e7eSjoerg *endBuf = SM.getCharacterData(Body->getRBracLoc());
671106f32e7eSjoerg *startLine = SM.getSpellingLineNumber(Body->getLBracLoc());
671206f32e7eSjoerg *startColumn = SM.getSpellingColumnNumber(Body->getLBracLoc());
671306f32e7eSjoerg *endLine = SM.getSpellingLineNumber(Body->getRBracLoc());
671406f32e7eSjoerg *endColumn = SM.getSpellingColumnNumber(Body->getRBracLoc());
671506f32e7eSjoerg }
671606f32e7eSjoerg
clang_getCursorReferenceNameRange(CXCursor C,unsigned NameFlags,unsigned PieceIndex)671706f32e7eSjoerg CXSourceRange clang_getCursorReferenceNameRange(CXCursor C, unsigned NameFlags,
671806f32e7eSjoerg unsigned PieceIndex) {
671906f32e7eSjoerg RefNamePieces Pieces;
672006f32e7eSjoerg
672106f32e7eSjoerg switch (C.kind) {
672206f32e7eSjoerg case CXCursor_MemberRefExpr:
672306f32e7eSjoerg if (const MemberExpr *E = dyn_cast<MemberExpr>(getCursorExpr(C)))
672406f32e7eSjoerg Pieces = buildPieces(NameFlags, true, E->getMemberNameInfo(),
672506f32e7eSjoerg E->getQualifierLoc().getSourceRange());
672606f32e7eSjoerg break;
672706f32e7eSjoerg
672806f32e7eSjoerg case CXCursor_DeclRefExpr:
672906f32e7eSjoerg if (const DeclRefExpr *E = dyn_cast<DeclRefExpr>(getCursorExpr(C))) {
673006f32e7eSjoerg SourceRange TemplateArgLoc(E->getLAngleLoc(), E->getRAngleLoc());
673106f32e7eSjoerg Pieces =
673206f32e7eSjoerg buildPieces(NameFlags, false, E->getNameInfo(),
673306f32e7eSjoerg E->getQualifierLoc().getSourceRange(), &TemplateArgLoc);
673406f32e7eSjoerg }
673506f32e7eSjoerg break;
673606f32e7eSjoerg
673706f32e7eSjoerg case CXCursor_CallExpr:
673806f32e7eSjoerg if (const CXXOperatorCallExpr *OCE =
673906f32e7eSjoerg dyn_cast<CXXOperatorCallExpr>(getCursorExpr(C))) {
674006f32e7eSjoerg const Expr *Callee = OCE->getCallee();
674106f32e7eSjoerg if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Callee))
674206f32e7eSjoerg Callee = ICE->getSubExpr();
674306f32e7eSjoerg
674406f32e7eSjoerg if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Callee))
674506f32e7eSjoerg Pieces = buildPieces(NameFlags, false, DRE->getNameInfo(),
674606f32e7eSjoerg DRE->getQualifierLoc().getSourceRange());
674706f32e7eSjoerg }
674806f32e7eSjoerg break;
674906f32e7eSjoerg
675006f32e7eSjoerg default:
675106f32e7eSjoerg break;
675206f32e7eSjoerg }
675306f32e7eSjoerg
675406f32e7eSjoerg if (Pieces.empty()) {
675506f32e7eSjoerg if (PieceIndex == 0)
675606f32e7eSjoerg return clang_getCursorExtent(C);
675706f32e7eSjoerg } else if (PieceIndex < Pieces.size()) {
675806f32e7eSjoerg SourceRange R = Pieces[PieceIndex];
675906f32e7eSjoerg if (R.isValid())
676006f32e7eSjoerg return cxloc::translateSourceRange(getCursorContext(C), R);
676106f32e7eSjoerg }
676206f32e7eSjoerg
676306f32e7eSjoerg return clang_getNullRange();
676406f32e7eSjoerg }
676506f32e7eSjoerg
clang_enableStackTraces(void)676606f32e7eSjoerg void clang_enableStackTraces(void) {
676706f32e7eSjoerg // FIXME: Provide an argv0 here so we can find llvm-symbolizer.
676806f32e7eSjoerg llvm::sys::PrintStackTraceOnErrorSignal(StringRef());
676906f32e7eSjoerg }
677006f32e7eSjoerg
clang_executeOnThread(void (* fn)(void *),void * user_data,unsigned stack_size)677106f32e7eSjoerg void clang_executeOnThread(void (*fn)(void *), void *user_data,
677206f32e7eSjoerg unsigned stack_size) {
6773*13fbcb42Sjoerg llvm::llvm_execute_on_thread(fn, user_data,
6774*13fbcb42Sjoerg stack_size == 0
6775*13fbcb42Sjoerg ? clang::DesiredStackSize
6776*13fbcb42Sjoerg : llvm::Optional<unsigned>(stack_size));
677706f32e7eSjoerg }
677806f32e7eSjoerg
677906f32e7eSjoerg //===----------------------------------------------------------------------===//
678006f32e7eSjoerg // Token-based Operations.
678106f32e7eSjoerg //===----------------------------------------------------------------------===//
678206f32e7eSjoerg
678306f32e7eSjoerg /* CXToken layout:
678406f32e7eSjoerg * int_data[0]: a CXTokenKind
678506f32e7eSjoerg * int_data[1]: starting token location
678606f32e7eSjoerg * int_data[2]: token length
678706f32e7eSjoerg * int_data[3]: reserved
678806f32e7eSjoerg * ptr_data: for identifiers and keywords, an IdentifierInfo*.
678906f32e7eSjoerg * otherwise unused.
679006f32e7eSjoerg */
clang_getTokenKind(CXToken CXTok)679106f32e7eSjoerg CXTokenKind clang_getTokenKind(CXToken CXTok) {
679206f32e7eSjoerg return static_cast<CXTokenKind>(CXTok.int_data[0]);
679306f32e7eSjoerg }
679406f32e7eSjoerg
clang_getTokenSpelling(CXTranslationUnit TU,CXToken CXTok)679506f32e7eSjoerg CXString clang_getTokenSpelling(CXTranslationUnit TU, CXToken CXTok) {
679606f32e7eSjoerg switch (clang_getTokenKind(CXTok)) {
679706f32e7eSjoerg case CXToken_Identifier:
679806f32e7eSjoerg case CXToken_Keyword:
679906f32e7eSjoerg // We know we have an IdentifierInfo*, so use that.
6800*13fbcb42Sjoerg return cxstring::createRef(
6801*13fbcb42Sjoerg static_cast<IdentifierInfo *>(CXTok.ptr_data)->getNameStart());
680206f32e7eSjoerg
680306f32e7eSjoerg case CXToken_Literal: {
680406f32e7eSjoerg // We have stashed the starting pointer in the ptr_data field. Use it.
680506f32e7eSjoerg const char *Text = static_cast<const char *>(CXTok.ptr_data);
680606f32e7eSjoerg return cxstring::createDup(StringRef(Text, CXTok.int_data[2]));
680706f32e7eSjoerg }
680806f32e7eSjoerg
680906f32e7eSjoerg case CXToken_Punctuation:
681006f32e7eSjoerg case CXToken_Comment:
681106f32e7eSjoerg break;
681206f32e7eSjoerg }
681306f32e7eSjoerg
681406f32e7eSjoerg if (isNotUsableTU(TU)) {
681506f32e7eSjoerg LOG_BAD_TU(TU);
681606f32e7eSjoerg return cxstring::createEmpty();
681706f32e7eSjoerg }
681806f32e7eSjoerg
681906f32e7eSjoerg // We have to find the starting buffer pointer the hard way, by
682006f32e7eSjoerg // deconstructing the source location.
682106f32e7eSjoerg ASTUnit *CXXUnit = cxtu::getASTUnit(TU);
682206f32e7eSjoerg if (!CXXUnit)
682306f32e7eSjoerg return cxstring::createEmpty();
682406f32e7eSjoerg
682506f32e7eSjoerg SourceLocation Loc = SourceLocation::getFromRawEncoding(CXTok.int_data[1]);
6826*13fbcb42Sjoerg std::pair<FileID, unsigned> LocInfo =
6827*13fbcb42Sjoerg CXXUnit->getSourceManager().getDecomposedSpellingLoc(Loc);
682806f32e7eSjoerg bool Invalid = false;
6829*13fbcb42Sjoerg StringRef Buffer =
6830*13fbcb42Sjoerg CXXUnit->getSourceManager().getBufferData(LocInfo.first, &Invalid);
683106f32e7eSjoerg if (Invalid)
683206f32e7eSjoerg return cxstring::createEmpty();
683306f32e7eSjoerg
683406f32e7eSjoerg return cxstring::createDup(Buffer.substr(LocInfo.second, CXTok.int_data[2]));
683506f32e7eSjoerg }
683606f32e7eSjoerg
clang_getTokenLocation(CXTranslationUnit TU,CXToken CXTok)683706f32e7eSjoerg CXSourceLocation clang_getTokenLocation(CXTranslationUnit TU, CXToken CXTok) {
683806f32e7eSjoerg if (isNotUsableTU(TU)) {
683906f32e7eSjoerg LOG_BAD_TU(TU);
684006f32e7eSjoerg return clang_getNullLocation();
684106f32e7eSjoerg }
684206f32e7eSjoerg
684306f32e7eSjoerg ASTUnit *CXXUnit = cxtu::getASTUnit(TU);
684406f32e7eSjoerg if (!CXXUnit)
684506f32e7eSjoerg return clang_getNullLocation();
684606f32e7eSjoerg
6847*13fbcb42Sjoerg return cxloc::translateSourceLocation(
6848*13fbcb42Sjoerg CXXUnit->getASTContext(),
684906f32e7eSjoerg SourceLocation::getFromRawEncoding(CXTok.int_data[1]));
685006f32e7eSjoerg }
685106f32e7eSjoerg
clang_getTokenExtent(CXTranslationUnit TU,CXToken CXTok)685206f32e7eSjoerg CXSourceRange clang_getTokenExtent(CXTranslationUnit TU, CXToken CXTok) {
685306f32e7eSjoerg if (isNotUsableTU(TU)) {
685406f32e7eSjoerg LOG_BAD_TU(TU);
685506f32e7eSjoerg return clang_getNullRange();
685606f32e7eSjoerg }
685706f32e7eSjoerg
685806f32e7eSjoerg ASTUnit *CXXUnit = cxtu::getASTUnit(TU);
685906f32e7eSjoerg if (!CXXUnit)
686006f32e7eSjoerg return clang_getNullRange();
686106f32e7eSjoerg
6862*13fbcb42Sjoerg return cxloc::translateSourceRange(
6863*13fbcb42Sjoerg CXXUnit->getASTContext(),
686406f32e7eSjoerg SourceLocation::getFromRawEncoding(CXTok.int_data[1]));
686506f32e7eSjoerg }
686606f32e7eSjoerg
getTokens(ASTUnit * CXXUnit,SourceRange Range,SmallVectorImpl<CXToken> & CXTokens)686706f32e7eSjoerg static void getTokens(ASTUnit *CXXUnit, SourceRange Range,
686806f32e7eSjoerg SmallVectorImpl<CXToken> &CXTokens) {
686906f32e7eSjoerg SourceManager &SourceMgr = CXXUnit->getSourceManager();
6870*13fbcb42Sjoerg std::pair<FileID, unsigned> BeginLocInfo =
6871*13fbcb42Sjoerg SourceMgr.getDecomposedSpellingLoc(Range.getBegin());
6872*13fbcb42Sjoerg std::pair<FileID, unsigned> EndLocInfo =
6873*13fbcb42Sjoerg SourceMgr.getDecomposedSpellingLoc(Range.getEnd());
687406f32e7eSjoerg
687506f32e7eSjoerg // Cannot tokenize across files.
687606f32e7eSjoerg if (BeginLocInfo.first != EndLocInfo.first)
687706f32e7eSjoerg return;
687806f32e7eSjoerg
687906f32e7eSjoerg // Create a lexer
688006f32e7eSjoerg bool Invalid = false;
6881*13fbcb42Sjoerg StringRef Buffer = SourceMgr.getBufferData(BeginLocInfo.first, &Invalid);
688206f32e7eSjoerg if (Invalid)
688306f32e7eSjoerg return;
688406f32e7eSjoerg
688506f32e7eSjoerg Lexer Lex(SourceMgr.getLocForStartOfFile(BeginLocInfo.first),
6886*13fbcb42Sjoerg CXXUnit->getASTContext().getLangOpts(), Buffer.begin(),
6887*13fbcb42Sjoerg Buffer.data() + BeginLocInfo.second, Buffer.end());
688806f32e7eSjoerg Lex.SetCommentRetentionState(true);
688906f32e7eSjoerg
689006f32e7eSjoerg // Lex tokens until we hit the end of the range.
689106f32e7eSjoerg const char *EffectiveBufferEnd = Buffer.data() + EndLocInfo.second;
689206f32e7eSjoerg Token Tok;
689306f32e7eSjoerg bool previousWasAt = false;
689406f32e7eSjoerg do {
689506f32e7eSjoerg // Lex the next token
689606f32e7eSjoerg Lex.LexFromRawLexer(Tok);
689706f32e7eSjoerg if (Tok.is(tok::eof))
689806f32e7eSjoerg break;
689906f32e7eSjoerg
690006f32e7eSjoerg // Initialize the CXToken.
690106f32e7eSjoerg CXToken CXTok;
690206f32e7eSjoerg
690306f32e7eSjoerg // - Common fields
690406f32e7eSjoerg CXTok.int_data[1] = Tok.getLocation().getRawEncoding();
690506f32e7eSjoerg CXTok.int_data[2] = Tok.getLength();
690606f32e7eSjoerg CXTok.int_data[3] = 0;
690706f32e7eSjoerg
690806f32e7eSjoerg // - Kind-specific fields
690906f32e7eSjoerg if (Tok.isLiteral()) {
691006f32e7eSjoerg CXTok.int_data[0] = CXToken_Literal;
691106f32e7eSjoerg CXTok.ptr_data = const_cast<char *>(Tok.getLiteralData());
691206f32e7eSjoerg } else if (Tok.is(tok::raw_identifier)) {
691306f32e7eSjoerg // Lookup the identifier to determine whether we have a keyword.
6914*13fbcb42Sjoerg IdentifierInfo *II = CXXUnit->getPreprocessor().LookUpIdentifierInfo(Tok);
691506f32e7eSjoerg
691606f32e7eSjoerg if ((II->getObjCKeywordID() != tok::objc_not_keyword) && previousWasAt) {
691706f32e7eSjoerg CXTok.int_data[0] = CXToken_Keyword;
6918*13fbcb42Sjoerg } else {
6919*13fbcb42Sjoerg CXTok.int_data[0] =
6920*13fbcb42Sjoerg Tok.is(tok::identifier) ? CXToken_Identifier : CXToken_Keyword;
692106f32e7eSjoerg }
692206f32e7eSjoerg CXTok.ptr_data = II;
692306f32e7eSjoerg } else if (Tok.is(tok::comment)) {
692406f32e7eSjoerg CXTok.int_data[0] = CXToken_Comment;
692506f32e7eSjoerg CXTok.ptr_data = nullptr;
692606f32e7eSjoerg } else {
692706f32e7eSjoerg CXTok.int_data[0] = CXToken_Punctuation;
692806f32e7eSjoerg CXTok.ptr_data = nullptr;
692906f32e7eSjoerg }
693006f32e7eSjoerg CXTokens.push_back(CXTok);
693106f32e7eSjoerg previousWasAt = Tok.is(tok::at);
693206f32e7eSjoerg } while (Lex.getBufferLocation() < EffectiveBufferEnd);
693306f32e7eSjoerg }
693406f32e7eSjoerg
clang_getToken(CXTranslationUnit TU,CXSourceLocation Location)693506f32e7eSjoerg CXToken *clang_getToken(CXTranslationUnit TU, CXSourceLocation Location) {
6936*13fbcb42Sjoerg LOG_FUNC_SECTION { *Log << TU << ' ' << Location; }
693706f32e7eSjoerg
693806f32e7eSjoerg if (isNotUsableTU(TU)) {
693906f32e7eSjoerg LOG_BAD_TU(TU);
694006f32e7eSjoerg return NULL;
694106f32e7eSjoerg }
694206f32e7eSjoerg
694306f32e7eSjoerg ASTUnit *CXXUnit = cxtu::getASTUnit(TU);
694406f32e7eSjoerg if (!CXXUnit)
694506f32e7eSjoerg return NULL;
694606f32e7eSjoerg
694706f32e7eSjoerg SourceLocation Begin = cxloc::translateSourceLocation(Location);
694806f32e7eSjoerg if (Begin.isInvalid())
694906f32e7eSjoerg return NULL;
695006f32e7eSjoerg SourceManager &SM = CXXUnit->getSourceManager();
695106f32e7eSjoerg std::pair<FileID, unsigned> DecomposedEnd = SM.getDecomposedLoc(Begin);
6952*13fbcb42Sjoerg DecomposedEnd.second +=
6953*13fbcb42Sjoerg Lexer::MeasureTokenLength(Begin, SM, CXXUnit->getLangOpts());
695406f32e7eSjoerg
6955*13fbcb42Sjoerg SourceLocation End =
6956*13fbcb42Sjoerg SM.getComposedLoc(DecomposedEnd.first, DecomposedEnd.second);
695706f32e7eSjoerg
695806f32e7eSjoerg SmallVector<CXToken, 32> CXTokens;
695906f32e7eSjoerg getTokens(CXXUnit, SourceRange(Begin, End), CXTokens);
696006f32e7eSjoerg
696106f32e7eSjoerg if (CXTokens.empty())
696206f32e7eSjoerg return NULL;
696306f32e7eSjoerg
696406f32e7eSjoerg CXTokens.resize(1);
696506f32e7eSjoerg CXToken *Token = static_cast<CXToken *>(llvm::safe_malloc(sizeof(CXToken)));
696606f32e7eSjoerg
696706f32e7eSjoerg memmove(Token, CXTokens.data(), sizeof(CXToken));
696806f32e7eSjoerg return Token;
696906f32e7eSjoerg }
697006f32e7eSjoerg
clang_tokenize(CXTranslationUnit TU,CXSourceRange Range,CXToken ** Tokens,unsigned * NumTokens)6971*13fbcb42Sjoerg void clang_tokenize(CXTranslationUnit TU, CXSourceRange Range, CXToken **Tokens,
6972*13fbcb42Sjoerg unsigned *NumTokens) {
6973*13fbcb42Sjoerg LOG_FUNC_SECTION { *Log << TU << ' ' << Range; }
697406f32e7eSjoerg
697506f32e7eSjoerg if (Tokens)
697606f32e7eSjoerg *Tokens = nullptr;
697706f32e7eSjoerg if (NumTokens)
697806f32e7eSjoerg *NumTokens = 0;
697906f32e7eSjoerg
698006f32e7eSjoerg if (isNotUsableTU(TU)) {
698106f32e7eSjoerg LOG_BAD_TU(TU);
698206f32e7eSjoerg return;
698306f32e7eSjoerg }
698406f32e7eSjoerg
698506f32e7eSjoerg ASTUnit *CXXUnit = cxtu::getASTUnit(TU);
698606f32e7eSjoerg if (!CXXUnit || !Tokens || !NumTokens)
698706f32e7eSjoerg return;
698806f32e7eSjoerg
698906f32e7eSjoerg ASTUnit::ConcurrencyCheck Check(*CXXUnit);
699006f32e7eSjoerg
699106f32e7eSjoerg SourceRange R = cxloc::translateCXSourceRange(Range);
699206f32e7eSjoerg if (R.isInvalid())
699306f32e7eSjoerg return;
699406f32e7eSjoerg
699506f32e7eSjoerg SmallVector<CXToken, 32> CXTokens;
699606f32e7eSjoerg getTokens(CXXUnit, R, CXTokens);
699706f32e7eSjoerg
699806f32e7eSjoerg if (CXTokens.empty())
699906f32e7eSjoerg return;
700006f32e7eSjoerg
700106f32e7eSjoerg *Tokens = static_cast<CXToken *>(
700206f32e7eSjoerg llvm::safe_malloc(sizeof(CXToken) * CXTokens.size()));
700306f32e7eSjoerg memmove(*Tokens, CXTokens.data(), sizeof(CXToken) * CXTokens.size());
700406f32e7eSjoerg *NumTokens = CXTokens.size();
700506f32e7eSjoerg }
700606f32e7eSjoerg
clang_disposeTokens(CXTranslationUnit TU,CXToken * Tokens,unsigned NumTokens)7007*13fbcb42Sjoerg void clang_disposeTokens(CXTranslationUnit TU, CXToken *Tokens,
7008*13fbcb42Sjoerg unsigned NumTokens) {
700906f32e7eSjoerg free(Tokens);
701006f32e7eSjoerg }
701106f32e7eSjoerg
701206f32e7eSjoerg //===----------------------------------------------------------------------===//
701306f32e7eSjoerg // Token annotation APIs.
701406f32e7eSjoerg //===----------------------------------------------------------------------===//
701506f32e7eSjoerg
701606f32e7eSjoerg static enum CXChildVisitResult AnnotateTokensVisitor(CXCursor cursor,
701706f32e7eSjoerg CXCursor parent,
701806f32e7eSjoerg CXClientData client_data);
701906f32e7eSjoerg static bool AnnotateTokensPostChildrenVisitor(CXCursor cursor,
702006f32e7eSjoerg CXClientData client_data);
702106f32e7eSjoerg
702206f32e7eSjoerg namespace {
702306f32e7eSjoerg class AnnotateTokensWorker {
702406f32e7eSjoerg CXToken *Tokens;
702506f32e7eSjoerg CXCursor *Cursors;
702606f32e7eSjoerg unsigned NumTokens;
702706f32e7eSjoerg unsigned TokIdx;
702806f32e7eSjoerg unsigned PreprocessingTokIdx;
702906f32e7eSjoerg CursorVisitor AnnotateVis;
703006f32e7eSjoerg SourceManager &SrcMgr;
703106f32e7eSjoerg bool HasContextSensitiveKeywords;
703206f32e7eSjoerg
703306f32e7eSjoerg struct PostChildrenAction {
703406f32e7eSjoerg CXCursor cursor;
703506f32e7eSjoerg enum Action { Invalid, Ignore, Postpone } action;
703606f32e7eSjoerg };
703706f32e7eSjoerg using PostChildrenActions = SmallVector<PostChildrenAction, 0>;
703806f32e7eSjoerg
703906f32e7eSjoerg struct PostChildrenInfo {
704006f32e7eSjoerg CXCursor Cursor;
704106f32e7eSjoerg SourceRange CursorRange;
704206f32e7eSjoerg unsigned BeforeReachingCursorIdx;
704306f32e7eSjoerg unsigned BeforeChildrenTokenIdx;
704406f32e7eSjoerg PostChildrenActions ChildActions;
704506f32e7eSjoerg };
704606f32e7eSjoerg SmallVector<PostChildrenInfo, 8> PostChildrenInfos;
704706f32e7eSjoerg
getTok(unsigned Idx)704806f32e7eSjoerg CXToken &getTok(unsigned Idx) {
704906f32e7eSjoerg assert(Idx < NumTokens);
705006f32e7eSjoerg return Tokens[Idx];
705106f32e7eSjoerg }
getTok(unsigned Idx) const705206f32e7eSjoerg const CXToken &getTok(unsigned Idx) const {
705306f32e7eSjoerg assert(Idx < NumTokens);
705406f32e7eSjoerg return Tokens[Idx];
705506f32e7eSjoerg }
MoreTokens() const705606f32e7eSjoerg bool MoreTokens() const { return TokIdx < NumTokens; }
NextToken() const705706f32e7eSjoerg unsigned NextToken() const { return TokIdx; }
AdvanceToken()705806f32e7eSjoerg void AdvanceToken() { ++TokIdx; }
GetTokenLoc(unsigned tokI)705906f32e7eSjoerg SourceLocation GetTokenLoc(unsigned tokI) {
706006f32e7eSjoerg return SourceLocation::getFromRawEncoding(getTok(tokI).int_data[1]);
706106f32e7eSjoerg }
isFunctionMacroToken(unsigned tokI) const706206f32e7eSjoerg bool isFunctionMacroToken(unsigned tokI) const {
706306f32e7eSjoerg return getTok(tokI).int_data[3] != 0;
706406f32e7eSjoerg }
getFunctionMacroTokenLoc(unsigned tokI) const706506f32e7eSjoerg SourceLocation getFunctionMacroTokenLoc(unsigned tokI) const {
706606f32e7eSjoerg return SourceLocation::getFromRawEncoding(getTok(tokI).int_data[3]);
706706f32e7eSjoerg }
706806f32e7eSjoerg
706906f32e7eSjoerg void annotateAndAdvanceTokens(CXCursor, RangeComparisonResult, SourceRange);
707006f32e7eSjoerg bool annotateAndAdvanceFunctionMacroTokens(CXCursor, RangeComparisonResult,
707106f32e7eSjoerg SourceRange);
707206f32e7eSjoerg
707306f32e7eSjoerg public:
AnnotateTokensWorker(CXToken * tokens,CXCursor * cursors,unsigned numTokens,CXTranslationUnit TU,SourceRange RegionOfInterest)707406f32e7eSjoerg AnnotateTokensWorker(CXToken *tokens, CXCursor *cursors, unsigned numTokens,
707506f32e7eSjoerg CXTranslationUnit TU, SourceRange RegionOfInterest)
7076*13fbcb42Sjoerg : Tokens(tokens), Cursors(cursors), NumTokens(numTokens), TokIdx(0),
7077*13fbcb42Sjoerg PreprocessingTokIdx(0),
7078*13fbcb42Sjoerg AnnotateVis(TU, AnnotateTokensVisitor, this,
707906f32e7eSjoerg /*VisitPreprocessorLast=*/true,
7080*13fbcb42Sjoerg /*VisitIncludedEntities=*/false, RegionOfInterest,
708106f32e7eSjoerg /*VisitDeclsOnly=*/false,
708206f32e7eSjoerg AnnotateTokensPostChildrenVisitor),
708306f32e7eSjoerg SrcMgr(cxtu::getASTUnit(TU)->getSourceManager()),
708406f32e7eSjoerg HasContextSensitiveKeywords(false) {}
708506f32e7eSjoerg
VisitChildren(CXCursor C)708606f32e7eSjoerg void VisitChildren(CXCursor C) { AnnotateVis.VisitChildren(C); }
708706f32e7eSjoerg enum CXChildVisitResult Visit(CXCursor cursor, CXCursor parent);
708806f32e7eSjoerg bool IsIgnoredChildCursor(CXCursor cursor) const;
708906f32e7eSjoerg PostChildrenActions DetermineChildActions(CXCursor Cursor) const;
709006f32e7eSjoerg
709106f32e7eSjoerg bool postVisitChildren(CXCursor cursor);
709206f32e7eSjoerg void HandlePostPonedChildCursors(const PostChildrenInfo &Info);
709306f32e7eSjoerg void HandlePostPonedChildCursor(CXCursor Cursor, unsigned StartTokenIndex);
709406f32e7eSjoerg
709506f32e7eSjoerg void AnnotateTokens();
709606f32e7eSjoerg
709706f32e7eSjoerg /// Determine whether the annotator saw any cursors that have
709806f32e7eSjoerg /// context-sensitive keywords.
hasContextSensitiveKeywords() const709906f32e7eSjoerg bool hasContextSensitiveKeywords() const {
710006f32e7eSjoerg return HasContextSensitiveKeywords;
710106f32e7eSjoerg }
710206f32e7eSjoerg
~AnnotateTokensWorker()7103*13fbcb42Sjoerg ~AnnotateTokensWorker() { assert(PostChildrenInfos.empty()); }
710406f32e7eSjoerg };
7105*13fbcb42Sjoerg } // namespace
710606f32e7eSjoerg
AnnotateTokens()710706f32e7eSjoerg void AnnotateTokensWorker::AnnotateTokens() {
710806f32e7eSjoerg // Walk the AST within the region of interest, annotating tokens
710906f32e7eSjoerg // along the way.
711006f32e7eSjoerg AnnotateVis.visitFileRegion();
711106f32e7eSjoerg }
711206f32e7eSjoerg
IsIgnoredChildCursor(CXCursor cursor) const711306f32e7eSjoerg bool AnnotateTokensWorker::IsIgnoredChildCursor(CXCursor cursor) const {
711406f32e7eSjoerg if (PostChildrenInfos.empty())
711506f32e7eSjoerg return false;
711606f32e7eSjoerg
711706f32e7eSjoerg for (const auto &ChildAction : PostChildrenInfos.back().ChildActions) {
711806f32e7eSjoerg if (ChildAction.cursor == cursor &&
711906f32e7eSjoerg ChildAction.action == PostChildrenAction::Ignore) {
712006f32e7eSjoerg return true;
712106f32e7eSjoerg }
712206f32e7eSjoerg }
712306f32e7eSjoerg
712406f32e7eSjoerg return false;
712506f32e7eSjoerg }
712606f32e7eSjoerg
GetSubscriptOrCallOperator(CXCursor Cursor)712706f32e7eSjoerg const CXXOperatorCallExpr *GetSubscriptOrCallOperator(CXCursor Cursor) {
712806f32e7eSjoerg if (!clang_isExpression(Cursor.kind))
712906f32e7eSjoerg return nullptr;
713006f32e7eSjoerg
713106f32e7eSjoerg const Expr *E = getCursorExpr(Cursor);
713206f32e7eSjoerg if (const auto *OCE = dyn_cast<CXXOperatorCallExpr>(E)) {
713306f32e7eSjoerg const OverloadedOperatorKind Kind = OCE->getOperator();
713406f32e7eSjoerg if (Kind == OO_Call || Kind == OO_Subscript)
713506f32e7eSjoerg return OCE;
713606f32e7eSjoerg }
713706f32e7eSjoerg
713806f32e7eSjoerg return nullptr;
713906f32e7eSjoerg }
714006f32e7eSjoerg
714106f32e7eSjoerg AnnotateTokensWorker::PostChildrenActions
DetermineChildActions(CXCursor Cursor) const714206f32e7eSjoerg AnnotateTokensWorker::DetermineChildActions(CXCursor Cursor) const {
714306f32e7eSjoerg PostChildrenActions actions;
714406f32e7eSjoerg
714506f32e7eSjoerg // The DeclRefExpr of CXXOperatorCallExpr refering to the custom operator is
714606f32e7eSjoerg // visited before the arguments to the operator call. For the Call and
714706f32e7eSjoerg // Subscript operator the range of this DeclRefExpr includes the whole call
714806f32e7eSjoerg // expression, so that all tokens in that range would be mapped to the
714906f32e7eSjoerg // operator function, including the tokens of the arguments. To avoid that,
715006f32e7eSjoerg // ensure to visit this DeclRefExpr as last node.
715106f32e7eSjoerg if (const auto *OCE = GetSubscriptOrCallOperator(Cursor)) {
715206f32e7eSjoerg const Expr *Callee = OCE->getCallee();
715306f32e7eSjoerg if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Callee)) {
715406f32e7eSjoerg const Expr *SubExpr = ICE->getSubExpr();
715506f32e7eSjoerg if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(SubExpr)) {
715606f32e7eSjoerg const Decl *parentDecl = getCursorDecl(Cursor);
715706f32e7eSjoerg CXTranslationUnit TU = clang_Cursor_getTranslationUnit(Cursor);
715806f32e7eSjoerg
715906f32e7eSjoerg // Visit the DeclRefExpr as last.
716006f32e7eSjoerg CXCursor cxChild = MakeCXCursor(DRE, parentDecl, TU);
716106f32e7eSjoerg actions.push_back({cxChild, PostChildrenAction::Postpone});
716206f32e7eSjoerg
716306f32e7eSjoerg // The parent of the DeclRefExpr, an ImplicitCastExpr, has an equally
716406f32e7eSjoerg // wide range as the DeclRefExpr. We can skip visiting this entirely.
716506f32e7eSjoerg cxChild = MakeCXCursor(ICE, parentDecl, TU);
716606f32e7eSjoerg actions.push_back({cxChild, PostChildrenAction::Ignore});
716706f32e7eSjoerg }
716806f32e7eSjoerg }
716906f32e7eSjoerg }
717006f32e7eSjoerg
717106f32e7eSjoerg return actions;
717206f32e7eSjoerg }
717306f32e7eSjoerg
updateCursorAnnotation(CXCursor & Cursor,const CXCursor & updateC)717406f32e7eSjoerg static inline void updateCursorAnnotation(CXCursor &Cursor,
717506f32e7eSjoerg const CXCursor &updateC) {
717606f32e7eSjoerg if (clang_isInvalid(updateC.kind) || !clang_isInvalid(Cursor.kind))
717706f32e7eSjoerg return;
717806f32e7eSjoerg Cursor = updateC;
717906f32e7eSjoerg }
718006f32e7eSjoerg
718106f32e7eSjoerg /// It annotates and advances tokens with a cursor until the comparison
718206f32e7eSjoerg //// between the cursor location and the source range is the same as
718306f32e7eSjoerg /// \arg compResult.
718406f32e7eSjoerg ///
718506f32e7eSjoerg /// Pass RangeBefore to annotate tokens with a cursor until a range is reached.
718606f32e7eSjoerg /// Pass RangeOverlap to annotate tokens inside a range.
annotateAndAdvanceTokens(CXCursor updateC,RangeComparisonResult compResult,SourceRange range)7187*13fbcb42Sjoerg void AnnotateTokensWorker::annotateAndAdvanceTokens(
7188*13fbcb42Sjoerg CXCursor updateC, RangeComparisonResult compResult, SourceRange range) {
718906f32e7eSjoerg while (MoreTokens()) {
719006f32e7eSjoerg const unsigned I = NextToken();
719106f32e7eSjoerg if (isFunctionMacroToken(I))
719206f32e7eSjoerg if (!annotateAndAdvanceFunctionMacroTokens(updateC, compResult, range))
719306f32e7eSjoerg return;
719406f32e7eSjoerg
719506f32e7eSjoerg SourceLocation TokLoc = GetTokenLoc(I);
719606f32e7eSjoerg if (LocationCompare(SrcMgr, TokLoc, range) == compResult) {
719706f32e7eSjoerg updateCursorAnnotation(Cursors[I], updateC);
719806f32e7eSjoerg AdvanceToken();
719906f32e7eSjoerg continue;
720006f32e7eSjoerg }
720106f32e7eSjoerg break;
720206f32e7eSjoerg }
720306f32e7eSjoerg }
720406f32e7eSjoerg
720506f32e7eSjoerg /// Special annotation handling for macro argument tokens.
720606f32e7eSjoerg /// \returns true if it advanced beyond all macro tokens, false otherwise.
annotateAndAdvanceFunctionMacroTokens(CXCursor updateC,RangeComparisonResult compResult,SourceRange range)720706f32e7eSjoerg bool AnnotateTokensWorker::annotateAndAdvanceFunctionMacroTokens(
7208*13fbcb42Sjoerg CXCursor updateC, RangeComparisonResult compResult, SourceRange range) {
720906f32e7eSjoerg assert(MoreTokens());
721006f32e7eSjoerg assert(isFunctionMacroToken(NextToken()) &&
721106f32e7eSjoerg "Should be called only for macro arg tokens");
721206f32e7eSjoerg
721306f32e7eSjoerg // This works differently than annotateAndAdvanceTokens; because expanded
721406f32e7eSjoerg // macro arguments can have arbitrary translation-unit source order, we do not
721506f32e7eSjoerg // advance the token index one by one until a token fails the range test.
721606f32e7eSjoerg // We only advance once past all of the macro arg tokens if all of them
721706f32e7eSjoerg // pass the range test. If one of them fails we keep the token index pointing
721806f32e7eSjoerg // at the start of the macro arg tokens so that the failing token will be
721906f32e7eSjoerg // annotated by a subsequent annotation try.
722006f32e7eSjoerg
722106f32e7eSjoerg bool atLeastOneCompFail = false;
722206f32e7eSjoerg
722306f32e7eSjoerg unsigned I = NextToken();
722406f32e7eSjoerg for (; I < NumTokens && isFunctionMacroToken(I); ++I) {
722506f32e7eSjoerg SourceLocation TokLoc = getFunctionMacroTokenLoc(I);
722606f32e7eSjoerg if (TokLoc.isFileID())
722706f32e7eSjoerg continue; // not macro arg token, it's parens or comma.
722806f32e7eSjoerg if (LocationCompare(SrcMgr, TokLoc, range) == compResult) {
722906f32e7eSjoerg if (clang_isInvalid(clang_getCursorKind(Cursors[I])))
723006f32e7eSjoerg Cursors[I] = updateC;
723106f32e7eSjoerg } else
723206f32e7eSjoerg atLeastOneCompFail = true;
723306f32e7eSjoerg }
723406f32e7eSjoerg
723506f32e7eSjoerg if (atLeastOneCompFail)
723606f32e7eSjoerg return false;
723706f32e7eSjoerg
723806f32e7eSjoerg TokIdx = I; // All of the tokens were handled, advance beyond all of them.
723906f32e7eSjoerg return true;
724006f32e7eSjoerg }
724106f32e7eSjoerg
Visit(CXCursor cursor,CXCursor parent)7242*13fbcb42Sjoerg enum CXChildVisitResult AnnotateTokensWorker::Visit(CXCursor cursor,
7243*13fbcb42Sjoerg CXCursor parent) {
724406f32e7eSjoerg SourceRange cursorRange = getRawCursorExtent(cursor);
724506f32e7eSjoerg if (cursorRange.isInvalid())
724606f32e7eSjoerg return CXChildVisit_Recurse;
724706f32e7eSjoerg
724806f32e7eSjoerg if (IsIgnoredChildCursor(cursor))
724906f32e7eSjoerg return CXChildVisit_Continue;
725006f32e7eSjoerg
725106f32e7eSjoerg if (!HasContextSensitiveKeywords) {
725206f32e7eSjoerg // Objective-C properties can have context-sensitive keywords.
725306f32e7eSjoerg if (cursor.kind == CXCursor_ObjCPropertyDecl) {
7254*13fbcb42Sjoerg if (const ObjCPropertyDecl *Property =
7255*13fbcb42Sjoerg dyn_cast_or_null<ObjCPropertyDecl>(getCursorDecl(cursor)))
7256*13fbcb42Sjoerg HasContextSensitiveKeywords =
7257*13fbcb42Sjoerg Property->getPropertyAttributesAsWritten() != 0;
725806f32e7eSjoerg }
725906f32e7eSjoerg // Objective-C methods can have context-sensitive keywords.
726006f32e7eSjoerg else if (cursor.kind == CXCursor_ObjCInstanceMethodDecl ||
726106f32e7eSjoerg cursor.kind == CXCursor_ObjCClassMethodDecl) {
7262*13fbcb42Sjoerg if (const ObjCMethodDecl *Method =
7263*13fbcb42Sjoerg dyn_cast_or_null<ObjCMethodDecl>(getCursorDecl(cursor))) {
726406f32e7eSjoerg if (Method->getObjCDeclQualifier())
726506f32e7eSjoerg HasContextSensitiveKeywords = true;
726606f32e7eSjoerg else {
726706f32e7eSjoerg for (const auto *P : Method->parameters()) {
726806f32e7eSjoerg if (P->getObjCDeclQualifier()) {
726906f32e7eSjoerg HasContextSensitiveKeywords = true;
727006f32e7eSjoerg break;
727106f32e7eSjoerg }
727206f32e7eSjoerg }
727306f32e7eSjoerg }
727406f32e7eSjoerg }
727506f32e7eSjoerg }
727606f32e7eSjoerg // C++ methods can have context-sensitive keywords.
727706f32e7eSjoerg else if (cursor.kind == CXCursor_CXXMethod) {
7278*13fbcb42Sjoerg if (const CXXMethodDecl *Method =
7279*13fbcb42Sjoerg dyn_cast_or_null<CXXMethodDecl>(getCursorDecl(cursor))) {
728006f32e7eSjoerg if (Method->hasAttr<FinalAttr>() || Method->hasAttr<OverrideAttr>())
728106f32e7eSjoerg HasContextSensitiveKeywords = true;
728206f32e7eSjoerg }
728306f32e7eSjoerg }
728406f32e7eSjoerg // C++ classes can have context-sensitive keywords.
728506f32e7eSjoerg else if (cursor.kind == CXCursor_StructDecl ||
728606f32e7eSjoerg cursor.kind == CXCursor_ClassDecl ||
728706f32e7eSjoerg cursor.kind == CXCursor_ClassTemplate ||
728806f32e7eSjoerg cursor.kind == CXCursor_ClassTemplatePartialSpecialization) {
728906f32e7eSjoerg if (const Decl *D = getCursorDecl(cursor))
729006f32e7eSjoerg if (D->hasAttr<FinalAttr>())
729106f32e7eSjoerg HasContextSensitiveKeywords = true;
729206f32e7eSjoerg }
729306f32e7eSjoerg }
729406f32e7eSjoerg
729506f32e7eSjoerg // Don't override a property annotation with its getter/setter method.
729606f32e7eSjoerg if (cursor.kind == CXCursor_ObjCInstanceMethodDecl &&
729706f32e7eSjoerg parent.kind == CXCursor_ObjCPropertyDecl)
729806f32e7eSjoerg return CXChildVisit_Continue;
729906f32e7eSjoerg
730006f32e7eSjoerg if (clang_isPreprocessing(cursor.kind)) {
730106f32e7eSjoerg // Items in the preprocessing record are kept separate from items in
730206f32e7eSjoerg // declarations, so we keep a separate token index.
730306f32e7eSjoerg unsigned SavedTokIdx = TokIdx;
730406f32e7eSjoerg TokIdx = PreprocessingTokIdx;
730506f32e7eSjoerg
730606f32e7eSjoerg // Skip tokens up until we catch up to the beginning of the preprocessing
730706f32e7eSjoerg // entry.
730806f32e7eSjoerg while (MoreTokens()) {
730906f32e7eSjoerg const unsigned I = NextToken();
731006f32e7eSjoerg SourceLocation TokLoc = GetTokenLoc(I);
731106f32e7eSjoerg switch (LocationCompare(SrcMgr, TokLoc, cursorRange)) {
731206f32e7eSjoerg case RangeBefore:
731306f32e7eSjoerg AdvanceToken();
731406f32e7eSjoerg continue;
731506f32e7eSjoerg case RangeAfter:
731606f32e7eSjoerg case RangeOverlap:
731706f32e7eSjoerg break;
731806f32e7eSjoerg }
731906f32e7eSjoerg break;
732006f32e7eSjoerg }
732106f32e7eSjoerg
732206f32e7eSjoerg // Look at all of the tokens within this range.
732306f32e7eSjoerg while (MoreTokens()) {
732406f32e7eSjoerg const unsigned I = NextToken();
732506f32e7eSjoerg SourceLocation TokLoc = GetTokenLoc(I);
732606f32e7eSjoerg switch (LocationCompare(SrcMgr, TokLoc, cursorRange)) {
732706f32e7eSjoerg case RangeBefore:
732806f32e7eSjoerg llvm_unreachable("Infeasible");
732906f32e7eSjoerg case RangeAfter:
733006f32e7eSjoerg break;
733106f32e7eSjoerg case RangeOverlap:
733206f32e7eSjoerg // For macro expansions, just note where the beginning of the macro
733306f32e7eSjoerg // expansion occurs.
733406f32e7eSjoerg if (cursor.kind == CXCursor_MacroExpansion) {
733506f32e7eSjoerg if (TokLoc == cursorRange.getBegin())
733606f32e7eSjoerg Cursors[I] = cursor;
733706f32e7eSjoerg AdvanceToken();
733806f32e7eSjoerg break;
733906f32e7eSjoerg }
734006f32e7eSjoerg // We may have already annotated macro names inside macro definitions.
734106f32e7eSjoerg if (Cursors[I].kind != CXCursor_MacroExpansion)
734206f32e7eSjoerg Cursors[I] = cursor;
734306f32e7eSjoerg AdvanceToken();
734406f32e7eSjoerg continue;
734506f32e7eSjoerg }
734606f32e7eSjoerg break;
734706f32e7eSjoerg }
734806f32e7eSjoerg
734906f32e7eSjoerg // Save the preprocessing token index; restore the non-preprocessing
735006f32e7eSjoerg // token index.
735106f32e7eSjoerg PreprocessingTokIdx = TokIdx;
735206f32e7eSjoerg TokIdx = SavedTokIdx;
735306f32e7eSjoerg return CXChildVisit_Recurse;
735406f32e7eSjoerg }
735506f32e7eSjoerg
735606f32e7eSjoerg if (cursorRange.isInvalid())
735706f32e7eSjoerg return CXChildVisit_Continue;
735806f32e7eSjoerg
735906f32e7eSjoerg unsigned BeforeReachingCursorIdx = NextToken();
736006f32e7eSjoerg const enum CXCursorKind cursorK = clang_getCursorKind(cursor);
736106f32e7eSjoerg const enum CXCursorKind K = clang_getCursorKind(parent);
736206f32e7eSjoerg const CXCursor updateC =
736306f32e7eSjoerg (clang_isInvalid(K) || K == CXCursor_TranslationUnit ||
736406f32e7eSjoerg // Attributes are annotated out-of-order, skip tokens until we reach it.
736506f32e7eSjoerg clang_isAttribute(cursor.kind))
7366*13fbcb42Sjoerg ? clang_getNullCursor()
7367*13fbcb42Sjoerg : parent;
736806f32e7eSjoerg
736906f32e7eSjoerg annotateAndAdvanceTokens(updateC, RangeBefore, cursorRange);
737006f32e7eSjoerg
737106f32e7eSjoerg // Avoid having the cursor of an expression "overwrite" the annotation of the
737206f32e7eSjoerg // variable declaration that it belongs to.
737306f32e7eSjoerg // This can happen for C++ constructor expressions whose range generally
737406f32e7eSjoerg // include the variable declaration, e.g.:
737506f32e7eSjoerg // MyCXXClass foo; // Make sure we don't annotate 'foo' as a CallExpr cursor.
737606f32e7eSjoerg if (clang_isExpression(cursorK) && MoreTokens()) {
737706f32e7eSjoerg const Expr *E = getCursorExpr(cursor);
737806f32e7eSjoerg if (const Decl *D = getCursorDecl(cursor)) {
737906f32e7eSjoerg const unsigned I = NextToken();
738006f32e7eSjoerg if (E->getBeginLoc().isValid() && D->getLocation().isValid() &&
738106f32e7eSjoerg E->getBeginLoc() == D->getLocation() &&
738206f32e7eSjoerg E->getBeginLoc() == GetTokenLoc(I)) {
738306f32e7eSjoerg updateCursorAnnotation(Cursors[I], updateC);
738406f32e7eSjoerg AdvanceToken();
738506f32e7eSjoerg }
738606f32e7eSjoerg }
738706f32e7eSjoerg }
738806f32e7eSjoerg
738906f32e7eSjoerg // Before recursing into the children keep some state that we are going
739006f32e7eSjoerg // to use in the AnnotateTokensWorker::postVisitChildren callback to do some
739106f32e7eSjoerg // extra work after the child nodes are visited.
739206f32e7eSjoerg // Note that we don't call VisitChildren here to avoid traversing statements
739306f32e7eSjoerg // code-recursively which can blow the stack.
739406f32e7eSjoerg
739506f32e7eSjoerg PostChildrenInfo Info;
739606f32e7eSjoerg Info.Cursor = cursor;
739706f32e7eSjoerg Info.CursorRange = cursorRange;
739806f32e7eSjoerg Info.BeforeReachingCursorIdx = BeforeReachingCursorIdx;
739906f32e7eSjoerg Info.BeforeChildrenTokenIdx = NextToken();
740006f32e7eSjoerg Info.ChildActions = DetermineChildActions(cursor);
740106f32e7eSjoerg PostChildrenInfos.push_back(Info);
740206f32e7eSjoerg
740306f32e7eSjoerg return CXChildVisit_Recurse;
740406f32e7eSjoerg }
740506f32e7eSjoerg
postVisitChildren(CXCursor cursor)740606f32e7eSjoerg bool AnnotateTokensWorker::postVisitChildren(CXCursor cursor) {
740706f32e7eSjoerg if (PostChildrenInfos.empty())
740806f32e7eSjoerg return false;
740906f32e7eSjoerg const PostChildrenInfo &Info = PostChildrenInfos.back();
741006f32e7eSjoerg if (!clang_equalCursors(Info.Cursor, cursor))
741106f32e7eSjoerg return false;
741206f32e7eSjoerg
741306f32e7eSjoerg HandlePostPonedChildCursors(Info);
741406f32e7eSjoerg
741506f32e7eSjoerg const unsigned BeforeChildren = Info.BeforeChildrenTokenIdx;
741606f32e7eSjoerg const unsigned AfterChildren = NextToken();
741706f32e7eSjoerg SourceRange cursorRange = Info.CursorRange;
741806f32e7eSjoerg
741906f32e7eSjoerg // Scan the tokens that are at the end of the cursor, but are not captured
742006f32e7eSjoerg // but the child cursors.
742106f32e7eSjoerg annotateAndAdvanceTokens(cursor, RangeOverlap, cursorRange);
742206f32e7eSjoerg
742306f32e7eSjoerg // Scan the tokens that are at the beginning of the cursor, but are not
742406f32e7eSjoerg // capture by the child cursors.
742506f32e7eSjoerg for (unsigned I = BeforeChildren; I != AfterChildren; ++I) {
742606f32e7eSjoerg if (!clang_isInvalid(clang_getCursorKind(Cursors[I])))
742706f32e7eSjoerg break;
742806f32e7eSjoerg
742906f32e7eSjoerg Cursors[I] = cursor;
743006f32e7eSjoerg }
743106f32e7eSjoerg
743206f32e7eSjoerg // Attributes are annotated out-of-order, rewind TokIdx to when we first
743306f32e7eSjoerg // encountered the attribute cursor.
743406f32e7eSjoerg if (clang_isAttribute(cursor.kind))
743506f32e7eSjoerg TokIdx = Info.BeforeReachingCursorIdx;
743606f32e7eSjoerg
743706f32e7eSjoerg PostChildrenInfos.pop_back();
743806f32e7eSjoerg return false;
743906f32e7eSjoerg }
744006f32e7eSjoerg
HandlePostPonedChildCursors(const PostChildrenInfo & Info)744106f32e7eSjoerg void AnnotateTokensWorker::HandlePostPonedChildCursors(
744206f32e7eSjoerg const PostChildrenInfo &Info) {
744306f32e7eSjoerg for (const auto &ChildAction : Info.ChildActions) {
744406f32e7eSjoerg if (ChildAction.action == PostChildrenAction::Postpone) {
744506f32e7eSjoerg HandlePostPonedChildCursor(ChildAction.cursor,
744606f32e7eSjoerg Info.BeforeChildrenTokenIdx);
744706f32e7eSjoerg }
744806f32e7eSjoerg }
744906f32e7eSjoerg }
745006f32e7eSjoerg
HandlePostPonedChildCursor(CXCursor Cursor,unsigned StartTokenIndex)745106f32e7eSjoerg void AnnotateTokensWorker::HandlePostPonedChildCursor(
745206f32e7eSjoerg CXCursor Cursor, unsigned StartTokenIndex) {
745306f32e7eSjoerg unsigned I = StartTokenIndex;
745406f32e7eSjoerg
745506f32e7eSjoerg // The bracket tokens of a Call or Subscript operator are mapped to
745606f32e7eSjoerg // CallExpr/CXXOperatorCallExpr because we skipped visiting the corresponding
745706f32e7eSjoerg // DeclRefExpr. Remap these tokens to the DeclRefExpr cursors.
745806f32e7eSjoerg for (unsigned RefNameRangeNr = 0; I < NumTokens; RefNameRangeNr++) {
745906f32e7eSjoerg const CXSourceRange CXRefNameRange = clang_getCursorReferenceNameRange(
746006f32e7eSjoerg Cursor, CXNameRange_WantQualifier, RefNameRangeNr);
746106f32e7eSjoerg if (clang_Range_isNull(CXRefNameRange))
746206f32e7eSjoerg break; // All ranges handled.
746306f32e7eSjoerg
746406f32e7eSjoerg SourceRange RefNameRange = cxloc::translateCXSourceRange(CXRefNameRange);
746506f32e7eSjoerg while (I < NumTokens) {
746606f32e7eSjoerg const SourceLocation TokenLocation = GetTokenLoc(I);
746706f32e7eSjoerg if (!TokenLocation.isValid())
746806f32e7eSjoerg break;
746906f32e7eSjoerg
747006f32e7eSjoerg // Adapt the end range, because LocationCompare() reports
747106f32e7eSjoerg // RangeOverlap even for the not-inclusive end location.
747206f32e7eSjoerg const SourceLocation fixedEnd =
747306f32e7eSjoerg RefNameRange.getEnd().getLocWithOffset(-1);
747406f32e7eSjoerg RefNameRange = SourceRange(RefNameRange.getBegin(), fixedEnd);
747506f32e7eSjoerg
747606f32e7eSjoerg const RangeComparisonResult ComparisonResult =
747706f32e7eSjoerg LocationCompare(SrcMgr, TokenLocation, RefNameRange);
747806f32e7eSjoerg
747906f32e7eSjoerg if (ComparisonResult == RangeOverlap) {
748006f32e7eSjoerg Cursors[I++] = Cursor;
748106f32e7eSjoerg } else if (ComparisonResult == RangeBefore) {
748206f32e7eSjoerg ++I; // Not relevant token, check next one.
748306f32e7eSjoerg } else if (ComparisonResult == RangeAfter) {
748406f32e7eSjoerg break; // All tokens updated for current range, check next.
748506f32e7eSjoerg }
748606f32e7eSjoerg }
748706f32e7eSjoerg }
748806f32e7eSjoerg }
748906f32e7eSjoerg
AnnotateTokensVisitor(CXCursor cursor,CXCursor parent,CXClientData client_data)749006f32e7eSjoerg static enum CXChildVisitResult AnnotateTokensVisitor(CXCursor cursor,
749106f32e7eSjoerg CXCursor parent,
749206f32e7eSjoerg CXClientData client_data) {
7493*13fbcb42Sjoerg return static_cast<AnnotateTokensWorker *>(client_data)
7494*13fbcb42Sjoerg ->Visit(cursor, parent);
749506f32e7eSjoerg }
749606f32e7eSjoerg
AnnotateTokensPostChildrenVisitor(CXCursor cursor,CXClientData client_data)749706f32e7eSjoerg static bool AnnotateTokensPostChildrenVisitor(CXCursor cursor,
749806f32e7eSjoerg CXClientData client_data) {
7499*13fbcb42Sjoerg return static_cast<AnnotateTokensWorker *>(client_data)
7500*13fbcb42Sjoerg ->postVisitChildren(cursor);
750106f32e7eSjoerg }
750206f32e7eSjoerg
750306f32e7eSjoerg namespace {
750406f32e7eSjoerg
750506f32e7eSjoerg /// Uses the macro expansions in the preprocessing record to find
750606f32e7eSjoerg /// and mark tokens that are macro arguments. This info is used by the
750706f32e7eSjoerg /// AnnotateTokensWorker.
750806f32e7eSjoerg class MarkMacroArgTokensVisitor {
750906f32e7eSjoerg SourceManager &SM;
751006f32e7eSjoerg CXToken *Tokens;
751106f32e7eSjoerg unsigned NumTokens;
751206f32e7eSjoerg unsigned CurIdx;
751306f32e7eSjoerg
751406f32e7eSjoerg public:
MarkMacroArgTokensVisitor(SourceManager & SM,CXToken * tokens,unsigned numTokens)7515*13fbcb42Sjoerg MarkMacroArgTokensVisitor(SourceManager &SM, CXToken *tokens,
7516*13fbcb42Sjoerg unsigned numTokens)
751706f32e7eSjoerg : SM(SM), Tokens(tokens), NumTokens(numTokens), CurIdx(0) {}
751806f32e7eSjoerg
visit(CXCursor cursor,CXCursor parent)751906f32e7eSjoerg CXChildVisitResult visit(CXCursor cursor, CXCursor parent) {
752006f32e7eSjoerg if (cursor.kind != CXCursor_MacroExpansion)
752106f32e7eSjoerg return CXChildVisit_Continue;
752206f32e7eSjoerg
752306f32e7eSjoerg SourceRange macroRange = getCursorMacroExpansion(cursor).getSourceRange();
752406f32e7eSjoerg if (macroRange.getBegin() == macroRange.getEnd())
752506f32e7eSjoerg return CXChildVisit_Continue; // it's not a function macro.
752606f32e7eSjoerg
752706f32e7eSjoerg for (; CurIdx < NumTokens; ++CurIdx) {
752806f32e7eSjoerg if (!SM.isBeforeInTranslationUnit(getTokenLoc(CurIdx),
752906f32e7eSjoerg macroRange.getBegin()))
753006f32e7eSjoerg break;
753106f32e7eSjoerg }
753206f32e7eSjoerg
753306f32e7eSjoerg if (CurIdx == NumTokens)
753406f32e7eSjoerg return CXChildVisit_Break;
753506f32e7eSjoerg
753606f32e7eSjoerg for (; CurIdx < NumTokens; ++CurIdx) {
753706f32e7eSjoerg SourceLocation tokLoc = getTokenLoc(CurIdx);
753806f32e7eSjoerg if (!SM.isBeforeInTranslationUnit(tokLoc, macroRange.getEnd()))
753906f32e7eSjoerg break;
754006f32e7eSjoerg
754106f32e7eSjoerg setFunctionMacroTokenLoc(CurIdx, SM.getMacroArgExpandedLocation(tokLoc));
754206f32e7eSjoerg }
754306f32e7eSjoerg
754406f32e7eSjoerg if (CurIdx == NumTokens)
754506f32e7eSjoerg return CXChildVisit_Break;
754606f32e7eSjoerg
754706f32e7eSjoerg return CXChildVisit_Continue;
754806f32e7eSjoerg }
754906f32e7eSjoerg
755006f32e7eSjoerg private:
getTok(unsigned Idx)755106f32e7eSjoerg CXToken &getTok(unsigned Idx) {
755206f32e7eSjoerg assert(Idx < NumTokens);
755306f32e7eSjoerg return Tokens[Idx];
755406f32e7eSjoerg }
getTok(unsigned Idx) const755506f32e7eSjoerg const CXToken &getTok(unsigned Idx) const {
755606f32e7eSjoerg assert(Idx < NumTokens);
755706f32e7eSjoerg return Tokens[Idx];
755806f32e7eSjoerg }
755906f32e7eSjoerg
getTokenLoc(unsigned tokI)756006f32e7eSjoerg SourceLocation getTokenLoc(unsigned tokI) {
756106f32e7eSjoerg return SourceLocation::getFromRawEncoding(getTok(tokI).int_data[1]);
756206f32e7eSjoerg }
756306f32e7eSjoerg
setFunctionMacroTokenLoc(unsigned tokI,SourceLocation loc)756406f32e7eSjoerg void setFunctionMacroTokenLoc(unsigned tokI, SourceLocation loc) {
756506f32e7eSjoerg // The third field is reserved and currently not used. Use it here
756606f32e7eSjoerg // to mark macro arg expanded tokens with their expanded locations.
756706f32e7eSjoerg getTok(tokI).int_data[3] = loc.getRawEncoding();
756806f32e7eSjoerg }
756906f32e7eSjoerg };
757006f32e7eSjoerg
757106f32e7eSjoerg } // end anonymous namespace
757206f32e7eSjoerg
757306f32e7eSjoerg static CXChildVisitResult
MarkMacroArgTokensVisitorDelegate(CXCursor cursor,CXCursor parent,CXClientData client_data)757406f32e7eSjoerg MarkMacroArgTokensVisitorDelegate(CXCursor cursor, CXCursor parent,
757506f32e7eSjoerg CXClientData client_data) {
7576*13fbcb42Sjoerg return static_cast<MarkMacroArgTokensVisitor *>(client_data)
7577*13fbcb42Sjoerg ->visit(cursor, parent);
757806f32e7eSjoerg }
757906f32e7eSjoerg
758006f32e7eSjoerg /// Used by \c annotatePreprocessorTokens.
758106f32e7eSjoerg /// \returns true if lexing was finished, false otherwise.
lexNext(Lexer & Lex,Token & Tok,unsigned & NextIdx,unsigned NumTokens)7582*13fbcb42Sjoerg static bool lexNext(Lexer &Lex, Token &Tok, unsigned &NextIdx,
7583*13fbcb42Sjoerg unsigned NumTokens) {
758406f32e7eSjoerg if (NextIdx >= NumTokens)
758506f32e7eSjoerg return true;
758606f32e7eSjoerg
758706f32e7eSjoerg ++NextIdx;
758806f32e7eSjoerg Lex.LexFromRawLexer(Tok);
758906f32e7eSjoerg return Tok.is(tok::eof);
759006f32e7eSjoerg }
759106f32e7eSjoerg
annotatePreprocessorTokens(CXTranslationUnit TU,SourceRange RegionOfInterest,CXCursor * Cursors,CXToken * Tokens,unsigned NumTokens)759206f32e7eSjoerg static void annotatePreprocessorTokens(CXTranslationUnit TU,
759306f32e7eSjoerg SourceRange RegionOfInterest,
7594*13fbcb42Sjoerg CXCursor *Cursors, CXToken *Tokens,
759506f32e7eSjoerg unsigned NumTokens) {
759606f32e7eSjoerg ASTUnit *CXXUnit = cxtu::getASTUnit(TU);
759706f32e7eSjoerg
759806f32e7eSjoerg Preprocessor &PP = CXXUnit->getPreprocessor();
759906f32e7eSjoerg SourceManager &SourceMgr = CXXUnit->getSourceManager();
7600*13fbcb42Sjoerg std::pair<FileID, unsigned> BeginLocInfo =
7601*13fbcb42Sjoerg SourceMgr.getDecomposedSpellingLoc(RegionOfInterest.getBegin());
7602*13fbcb42Sjoerg std::pair<FileID, unsigned> EndLocInfo =
7603*13fbcb42Sjoerg SourceMgr.getDecomposedSpellingLoc(RegionOfInterest.getEnd());
760406f32e7eSjoerg
760506f32e7eSjoerg if (BeginLocInfo.first != EndLocInfo.first)
760606f32e7eSjoerg return;
760706f32e7eSjoerg
760806f32e7eSjoerg StringRef Buffer;
760906f32e7eSjoerg bool Invalid = false;
761006f32e7eSjoerg Buffer = SourceMgr.getBufferData(BeginLocInfo.first, &Invalid);
761106f32e7eSjoerg if (Buffer.empty() || Invalid)
761206f32e7eSjoerg return;
761306f32e7eSjoerg
761406f32e7eSjoerg Lexer Lex(SourceMgr.getLocForStartOfFile(BeginLocInfo.first),
7615*13fbcb42Sjoerg CXXUnit->getASTContext().getLangOpts(), Buffer.begin(),
7616*13fbcb42Sjoerg Buffer.data() + BeginLocInfo.second, Buffer.end());
761706f32e7eSjoerg Lex.SetCommentRetentionState(true);
761806f32e7eSjoerg
761906f32e7eSjoerg unsigned NextIdx = 0;
762006f32e7eSjoerg // Lex tokens in raw mode until we hit the end of the range, to avoid
762106f32e7eSjoerg // entering #includes or expanding macros.
762206f32e7eSjoerg while (true) {
762306f32e7eSjoerg Token Tok;
762406f32e7eSjoerg if (lexNext(Lex, Tok, NextIdx, NumTokens))
762506f32e7eSjoerg break;
762606f32e7eSjoerg unsigned TokIdx = NextIdx - 1;
762706f32e7eSjoerg assert(Tok.getLocation() ==
762806f32e7eSjoerg SourceLocation::getFromRawEncoding(Tokens[TokIdx].int_data[1]));
762906f32e7eSjoerg
763006f32e7eSjoerg reprocess:
763106f32e7eSjoerg if (Tok.is(tok::hash) && Tok.isAtStartOfLine()) {
763206f32e7eSjoerg // We have found a preprocessing directive. Annotate the tokens
763306f32e7eSjoerg // appropriately.
763406f32e7eSjoerg //
763506f32e7eSjoerg // FIXME: Some simple tests here could identify macro definitions and
763606f32e7eSjoerg // #undefs, to provide specific cursor kinds for those.
763706f32e7eSjoerg
763806f32e7eSjoerg SourceLocation BeginLoc = Tok.getLocation();
763906f32e7eSjoerg if (lexNext(Lex, Tok, NextIdx, NumTokens))
764006f32e7eSjoerg break;
764106f32e7eSjoerg
764206f32e7eSjoerg MacroInfo *MI = nullptr;
764306f32e7eSjoerg if (Tok.is(tok::raw_identifier) && Tok.getRawIdentifier() == "define") {
764406f32e7eSjoerg if (lexNext(Lex, Tok, NextIdx, NumTokens))
764506f32e7eSjoerg break;
764606f32e7eSjoerg
764706f32e7eSjoerg if (Tok.is(tok::raw_identifier)) {
764806f32e7eSjoerg IdentifierInfo &II =
764906f32e7eSjoerg PP.getIdentifierTable().get(Tok.getRawIdentifier());
765006f32e7eSjoerg SourceLocation MappedTokLoc =
765106f32e7eSjoerg CXXUnit->mapLocationToPreamble(Tok.getLocation());
765206f32e7eSjoerg MI = getMacroInfo(II, MappedTokLoc, TU);
765306f32e7eSjoerg }
765406f32e7eSjoerg }
765506f32e7eSjoerg
765606f32e7eSjoerg bool finished = false;
765706f32e7eSjoerg do {
765806f32e7eSjoerg if (lexNext(Lex, Tok, NextIdx, NumTokens)) {
765906f32e7eSjoerg finished = true;
766006f32e7eSjoerg break;
766106f32e7eSjoerg }
766206f32e7eSjoerg // If we are in a macro definition, check if the token was ever a
766306f32e7eSjoerg // macro name and annotate it if that's the case.
766406f32e7eSjoerg if (MI) {
766506f32e7eSjoerg SourceLocation SaveLoc = Tok.getLocation();
766606f32e7eSjoerg Tok.setLocation(CXXUnit->mapLocationToPreamble(SaveLoc));
766706f32e7eSjoerg MacroDefinitionRecord *MacroDef =
766806f32e7eSjoerg checkForMacroInMacroDefinition(MI, Tok, TU);
766906f32e7eSjoerg Tok.setLocation(SaveLoc);
767006f32e7eSjoerg if (MacroDef)
767106f32e7eSjoerg Cursors[NextIdx - 1] =
767206f32e7eSjoerg MakeMacroExpansionCursor(MacroDef, Tok.getLocation(), TU);
767306f32e7eSjoerg }
767406f32e7eSjoerg } while (!Tok.isAtStartOfLine());
767506f32e7eSjoerg
767606f32e7eSjoerg unsigned LastIdx = finished ? NextIdx - 1 : NextIdx - 2;
767706f32e7eSjoerg assert(TokIdx <= LastIdx);
767806f32e7eSjoerg SourceLocation EndLoc =
767906f32e7eSjoerg SourceLocation::getFromRawEncoding(Tokens[LastIdx].int_data[1]);
768006f32e7eSjoerg CXCursor Cursor =
768106f32e7eSjoerg MakePreprocessingDirectiveCursor(SourceRange(BeginLoc, EndLoc), TU);
768206f32e7eSjoerg
768306f32e7eSjoerg for (; TokIdx <= LastIdx; ++TokIdx)
768406f32e7eSjoerg updateCursorAnnotation(Cursors[TokIdx], Cursor);
768506f32e7eSjoerg
768606f32e7eSjoerg if (finished)
768706f32e7eSjoerg break;
768806f32e7eSjoerg goto reprocess;
768906f32e7eSjoerg }
769006f32e7eSjoerg }
769106f32e7eSjoerg }
769206f32e7eSjoerg
769306f32e7eSjoerg // This gets run a separate thread to avoid stack blowout.
clang_annotateTokensImpl(CXTranslationUnit TU,ASTUnit * CXXUnit,CXToken * Tokens,unsigned NumTokens,CXCursor * Cursors)769406f32e7eSjoerg static void clang_annotateTokensImpl(CXTranslationUnit TU, ASTUnit *CXXUnit,
769506f32e7eSjoerg CXToken *Tokens, unsigned NumTokens,
769606f32e7eSjoerg CXCursor *Cursors) {
769706f32e7eSjoerg CIndexer *CXXIdx = TU->CIdx;
769806f32e7eSjoerg if (CXXIdx->isOptEnabled(CXGlobalOpt_ThreadBackgroundPriorityForEditing))
769906f32e7eSjoerg setThreadBackgroundPriority();
770006f32e7eSjoerg
770106f32e7eSjoerg // Determine the region of interest, which contains all of the tokens.
770206f32e7eSjoerg SourceRange RegionOfInterest;
770306f32e7eSjoerg RegionOfInterest.setBegin(
770406f32e7eSjoerg cxloc::translateSourceLocation(clang_getTokenLocation(TU, Tokens[0])));
7705*13fbcb42Sjoerg RegionOfInterest.setEnd(cxloc::translateSourceLocation(
7706*13fbcb42Sjoerg clang_getTokenLocation(TU, Tokens[NumTokens - 1])));
770706f32e7eSjoerg
770806f32e7eSjoerg // Relex the tokens within the source range to look for preprocessing
770906f32e7eSjoerg // directives.
771006f32e7eSjoerg annotatePreprocessorTokens(TU, RegionOfInterest, Cursors, Tokens, NumTokens);
771106f32e7eSjoerg
771206f32e7eSjoerg // If begin location points inside a macro argument, set it to the expansion
771306f32e7eSjoerg // location so we can have the full context when annotating semantically.
771406f32e7eSjoerg {
771506f32e7eSjoerg SourceManager &SM = CXXUnit->getSourceManager();
771606f32e7eSjoerg SourceLocation Loc =
771706f32e7eSjoerg SM.getMacroArgExpandedLocation(RegionOfInterest.getBegin());
771806f32e7eSjoerg if (Loc.isMacroID())
771906f32e7eSjoerg RegionOfInterest.setBegin(SM.getExpansionLoc(Loc));
772006f32e7eSjoerg }
772106f32e7eSjoerg
772206f32e7eSjoerg if (CXXUnit->getPreprocessor().getPreprocessingRecord()) {
772306f32e7eSjoerg // Search and mark tokens that are macro argument expansions.
7724*13fbcb42Sjoerg MarkMacroArgTokensVisitor Visitor(CXXUnit->getSourceManager(), Tokens,
7725*13fbcb42Sjoerg NumTokens);
7726*13fbcb42Sjoerg CursorVisitor MacroArgMarker(
7727*13fbcb42Sjoerg TU, MarkMacroArgTokensVisitorDelegate, &Visitor,
772806f32e7eSjoerg /*VisitPreprocessorLast=*/true,
7729*13fbcb42Sjoerg /*VisitIncludedEntities=*/false, RegionOfInterest);
773006f32e7eSjoerg MacroArgMarker.visitPreprocessedEntitiesInRegion();
773106f32e7eSjoerg }
773206f32e7eSjoerg
773306f32e7eSjoerg // Annotate all of the source locations in the region of interest that map to
773406f32e7eSjoerg // a specific cursor.
773506f32e7eSjoerg AnnotateTokensWorker W(Tokens, Cursors, NumTokens, TU, RegionOfInterest);
773606f32e7eSjoerg
773706f32e7eSjoerg // FIXME: We use a ridiculous stack size here because the data-recursion
773806f32e7eSjoerg // algorithm uses a large stack frame than the non-data recursive version,
773906f32e7eSjoerg // and AnnotationTokensWorker currently transforms the data-recursion
774006f32e7eSjoerg // algorithm back into a traditional recursion by explicitly calling
774106f32e7eSjoerg // VisitChildren(). We will need to remove this explicit recursive call.
774206f32e7eSjoerg W.AnnotateTokens();
774306f32e7eSjoerg
774406f32e7eSjoerg // If we ran into any entities that involve context-sensitive keywords,
774506f32e7eSjoerg // take another pass through the tokens to mark them as such.
774606f32e7eSjoerg if (W.hasContextSensitiveKeywords()) {
774706f32e7eSjoerg for (unsigned I = 0; I != NumTokens; ++I) {
774806f32e7eSjoerg if (clang_getTokenKind(Tokens[I]) != CXToken_Identifier)
774906f32e7eSjoerg continue;
775006f32e7eSjoerg
775106f32e7eSjoerg if (Cursors[I].kind == CXCursor_ObjCPropertyDecl) {
775206f32e7eSjoerg IdentifierInfo *II = static_cast<IdentifierInfo *>(Tokens[I].ptr_data);
7753*13fbcb42Sjoerg if (const ObjCPropertyDecl *Property =
7754*13fbcb42Sjoerg dyn_cast_or_null<ObjCPropertyDecl>(getCursorDecl(Cursors[I]))) {
775506f32e7eSjoerg if (Property->getPropertyAttributesAsWritten() != 0 &&
775606f32e7eSjoerg llvm::StringSwitch<bool>(II->getName())
775706f32e7eSjoerg .Case("readonly", true)
775806f32e7eSjoerg .Case("assign", true)
775906f32e7eSjoerg .Case("unsafe_unretained", true)
776006f32e7eSjoerg .Case("readwrite", true)
776106f32e7eSjoerg .Case("retain", true)
776206f32e7eSjoerg .Case("copy", true)
776306f32e7eSjoerg .Case("nonatomic", true)
776406f32e7eSjoerg .Case("atomic", true)
776506f32e7eSjoerg .Case("getter", true)
776606f32e7eSjoerg .Case("setter", true)
776706f32e7eSjoerg .Case("strong", true)
776806f32e7eSjoerg .Case("weak", true)
776906f32e7eSjoerg .Case("class", true)
777006f32e7eSjoerg .Default(false))
777106f32e7eSjoerg Tokens[I].int_data[0] = CXToken_Keyword;
777206f32e7eSjoerg }
777306f32e7eSjoerg continue;
777406f32e7eSjoerg }
777506f32e7eSjoerg
777606f32e7eSjoerg if (Cursors[I].kind == CXCursor_ObjCInstanceMethodDecl ||
777706f32e7eSjoerg Cursors[I].kind == CXCursor_ObjCClassMethodDecl) {
777806f32e7eSjoerg IdentifierInfo *II = static_cast<IdentifierInfo *>(Tokens[I].ptr_data);
777906f32e7eSjoerg if (llvm::StringSwitch<bool>(II->getName())
778006f32e7eSjoerg .Case("in", true)
778106f32e7eSjoerg .Case("out", true)
778206f32e7eSjoerg .Case("inout", true)
778306f32e7eSjoerg .Case("oneway", true)
778406f32e7eSjoerg .Case("bycopy", true)
778506f32e7eSjoerg .Case("byref", true)
778606f32e7eSjoerg .Default(false))
778706f32e7eSjoerg Tokens[I].int_data[0] = CXToken_Keyword;
778806f32e7eSjoerg continue;
778906f32e7eSjoerg }
779006f32e7eSjoerg
779106f32e7eSjoerg if (Cursors[I].kind == CXCursor_CXXFinalAttr ||
779206f32e7eSjoerg Cursors[I].kind == CXCursor_CXXOverrideAttr) {
779306f32e7eSjoerg Tokens[I].int_data[0] = CXToken_Keyword;
779406f32e7eSjoerg continue;
779506f32e7eSjoerg }
779606f32e7eSjoerg }
779706f32e7eSjoerg }
779806f32e7eSjoerg }
779906f32e7eSjoerg
clang_annotateTokens(CXTranslationUnit TU,CXToken * Tokens,unsigned NumTokens,CXCursor * Cursors)7800*13fbcb42Sjoerg void clang_annotateTokens(CXTranslationUnit TU, CXToken *Tokens,
7801*13fbcb42Sjoerg unsigned NumTokens, CXCursor *Cursors) {
780206f32e7eSjoerg if (isNotUsableTU(TU)) {
780306f32e7eSjoerg LOG_BAD_TU(TU);
780406f32e7eSjoerg return;
780506f32e7eSjoerg }
780606f32e7eSjoerg if (NumTokens == 0 || !Tokens || !Cursors) {
780706f32e7eSjoerg LOG_FUNC_SECTION { *Log << "<null input>"; }
780806f32e7eSjoerg return;
780906f32e7eSjoerg }
781006f32e7eSjoerg
781106f32e7eSjoerg LOG_FUNC_SECTION {
781206f32e7eSjoerg *Log << TU << ' ';
781306f32e7eSjoerg CXSourceLocation bloc = clang_getTokenLocation(TU, Tokens[0]);
781406f32e7eSjoerg CXSourceLocation eloc = clang_getTokenLocation(TU, Tokens[NumTokens - 1]);
781506f32e7eSjoerg *Log << clang_getRange(bloc, eloc);
781606f32e7eSjoerg }
781706f32e7eSjoerg
781806f32e7eSjoerg // Any token we don't specifically annotate will have a NULL cursor.
781906f32e7eSjoerg CXCursor C = clang_getNullCursor();
782006f32e7eSjoerg for (unsigned I = 0; I != NumTokens; ++I)
782106f32e7eSjoerg Cursors[I] = C;
782206f32e7eSjoerg
782306f32e7eSjoerg ASTUnit *CXXUnit = cxtu::getASTUnit(TU);
782406f32e7eSjoerg if (!CXXUnit)
782506f32e7eSjoerg return;
782606f32e7eSjoerg
782706f32e7eSjoerg ASTUnit::ConcurrencyCheck Check(*CXXUnit);
782806f32e7eSjoerg
782906f32e7eSjoerg auto AnnotateTokensImpl = [=]() {
783006f32e7eSjoerg clang_annotateTokensImpl(TU, CXXUnit, Tokens, NumTokens, Cursors);
783106f32e7eSjoerg };
783206f32e7eSjoerg llvm::CrashRecoveryContext CRC;
783306f32e7eSjoerg if (!RunSafely(CRC, AnnotateTokensImpl, GetSafetyThreadStackSize() * 2)) {
783406f32e7eSjoerg fprintf(stderr, "libclang: crash detected while annotating tokens\n");
783506f32e7eSjoerg }
783606f32e7eSjoerg }
783706f32e7eSjoerg
783806f32e7eSjoerg //===----------------------------------------------------------------------===//
783906f32e7eSjoerg // Operations for querying linkage of a cursor.
784006f32e7eSjoerg //===----------------------------------------------------------------------===//
784106f32e7eSjoerg
clang_getCursorLinkage(CXCursor cursor)784206f32e7eSjoerg CXLinkageKind clang_getCursorLinkage(CXCursor cursor) {
784306f32e7eSjoerg if (!clang_isDeclaration(cursor.kind))
784406f32e7eSjoerg return CXLinkage_Invalid;
784506f32e7eSjoerg
784606f32e7eSjoerg const Decl *D = cxcursor::getCursorDecl(cursor);
784706f32e7eSjoerg if (const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(D))
784806f32e7eSjoerg switch (ND->getLinkageInternal()) {
784906f32e7eSjoerg case NoLinkage:
7850*13fbcb42Sjoerg case VisibleNoLinkage:
7851*13fbcb42Sjoerg return CXLinkage_NoLinkage;
785206f32e7eSjoerg case ModuleInternalLinkage:
7853*13fbcb42Sjoerg case InternalLinkage:
7854*13fbcb42Sjoerg return CXLinkage_Internal;
7855*13fbcb42Sjoerg case UniqueExternalLinkage:
7856*13fbcb42Sjoerg return CXLinkage_UniqueExternal;
785706f32e7eSjoerg case ModuleLinkage:
7858*13fbcb42Sjoerg case ExternalLinkage:
7859*13fbcb42Sjoerg return CXLinkage_External;
786006f32e7eSjoerg };
786106f32e7eSjoerg
786206f32e7eSjoerg return CXLinkage_Invalid;
786306f32e7eSjoerg }
786406f32e7eSjoerg
786506f32e7eSjoerg //===----------------------------------------------------------------------===//
786606f32e7eSjoerg // Operations for querying visibility of a cursor.
786706f32e7eSjoerg //===----------------------------------------------------------------------===//
786806f32e7eSjoerg
clang_getCursorVisibility(CXCursor cursor)786906f32e7eSjoerg CXVisibilityKind clang_getCursorVisibility(CXCursor cursor) {
787006f32e7eSjoerg if (!clang_isDeclaration(cursor.kind))
787106f32e7eSjoerg return CXVisibility_Invalid;
787206f32e7eSjoerg
787306f32e7eSjoerg const Decl *D = cxcursor::getCursorDecl(cursor);
787406f32e7eSjoerg if (const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(D))
787506f32e7eSjoerg switch (ND->getVisibility()) {
7876*13fbcb42Sjoerg case HiddenVisibility:
7877*13fbcb42Sjoerg return CXVisibility_Hidden;
7878*13fbcb42Sjoerg case ProtectedVisibility:
7879*13fbcb42Sjoerg return CXVisibility_Protected;
7880*13fbcb42Sjoerg case DefaultVisibility:
7881*13fbcb42Sjoerg return CXVisibility_Default;
788206f32e7eSjoerg };
788306f32e7eSjoerg
788406f32e7eSjoerg return CXVisibility_Invalid;
788506f32e7eSjoerg }
788606f32e7eSjoerg
788706f32e7eSjoerg //===----------------------------------------------------------------------===//
788806f32e7eSjoerg // Operations for querying language of a cursor.
788906f32e7eSjoerg //===----------------------------------------------------------------------===//
789006f32e7eSjoerg
getDeclLanguage(const Decl * D)789106f32e7eSjoerg static CXLanguageKind getDeclLanguage(const Decl *D) {
789206f32e7eSjoerg if (!D)
789306f32e7eSjoerg return CXLanguage_C;
789406f32e7eSjoerg
789506f32e7eSjoerg switch (D->getKind()) {
789606f32e7eSjoerg default:
789706f32e7eSjoerg break;
789806f32e7eSjoerg case Decl::ImplicitParam:
789906f32e7eSjoerg case Decl::ObjCAtDefsField:
790006f32e7eSjoerg case Decl::ObjCCategory:
790106f32e7eSjoerg case Decl::ObjCCategoryImpl:
790206f32e7eSjoerg case Decl::ObjCCompatibleAlias:
790306f32e7eSjoerg case Decl::ObjCImplementation:
790406f32e7eSjoerg case Decl::ObjCInterface:
790506f32e7eSjoerg case Decl::ObjCIvar:
790606f32e7eSjoerg case Decl::ObjCMethod:
790706f32e7eSjoerg case Decl::ObjCProperty:
790806f32e7eSjoerg case Decl::ObjCPropertyImpl:
790906f32e7eSjoerg case Decl::ObjCProtocol:
791006f32e7eSjoerg case Decl::ObjCTypeParam:
791106f32e7eSjoerg return CXLanguage_ObjC;
791206f32e7eSjoerg case Decl::CXXConstructor:
791306f32e7eSjoerg case Decl::CXXConversion:
791406f32e7eSjoerg case Decl::CXXDestructor:
791506f32e7eSjoerg case Decl::CXXMethod:
791606f32e7eSjoerg case Decl::CXXRecord:
791706f32e7eSjoerg case Decl::ClassTemplate:
791806f32e7eSjoerg case Decl::ClassTemplatePartialSpecialization:
791906f32e7eSjoerg case Decl::ClassTemplateSpecialization:
792006f32e7eSjoerg case Decl::Friend:
792106f32e7eSjoerg case Decl::FriendTemplate:
792206f32e7eSjoerg case Decl::FunctionTemplate:
792306f32e7eSjoerg case Decl::LinkageSpec:
792406f32e7eSjoerg case Decl::Namespace:
792506f32e7eSjoerg case Decl::NamespaceAlias:
792606f32e7eSjoerg case Decl::NonTypeTemplateParm:
792706f32e7eSjoerg case Decl::StaticAssert:
792806f32e7eSjoerg case Decl::TemplateTemplateParm:
792906f32e7eSjoerg case Decl::TemplateTypeParm:
793006f32e7eSjoerg case Decl::UnresolvedUsingTypename:
793106f32e7eSjoerg case Decl::UnresolvedUsingValue:
793206f32e7eSjoerg case Decl::Using:
793306f32e7eSjoerg case Decl::UsingDirective:
793406f32e7eSjoerg case Decl::UsingShadow:
793506f32e7eSjoerg return CXLanguage_CPlusPlus;
793606f32e7eSjoerg }
793706f32e7eSjoerg
793806f32e7eSjoerg return CXLanguage_C;
793906f32e7eSjoerg }
794006f32e7eSjoerg
getCursorAvailabilityForDecl(const Decl * D)794106f32e7eSjoerg static CXAvailabilityKind getCursorAvailabilityForDecl(const Decl *D) {
794206f32e7eSjoerg if (isa<FunctionDecl>(D) && cast<FunctionDecl>(D)->isDeleted())
794306f32e7eSjoerg return CXAvailability_NotAvailable;
794406f32e7eSjoerg
794506f32e7eSjoerg switch (D->getAvailability()) {
794606f32e7eSjoerg case AR_Available:
794706f32e7eSjoerg case AR_NotYetIntroduced:
794806f32e7eSjoerg if (const EnumConstantDecl *EnumConst = dyn_cast<EnumConstantDecl>(D))
794906f32e7eSjoerg return getCursorAvailabilityForDecl(
795006f32e7eSjoerg cast<Decl>(EnumConst->getDeclContext()));
795106f32e7eSjoerg return CXAvailability_Available;
795206f32e7eSjoerg
795306f32e7eSjoerg case AR_Deprecated:
795406f32e7eSjoerg return CXAvailability_Deprecated;
795506f32e7eSjoerg
795606f32e7eSjoerg case AR_Unavailable:
795706f32e7eSjoerg return CXAvailability_NotAvailable;
795806f32e7eSjoerg }
795906f32e7eSjoerg
796006f32e7eSjoerg llvm_unreachable("Unknown availability kind!");
796106f32e7eSjoerg }
796206f32e7eSjoerg
clang_getCursorAvailability(CXCursor cursor)796306f32e7eSjoerg enum CXAvailabilityKind clang_getCursorAvailability(CXCursor cursor) {
796406f32e7eSjoerg if (clang_isDeclaration(cursor.kind))
796506f32e7eSjoerg if (const Decl *D = cxcursor::getCursorDecl(cursor))
796606f32e7eSjoerg return getCursorAvailabilityForDecl(D);
796706f32e7eSjoerg
796806f32e7eSjoerg return CXAvailability_Available;
796906f32e7eSjoerg }
797006f32e7eSjoerg
convertVersion(VersionTuple In)797106f32e7eSjoerg static CXVersion convertVersion(VersionTuple In) {
797206f32e7eSjoerg CXVersion Out = {-1, -1, -1};
797306f32e7eSjoerg if (In.empty())
797406f32e7eSjoerg return Out;
797506f32e7eSjoerg
797606f32e7eSjoerg Out.Major = In.getMajor();
797706f32e7eSjoerg
797806f32e7eSjoerg Optional<unsigned> Minor = In.getMinor();
797906f32e7eSjoerg if (Minor.hasValue())
798006f32e7eSjoerg Out.Minor = *Minor;
798106f32e7eSjoerg else
798206f32e7eSjoerg return Out;
798306f32e7eSjoerg
798406f32e7eSjoerg Optional<unsigned> Subminor = In.getSubminor();
798506f32e7eSjoerg if (Subminor.hasValue())
798606f32e7eSjoerg Out.Subminor = *Subminor;
798706f32e7eSjoerg
798806f32e7eSjoerg return Out;
798906f32e7eSjoerg }
799006f32e7eSjoerg
getCursorPlatformAvailabilityForDecl(const Decl * D,int * always_deprecated,CXString * deprecated_message,int * always_unavailable,CXString * unavailable_message,SmallVectorImpl<AvailabilityAttr * > & AvailabilityAttrs)799106f32e7eSjoerg static void getCursorPlatformAvailabilityForDecl(
799206f32e7eSjoerg const Decl *D, int *always_deprecated, CXString *deprecated_message,
799306f32e7eSjoerg int *always_unavailable, CXString *unavailable_message,
799406f32e7eSjoerg SmallVectorImpl<AvailabilityAttr *> &AvailabilityAttrs) {
799506f32e7eSjoerg bool HadAvailAttr = false;
799606f32e7eSjoerg for (auto A : D->attrs()) {
799706f32e7eSjoerg if (DeprecatedAttr *Deprecated = dyn_cast<DeprecatedAttr>(A)) {
799806f32e7eSjoerg HadAvailAttr = true;
799906f32e7eSjoerg if (always_deprecated)
800006f32e7eSjoerg *always_deprecated = 1;
800106f32e7eSjoerg if (deprecated_message) {
800206f32e7eSjoerg clang_disposeString(*deprecated_message);
800306f32e7eSjoerg *deprecated_message = cxstring::createDup(Deprecated->getMessage());
800406f32e7eSjoerg }
800506f32e7eSjoerg continue;
800606f32e7eSjoerg }
800706f32e7eSjoerg
800806f32e7eSjoerg if (UnavailableAttr *Unavailable = dyn_cast<UnavailableAttr>(A)) {
800906f32e7eSjoerg HadAvailAttr = true;
801006f32e7eSjoerg if (always_unavailable)
801106f32e7eSjoerg *always_unavailable = 1;
801206f32e7eSjoerg if (unavailable_message) {
801306f32e7eSjoerg clang_disposeString(*unavailable_message);
801406f32e7eSjoerg *unavailable_message = cxstring::createDup(Unavailable->getMessage());
801506f32e7eSjoerg }
801606f32e7eSjoerg continue;
801706f32e7eSjoerg }
801806f32e7eSjoerg
801906f32e7eSjoerg if (AvailabilityAttr *Avail = dyn_cast<AvailabilityAttr>(A)) {
802006f32e7eSjoerg AvailabilityAttrs.push_back(Avail);
802106f32e7eSjoerg HadAvailAttr = true;
802206f32e7eSjoerg }
802306f32e7eSjoerg }
802406f32e7eSjoerg
802506f32e7eSjoerg if (!HadAvailAttr)
802606f32e7eSjoerg if (const EnumConstantDecl *EnumConst = dyn_cast<EnumConstantDecl>(D))
802706f32e7eSjoerg return getCursorPlatformAvailabilityForDecl(
802806f32e7eSjoerg cast<Decl>(EnumConst->getDeclContext()), always_deprecated,
802906f32e7eSjoerg deprecated_message, always_unavailable, unavailable_message,
803006f32e7eSjoerg AvailabilityAttrs);
803106f32e7eSjoerg
803206f32e7eSjoerg if (AvailabilityAttrs.empty())
803306f32e7eSjoerg return;
803406f32e7eSjoerg
8035*13fbcb42Sjoerg llvm::sort(
8036*13fbcb42Sjoerg AvailabilityAttrs, [](AvailabilityAttr *LHS, AvailabilityAttr *RHS) {
8037*13fbcb42Sjoerg return LHS->getPlatform()->getName() < RHS->getPlatform()->getName();
803806f32e7eSjoerg });
803906f32e7eSjoerg ASTContext &Ctx = D->getASTContext();
804006f32e7eSjoerg auto It = std::unique(
804106f32e7eSjoerg AvailabilityAttrs.begin(), AvailabilityAttrs.end(),
804206f32e7eSjoerg [&Ctx](AvailabilityAttr *LHS, AvailabilityAttr *RHS) {
804306f32e7eSjoerg if (LHS->getPlatform() != RHS->getPlatform())
804406f32e7eSjoerg return false;
804506f32e7eSjoerg
804606f32e7eSjoerg if (LHS->getIntroduced() == RHS->getIntroduced() &&
804706f32e7eSjoerg LHS->getDeprecated() == RHS->getDeprecated() &&
804806f32e7eSjoerg LHS->getObsoleted() == RHS->getObsoleted() &&
804906f32e7eSjoerg LHS->getMessage() == RHS->getMessage() &&
805006f32e7eSjoerg LHS->getReplacement() == RHS->getReplacement())
805106f32e7eSjoerg return true;
805206f32e7eSjoerg
805306f32e7eSjoerg if ((!LHS->getIntroduced().empty() && !RHS->getIntroduced().empty()) ||
805406f32e7eSjoerg (!LHS->getDeprecated().empty() && !RHS->getDeprecated().empty()) ||
805506f32e7eSjoerg (!LHS->getObsoleted().empty() && !RHS->getObsoleted().empty()))
805606f32e7eSjoerg return false;
805706f32e7eSjoerg
805806f32e7eSjoerg if (LHS->getIntroduced().empty() && !RHS->getIntroduced().empty())
805906f32e7eSjoerg LHS->setIntroduced(Ctx, RHS->getIntroduced());
806006f32e7eSjoerg
806106f32e7eSjoerg if (LHS->getDeprecated().empty() && !RHS->getDeprecated().empty()) {
806206f32e7eSjoerg LHS->setDeprecated(Ctx, RHS->getDeprecated());
806306f32e7eSjoerg if (LHS->getMessage().empty())
806406f32e7eSjoerg LHS->setMessage(Ctx, RHS->getMessage());
806506f32e7eSjoerg if (LHS->getReplacement().empty())
806606f32e7eSjoerg LHS->setReplacement(Ctx, RHS->getReplacement());
806706f32e7eSjoerg }
806806f32e7eSjoerg
806906f32e7eSjoerg if (LHS->getObsoleted().empty() && !RHS->getObsoleted().empty()) {
807006f32e7eSjoerg LHS->setObsoleted(Ctx, RHS->getObsoleted());
807106f32e7eSjoerg if (LHS->getMessage().empty())
807206f32e7eSjoerg LHS->setMessage(Ctx, RHS->getMessage());
807306f32e7eSjoerg if (LHS->getReplacement().empty())
807406f32e7eSjoerg LHS->setReplacement(Ctx, RHS->getReplacement());
807506f32e7eSjoerg }
807606f32e7eSjoerg
807706f32e7eSjoerg return true;
807806f32e7eSjoerg });
807906f32e7eSjoerg AvailabilityAttrs.erase(It, AvailabilityAttrs.end());
808006f32e7eSjoerg }
808106f32e7eSjoerg
clang_getCursorPlatformAvailability(CXCursor cursor,int * always_deprecated,CXString * deprecated_message,int * always_unavailable,CXString * unavailable_message,CXPlatformAvailability * availability,int availability_size)808206f32e7eSjoerg int clang_getCursorPlatformAvailability(CXCursor cursor, int *always_deprecated,
808306f32e7eSjoerg CXString *deprecated_message,
808406f32e7eSjoerg int *always_unavailable,
808506f32e7eSjoerg CXString *unavailable_message,
808606f32e7eSjoerg CXPlatformAvailability *availability,
808706f32e7eSjoerg int availability_size) {
808806f32e7eSjoerg if (always_deprecated)
808906f32e7eSjoerg *always_deprecated = 0;
809006f32e7eSjoerg if (deprecated_message)
809106f32e7eSjoerg *deprecated_message = cxstring::createEmpty();
809206f32e7eSjoerg if (always_unavailable)
809306f32e7eSjoerg *always_unavailable = 0;
809406f32e7eSjoerg if (unavailable_message)
809506f32e7eSjoerg *unavailable_message = cxstring::createEmpty();
809606f32e7eSjoerg
809706f32e7eSjoerg if (!clang_isDeclaration(cursor.kind))
809806f32e7eSjoerg return 0;
809906f32e7eSjoerg
810006f32e7eSjoerg const Decl *D = cxcursor::getCursorDecl(cursor);
810106f32e7eSjoerg if (!D)
810206f32e7eSjoerg return 0;
810306f32e7eSjoerg
810406f32e7eSjoerg SmallVector<AvailabilityAttr *, 8> AvailabilityAttrs;
810506f32e7eSjoerg getCursorPlatformAvailabilityForDecl(D, always_deprecated, deprecated_message,
810606f32e7eSjoerg always_unavailable, unavailable_message,
810706f32e7eSjoerg AvailabilityAttrs);
810806f32e7eSjoerg for (const auto &Avail :
810906f32e7eSjoerg llvm::enumerate(llvm::makeArrayRef(AvailabilityAttrs)
811006f32e7eSjoerg .take_front(availability_size))) {
811106f32e7eSjoerg availability[Avail.index()].Platform =
811206f32e7eSjoerg cxstring::createDup(Avail.value()->getPlatform()->getName());
811306f32e7eSjoerg availability[Avail.index()].Introduced =
811406f32e7eSjoerg convertVersion(Avail.value()->getIntroduced());
811506f32e7eSjoerg availability[Avail.index()].Deprecated =
811606f32e7eSjoerg convertVersion(Avail.value()->getDeprecated());
811706f32e7eSjoerg availability[Avail.index()].Obsoleted =
811806f32e7eSjoerg convertVersion(Avail.value()->getObsoleted());
811906f32e7eSjoerg availability[Avail.index()].Unavailable = Avail.value()->getUnavailable();
812006f32e7eSjoerg availability[Avail.index()].Message =
812106f32e7eSjoerg cxstring::createDup(Avail.value()->getMessage());
812206f32e7eSjoerg }
812306f32e7eSjoerg
812406f32e7eSjoerg return AvailabilityAttrs.size();
812506f32e7eSjoerg }
812606f32e7eSjoerg
clang_disposeCXPlatformAvailability(CXPlatformAvailability * availability)812706f32e7eSjoerg void clang_disposeCXPlatformAvailability(CXPlatformAvailability *availability) {
812806f32e7eSjoerg clang_disposeString(availability->Platform);
812906f32e7eSjoerg clang_disposeString(availability->Message);
813006f32e7eSjoerg }
813106f32e7eSjoerg
clang_getCursorLanguage(CXCursor cursor)813206f32e7eSjoerg CXLanguageKind clang_getCursorLanguage(CXCursor cursor) {
813306f32e7eSjoerg if (clang_isDeclaration(cursor.kind))
813406f32e7eSjoerg return getDeclLanguage(cxcursor::getCursorDecl(cursor));
813506f32e7eSjoerg
813606f32e7eSjoerg return CXLanguage_Invalid;
813706f32e7eSjoerg }
813806f32e7eSjoerg
clang_getCursorTLSKind(CXCursor cursor)813906f32e7eSjoerg CXTLSKind clang_getCursorTLSKind(CXCursor cursor) {
814006f32e7eSjoerg const Decl *D = cxcursor::getCursorDecl(cursor);
814106f32e7eSjoerg if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
814206f32e7eSjoerg switch (VD->getTLSKind()) {
814306f32e7eSjoerg case VarDecl::TLS_None:
814406f32e7eSjoerg return CXTLS_None;
814506f32e7eSjoerg case VarDecl::TLS_Dynamic:
814606f32e7eSjoerg return CXTLS_Dynamic;
814706f32e7eSjoerg case VarDecl::TLS_Static:
814806f32e7eSjoerg return CXTLS_Static;
814906f32e7eSjoerg }
815006f32e7eSjoerg }
815106f32e7eSjoerg
815206f32e7eSjoerg return CXTLS_None;
815306f32e7eSjoerg }
815406f32e7eSjoerg
815506f32e7eSjoerg /// If the given cursor is the "templated" declaration
815606f32e7eSjoerg /// describing a class or function template, return the class or
815706f32e7eSjoerg /// function template.
maybeGetTemplateCursor(const Decl * D)815806f32e7eSjoerg static const Decl *maybeGetTemplateCursor(const Decl *D) {
815906f32e7eSjoerg if (!D)
816006f32e7eSjoerg return nullptr;
816106f32e7eSjoerg
816206f32e7eSjoerg if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
816306f32e7eSjoerg if (FunctionTemplateDecl *FunTmpl = FD->getDescribedFunctionTemplate())
816406f32e7eSjoerg return FunTmpl;
816506f32e7eSjoerg
816606f32e7eSjoerg if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D))
816706f32e7eSjoerg if (ClassTemplateDecl *ClassTmpl = RD->getDescribedClassTemplate())
816806f32e7eSjoerg return ClassTmpl;
816906f32e7eSjoerg
817006f32e7eSjoerg return D;
817106f32e7eSjoerg }
817206f32e7eSjoerg
clang_Cursor_getStorageClass(CXCursor C)817306f32e7eSjoerg enum CX_StorageClass clang_Cursor_getStorageClass(CXCursor C) {
817406f32e7eSjoerg StorageClass sc = SC_None;
817506f32e7eSjoerg const Decl *D = getCursorDecl(C);
817606f32e7eSjoerg if (D) {
817706f32e7eSjoerg if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
817806f32e7eSjoerg sc = FD->getStorageClass();
817906f32e7eSjoerg } else if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
818006f32e7eSjoerg sc = VD->getStorageClass();
818106f32e7eSjoerg } else {
818206f32e7eSjoerg return CX_SC_Invalid;
818306f32e7eSjoerg }
818406f32e7eSjoerg } else {
818506f32e7eSjoerg return CX_SC_Invalid;
818606f32e7eSjoerg }
818706f32e7eSjoerg switch (sc) {
818806f32e7eSjoerg case SC_None:
818906f32e7eSjoerg return CX_SC_None;
819006f32e7eSjoerg case SC_Extern:
819106f32e7eSjoerg return CX_SC_Extern;
819206f32e7eSjoerg case SC_Static:
819306f32e7eSjoerg return CX_SC_Static;
819406f32e7eSjoerg case SC_PrivateExtern:
819506f32e7eSjoerg return CX_SC_PrivateExtern;
819606f32e7eSjoerg case SC_Auto:
819706f32e7eSjoerg return CX_SC_Auto;
819806f32e7eSjoerg case SC_Register:
819906f32e7eSjoerg return CX_SC_Register;
820006f32e7eSjoerg }
820106f32e7eSjoerg llvm_unreachable("Unhandled storage class!");
820206f32e7eSjoerg }
820306f32e7eSjoerg
clang_getCursorSemanticParent(CXCursor cursor)820406f32e7eSjoerg CXCursor clang_getCursorSemanticParent(CXCursor cursor) {
820506f32e7eSjoerg if (clang_isDeclaration(cursor.kind)) {
820606f32e7eSjoerg if (const Decl *D = getCursorDecl(cursor)) {
820706f32e7eSjoerg const DeclContext *DC = D->getDeclContext();
820806f32e7eSjoerg if (!DC)
820906f32e7eSjoerg return clang_getNullCursor();
821006f32e7eSjoerg
821106f32e7eSjoerg return MakeCXCursor(maybeGetTemplateCursor(cast<Decl>(DC)),
821206f32e7eSjoerg getCursorTU(cursor));
821306f32e7eSjoerg }
821406f32e7eSjoerg }
821506f32e7eSjoerg
821606f32e7eSjoerg if (clang_isStatement(cursor.kind) || clang_isExpression(cursor.kind)) {
821706f32e7eSjoerg if (const Decl *D = getCursorDecl(cursor))
821806f32e7eSjoerg return MakeCXCursor(D, getCursorTU(cursor));
821906f32e7eSjoerg }
822006f32e7eSjoerg
822106f32e7eSjoerg return clang_getNullCursor();
822206f32e7eSjoerg }
822306f32e7eSjoerg
clang_getCursorLexicalParent(CXCursor cursor)822406f32e7eSjoerg CXCursor clang_getCursorLexicalParent(CXCursor cursor) {
822506f32e7eSjoerg if (clang_isDeclaration(cursor.kind)) {
822606f32e7eSjoerg if (const Decl *D = getCursorDecl(cursor)) {
822706f32e7eSjoerg const DeclContext *DC = D->getLexicalDeclContext();
822806f32e7eSjoerg if (!DC)
822906f32e7eSjoerg return clang_getNullCursor();
823006f32e7eSjoerg
823106f32e7eSjoerg return MakeCXCursor(maybeGetTemplateCursor(cast<Decl>(DC)),
823206f32e7eSjoerg getCursorTU(cursor));
823306f32e7eSjoerg }
823406f32e7eSjoerg }
823506f32e7eSjoerg
823606f32e7eSjoerg // FIXME: Note that we can't easily compute the lexical context of a
823706f32e7eSjoerg // statement or expression, so we return nothing.
823806f32e7eSjoerg return clang_getNullCursor();
823906f32e7eSjoerg }
824006f32e7eSjoerg
clang_getIncludedFile(CXCursor cursor)824106f32e7eSjoerg CXFile clang_getIncludedFile(CXCursor cursor) {
824206f32e7eSjoerg if (cursor.kind != CXCursor_InclusionDirective)
824306f32e7eSjoerg return nullptr;
824406f32e7eSjoerg
824506f32e7eSjoerg const InclusionDirective *ID = getCursorInclusionDirective(cursor);
824606f32e7eSjoerg return const_cast<FileEntry *>(ID->getFile());
824706f32e7eSjoerg }
824806f32e7eSjoerg
clang_Cursor_getObjCPropertyAttributes(CXCursor C,unsigned reserved)824906f32e7eSjoerg unsigned clang_Cursor_getObjCPropertyAttributes(CXCursor C, unsigned reserved) {
825006f32e7eSjoerg if (C.kind != CXCursor_ObjCPropertyDecl)
825106f32e7eSjoerg return CXObjCPropertyAttr_noattr;
825206f32e7eSjoerg
825306f32e7eSjoerg unsigned Result = CXObjCPropertyAttr_noattr;
825406f32e7eSjoerg const ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(getCursorDecl(C));
8255*13fbcb42Sjoerg ObjCPropertyAttribute::Kind Attr = PD->getPropertyAttributesAsWritten();
825606f32e7eSjoerg
825706f32e7eSjoerg #define SET_CXOBJCPROP_ATTR(A) \
8258*13fbcb42Sjoerg if (Attr & ObjCPropertyAttribute::kind_##A) \
825906f32e7eSjoerg Result |= CXObjCPropertyAttr_##A
826006f32e7eSjoerg SET_CXOBJCPROP_ATTR(readonly);
826106f32e7eSjoerg SET_CXOBJCPROP_ATTR(getter);
826206f32e7eSjoerg SET_CXOBJCPROP_ATTR(assign);
826306f32e7eSjoerg SET_CXOBJCPROP_ATTR(readwrite);
826406f32e7eSjoerg SET_CXOBJCPROP_ATTR(retain);
826506f32e7eSjoerg SET_CXOBJCPROP_ATTR(copy);
826606f32e7eSjoerg SET_CXOBJCPROP_ATTR(nonatomic);
826706f32e7eSjoerg SET_CXOBJCPROP_ATTR(setter);
826806f32e7eSjoerg SET_CXOBJCPROP_ATTR(atomic);
826906f32e7eSjoerg SET_CXOBJCPROP_ATTR(weak);
827006f32e7eSjoerg SET_CXOBJCPROP_ATTR(strong);
827106f32e7eSjoerg SET_CXOBJCPROP_ATTR(unsafe_unretained);
827206f32e7eSjoerg SET_CXOBJCPROP_ATTR(class);
827306f32e7eSjoerg #undef SET_CXOBJCPROP_ATTR
827406f32e7eSjoerg
827506f32e7eSjoerg return Result;
827606f32e7eSjoerg }
827706f32e7eSjoerg
clang_Cursor_getObjCPropertyGetterName(CXCursor C)827806f32e7eSjoerg CXString clang_Cursor_getObjCPropertyGetterName(CXCursor C) {
827906f32e7eSjoerg if (C.kind != CXCursor_ObjCPropertyDecl)
828006f32e7eSjoerg return cxstring::createNull();
828106f32e7eSjoerg
828206f32e7eSjoerg const ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(getCursorDecl(C));
828306f32e7eSjoerg Selector sel = PD->getGetterName();
828406f32e7eSjoerg if (sel.isNull())
828506f32e7eSjoerg return cxstring::createNull();
828606f32e7eSjoerg
828706f32e7eSjoerg return cxstring::createDup(sel.getAsString());
828806f32e7eSjoerg }
828906f32e7eSjoerg
clang_Cursor_getObjCPropertySetterName(CXCursor C)829006f32e7eSjoerg CXString clang_Cursor_getObjCPropertySetterName(CXCursor C) {
829106f32e7eSjoerg if (C.kind != CXCursor_ObjCPropertyDecl)
829206f32e7eSjoerg return cxstring::createNull();
829306f32e7eSjoerg
829406f32e7eSjoerg const ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(getCursorDecl(C));
829506f32e7eSjoerg Selector sel = PD->getSetterName();
829606f32e7eSjoerg if (sel.isNull())
829706f32e7eSjoerg return cxstring::createNull();
829806f32e7eSjoerg
829906f32e7eSjoerg return cxstring::createDup(sel.getAsString());
830006f32e7eSjoerg }
830106f32e7eSjoerg
clang_Cursor_getObjCDeclQualifiers(CXCursor C)830206f32e7eSjoerg unsigned clang_Cursor_getObjCDeclQualifiers(CXCursor C) {
830306f32e7eSjoerg if (!clang_isDeclaration(C.kind))
830406f32e7eSjoerg return CXObjCDeclQualifier_None;
830506f32e7eSjoerg
830606f32e7eSjoerg Decl::ObjCDeclQualifier QT = Decl::OBJC_TQ_None;
830706f32e7eSjoerg const Decl *D = getCursorDecl(C);
830806f32e7eSjoerg if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
830906f32e7eSjoerg QT = MD->getObjCDeclQualifier();
831006f32e7eSjoerg else if (const ParmVarDecl *PD = dyn_cast<ParmVarDecl>(D))
831106f32e7eSjoerg QT = PD->getObjCDeclQualifier();
831206f32e7eSjoerg if (QT == Decl::OBJC_TQ_None)
831306f32e7eSjoerg return CXObjCDeclQualifier_None;
831406f32e7eSjoerg
831506f32e7eSjoerg unsigned Result = CXObjCDeclQualifier_None;
8316*13fbcb42Sjoerg if (QT & Decl::OBJC_TQ_In)
8317*13fbcb42Sjoerg Result |= CXObjCDeclQualifier_In;
8318*13fbcb42Sjoerg if (QT & Decl::OBJC_TQ_Inout)
8319*13fbcb42Sjoerg Result |= CXObjCDeclQualifier_Inout;
8320*13fbcb42Sjoerg if (QT & Decl::OBJC_TQ_Out)
8321*13fbcb42Sjoerg Result |= CXObjCDeclQualifier_Out;
8322*13fbcb42Sjoerg if (QT & Decl::OBJC_TQ_Bycopy)
8323*13fbcb42Sjoerg Result |= CXObjCDeclQualifier_Bycopy;
8324*13fbcb42Sjoerg if (QT & Decl::OBJC_TQ_Byref)
8325*13fbcb42Sjoerg Result |= CXObjCDeclQualifier_Byref;
8326*13fbcb42Sjoerg if (QT & Decl::OBJC_TQ_Oneway)
8327*13fbcb42Sjoerg Result |= CXObjCDeclQualifier_Oneway;
832806f32e7eSjoerg
832906f32e7eSjoerg return Result;
833006f32e7eSjoerg }
833106f32e7eSjoerg
clang_Cursor_isObjCOptional(CXCursor C)833206f32e7eSjoerg unsigned clang_Cursor_isObjCOptional(CXCursor C) {
833306f32e7eSjoerg if (!clang_isDeclaration(C.kind))
833406f32e7eSjoerg return 0;
833506f32e7eSjoerg
833606f32e7eSjoerg const Decl *D = getCursorDecl(C);
833706f32e7eSjoerg if (const ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(D))
833806f32e7eSjoerg return PD->getPropertyImplementation() == ObjCPropertyDecl::Optional;
833906f32e7eSjoerg if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
834006f32e7eSjoerg return MD->getImplementationControl() == ObjCMethodDecl::Optional;
834106f32e7eSjoerg
834206f32e7eSjoerg return 0;
834306f32e7eSjoerg }
834406f32e7eSjoerg
clang_Cursor_isVariadic(CXCursor C)834506f32e7eSjoerg unsigned clang_Cursor_isVariadic(CXCursor C) {
834606f32e7eSjoerg if (!clang_isDeclaration(C.kind))
834706f32e7eSjoerg return 0;
834806f32e7eSjoerg
834906f32e7eSjoerg const Decl *D = getCursorDecl(C);
835006f32e7eSjoerg if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
835106f32e7eSjoerg return FD->isVariadic();
835206f32e7eSjoerg if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
835306f32e7eSjoerg return MD->isVariadic();
835406f32e7eSjoerg
835506f32e7eSjoerg return 0;
835606f32e7eSjoerg }
835706f32e7eSjoerg
clang_Cursor_isExternalSymbol(CXCursor C,CXString * language,CXString * definedIn,unsigned * isGenerated)8358*13fbcb42Sjoerg unsigned clang_Cursor_isExternalSymbol(CXCursor C, CXString *language,
8359*13fbcb42Sjoerg CXString *definedIn,
836006f32e7eSjoerg unsigned *isGenerated) {
836106f32e7eSjoerg if (!clang_isDeclaration(C.kind))
836206f32e7eSjoerg return 0;
836306f32e7eSjoerg
836406f32e7eSjoerg const Decl *D = getCursorDecl(C);
836506f32e7eSjoerg
836606f32e7eSjoerg if (auto *attr = D->getExternalSourceSymbolAttr()) {
836706f32e7eSjoerg if (language)
836806f32e7eSjoerg *language = cxstring::createDup(attr->getLanguage());
836906f32e7eSjoerg if (definedIn)
837006f32e7eSjoerg *definedIn = cxstring::createDup(attr->getDefinedIn());
837106f32e7eSjoerg if (isGenerated)
837206f32e7eSjoerg *isGenerated = attr->getGeneratedDeclaration();
837306f32e7eSjoerg return 1;
837406f32e7eSjoerg }
837506f32e7eSjoerg return 0;
837606f32e7eSjoerg }
837706f32e7eSjoerg
clang_Cursor_getCommentRange(CXCursor C)837806f32e7eSjoerg CXSourceRange clang_Cursor_getCommentRange(CXCursor C) {
837906f32e7eSjoerg if (!clang_isDeclaration(C.kind))
838006f32e7eSjoerg return clang_getNullRange();
838106f32e7eSjoerg
838206f32e7eSjoerg const Decl *D = getCursorDecl(C);
838306f32e7eSjoerg ASTContext &Context = getCursorContext(C);
838406f32e7eSjoerg const RawComment *RC = Context.getRawCommentForAnyRedecl(D);
838506f32e7eSjoerg if (!RC)
838606f32e7eSjoerg return clang_getNullRange();
838706f32e7eSjoerg
838806f32e7eSjoerg return cxloc::translateSourceRange(Context, RC->getSourceRange());
838906f32e7eSjoerg }
839006f32e7eSjoerg
clang_Cursor_getRawCommentText(CXCursor C)839106f32e7eSjoerg CXString clang_Cursor_getRawCommentText(CXCursor C) {
839206f32e7eSjoerg if (!clang_isDeclaration(C.kind))
839306f32e7eSjoerg return cxstring::createNull();
839406f32e7eSjoerg
839506f32e7eSjoerg const Decl *D = getCursorDecl(C);
839606f32e7eSjoerg ASTContext &Context = getCursorContext(C);
839706f32e7eSjoerg const RawComment *RC = Context.getRawCommentForAnyRedecl(D);
8398*13fbcb42Sjoerg StringRef RawText =
8399*13fbcb42Sjoerg RC ? RC->getRawText(Context.getSourceManager()) : StringRef();
840006f32e7eSjoerg
840106f32e7eSjoerg // Don't duplicate the string because RawText points directly into source
840206f32e7eSjoerg // code.
840306f32e7eSjoerg return cxstring::createRef(RawText);
840406f32e7eSjoerg }
840506f32e7eSjoerg
clang_Cursor_getBriefCommentText(CXCursor C)840606f32e7eSjoerg CXString clang_Cursor_getBriefCommentText(CXCursor C) {
840706f32e7eSjoerg if (!clang_isDeclaration(C.kind))
840806f32e7eSjoerg return cxstring::createNull();
840906f32e7eSjoerg
841006f32e7eSjoerg const Decl *D = getCursorDecl(C);
841106f32e7eSjoerg const ASTContext &Context = getCursorContext(C);
841206f32e7eSjoerg const RawComment *RC = Context.getRawCommentForAnyRedecl(D);
841306f32e7eSjoerg
841406f32e7eSjoerg if (RC) {
841506f32e7eSjoerg StringRef BriefText = RC->getBriefText(Context);
841606f32e7eSjoerg
841706f32e7eSjoerg // Don't duplicate the string because RawComment ensures that this memory
841806f32e7eSjoerg // will not go away.
841906f32e7eSjoerg return cxstring::createRef(BriefText);
842006f32e7eSjoerg }
842106f32e7eSjoerg
842206f32e7eSjoerg return cxstring::createNull();
842306f32e7eSjoerg }
842406f32e7eSjoerg
clang_Cursor_getModule(CXCursor C)842506f32e7eSjoerg CXModule clang_Cursor_getModule(CXCursor C) {
842606f32e7eSjoerg if (C.kind == CXCursor_ModuleImportDecl) {
842706f32e7eSjoerg if (const ImportDecl *ImportD =
842806f32e7eSjoerg dyn_cast_or_null<ImportDecl>(getCursorDecl(C)))
842906f32e7eSjoerg return ImportD->getImportedModule();
843006f32e7eSjoerg }
843106f32e7eSjoerg
843206f32e7eSjoerg return nullptr;
843306f32e7eSjoerg }
843406f32e7eSjoerg
clang_getModuleForFile(CXTranslationUnit TU,CXFile File)843506f32e7eSjoerg CXModule clang_getModuleForFile(CXTranslationUnit TU, CXFile File) {
843606f32e7eSjoerg if (isNotUsableTU(TU)) {
843706f32e7eSjoerg LOG_BAD_TU(TU);
843806f32e7eSjoerg return nullptr;
843906f32e7eSjoerg }
844006f32e7eSjoerg if (!File)
844106f32e7eSjoerg return nullptr;
844206f32e7eSjoerg FileEntry *FE = static_cast<FileEntry *>(File);
844306f32e7eSjoerg
844406f32e7eSjoerg ASTUnit &Unit = *cxtu::getASTUnit(TU);
844506f32e7eSjoerg HeaderSearch &HS = Unit.getPreprocessor().getHeaderSearchInfo();
844606f32e7eSjoerg ModuleMap::KnownHeader Header = HS.findModuleForHeader(FE);
844706f32e7eSjoerg
844806f32e7eSjoerg return Header.getModule();
844906f32e7eSjoerg }
845006f32e7eSjoerg
clang_Module_getASTFile(CXModule CXMod)845106f32e7eSjoerg CXFile clang_Module_getASTFile(CXModule CXMod) {
845206f32e7eSjoerg if (!CXMod)
845306f32e7eSjoerg return nullptr;
845406f32e7eSjoerg Module *Mod = static_cast<Module *>(CXMod);
8455*13fbcb42Sjoerg if (auto File = Mod->getASTFile())
8456*13fbcb42Sjoerg return const_cast<FileEntry *>(&File->getFileEntry());
8457*13fbcb42Sjoerg return nullptr;
845806f32e7eSjoerg }
845906f32e7eSjoerg
clang_Module_getParent(CXModule CXMod)846006f32e7eSjoerg CXModule clang_Module_getParent(CXModule CXMod) {
846106f32e7eSjoerg if (!CXMod)
846206f32e7eSjoerg return nullptr;
846306f32e7eSjoerg Module *Mod = static_cast<Module *>(CXMod);
846406f32e7eSjoerg return Mod->Parent;
846506f32e7eSjoerg }
846606f32e7eSjoerg
clang_Module_getName(CXModule CXMod)846706f32e7eSjoerg CXString clang_Module_getName(CXModule CXMod) {
846806f32e7eSjoerg if (!CXMod)
846906f32e7eSjoerg return cxstring::createEmpty();
847006f32e7eSjoerg Module *Mod = static_cast<Module *>(CXMod);
847106f32e7eSjoerg return cxstring::createDup(Mod->Name);
847206f32e7eSjoerg }
847306f32e7eSjoerg
clang_Module_getFullName(CXModule CXMod)847406f32e7eSjoerg CXString clang_Module_getFullName(CXModule CXMod) {
847506f32e7eSjoerg if (!CXMod)
847606f32e7eSjoerg return cxstring::createEmpty();
847706f32e7eSjoerg Module *Mod = static_cast<Module *>(CXMod);
847806f32e7eSjoerg return cxstring::createDup(Mod->getFullModuleName());
847906f32e7eSjoerg }
848006f32e7eSjoerg
clang_Module_isSystem(CXModule CXMod)848106f32e7eSjoerg int clang_Module_isSystem(CXModule CXMod) {
848206f32e7eSjoerg if (!CXMod)
848306f32e7eSjoerg return 0;
848406f32e7eSjoerg Module *Mod = static_cast<Module *>(CXMod);
848506f32e7eSjoerg return Mod->IsSystem;
848606f32e7eSjoerg }
848706f32e7eSjoerg
clang_Module_getNumTopLevelHeaders(CXTranslationUnit TU,CXModule CXMod)848806f32e7eSjoerg unsigned clang_Module_getNumTopLevelHeaders(CXTranslationUnit TU,
848906f32e7eSjoerg CXModule CXMod) {
849006f32e7eSjoerg if (isNotUsableTU(TU)) {
849106f32e7eSjoerg LOG_BAD_TU(TU);
849206f32e7eSjoerg return 0;
849306f32e7eSjoerg }
849406f32e7eSjoerg if (!CXMod)
849506f32e7eSjoerg return 0;
849606f32e7eSjoerg Module *Mod = static_cast<Module *>(CXMod);
849706f32e7eSjoerg FileManager &FileMgr = cxtu::getASTUnit(TU)->getFileManager();
849806f32e7eSjoerg ArrayRef<const FileEntry *> TopHeaders = Mod->getTopHeaders(FileMgr);
849906f32e7eSjoerg return TopHeaders.size();
850006f32e7eSjoerg }
850106f32e7eSjoerg
clang_Module_getTopLevelHeader(CXTranslationUnit TU,CXModule CXMod,unsigned Index)8502*13fbcb42Sjoerg CXFile clang_Module_getTopLevelHeader(CXTranslationUnit TU, CXModule CXMod,
8503*13fbcb42Sjoerg unsigned Index) {
850406f32e7eSjoerg if (isNotUsableTU(TU)) {
850506f32e7eSjoerg LOG_BAD_TU(TU);
850606f32e7eSjoerg return nullptr;
850706f32e7eSjoerg }
850806f32e7eSjoerg if (!CXMod)
850906f32e7eSjoerg return nullptr;
851006f32e7eSjoerg Module *Mod = static_cast<Module *>(CXMod);
851106f32e7eSjoerg FileManager &FileMgr = cxtu::getASTUnit(TU)->getFileManager();
851206f32e7eSjoerg
851306f32e7eSjoerg ArrayRef<const FileEntry *> TopHeaders = Mod->getTopHeaders(FileMgr);
851406f32e7eSjoerg if (Index < TopHeaders.size())
851506f32e7eSjoerg return const_cast<FileEntry *>(TopHeaders[Index]);
851606f32e7eSjoerg
851706f32e7eSjoerg return nullptr;
851806f32e7eSjoerg }
851906f32e7eSjoerg
852006f32e7eSjoerg //===----------------------------------------------------------------------===//
852106f32e7eSjoerg // C++ AST instrospection.
852206f32e7eSjoerg //===----------------------------------------------------------------------===//
852306f32e7eSjoerg
clang_CXXConstructor_isDefaultConstructor(CXCursor C)852406f32e7eSjoerg unsigned clang_CXXConstructor_isDefaultConstructor(CXCursor C) {
852506f32e7eSjoerg if (!clang_isDeclaration(C.kind))
852606f32e7eSjoerg return 0;
852706f32e7eSjoerg
852806f32e7eSjoerg const Decl *D = cxcursor::getCursorDecl(C);
852906f32e7eSjoerg const CXXConstructorDecl *Constructor =
853006f32e7eSjoerg D ? dyn_cast_or_null<CXXConstructorDecl>(D->getAsFunction()) : nullptr;
853106f32e7eSjoerg return (Constructor && Constructor->isDefaultConstructor()) ? 1 : 0;
853206f32e7eSjoerg }
853306f32e7eSjoerg
clang_CXXConstructor_isCopyConstructor(CXCursor C)853406f32e7eSjoerg unsigned clang_CXXConstructor_isCopyConstructor(CXCursor C) {
853506f32e7eSjoerg if (!clang_isDeclaration(C.kind))
853606f32e7eSjoerg return 0;
853706f32e7eSjoerg
853806f32e7eSjoerg const Decl *D = cxcursor::getCursorDecl(C);
853906f32e7eSjoerg const CXXConstructorDecl *Constructor =
854006f32e7eSjoerg D ? dyn_cast_or_null<CXXConstructorDecl>(D->getAsFunction()) : nullptr;
854106f32e7eSjoerg return (Constructor && Constructor->isCopyConstructor()) ? 1 : 0;
854206f32e7eSjoerg }
854306f32e7eSjoerg
clang_CXXConstructor_isMoveConstructor(CXCursor C)854406f32e7eSjoerg unsigned clang_CXXConstructor_isMoveConstructor(CXCursor C) {
854506f32e7eSjoerg if (!clang_isDeclaration(C.kind))
854606f32e7eSjoerg return 0;
854706f32e7eSjoerg
854806f32e7eSjoerg const Decl *D = cxcursor::getCursorDecl(C);
854906f32e7eSjoerg const CXXConstructorDecl *Constructor =
855006f32e7eSjoerg D ? dyn_cast_or_null<CXXConstructorDecl>(D->getAsFunction()) : nullptr;
855106f32e7eSjoerg return (Constructor && Constructor->isMoveConstructor()) ? 1 : 0;
855206f32e7eSjoerg }
855306f32e7eSjoerg
clang_CXXConstructor_isConvertingConstructor(CXCursor C)855406f32e7eSjoerg unsigned clang_CXXConstructor_isConvertingConstructor(CXCursor C) {
855506f32e7eSjoerg if (!clang_isDeclaration(C.kind))
855606f32e7eSjoerg return 0;
855706f32e7eSjoerg
855806f32e7eSjoerg const Decl *D = cxcursor::getCursorDecl(C);
855906f32e7eSjoerg const CXXConstructorDecl *Constructor =
856006f32e7eSjoerg D ? dyn_cast_or_null<CXXConstructorDecl>(D->getAsFunction()) : nullptr;
856106f32e7eSjoerg // Passing 'false' excludes constructors marked 'explicit'.
856206f32e7eSjoerg return (Constructor && Constructor->isConvertingConstructor(false)) ? 1 : 0;
856306f32e7eSjoerg }
856406f32e7eSjoerg
clang_CXXField_isMutable(CXCursor C)856506f32e7eSjoerg unsigned clang_CXXField_isMutable(CXCursor C) {
856606f32e7eSjoerg if (!clang_isDeclaration(C.kind))
856706f32e7eSjoerg return 0;
856806f32e7eSjoerg
856906f32e7eSjoerg if (const auto D = cxcursor::getCursorDecl(C))
857006f32e7eSjoerg if (const auto FD = dyn_cast_or_null<FieldDecl>(D))
857106f32e7eSjoerg return FD->isMutable() ? 1 : 0;
857206f32e7eSjoerg return 0;
857306f32e7eSjoerg }
857406f32e7eSjoerg
clang_CXXMethod_isPureVirtual(CXCursor C)857506f32e7eSjoerg unsigned clang_CXXMethod_isPureVirtual(CXCursor C) {
857606f32e7eSjoerg if (!clang_isDeclaration(C.kind))
857706f32e7eSjoerg return 0;
857806f32e7eSjoerg
857906f32e7eSjoerg const Decl *D = cxcursor::getCursorDecl(C);
858006f32e7eSjoerg const CXXMethodDecl *Method =
858106f32e7eSjoerg D ? dyn_cast_or_null<CXXMethodDecl>(D->getAsFunction()) : nullptr;
858206f32e7eSjoerg return (Method && Method->isVirtual() && Method->isPure()) ? 1 : 0;
858306f32e7eSjoerg }
858406f32e7eSjoerg
clang_CXXMethod_isConst(CXCursor C)858506f32e7eSjoerg unsigned clang_CXXMethod_isConst(CXCursor C) {
858606f32e7eSjoerg if (!clang_isDeclaration(C.kind))
858706f32e7eSjoerg return 0;
858806f32e7eSjoerg
858906f32e7eSjoerg const Decl *D = cxcursor::getCursorDecl(C);
859006f32e7eSjoerg const CXXMethodDecl *Method =
859106f32e7eSjoerg D ? dyn_cast_or_null<CXXMethodDecl>(D->getAsFunction()) : nullptr;
859206f32e7eSjoerg return (Method && Method->getMethodQualifiers().hasConst()) ? 1 : 0;
859306f32e7eSjoerg }
859406f32e7eSjoerg
clang_CXXMethod_isDefaulted(CXCursor C)859506f32e7eSjoerg unsigned clang_CXXMethod_isDefaulted(CXCursor C) {
859606f32e7eSjoerg if (!clang_isDeclaration(C.kind))
859706f32e7eSjoerg return 0;
859806f32e7eSjoerg
859906f32e7eSjoerg const Decl *D = cxcursor::getCursorDecl(C);
860006f32e7eSjoerg const CXXMethodDecl *Method =
860106f32e7eSjoerg D ? dyn_cast_or_null<CXXMethodDecl>(D->getAsFunction()) : nullptr;
860206f32e7eSjoerg return (Method && Method->isDefaulted()) ? 1 : 0;
860306f32e7eSjoerg }
860406f32e7eSjoerg
clang_CXXMethod_isStatic(CXCursor C)860506f32e7eSjoerg unsigned clang_CXXMethod_isStatic(CXCursor C) {
860606f32e7eSjoerg if (!clang_isDeclaration(C.kind))
860706f32e7eSjoerg return 0;
860806f32e7eSjoerg
860906f32e7eSjoerg const Decl *D = cxcursor::getCursorDecl(C);
861006f32e7eSjoerg const CXXMethodDecl *Method =
861106f32e7eSjoerg D ? dyn_cast_or_null<CXXMethodDecl>(D->getAsFunction()) : nullptr;
861206f32e7eSjoerg return (Method && Method->isStatic()) ? 1 : 0;
861306f32e7eSjoerg }
861406f32e7eSjoerg
clang_CXXMethod_isVirtual(CXCursor C)861506f32e7eSjoerg unsigned clang_CXXMethod_isVirtual(CXCursor C) {
861606f32e7eSjoerg if (!clang_isDeclaration(C.kind))
861706f32e7eSjoerg return 0;
861806f32e7eSjoerg
861906f32e7eSjoerg const Decl *D = cxcursor::getCursorDecl(C);
862006f32e7eSjoerg const CXXMethodDecl *Method =
862106f32e7eSjoerg D ? dyn_cast_or_null<CXXMethodDecl>(D->getAsFunction()) : nullptr;
862206f32e7eSjoerg return (Method && Method->isVirtual()) ? 1 : 0;
862306f32e7eSjoerg }
862406f32e7eSjoerg
clang_CXXRecord_isAbstract(CXCursor C)862506f32e7eSjoerg unsigned clang_CXXRecord_isAbstract(CXCursor C) {
862606f32e7eSjoerg if (!clang_isDeclaration(C.kind))
862706f32e7eSjoerg return 0;
862806f32e7eSjoerg
862906f32e7eSjoerg const auto *D = cxcursor::getCursorDecl(C);
863006f32e7eSjoerg const auto *RD = dyn_cast_or_null<CXXRecordDecl>(D);
863106f32e7eSjoerg if (RD)
863206f32e7eSjoerg RD = RD->getDefinition();
863306f32e7eSjoerg return (RD && RD->isAbstract()) ? 1 : 0;
863406f32e7eSjoerg }
863506f32e7eSjoerg
clang_EnumDecl_isScoped(CXCursor C)863606f32e7eSjoerg unsigned clang_EnumDecl_isScoped(CXCursor C) {
863706f32e7eSjoerg if (!clang_isDeclaration(C.kind))
863806f32e7eSjoerg return 0;
863906f32e7eSjoerg
864006f32e7eSjoerg const Decl *D = cxcursor::getCursorDecl(C);
864106f32e7eSjoerg auto *Enum = dyn_cast_or_null<EnumDecl>(D);
864206f32e7eSjoerg return (Enum && Enum->isScoped()) ? 1 : 0;
864306f32e7eSjoerg }
864406f32e7eSjoerg
864506f32e7eSjoerg //===----------------------------------------------------------------------===//
864606f32e7eSjoerg // Attribute introspection.
864706f32e7eSjoerg //===----------------------------------------------------------------------===//
864806f32e7eSjoerg
clang_getIBOutletCollectionType(CXCursor C)864906f32e7eSjoerg CXType clang_getIBOutletCollectionType(CXCursor C) {
865006f32e7eSjoerg if (C.kind != CXCursor_IBOutletCollectionAttr)
865106f32e7eSjoerg return cxtype::MakeCXType(QualType(), cxcursor::getCursorTU(C));
865206f32e7eSjoerg
865306f32e7eSjoerg const IBOutletCollectionAttr *A =
865406f32e7eSjoerg cast<IBOutletCollectionAttr>(cxcursor::getCursorAttr(C));
865506f32e7eSjoerg
865606f32e7eSjoerg return cxtype::MakeCXType(A->getInterface(), cxcursor::getCursorTU(C));
865706f32e7eSjoerg }
865806f32e7eSjoerg
865906f32e7eSjoerg //===----------------------------------------------------------------------===//
866006f32e7eSjoerg // Inspecting memory usage.
866106f32e7eSjoerg //===----------------------------------------------------------------------===//
866206f32e7eSjoerg
866306f32e7eSjoerg typedef std::vector<CXTUResourceUsageEntry> MemUsageEntries;
866406f32e7eSjoerg
createCXTUResourceUsageEntry(MemUsageEntries & entries,enum CXTUResourceUsageKind k,unsigned long amount)866506f32e7eSjoerg static inline void createCXTUResourceUsageEntry(MemUsageEntries &entries,
866606f32e7eSjoerg enum CXTUResourceUsageKind k,
866706f32e7eSjoerg unsigned long amount) {
866806f32e7eSjoerg CXTUResourceUsageEntry entry = {k, amount};
866906f32e7eSjoerg entries.push_back(entry);
867006f32e7eSjoerg }
867106f32e7eSjoerg
clang_getTUResourceUsageName(CXTUResourceUsageKind kind)867206f32e7eSjoerg const char *clang_getTUResourceUsageName(CXTUResourceUsageKind kind) {
867306f32e7eSjoerg const char *str = "";
867406f32e7eSjoerg switch (kind) {
867506f32e7eSjoerg case CXTUResourceUsage_AST:
867606f32e7eSjoerg str = "ASTContext: expressions, declarations, and types";
867706f32e7eSjoerg break;
867806f32e7eSjoerg case CXTUResourceUsage_Identifiers:
867906f32e7eSjoerg str = "ASTContext: identifiers";
868006f32e7eSjoerg break;
868106f32e7eSjoerg case CXTUResourceUsage_Selectors:
868206f32e7eSjoerg str = "ASTContext: selectors";
868306f32e7eSjoerg break;
868406f32e7eSjoerg case CXTUResourceUsage_GlobalCompletionResults:
868506f32e7eSjoerg str = "Code completion: cached global results";
868606f32e7eSjoerg break;
868706f32e7eSjoerg case CXTUResourceUsage_SourceManagerContentCache:
868806f32e7eSjoerg str = "SourceManager: content cache allocator";
868906f32e7eSjoerg break;
869006f32e7eSjoerg case CXTUResourceUsage_AST_SideTables:
869106f32e7eSjoerg str = "ASTContext: side tables";
869206f32e7eSjoerg break;
869306f32e7eSjoerg case CXTUResourceUsage_SourceManager_Membuffer_Malloc:
869406f32e7eSjoerg str = "SourceManager: malloc'ed memory buffers";
869506f32e7eSjoerg break;
869606f32e7eSjoerg case CXTUResourceUsage_SourceManager_Membuffer_MMap:
869706f32e7eSjoerg str = "SourceManager: mmap'ed memory buffers";
869806f32e7eSjoerg break;
869906f32e7eSjoerg case CXTUResourceUsage_ExternalASTSource_Membuffer_Malloc:
870006f32e7eSjoerg str = "ExternalASTSource: malloc'ed memory buffers";
870106f32e7eSjoerg break;
870206f32e7eSjoerg case CXTUResourceUsage_ExternalASTSource_Membuffer_MMap:
870306f32e7eSjoerg str = "ExternalASTSource: mmap'ed memory buffers";
870406f32e7eSjoerg break;
870506f32e7eSjoerg case CXTUResourceUsage_Preprocessor:
870606f32e7eSjoerg str = "Preprocessor: malloc'ed memory";
870706f32e7eSjoerg break;
870806f32e7eSjoerg case CXTUResourceUsage_PreprocessingRecord:
870906f32e7eSjoerg str = "Preprocessor: PreprocessingRecord";
871006f32e7eSjoerg break;
871106f32e7eSjoerg case CXTUResourceUsage_SourceManager_DataStructures:
871206f32e7eSjoerg str = "SourceManager: data structures and tables";
871306f32e7eSjoerg break;
871406f32e7eSjoerg case CXTUResourceUsage_Preprocessor_HeaderSearch:
871506f32e7eSjoerg str = "Preprocessor: header search tables";
871606f32e7eSjoerg break;
871706f32e7eSjoerg }
871806f32e7eSjoerg return str;
871906f32e7eSjoerg }
872006f32e7eSjoerg
clang_getCXTUResourceUsage(CXTranslationUnit TU)872106f32e7eSjoerg CXTUResourceUsage clang_getCXTUResourceUsage(CXTranslationUnit TU) {
872206f32e7eSjoerg if (isNotUsableTU(TU)) {
872306f32e7eSjoerg LOG_BAD_TU(TU);
872406f32e7eSjoerg CXTUResourceUsage usage = {(void *)nullptr, 0, nullptr};
872506f32e7eSjoerg return usage;
872606f32e7eSjoerg }
872706f32e7eSjoerg
872806f32e7eSjoerg ASTUnit *astUnit = cxtu::getASTUnit(TU);
872906f32e7eSjoerg std::unique_ptr<MemUsageEntries> entries(new MemUsageEntries());
873006f32e7eSjoerg ASTContext &astContext = astUnit->getASTContext();
873106f32e7eSjoerg
873206f32e7eSjoerg // How much memory is used by AST nodes and types?
8733*13fbcb42Sjoerg createCXTUResourceUsageEntry(
8734*13fbcb42Sjoerg *entries, CXTUResourceUsage_AST,
873506f32e7eSjoerg (unsigned long)astContext.getASTAllocatedMemory());
873606f32e7eSjoerg
873706f32e7eSjoerg // How much memory is used by identifiers?
8738*13fbcb42Sjoerg createCXTUResourceUsageEntry(
8739*13fbcb42Sjoerg *entries, CXTUResourceUsage_Identifiers,
874006f32e7eSjoerg (unsigned long)astContext.Idents.getAllocator().getTotalMemory());
874106f32e7eSjoerg
874206f32e7eSjoerg // How much memory is used for selectors?
8743*13fbcb42Sjoerg createCXTUResourceUsageEntry(
8744*13fbcb42Sjoerg *entries, CXTUResourceUsage_Selectors,
874506f32e7eSjoerg (unsigned long)astContext.Selectors.getTotalMemory());
874606f32e7eSjoerg
874706f32e7eSjoerg // How much memory is used by ASTContext's side tables?
8748*13fbcb42Sjoerg createCXTUResourceUsageEntry(
8749*13fbcb42Sjoerg *entries, CXTUResourceUsage_AST_SideTables,
875006f32e7eSjoerg (unsigned long)astContext.getSideTableAllocatedMemory());
875106f32e7eSjoerg
875206f32e7eSjoerg // How much memory is used for caching global code completion results?
875306f32e7eSjoerg unsigned long completionBytes = 0;
875406f32e7eSjoerg if (GlobalCodeCompletionAllocator *completionAllocator =
875506f32e7eSjoerg astUnit->getCachedCompletionAllocator().get()) {
875606f32e7eSjoerg completionBytes = completionAllocator->getTotalMemory();
875706f32e7eSjoerg }
8758*13fbcb42Sjoerg createCXTUResourceUsageEntry(
8759*13fbcb42Sjoerg *entries, CXTUResourceUsage_GlobalCompletionResults, completionBytes);
876006f32e7eSjoerg
876106f32e7eSjoerg // How much memory is being used by SourceManager's content cache?
8762*13fbcb42Sjoerg createCXTUResourceUsageEntry(
8763*13fbcb42Sjoerg *entries, CXTUResourceUsage_SourceManagerContentCache,
876406f32e7eSjoerg (unsigned long)astContext.getSourceManager().getContentCacheSize());
876506f32e7eSjoerg
876606f32e7eSjoerg // How much memory is being used by the MemoryBuffer's in SourceManager?
876706f32e7eSjoerg const SourceManager::MemoryBufferSizes &srcBufs =
876806f32e7eSjoerg astUnit->getSourceManager().getMemoryBufferSizes();
876906f32e7eSjoerg
877006f32e7eSjoerg createCXTUResourceUsageEntry(*entries,
877106f32e7eSjoerg CXTUResourceUsage_SourceManager_Membuffer_Malloc,
877206f32e7eSjoerg (unsigned long)srcBufs.malloc_bytes);
877306f32e7eSjoerg createCXTUResourceUsageEntry(*entries,
877406f32e7eSjoerg CXTUResourceUsage_SourceManager_Membuffer_MMap,
877506f32e7eSjoerg (unsigned long)srcBufs.mmap_bytes);
8776*13fbcb42Sjoerg createCXTUResourceUsageEntry(
8777*13fbcb42Sjoerg *entries, CXTUResourceUsage_SourceManager_DataStructures,
8778*13fbcb42Sjoerg (unsigned long)astContext.getSourceManager().getDataStructureSizes());
877906f32e7eSjoerg
878006f32e7eSjoerg // How much memory is being used by the ExternalASTSource?
878106f32e7eSjoerg if (ExternalASTSource *esrc = astContext.getExternalSource()) {
878206f32e7eSjoerg const ExternalASTSource::MemoryBufferSizes &sizes =
878306f32e7eSjoerg esrc->getMemoryBufferSizes();
878406f32e7eSjoerg
8785*13fbcb42Sjoerg createCXTUResourceUsageEntry(
8786*13fbcb42Sjoerg *entries, CXTUResourceUsage_ExternalASTSource_Membuffer_Malloc,
878706f32e7eSjoerg (unsigned long)sizes.malloc_bytes);
8788*13fbcb42Sjoerg createCXTUResourceUsageEntry(
8789*13fbcb42Sjoerg *entries, CXTUResourceUsage_ExternalASTSource_Membuffer_MMap,
879006f32e7eSjoerg (unsigned long)sizes.mmap_bytes);
879106f32e7eSjoerg }
879206f32e7eSjoerg
879306f32e7eSjoerg // How much memory is being used by the Preprocessor?
879406f32e7eSjoerg Preprocessor &pp = astUnit->getPreprocessor();
8795*13fbcb42Sjoerg createCXTUResourceUsageEntry(*entries, CXTUResourceUsage_Preprocessor,
879606f32e7eSjoerg pp.getTotalMemory());
879706f32e7eSjoerg
879806f32e7eSjoerg if (PreprocessingRecord *pRec = pp.getPreprocessingRecord()) {
879906f32e7eSjoerg createCXTUResourceUsageEntry(*entries,
880006f32e7eSjoerg CXTUResourceUsage_PreprocessingRecord,
880106f32e7eSjoerg pRec->getTotalMemory());
880206f32e7eSjoerg }
880306f32e7eSjoerg
880406f32e7eSjoerg createCXTUResourceUsageEntry(*entries,
880506f32e7eSjoerg CXTUResourceUsage_Preprocessor_HeaderSearch,
880606f32e7eSjoerg pp.getHeaderSearchInfo().getTotalMemory());
880706f32e7eSjoerg
8808*13fbcb42Sjoerg CXTUResourceUsage usage = {(void *)entries.get(), (unsigned)entries->size(),
880906f32e7eSjoerg !entries->empty() ? &(*entries)[0] : nullptr};
881006f32e7eSjoerg (void)entries.release();
881106f32e7eSjoerg return usage;
881206f32e7eSjoerg }
881306f32e7eSjoerg
clang_disposeCXTUResourceUsage(CXTUResourceUsage usage)881406f32e7eSjoerg void clang_disposeCXTUResourceUsage(CXTUResourceUsage usage) {
881506f32e7eSjoerg if (usage.data)
881606f32e7eSjoerg delete (MemUsageEntries *)usage.data;
881706f32e7eSjoerg }
881806f32e7eSjoerg
clang_getSkippedRanges(CXTranslationUnit TU,CXFile file)881906f32e7eSjoerg CXSourceRangeList *clang_getSkippedRanges(CXTranslationUnit TU, CXFile file) {
882006f32e7eSjoerg CXSourceRangeList *skipped = new CXSourceRangeList;
882106f32e7eSjoerg skipped->count = 0;
882206f32e7eSjoerg skipped->ranges = nullptr;
882306f32e7eSjoerg
882406f32e7eSjoerg if (isNotUsableTU(TU)) {
882506f32e7eSjoerg LOG_BAD_TU(TU);
882606f32e7eSjoerg return skipped;
882706f32e7eSjoerg }
882806f32e7eSjoerg
882906f32e7eSjoerg if (!file)
883006f32e7eSjoerg return skipped;
883106f32e7eSjoerg
883206f32e7eSjoerg ASTUnit *astUnit = cxtu::getASTUnit(TU);
8833*13fbcb42Sjoerg PreprocessingRecord *ppRec =
8834*13fbcb42Sjoerg astUnit->getPreprocessor().getPreprocessingRecord();
883506f32e7eSjoerg if (!ppRec)
883606f32e7eSjoerg return skipped;
883706f32e7eSjoerg
883806f32e7eSjoerg ASTContext &Ctx = astUnit->getASTContext();
883906f32e7eSjoerg SourceManager &sm = Ctx.getSourceManager();
884006f32e7eSjoerg FileEntry *fileEntry = static_cast<FileEntry *>(file);
884106f32e7eSjoerg FileID wantedFileID = sm.translateFile(fileEntry);
884206f32e7eSjoerg bool isMainFile = wantedFileID == sm.getMainFileID();
884306f32e7eSjoerg
884406f32e7eSjoerg const std::vector<SourceRange> &SkippedRanges = ppRec->getSkippedRanges();
884506f32e7eSjoerg std::vector<SourceRange> wantedRanges;
8846*13fbcb42Sjoerg for (std::vector<SourceRange>::const_iterator i = SkippedRanges.begin(),
8847*13fbcb42Sjoerg ei = SkippedRanges.end();
884806f32e7eSjoerg i != ei; ++i) {
8849*13fbcb42Sjoerg if (sm.getFileID(i->getBegin()) == wantedFileID ||
8850*13fbcb42Sjoerg sm.getFileID(i->getEnd()) == wantedFileID)
885106f32e7eSjoerg wantedRanges.push_back(*i);
8852*13fbcb42Sjoerg else if (isMainFile && (astUnit->isInPreambleFileID(i->getBegin()) ||
8853*13fbcb42Sjoerg astUnit->isInPreambleFileID(i->getEnd())))
885406f32e7eSjoerg wantedRanges.push_back(*i);
885506f32e7eSjoerg }
885606f32e7eSjoerg
885706f32e7eSjoerg skipped->count = wantedRanges.size();
885806f32e7eSjoerg skipped->ranges = new CXSourceRange[skipped->count];
885906f32e7eSjoerg for (unsigned i = 0, ei = skipped->count; i != ei; ++i)
886006f32e7eSjoerg skipped->ranges[i] = cxloc::translateSourceRange(Ctx, wantedRanges[i]);
886106f32e7eSjoerg
886206f32e7eSjoerg return skipped;
886306f32e7eSjoerg }
886406f32e7eSjoerg
clang_getAllSkippedRanges(CXTranslationUnit TU)886506f32e7eSjoerg CXSourceRangeList *clang_getAllSkippedRanges(CXTranslationUnit TU) {
886606f32e7eSjoerg CXSourceRangeList *skipped = new CXSourceRangeList;
886706f32e7eSjoerg skipped->count = 0;
886806f32e7eSjoerg skipped->ranges = nullptr;
886906f32e7eSjoerg
887006f32e7eSjoerg if (isNotUsableTU(TU)) {
887106f32e7eSjoerg LOG_BAD_TU(TU);
887206f32e7eSjoerg return skipped;
887306f32e7eSjoerg }
887406f32e7eSjoerg
887506f32e7eSjoerg ASTUnit *astUnit = cxtu::getASTUnit(TU);
8876*13fbcb42Sjoerg PreprocessingRecord *ppRec =
8877*13fbcb42Sjoerg astUnit->getPreprocessor().getPreprocessingRecord();
887806f32e7eSjoerg if (!ppRec)
887906f32e7eSjoerg return skipped;
888006f32e7eSjoerg
888106f32e7eSjoerg ASTContext &Ctx = astUnit->getASTContext();
888206f32e7eSjoerg
888306f32e7eSjoerg const std::vector<SourceRange> &SkippedRanges = ppRec->getSkippedRanges();
888406f32e7eSjoerg
888506f32e7eSjoerg skipped->count = SkippedRanges.size();
888606f32e7eSjoerg skipped->ranges = new CXSourceRange[skipped->count];
888706f32e7eSjoerg for (unsigned i = 0, ei = skipped->count; i != ei; ++i)
888806f32e7eSjoerg skipped->ranges[i] = cxloc::translateSourceRange(Ctx, SkippedRanges[i]);
888906f32e7eSjoerg
889006f32e7eSjoerg return skipped;
889106f32e7eSjoerg }
889206f32e7eSjoerg
clang_disposeSourceRangeList(CXSourceRangeList * ranges)889306f32e7eSjoerg void clang_disposeSourceRangeList(CXSourceRangeList *ranges) {
889406f32e7eSjoerg if (ranges) {
889506f32e7eSjoerg delete[] ranges->ranges;
889606f32e7eSjoerg delete ranges;
889706f32e7eSjoerg }
889806f32e7eSjoerg }
889906f32e7eSjoerg
PrintLibclangResourceUsage(CXTranslationUnit TU)890006f32e7eSjoerg void clang::PrintLibclangResourceUsage(CXTranslationUnit TU) {
890106f32e7eSjoerg CXTUResourceUsage Usage = clang_getCXTUResourceUsage(TU);
890206f32e7eSjoerg for (unsigned I = 0; I != Usage.numEntries; ++I)
890306f32e7eSjoerg fprintf(stderr, " %s: %lu\n",
890406f32e7eSjoerg clang_getTUResourceUsageName(Usage.entries[I].kind),
890506f32e7eSjoerg Usage.entries[I].amount);
890606f32e7eSjoerg
890706f32e7eSjoerg clang_disposeCXTUResourceUsage(Usage);
890806f32e7eSjoerg }
890906f32e7eSjoerg
clang_Cursor_getVarDeclInitializer(CXCursor cursor)8910*13fbcb42Sjoerg CXCursor clang_Cursor_getVarDeclInitializer(CXCursor cursor) {
8911*13fbcb42Sjoerg const Decl *const D = getCursorDecl(cursor);
8912*13fbcb42Sjoerg if (!D)
8913*13fbcb42Sjoerg return clang_getNullCursor();
8914*13fbcb42Sjoerg const auto *const VD = dyn_cast<VarDecl>(D);
8915*13fbcb42Sjoerg if (!VD)
8916*13fbcb42Sjoerg return clang_getNullCursor();
8917*13fbcb42Sjoerg const Expr *const Init = VD->getInit();
8918*13fbcb42Sjoerg if (!Init)
8919*13fbcb42Sjoerg return clang_getNullCursor();
8920*13fbcb42Sjoerg
8921*13fbcb42Sjoerg return cxcursor::MakeCXCursor(Init, VD, cxcursor::getCursorTU(cursor));
8922*13fbcb42Sjoerg }
8923*13fbcb42Sjoerg
clang_Cursor_hasVarDeclGlobalStorage(CXCursor cursor)8924*13fbcb42Sjoerg int clang_Cursor_hasVarDeclGlobalStorage(CXCursor cursor) {
8925*13fbcb42Sjoerg const Decl *const D = getCursorDecl(cursor);
8926*13fbcb42Sjoerg if (!D)
8927*13fbcb42Sjoerg return -1;
8928*13fbcb42Sjoerg const auto *const VD = dyn_cast<VarDecl>(D);
8929*13fbcb42Sjoerg if (!VD)
8930*13fbcb42Sjoerg return -1;
8931*13fbcb42Sjoerg
8932*13fbcb42Sjoerg return VD->hasGlobalStorage();
8933*13fbcb42Sjoerg }
8934*13fbcb42Sjoerg
clang_Cursor_hasVarDeclExternalStorage(CXCursor cursor)8935*13fbcb42Sjoerg int clang_Cursor_hasVarDeclExternalStorage(CXCursor cursor) {
8936*13fbcb42Sjoerg const Decl *const D = getCursorDecl(cursor);
8937*13fbcb42Sjoerg if (!D)
8938*13fbcb42Sjoerg return -1;
8939*13fbcb42Sjoerg const auto *const VD = dyn_cast<VarDecl>(D);
8940*13fbcb42Sjoerg if (!VD)
8941*13fbcb42Sjoerg return -1;
8942*13fbcb42Sjoerg
8943*13fbcb42Sjoerg return VD->hasExternalStorage();
8944*13fbcb42Sjoerg }
8945*13fbcb42Sjoerg
894606f32e7eSjoerg //===----------------------------------------------------------------------===//
894706f32e7eSjoerg // Misc. utility functions.
894806f32e7eSjoerg //===----------------------------------------------------------------------===//
894906f32e7eSjoerg
895006f32e7eSjoerg /// Default to using our desired 8 MB stack size on "safety" threads.
895106f32e7eSjoerg static unsigned SafetyStackThreadSize = DesiredStackSize;
895206f32e7eSjoerg
895306f32e7eSjoerg namespace clang {
895406f32e7eSjoerg
RunSafely(llvm::CrashRecoveryContext & CRC,llvm::function_ref<void ()> Fn,unsigned Size)895506f32e7eSjoerg bool RunSafely(llvm::CrashRecoveryContext &CRC, llvm::function_ref<void()> Fn,
895606f32e7eSjoerg unsigned Size) {
895706f32e7eSjoerg if (!Size)
895806f32e7eSjoerg Size = GetSafetyThreadStackSize();
895906f32e7eSjoerg if (Size && !getenv("LIBCLANG_NOTHREADS"))
896006f32e7eSjoerg return CRC.RunSafelyOnThread(Fn, Size);
896106f32e7eSjoerg return CRC.RunSafely(Fn);
896206f32e7eSjoerg }
896306f32e7eSjoerg
GetSafetyThreadStackSize()8964*13fbcb42Sjoerg unsigned GetSafetyThreadStackSize() { return SafetyStackThreadSize; }
896506f32e7eSjoerg
SetSafetyThreadStackSize(unsigned Value)8966*13fbcb42Sjoerg void SetSafetyThreadStackSize(unsigned Value) { SafetyStackThreadSize = Value; }
896706f32e7eSjoerg
8968*13fbcb42Sjoerg } // namespace clang
896906f32e7eSjoerg
setThreadBackgroundPriority()897006f32e7eSjoerg void clang::setThreadBackgroundPriority() {
897106f32e7eSjoerg if (getenv("LIBCLANG_BGPRIO_DISABLE"))
897206f32e7eSjoerg return;
897306f32e7eSjoerg
897406f32e7eSjoerg #if LLVM_ENABLE_THREADS
897506f32e7eSjoerg llvm::set_thread_priority(llvm::ThreadPriority::Background);
897606f32e7eSjoerg #endif
897706f32e7eSjoerg }
897806f32e7eSjoerg
printDiagsToStderr(ASTUnit * Unit)897906f32e7eSjoerg void cxindex::printDiagsToStderr(ASTUnit *Unit) {
898006f32e7eSjoerg if (!Unit)
898106f32e7eSjoerg return;
898206f32e7eSjoerg
898306f32e7eSjoerg for (ASTUnit::stored_diag_iterator D = Unit->stored_diag_begin(),
898406f32e7eSjoerg DEnd = Unit->stored_diag_end();
898506f32e7eSjoerg D != DEnd; ++D) {
898606f32e7eSjoerg CXStoredDiagnostic Diag(*D, Unit->getLangOpts());
8987*13fbcb42Sjoerg CXString Msg =
8988*13fbcb42Sjoerg clang_formatDiagnostic(&Diag, clang_defaultDiagnosticDisplayOptions());
898906f32e7eSjoerg fprintf(stderr, "%s\n", clang_getCString(Msg));
899006f32e7eSjoerg clang_disposeString(Msg);
899106f32e7eSjoerg }
899206f32e7eSjoerg #ifdef _WIN32
899306f32e7eSjoerg // On Windows, force a flush, since there may be multiple copies of
899406f32e7eSjoerg // stderr and stdout in the file system, all with different buffers
899506f32e7eSjoerg // but writing to the same device.
899606f32e7eSjoerg fflush(stderr);
899706f32e7eSjoerg #endif
899806f32e7eSjoerg }
899906f32e7eSjoerg
getMacroInfo(const IdentifierInfo & II,SourceLocation MacroDefLoc,CXTranslationUnit TU)900006f32e7eSjoerg MacroInfo *cxindex::getMacroInfo(const IdentifierInfo &II,
900106f32e7eSjoerg SourceLocation MacroDefLoc,
900206f32e7eSjoerg CXTranslationUnit TU) {
900306f32e7eSjoerg if (MacroDefLoc.isInvalid() || !TU)
900406f32e7eSjoerg return nullptr;
900506f32e7eSjoerg if (!II.hadMacroDefinition())
900606f32e7eSjoerg return nullptr;
900706f32e7eSjoerg
900806f32e7eSjoerg ASTUnit *Unit = cxtu::getASTUnit(TU);
900906f32e7eSjoerg Preprocessor &PP = Unit->getPreprocessor();
901006f32e7eSjoerg MacroDirective *MD = PP.getLocalMacroDirectiveHistory(&II);
901106f32e7eSjoerg if (MD) {
9012*13fbcb42Sjoerg for (MacroDirective::DefInfo Def = MD->getDefinition(); Def;
9013*13fbcb42Sjoerg Def = Def.getPreviousDefinition()) {
901406f32e7eSjoerg if (MacroDefLoc == Def.getMacroInfo()->getDefinitionLoc())
901506f32e7eSjoerg return Def.getMacroInfo();
901606f32e7eSjoerg }
901706f32e7eSjoerg }
901806f32e7eSjoerg
901906f32e7eSjoerg return nullptr;
902006f32e7eSjoerg }
902106f32e7eSjoerg
getMacroInfo(const MacroDefinitionRecord * MacroDef,CXTranslationUnit TU)902206f32e7eSjoerg const MacroInfo *cxindex::getMacroInfo(const MacroDefinitionRecord *MacroDef,
902306f32e7eSjoerg CXTranslationUnit TU) {
902406f32e7eSjoerg if (!MacroDef || !TU)
902506f32e7eSjoerg return nullptr;
902606f32e7eSjoerg const IdentifierInfo *II = MacroDef->getName();
902706f32e7eSjoerg if (!II)
902806f32e7eSjoerg return nullptr;
902906f32e7eSjoerg
903006f32e7eSjoerg return getMacroInfo(*II, MacroDef->getLocation(), TU);
903106f32e7eSjoerg }
903206f32e7eSjoerg
903306f32e7eSjoerg MacroDefinitionRecord *
checkForMacroInMacroDefinition(const MacroInfo * MI,const Token & Tok,CXTranslationUnit TU)903406f32e7eSjoerg cxindex::checkForMacroInMacroDefinition(const MacroInfo *MI, const Token &Tok,
903506f32e7eSjoerg CXTranslationUnit TU) {
903606f32e7eSjoerg if (!MI || !TU)
903706f32e7eSjoerg return nullptr;
903806f32e7eSjoerg if (Tok.isNot(tok::raw_identifier))
903906f32e7eSjoerg return nullptr;
904006f32e7eSjoerg
904106f32e7eSjoerg if (MI->getNumTokens() == 0)
904206f32e7eSjoerg return nullptr;
904306f32e7eSjoerg SourceRange DefRange(MI->getReplacementToken(0).getLocation(),
904406f32e7eSjoerg MI->getDefinitionEndLoc());
904506f32e7eSjoerg ASTUnit *Unit = cxtu::getASTUnit(TU);
904606f32e7eSjoerg
904706f32e7eSjoerg // Check that the token is inside the definition and not its argument list.
904806f32e7eSjoerg SourceManager &SM = Unit->getSourceManager();
904906f32e7eSjoerg if (SM.isBeforeInTranslationUnit(Tok.getLocation(), DefRange.getBegin()))
905006f32e7eSjoerg return nullptr;
905106f32e7eSjoerg if (SM.isBeforeInTranslationUnit(DefRange.getEnd(), Tok.getLocation()))
905206f32e7eSjoerg return nullptr;
905306f32e7eSjoerg
905406f32e7eSjoerg Preprocessor &PP = Unit->getPreprocessor();
905506f32e7eSjoerg PreprocessingRecord *PPRec = PP.getPreprocessingRecord();
905606f32e7eSjoerg if (!PPRec)
905706f32e7eSjoerg return nullptr;
905806f32e7eSjoerg
905906f32e7eSjoerg IdentifierInfo &II = PP.getIdentifierTable().get(Tok.getRawIdentifier());
906006f32e7eSjoerg if (!II.hadMacroDefinition())
906106f32e7eSjoerg return nullptr;
906206f32e7eSjoerg
906306f32e7eSjoerg // Check that the identifier is not one of the macro arguments.
906406f32e7eSjoerg if (std::find(MI->param_begin(), MI->param_end(), &II) != MI->param_end())
906506f32e7eSjoerg return nullptr;
906606f32e7eSjoerg
906706f32e7eSjoerg MacroDirective *InnerMD = PP.getLocalMacroDirectiveHistory(&II);
906806f32e7eSjoerg if (!InnerMD)
906906f32e7eSjoerg return nullptr;
907006f32e7eSjoerg
907106f32e7eSjoerg return PPRec->findMacroDefinition(InnerMD->getMacroInfo());
907206f32e7eSjoerg }
907306f32e7eSjoerg
907406f32e7eSjoerg MacroDefinitionRecord *
checkForMacroInMacroDefinition(const MacroInfo * MI,SourceLocation Loc,CXTranslationUnit TU)907506f32e7eSjoerg cxindex::checkForMacroInMacroDefinition(const MacroInfo *MI, SourceLocation Loc,
907606f32e7eSjoerg CXTranslationUnit TU) {
907706f32e7eSjoerg if (Loc.isInvalid() || !MI || !TU)
907806f32e7eSjoerg return nullptr;
907906f32e7eSjoerg
908006f32e7eSjoerg if (MI->getNumTokens() == 0)
908106f32e7eSjoerg return nullptr;
908206f32e7eSjoerg ASTUnit *Unit = cxtu::getASTUnit(TU);
908306f32e7eSjoerg Preprocessor &PP = Unit->getPreprocessor();
908406f32e7eSjoerg if (!PP.getPreprocessingRecord())
908506f32e7eSjoerg return nullptr;
908606f32e7eSjoerg Loc = Unit->getSourceManager().getSpellingLoc(Loc);
908706f32e7eSjoerg Token Tok;
908806f32e7eSjoerg if (PP.getRawToken(Loc, Tok))
908906f32e7eSjoerg return nullptr;
909006f32e7eSjoerg
909106f32e7eSjoerg return checkForMacroInMacroDefinition(MI, Tok, TU);
909206f32e7eSjoerg }
909306f32e7eSjoerg
clang_getClangVersion()909406f32e7eSjoerg CXString clang_getClangVersion() {
909506f32e7eSjoerg return cxstring::createDup(getClangFullVersion());
909606f32e7eSjoerg }
909706f32e7eSjoerg
operator <<(CXTranslationUnit TU)909806f32e7eSjoerg Logger &cxindex::Logger::operator<<(CXTranslationUnit TU) {
909906f32e7eSjoerg if (TU) {
910006f32e7eSjoerg if (ASTUnit *Unit = cxtu::getASTUnit(TU)) {
910106f32e7eSjoerg LogOS << '<' << Unit->getMainFileName() << '>';
910206f32e7eSjoerg if (Unit->isMainFileAST())
910306f32e7eSjoerg LogOS << " (" << Unit->getASTFileName() << ')';
910406f32e7eSjoerg return *this;
910506f32e7eSjoerg }
910606f32e7eSjoerg } else {
910706f32e7eSjoerg LogOS << "<NULL TU>";
910806f32e7eSjoerg }
910906f32e7eSjoerg return *this;
911006f32e7eSjoerg }
911106f32e7eSjoerg
operator <<(const FileEntry * FE)911206f32e7eSjoerg Logger &cxindex::Logger::operator<<(const FileEntry *FE) {
911306f32e7eSjoerg *this << FE->getName();
911406f32e7eSjoerg return *this;
911506f32e7eSjoerg }
911606f32e7eSjoerg
operator <<(CXCursor cursor)911706f32e7eSjoerg Logger &cxindex::Logger::operator<<(CXCursor cursor) {
911806f32e7eSjoerg CXString cursorName = clang_getCursorDisplayName(cursor);
911906f32e7eSjoerg *this << cursorName << "@" << clang_getCursorLocation(cursor);
912006f32e7eSjoerg clang_disposeString(cursorName);
912106f32e7eSjoerg return *this;
912206f32e7eSjoerg }
912306f32e7eSjoerg
operator <<(CXSourceLocation Loc)912406f32e7eSjoerg Logger &cxindex::Logger::operator<<(CXSourceLocation Loc) {
912506f32e7eSjoerg CXFile File;
912606f32e7eSjoerg unsigned Line, Column;
912706f32e7eSjoerg clang_getFileLocation(Loc, &File, &Line, &Column, nullptr);
912806f32e7eSjoerg CXString FileName = clang_getFileName(File);
912906f32e7eSjoerg *this << llvm::format("(%s:%d:%d)", clang_getCString(FileName), Line, Column);
913006f32e7eSjoerg clang_disposeString(FileName);
913106f32e7eSjoerg return *this;
913206f32e7eSjoerg }
913306f32e7eSjoerg
operator <<(CXSourceRange range)913406f32e7eSjoerg Logger &cxindex::Logger::operator<<(CXSourceRange range) {
913506f32e7eSjoerg CXSourceLocation BLoc = clang_getRangeStart(range);
913606f32e7eSjoerg CXSourceLocation ELoc = clang_getRangeEnd(range);
913706f32e7eSjoerg
913806f32e7eSjoerg CXFile BFile;
913906f32e7eSjoerg unsigned BLine, BColumn;
914006f32e7eSjoerg clang_getFileLocation(BLoc, &BFile, &BLine, &BColumn, nullptr);
914106f32e7eSjoerg
914206f32e7eSjoerg CXFile EFile;
914306f32e7eSjoerg unsigned ELine, EColumn;
914406f32e7eSjoerg clang_getFileLocation(ELoc, &EFile, &ELine, &EColumn, nullptr);
914506f32e7eSjoerg
914606f32e7eSjoerg CXString BFileName = clang_getFileName(BFile);
914706f32e7eSjoerg if (BFile == EFile) {
914806f32e7eSjoerg *this << llvm::format("[%s %d:%d-%d:%d]", clang_getCString(BFileName),
914906f32e7eSjoerg BLine, BColumn, ELine, EColumn);
915006f32e7eSjoerg } else {
915106f32e7eSjoerg CXString EFileName = clang_getFileName(EFile);
9152*13fbcb42Sjoerg *this << llvm::format("[%s:%d:%d - ", clang_getCString(BFileName), BLine,
9153*13fbcb42Sjoerg BColumn)
9154*13fbcb42Sjoerg << llvm::format("%s:%d:%d]", clang_getCString(EFileName), ELine,
9155*13fbcb42Sjoerg EColumn);
915606f32e7eSjoerg clang_disposeString(EFileName);
915706f32e7eSjoerg }
915806f32e7eSjoerg clang_disposeString(BFileName);
915906f32e7eSjoerg return *this;
916006f32e7eSjoerg }
916106f32e7eSjoerg
operator <<(CXString Str)916206f32e7eSjoerg Logger &cxindex::Logger::operator<<(CXString Str) {
916306f32e7eSjoerg *this << clang_getCString(Str);
916406f32e7eSjoerg return *this;
916506f32e7eSjoerg }
916606f32e7eSjoerg
operator <<(const llvm::format_object_base & Fmt)916706f32e7eSjoerg Logger &cxindex::Logger::operator<<(const llvm::format_object_base &Fmt) {
916806f32e7eSjoerg LogOS << Fmt;
916906f32e7eSjoerg return *this;
917006f32e7eSjoerg }
917106f32e7eSjoerg
917206f32e7eSjoerg static llvm::ManagedStatic<std::mutex> LoggingMutex;
917306f32e7eSjoerg
~Logger()917406f32e7eSjoerg cxindex::Logger::~Logger() {
917506f32e7eSjoerg std::lock_guard<std::mutex> L(*LoggingMutex);
917606f32e7eSjoerg
917706f32e7eSjoerg static llvm::TimeRecord sBeginTR = llvm::TimeRecord::getCurrentTime();
917806f32e7eSjoerg
917906f32e7eSjoerg raw_ostream &OS = llvm::errs();
918006f32e7eSjoerg OS << "[libclang:" << Name << ':';
918106f32e7eSjoerg
918206f32e7eSjoerg #ifdef USE_DARWIN_THREADS
918306f32e7eSjoerg // TODO: Portability.
918406f32e7eSjoerg mach_port_t tid = pthread_mach_thread_np(pthread_self());
918506f32e7eSjoerg OS << tid << ':';
918606f32e7eSjoerg #endif
918706f32e7eSjoerg
918806f32e7eSjoerg llvm::TimeRecord TR = llvm::TimeRecord::getCurrentTime();
918906f32e7eSjoerg OS << llvm::format("%7.4f] ", TR.getWallTime() - sBeginTR.getWallTime());
919006f32e7eSjoerg OS << Msg << '\n';
919106f32e7eSjoerg
919206f32e7eSjoerg if (Trace) {
919306f32e7eSjoerg llvm::sys::PrintStackTrace(OS);
919406f32e7eSjoerg OS << "--------------------------------------------------\n";
919506f32e7eSjoerg }
919606f32e7eSjoerg }
9197